Spider
Spider

Reputation: 983

ffprobe vs C api ffmpeg gives different results on mp3 without id3 tag

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

Answers (0)

Related Questions