[FFmpeg-devel] [PATCH v2 1/2] avformat/flvdec: implement support for parsing ModEx data
Leo Izen
leo.izen at gmail.com
Fri Jan 17 01:36:21 EET 2025
On 1/16/25 6:32 PM, Timo Rothenpieler wrote:
> On 17.01.2025 00:16, Leo Izen wrote:
>> On 1/15/25 5:41 PM, Timo Rothenpieler wrote:
>>> ---
>>> libavformat/flv.h | 5 ++++
>>> libavformat/flvdec.c | 68 ++++++++++++++++++++++++++++++++++++++++++++
>>> 2 files changed, 73 insertions(+)
>>>
>>> diff --git a/libavformat/flv.h b/libavformat/flv.h
>>> index 74d3b8de8b..d8f7980f2e 100644
>>> --- a/libavformat/flv.h
>>> +++ b/libavformat/flv.h
>>> @@ -130,6 +130,7 @@ enum {
>>> PacketTypeMetadata = 4,
>>> PacketTypeMPEG2TSSequenceStart = 5,
>>> PacketTypeMultitrack = 6,
>>> + PacketTypeModEx = 7,
>>> };
>>> enum {
>>> @@ -139,6 +140,10 @@ enum {
>>> AudioPacketTypeMultitrack = 5,
>>> };
>>> +enum {
>>> + PacketModExTypeTimestampOffsetNano = 0,
>>> +};
>>> +
>>> enum {
>>> AudioChannelOrderUnspecified = 0,
>>> AudioChannelOrderNative = 1,
>>> diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
>>> index 2f46475d08..61dd19a691 100644
>>> --- a/libavformat/flvdec.c
>>> +++ b/libavformat/flvdec.c
>>> @@ -1279,6 +1279,62 @@ static int
>>> flv_update_video_color_info(AVFormatContext *s, AVStream *st)
>>> return 0;
>>> }
>>> +static int flv_parse_mod_ex_data(AVFormatContext *s, int *pkt_type,
>>> int *size, int64_t *dts)
>>> +{
>>> + int ex_type, ret;
>>> + uint8_t *ex_data;
>>> +
>>> + int ex_size = (uint8_t)avio_r8(s->pb) + 1;
>>> + *size -= 1;
>>> +
>>> + if (ex_size == 256) {
>>> + ex_size = (uint16_t)avio_rb16(s->pb) + 1;
>>> + *size -= 2;
>>> + }
>>> +
>>> + if (ex_size >= *size) {
>>> + av_log(s, AV_LOG_WARNING, "ModEx size larger than remaining
>>> data!\n");
>>> + return AVERROR(EINVAL);
>>> + }
>>> +
>>> + ex_data = av_malloc(ex_size);
>>> + if (!ex_data)
>>> + return AVERROR(ENOMEM);
>>> +
>>> + ret = avio_read(s->pb, ex_data, ex_size);
>>> + if (ret < 0) {
>>> + av_free(ex_data);
>>> + return ret;
>>> + }
>>> + *size -= ex_size;
>>> +
>>> + ex_type = (uint8_t)avio_r8(s->pb);
>>> + *size -= 1;
>>> +
>>> + *pkt_type = ex_type & 0x0f;
>>> + ex_type &= 0xf0;
>>> +
>>> + if (ex_type == PacketModExTypeTimestampOffsetNano) {
>>> + uint32_t nano_offset;
>>> +
>>> + if (ex_size != 3) {
>>> + av_log(s, AV_LOG_WARNING, "Invalid ModEx size for Type
>>> TimestampOffsetNano!\n");
>>> + nano_offset = 0;
>>> + } else {
>>> + nano_offset = (ex_data[0] << 16) | (ex_data[1] << 8) |
>>> ex_data[2];
>>> + }
>>> +
>>> + // this is not likely to ever add anything, but right now
>>> timestamps are with ms precision
>>> + *dts += nano_offset / 1000000;
>>> + } else {
>>> + av_log(s, AV_LOG_INFO, "Unknown ModEx type: %d", ex_type);
>>> + }
>>> +
>>> + av_free(ex_data);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
>>> {
>>> FLVContext *flv = s->priv_data;
>>> @@ -1347,6 +1403,12 @@ retry:
>>> enhanced_flv = 1;
>>> pkt_type = flags & ~FLV_AUDIO_CODECID_MASK;
>>> + while (pkt_type == PacketTypeModEx) {
>>> + ret = flv_parse_mod_ex_data(s, &pkt_type, &size, &dts);
>>> + if (ret < 0)
>>> + goto leave;
>>> + }
>>> +
>>
>>
>> Just to double check, is this a while loop instead of an if statement
>> because multiple of these can exist in a row? If so, should we in
>> theory add nano_offset together multiple times? i.e. if we have 500 us
>> twice, wouldn't that add together to 1 ms of DTS offset, rather than
>> 0, per current implementation? Or is this really not an issue in
>> practice?
>>
> The while loop is straight from the spec.
> There can be multiple of this in a row. But I'm pretty sure the intent
> of that is to prepare for additional future types, not to send the nano
> offset multiple times.
> That'd be pretty pointless, given you can add more than 1ms via it, and
> at that point you could just increase the regular ms accuracy timestamp.
I see, that makes sense. No other comments on this patch then.
- Leo Izen (Traneptora)
More information about the ffmpeg-devel
mailing list