aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat
diff options
context:
space:
mode:
authorTimo Rothenpieler <timo@rothenpieler.org>2025-01-15 01:19:57 +0100
committerTimo Rothenpieler <timo@rothenpieler.org>2025-01-18 21:57:02 +0100
commitced9fddec0e45e1ce1b3425a1fed66af971e934c (patch)
tree7b88fff3bb31422cf150a07f4ade90a5fc6e4cb7 /libavformat
parent4c96d6bf75357ab13808efc9f08c1b41b1bf5bdf (diff)
downloadffmpeg-ced9fddec0e45e1ce1b3425a1fed66af971e934c.tar.gz
avformat/flvdec: implement support for parsing ModEx data
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/flv.h5
-rw-r--r--libavformat/flvdec.c68
2 files changed, 73 insertions, 0 deletions
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 {
@@ -140,6 +141,10 @@ enum {
};
enum {
+ PacketModExTypeTimestampOffsetNano = 0,
+};
+
+enum {
AudioChannelOrderUnspecified = 0,
AudioChannelOrderNative = 1,
AudioChannelOrderCustom = 2,
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;
+ }
+
if (pkt_type == AudioPacketTypeMultitrack) {
uint8_t types = avio_r8(s->pb);
multitrack_type = types & 0xF0;
@@ -1376,6 +1438,12 @@ retry:
pkt_type = enhanced_flv ? codec_id : 0;
size--;
+ while (pkt_type == PacketTypeModEx) {
+ ret = flv_parse_mod_ex_data(s, &pkt_type, &size, &dts);
+ if (ret < 0)
+ goto leave;
+ }
+
if (pkt_type == PacketTypeMultitrack) {
uint8_t types = avio_r8(s->pb);
multitrack_type = types & 0xF0;