Reputation: 983
I have an issue with an application I'm writing with ffmpeg api.
I have an mp3 file that is missing id3 tags (it starts with frame data 0xFFFB).
Now if I'm running ffprobe on this file, the av_format_dump from ffprobe gives this info:
[AVFormatContext @ 0000015509158a00] Opening 'OhYeah.mp3' for reading
[file @ 0000015509158fc0] Setting default whitelist 'file,crypto,data'
Probing mp3 score:1 size:2048
Probing mp3 score:25 size:4096
Probing mp3 score:51 size:8192
[mp3 @ 0000015509158a00] Format mp3 probed with size=8192 and score=51
[mp3 @ 0000015509158a00] pad 576 1418
[mp3 @ 0000015509158a00] Skipping 0 bytes of junk at 835.
[mp3 @ 0000015509158a00] Before avformat_find_stream_info() pos: 835 bytes read:97968 seeks:1 nb_streams:1
[mp3 @ 0000015509158a00] demuxer injecting skip 1105 / discard 0
[mp3float @ 0000015509162000] skip 1105 / discard 0 samples due to side data
[mp3float @ 0000015509162000] skip 1105/1152 samples
[mp3 @ 0000015509158a00] All info found
[mp3 @ 0000015509158a00] stream 0: start_time: 0.0250567 duration: 2.011429
[mp3 @ 0000015509158a00] format: start_time: 0.025057 duration: 2.011429 (estimate from stream) bitrate=259 kb/s
[mp3 @ 0000015509158a00] After avformat_find_stream_info() pos: 42819 bytes read:130400 seeks:1 frames:50
Input #0, mp3, from 'OhYeah.mp3':
Duration: 00:00:02.01, start: 0.025057, bitrate: 259 kb/s
Stream #0:0, 50, 1/14112000: Audio: mp3 (mp3float), 44100 Hz, stereo, fltp, 256 kb/s
Metadata:
encoder : LAME3.100
[AVIOContext @ 0000015509161a80] Statistics: 130400 bytes read, 1 seeks
But if I do the same in C++ I get wrong duration:
[AVFormatContext @ 0x236c2f0] Opening '/tmp/OhYeah.mp3' for reading"}
"[file @ 0x236c6b0] Setting default whitelist 'file,crypto,data'"}
'Probing mp3 score:1 size:2048'}
'Probing mp3 score:25 size:4096'}
'Probing mp3 score:51 size:8192'}
'[mp3 @ 0x236c2f0] Format mp3 probed with size=8192 and score=51'}
'[mp3 @ 0x236c2f0] invalid concatenated file detected - using bitrate for duration'}
'[mp3 @ 0x236c2f0] pad 576 1418'}
'[mp3 @ 0x236c2f0] Skipping 0 bytes of junk at 835.'}
'[mp3 @ 0x236c2f0] Before avformat_find_stream_info() pos: 835 bytes read:65536 seeks:2 nb_streams:1'}
'[mp3 @ 0x236c2f0] demuxer injecting skip 1105 / discard 0'}
'[mp3float @ 0x2374cd0] skip 1105 / discard 0 samples due to side data'}
'[mp3float @ 0x2374cd0] skip 1105/1152 samples'}
'[mp3 @ 0x236c2f0] All info found'}
'[mp3 @ 0x236c2f0] Estimating duration from bitrate, this may be inaccurate'}
'[mp3 @ 0x236c2f0] stream 0: start_time: 0.0250567 duration: 53521.548438'}
'[mp3 @ 0x236c2f0] format: start_time: 0.025057 dur….548438 (estimate from bit rate) bitrate=256 kb/s'}
'[mp3 @ 0x236c2f0] format: start_time: 0.025057 duration: 53521.548438 (estimate from bit rate) bitrate=256 kb/s"
'[mp3 @ 0x236c2f0] After avformat_find_stream_info() pos: 42819 bytes read:97968 seeks:2 frames:50'}
"Input #0, mp3, from '/tmp/OhYeah.mp3':"}
' Duration: 14:52:01.55, start: 0.025057, bitrate: 256 kb/s'}
' Stream #0:0, 50, 1/14112000: Audio: mp3 (mp3float), 44100 Hz, stereo, fltp, 256 kb/s'}
' Metadata:'}
' encoder : LAME3.100'}
'[AVIOContext @ 0x2374780] Statistics: 97968 bytes read, 2 seeks'}
I've also tried to set scan_all_pmts flag...
Here is my code:
av_log_set_level(AV_LOG_TRACE);
AVDictionary *options = nullptr;
av_dict_set(&options, "scan_all_pmts", "1", AV_DICT_MATCH_CASE);
AVFormatContext *format_context = nullptr;
int ret = avformat_open_input(&format_context, path.c_str(), nullptr, &options);
if (ret < 0)
{
char strError[AV_ERROR_MAX_STRING_SIZE];
av_strerror(ret, strError, sizeof(strError));
LOG(1, "Error opening input file: %s, error %s\n", path.c_str(), strError);
retObj.set("status", "error");
retObj.set("error", strError);
return retObj;
}
ret = avformat_find_stream_info(format_context, nullptr);
if (ret < 0)
{
char strError[AV_ERROR_MAX_STRING_SIZE];
av_strerror(ret, strError, sizeof(strError));
LOG(1, "Error retrieving stream information: %s, error %s\n", path.c_str(), strError);
avformat_close_input(&format_context);
retObj.set("status", "error");
retObj.set("error", strError);
return retObj;
}
av_dump_format(format_context, 0, path.c_str(), 0);
The only way I can get the duration right now, is by calculating the packages duration sum:
// seek packages and calculate duration
float duration = 0;
AVPacket pkg;
av_init_packet(&pkg);
pkg.data = nullptr;
pkg.size = 0;
while (av_read_frame(format_context, &pkg) >= 0)
{
if (pkg.stream_index == audioStreamIndex)
{
duration += av_q2d(format_context->streams[audioStreamIndex]->time_base) * pkg.duration;
}
av_packet_unref(&pkg);
}
LOG(3, "duration: %f\n", duration);
So what does ffprobe do differently to be able to read this mp3, also it's reading more bytes before calling avformat_find_stream_info...
I tried to look at the ffprobe code but other than scan_all_pmts didn't see anything suspicious.
Upvotes: 1
Views: 111