[FFmpeg-devel] [PATCH] fix MXF audio PTS calculation for compressed audio (ADTS/AAC)

Markus Schumann go4shoe at hotmail.com
Thu Sep 6 00:37:18 EEST 2018



> On Sep 5, 2018, at 16:06, Marton Balint <cus at passwd.hu> wrote:
> 
> 
> 
>> On Tue, 4 Sep 2018, Markus Schumann wrote:
>> 
>> ---
>> libavformat/mxfdec.c | 67 +++++++++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 66 insertions(+), 1 deletion(-)
>> 
>> diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
>> index 8e1089620f..adfffd954a
>> --- a/libavformat/mxfdec.c
>> +++ b/libavformat/mxfdec.c
>> @@ -3266,9 +3266,63 @@ static int64_t mxf_set_current_edit_unit(MXFContext *mxf, AVStream *st, int64_t
>>    return mxf_set_current_edit_unit(mxf, st, current_offset, 0);
>> }
>> 
>> +static int mxf_aac_adts_count_frames(MXFContext *mxf, AVCodecParameters *par,
>> +                                     AVPacket *pkt)
>> +{
>> +    const uint8_t *end_ptr;
>> +    uint8_t *data_ptr;
>> +    int32_t aac_frame_length, adts_frame_count;
>> +    uint8_t sample_rate_index;
>> +    uint8_t channel_configuration;
>> +
>> +    data_ptr = pkt->data;
>> +    end_ptr = pkt->data + pkt->size;
>> +       adts_frame_count = 0;
>> +
>> +       /* ADTS header is 7 bytes */
>> +       if (pkt->size < 7)
>> +               return 0;
>> +
>> +       /* check for sync bits 0xfff */
>> +       if (data_ptr[0] != 0xff || (data_ptr[1] & 0xf0) != 0xf0) return AVERROR(EINVAL);
>> +
>> +       sample_rate_index = (data_ptr[2] & 0x3c) >> 2;
>> +
>> +       channel_configuration = ((data_ptr[2] & 0x01) << 2) | ((data_ptr[3] & 0xc0) >> 6);
>> +
>> +       adts_frame_count = 1;
>> +
>> +       data_ptr += 7;
>> +
>> +       for (; data_ptr + 7 < end_ptr; ++data_ptr)
>> +       {
>> +               /* check for sync bits 0xfff */
>> +               if (data_ptr[0] != 0xff || (data_ptr[1] & 0xf0) != 0xf0) continue;
>> +
>> +               /* make sure sample rate is identical */
>> +               if (sample_rate_index != (data_ptr[2] & 0x3c) >> 2) continue;
>> +
>> +               /* make sure channel configuration is identical */
>> +               if (channel_configuration != (((data_ptr[2] & 0x01) << 2) | ((data_ptr[3] & 0xc0) >> 6))) continue;
>> +
>> +               aac_frame_length = ((int32_t)(data_ptr[3] & 0x03) << 11) | ((int32_t)data_ptr[4] << 3) | ((int32_t)(data_ptr[5] & 0xe0) >> 5);
>> +
>> +               /* sanity check on the frame length */
>> +               if (aac_frame_length < 1 || aac_frame_length > 8 * 768 + 7 + 2) continue;
>> +
>> +               ++adts_frame_count;
>> +
>> +               data_ptr += 7;
>> +       }
>> +
>> +       return adts_frame_count;
>> +}
>> +
>> static int mxf_set_audio_pts(MXFContext *mxf, AVCodecParameters *par,
>>                             AVPacket *pkt)
>> {
>> +    int frame_count;
>> +
>>    MXFTrack *track = mxf->fc->streams[pkt->stream_index]->priv_data;
>>    int64_t bits_per_sample = par->bits_per_coded_sample;
>> 
>> @@ -3281,7 +3335,18 @@ static int mxf_set_audio_pts(MXFContext *mxf, AVCodecParameters *par,
>>        || bits_per_sample <= 0
>>        || par->channels * (int64_t)bits_per_sample < 8)
>>        return AVERROR(EINVAL);
>> -    track->sample_count += pkt->size / (par->channels * (int64_t)bits_per_sample / 8);
>> +
>> +    switch (par->codec_id) {
>> +    case AV_CODEC_ID_AAC:
>> +        frame_count =  mxf_aac_adts_count_frames(mxf, par, pkt);
>> +        if (frame_count < 0) return AVERROR(EINVAL);
>> +        track->sample_count += 1024 * frame_count;
>> +       break;
>> +    default:
>> +       /* here we assume PCM */
>> +       track->sample_count += pkt->size / (par->channels * (int64_t)bits_per_sample / 8);
>> +       break;
>> +    }
>>    return 0;
> 
> I just pushed a patch which fixes the error messages decoding frame wrapped (as in 25fps frame wrapped) AAC packets. Obviously audio packet pts-es will not be sample correct, but they should be accurate enough for average use cases. (and it is not uncommon that demuxers are unable to provide sample accurate timestamps).
> 
> In general it is not a good idea to put codec parsing code in a demuxer, we have parsers for that. So an alternative approach might be to return AV_NOPTS_VALUE from the mxf demuxer and let the aac parser fill in the timestamps, but in this case, since we can determine a rough timestamp based on the format, I think it is better if we return that, because that is what the other demuxers are doing as well.
> 
> Is there a use case which does not work for you using the current git master?
> 
> Thanks,
> Marton
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

I just built FFmpeg master with your changes and then VLC using FFmpeg master. 

My sample from ticket #7366 plays fine in VLC with your changes.

So your changes should be good enough.

Thanks Markus.



More information about the ffmpeg-devel mailing list