[FFmpeg-devel] [PATCH v3 1/7] avformat/matroskadec: support parsing more than one BlockMore element

James Almer jamrial at gmail.com
Thu Mar 30 05:04:42 EEST 2023


Signed-off-by: James Almer <jamrial at gmail.com>
---
Changes since v2: Cast 8 to size_t and fixed a return value.

 libavformat/matroskadec.c | 62 ++++++++++++++++++++++++++-------------
 1 file changed, 41 insertions(+), 21 deletions(-)

diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 3a888e3ada..b7f9870f3d 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -349,13 +349,17 @@ typedef struct MatroskaLevel {
     uint64_t length;
 } MatroskaLevel;
 
+typedef struct MatroskaBlockMore {
+    uint64_t additional_id;
+    EbmlBin  additional;
+} MatroskaBlockMore;
+
 typedef struct MatroskaBlock {
     uint64_t duration;
     CountedElement reference;
     uint64_t non_simple;
     EbmlBin  bin;
-    uint64_t additional_id;
-    EbmlBin  additional;
+    EbmlList blockmore;
     int64_t  discard_padding;
 } MatroskaBlock;
 
@@ -759,13 +763,13 @@ static EbmlSyntax matroska_segments[] = {
 };
 
 static EbmlSyntax matroska_blockmore[] = {
-    { MATROSKA_ID_BLOCKADDID,      EBML_UINT, 0, 0, offsetof(MatroskaBlock,additional_id), { .u = 1 } },
-    { MATROSKA_ID_BLOCKADDITIONAL, EBML_BIN,  0, 0, offsetof(MatroskaBlock,additional) },
+    { MATROSKA_ID_BLOCKADDID,      EBML_UINT, 0, 0, offsetof(MatroskaBlockMore,additional_id), { .u = 1 } },
+    { MATROSKA_ID_BLOCKADDITIONAL, EBML_BIN,  0, 0, offsetof(MatroskaBlockMore,additional) },
     CHILD_OF(matroska_blockadditions)
 };
 
 static EbmlSyntax matroska_blockadditions[] = {
-    { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, 0, 0, {.n = matroska_blockmore} },
+    { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, sizeof(MatroskaBlockMore), offsetof(MatroskaBlock, blockmore), { .n = matroska_blockmore } },
     CHILD_OF(matroska_blockgroup)
 };
 
@@ -3610,12 +3614,28 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska,
     return 0;
 }
 
+static int matroska_parse_block_additional(MatroskaDemuxContext *matroska,
+                                           AVPacket *pkt,
+                                           const uint8_t *data, int size, uint64_t id)
+{
+    uint8_t *side_data = av_packet_new_side_data(pkt,
+                                                 AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
+                                                 size + (size_t)8);
+    if (!side_data)
+        return AVERROR(ENOMEM);
+
+    AV_WB64(side_data, id);
+    memcpy(side_data + 8, data, size);
+
+    return 0;
+}
+
 static int matroska_parse_frame(MatroskaDemuxContext *matroska,
                                 MatroskaTrack *track, AVStream *st,
                                 AVBufferRef *buf, uint8_t *data, int pkt_size,
                                 uint64_t timecode, uint64_t lace_duration,
                                 int64_t pos, int is_keyframe,
-                                uint8_t *additional, uint64_t additional_id, int additional_size,
+                                MatroskaBlockMore *blockmore, int nb_blockmore,
                                 int64_t discard_padding)
 {
     uint8_t *pkt_data = data;
@@ -3647,7 +3667,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
         buf = NULL;
     }
 
-    if (!pkt_size && !additional_size)
+    if (!pkt_size && !nb_blockmore)
         goto no_output;
 
     if (!buf)
@@ -3666,16 +3686,18 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
     pkt->flags        = is_keyframe;
     pkt->stream_index = st->index;
 
-    if (additional_size > 0) {
-        uint8_t *side_data = av_packet_new_side_data(pkt,
-                                                     AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
-                                                     additional_size + 8);
-        if (!side_data) {
+    for (int i = 0; i < nb_blockmore; i++) {
+        MatroskaBlockMore *more = &blockmore[i];
+
+        if (!more->additional.size)
+            continue;
+
+        res = matroska_parse_block_additional(matroska, pkt, more->additional.data,
+                                              more->additional.size, more->additional_id);
+        if (res < 0) {
             av_packet_unref(pkt);
-            return AVERROR(ENOMEM);
+            return res;
         }
-        AV_WB64(side_data, additional_id);
-        memcpy(side_data + 8, additional, additional_size);
     }
 
     if (discard_padding) {
@@ -3721,7 +3743,7 @@ fail:
 static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf, uint8_t *data,
                                 int size, int64_t pos, uint64_t cluster_time,
                                 uint64_t block_duration, int is_keyframe,
-                                uint8_t *additional, uint64_t additional_id, int additional_size,
+                                MatroskaBlockMore *blockmore, int nb_blockmore,
                                 int64_t cluster_pos, int64_t discard_padding)
 {
     uint64_t timecode = AV_NOPTS_VALUE;
@@ -3856,7 +3878,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf
             res = matroska_parse_frame(matroska, track, st, buf, out_data,
                                        out_size, timecode, lace_duration,
                                        pos, !n ? is_keyframe : 0,
-                                       additional, additional_id, additional_size,
+                                       blockmore, nb_blockmore,
                                        discard_padding);
             if (res)
                 return res;
@@ -3897,14 +3919,12 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
 
         if (res >= 0 && block->bin.size > 0) {
             int is_keyframe = block->non_simple ? block->reference.count == 0 : -1;
-            uint8_t* additional = block->additional.size > 0 ?
-                                    block->additional.data : NULL;
 
             res = matroska_parse_block(matroska, block->bin.buf, block->bin.data,
                                        block->bin.size, block->bin.pos,
                                        cluster->timecode, block->duration,
-                                       is_keyframe, additional, block->additional_id,
-                                       block->additional.size, cluster->pos,
+                                       is_keyframe, block->blockmore.elem,
+                                       block->blockmore.nb_elem, cluster->pos,
                                        block->discard_padding);
         }
 
-- 
2.40.0



More information about the ffmpeg-devel mailing list