[FFmpeg-devel] [PATCH] avformat/matroskaenc: always reserve max aac private data
Andreas Rheinhardt
andreas.rheinhardt at gmail.com
Fri May 1 20:55:00 EEST 2020
John Stebbins:
> On Fri, 2020-05-01 at 19:22 +0200, Andreas Rheinhardt wrote:
>> John Stebbins:
>>> When extra data is updated using AV_PKT_DATA_NEW_EXTRADATA, the
>>> data is
>>> written plus extra space is reserved for the max possible size
>>> extradata.
>>> But when extradata is written during mkv_write_header, no extra
>>> space is
>>> reserved. So the side data update overwrites whatever follows the
>>> extradata in the track header and results in an invalid file.
>>> ---
>>> libavformat/matroskaenc.c | 14 ++++++++------
>>> 1 file changed, 8 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
>>> index 784973a951..e6917002c4 100644
>>> --- a/libavformat/matroskaenc.c
>>> +++ b/libavformat/matroskaenc.c
>>> @@ -728,8 +728,6 @@ static int
>>> mkv_write_native_codecprivate(AVFormatContext *s, AVIOContext *pb,
>>> case AV_CODEC_ID_AAC:
>>> if (par->extradata_size)
>>> avio_write(dyn_cp, par->extradata, par-
>>>> extradata_size);
>>> - else
>>> - put_ebml_void(pb, MAX_PCE_SIZE + 2 + 4);
>>> break;
>>> default:
>>> if (par->codec_id == AV_CODEC_ID_PRORES &&
>>> @@ -749,6 +747,7 @@ static int
>>> mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb,
>>> AVIOContext *dyn_cp;
>>> uint8_t *codecpriv;
>>> int ret, codecpriv_size;
>>> + int64_t offset;
>>>
>>> ret = avio_open_dyn_buf(&dyn_cp);
>>> if (ret < 0)
>>> @@ -802,9 +801,15 @@ static int
>>> mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb,
>>> }
>>>
>>> codecpriv_size = avio_get_dyn_buf(dyn_cp, &codecpriv);
>>> + offset = avio_tell(pb);
>>> if (codecpriv_size)
>>> put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv,
>>> codecpriv_size);
>>> + if (par->codec_id == AV_CODEC_ID_AAC) {
>>> + int filler = MAX_PCE_SIZE + 2 + 4 - (avio_tell(pb) -
>>> offset);
>>> + if (filler)
>>> + put_ebml_void(pb, filler);
>>> + }
>>> ffio_free_dyn_buf(&dyn_cp);
>>> return ret;
>>> }
>>> @@ -2182,7 +2187,7 @@ static int
>>> mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt)
>>> switch (par->codec_id) {
>>> case AV_CODEC_ID_AAC:
>>> if (side_data_size && (s->pb->seekable &
>>> AVIO_SEEKABLE_NORMAL) && !mkv->is_live) {
>>> - int filler, output_sample_rate = 0;
>>> + int output_sample_rate = 0;
>>> ret = get_aac_sample_rates(s, side_data,
>>> side_data_size, &track->sample_rate,
>>> &output_sample_rate);
>>> if (ret < 0)
>>> @@ -2195,9 +2200,6 @@ static int
>>> mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt)
>>> memcpy(par->extradata, side_data, side_data_size);
>>> avio_seek(mkv->tracks_bc, track->codecpriv_offset,
>>> SEEK_SET);
>>> mkv_write_codecprivate(s, mkv->tracks_bc, par, 1, 0);
>>> - filler = MAX_PCE_SIZE + 2 + 4 - (avio_tell(mkv-
>>>> tracks_bc) - track->codecpriv_offset);
>>> - if (filler)
>>> - put_ebml_void(mkv->tracks_bc, filler);
>>> avio_seek(mkv->tracks_bc, track->sample_rate_offset,
>>> SEEK_SET);
>>> put_ebml_float(mkv->tracks_bc,
>>> MATROSKA_ID_AUDIOSAMPLINGFREQ, track->sample_rate);
>>> put_ebml_float(mkv->tracks_bc,
>>> MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);
>>>
>> If we already had extradata when writing the header, then what
>> guarantees us that the new extradata is better and should be
>> preferred
>> to the old extradata? (I don't know the details of AAC extradata, but
>> is
>> it possible that the extradata is simply incompatible to the old one
>> (e.g. when a user splices together actually incompatible streams)?)
>>
>
> The test case is a TS file with aac audio. It TS files, it is
> certainly possible for stream parameters to change on the fly. But, if
> the extradata changes, there's really no way to handle it in mkv since
> this data is global in mkv. So perhaps a better solution is to ignore
> side data extradata if it's already been written once?
>
In this scenario there is no way to know whether the new extradata is
better than the old one. If we ignore the extradata in such scenarios,
then is such a file even decodable?
- Andreas
More information about the ffmpeg-devel
mailing list