avformat/matroskadec: Don't keep old blocks
authorAndreas Rheinhardt <andreas.rheinhardt@gmail.com>
Thu, 16 May 2019 22:29:59 +0000 (00:29 +0200)
committerJames Almer <jamrial@gmail.com>
Sun, 23 Jun 2019 03:47:50 +0000 (00:47 -0300)
Before this commit, the Matroska muxer would read a block when required
to do so, parse the block, create and return the necessary AVPackets and
yet keep the blocks (in a dynamically allocated list), although they
aren't used at all any more. This has been changed. There is no list any
more and the block is immediately discarded after parsing.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
libavformat/matroskadec.c

index b594bc4..c449edf 100644 (file)
@@ -304,9 +304,20 @@ typedef struct MatroskaLevel {
     uint64_t length;
 } MatroskaLevel;
 
+typedef struct MatroskaBlock {
+    uint64_t duration;
+    int64_t  reference;
+    uint64_t non_simple;
+    EbmlBin  bin;
+    uint64_t additional_id;
+    EbmlBin  additional;
+    int64_t discard_padding;
+} MatroskaBlock;
+
 typedef struct MatroskaCluster {
+    MatroskaBlock block;
     uint64_t timecode;
-    EbmlList blocks;
+    int64_t pos;
 } MatroskaCluster;
 
 typedef struct MatroskaLevel1Element {
@@ -356,8 +367,6 @@ typedef struct MatroskaDemuxContext {
     MatroskaLevel1Element level1_elems[64];
     int num_level1_elems;
 
-    int current_cluster_num_blocks;
-    int64_t current_cluster_pos;
     MatroskaCluster current_cluster;
 
     /* WebM DASH Manifest live flag */
@@ -367,16 +376,6 @@ typedef struct MatroskaDemuxContext {
     int bandwidth;
 } MatroskaDemuxContext;
 
-typedef struct MatroskaBlock {
-    uint64_t duration;
-    int64_t  reference;
-    uint64_t non_simple;
-    EbmlBin  bin;
-    uint64_t additional_id;
-    EbmlBin  additional;
-    int64_t discard_padding;
-} MatroskaBlock;
-
 static const EbmlSyntax ebml_header[] = {
     { EBML_ID_EBMLREADVERSION,    EBML_UINT, 0, offsetof(Ebml, version),         { .u = EBML_VERSION } },
     { EBML_ID_EBMLMAXSIZELENGTH,  EBML_UINT, 0, offsetof(Ebml, max_size),        { .u = 8 } },
@@ -705,9 +704,9 @@ static const EbmlSyntax matroska_blockgroup[] = {
 };
 
 static const EbmlSyntax matroska_cluster_parsing[] = {
-    { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0,                     offsetof(MatroskaCluster, timecode) },
-    { MATROSKA_ID_BLOCKGROUP,      EBML_NEST, sizeof(MatroskaBlock), offsetof(MatroskaCluster, blocks), { .n = matroska_blockgroup } },
-    { MATROSKA_ID_SIMPLEBLOCK,     EBML_PASS, sizeof(MatroskaBlock), offsetof(MatroskaCluster, blocks), { .n = matroska_blockgroup } },
+    { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, offsetof(MatroskaCluster, timecode) },
+    { MATROSKA_ID_BLOCKGROUP,      EBML_NEST, 0, 0, { .n = matroska_blockgroup } },
+    { MATROSKA_ID_SIMPLEBLOCK,     EBML_PASS, 0, 0, { .n = matroska_blockgroup } },
     { MATROSKA_ID_CLUSTERPOSITION, EBML_NONE },
     { MATROSKA_ID_CLUSTERPREVSIZE, EBML_NONE },
     { MATROSKA_ID_INFO,            EBML_NONE },
@@ -3452,57 +3451,48 @@ end:
 
 static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
 {
-    EbmlList *blocks_list;
-    MatroskaBlock *blocks;
-    int i, res;
+    MatroskaCluster *cluster = &matroska->current_cluster;
+    MatroskaBlock     *block = &cluster->block;
+    int res;
     res = ebml_parse(matroska,
                      matroska_cluster_parsing,
-                     &matroska->current_cluster);
+                     cluster);
     if (res == 1) {
         /* New Cluster */
-        if (matroska->current_cluster_pos)
+        if (cluster->pos)
             ebml_level_end(matroska);
-        ebml_free(matroska_cluster_parsing, &matroska->current_cluster);
-        memset(&matroska->current_cluster, 0, sizeof(MatroskaCluster));
-        matroska->current_cluster_num_blocks = 0;
-        matroska->current_cluster_pos        = avio_tell(matroska->ctx->pb);
+        cluster->pos = avio_tell(matroska->ctx->pb);
         /* sizeof the ID which was already read */
         if (matroska->current_id)
-            matroska->current_cluster_pos -= 4;
+            cluster->pos -= 4;
         res = ebml_parse(matroska,
                          matroska_clusters,
-                         &matroska->current_cluster);
+                         cluster);
         /* Try parsing the block again. */
         if (res == 1)
             res = ebml_parse(matroska,
                              matroska_cluster_parsing,
-                             &matroska->current_cluster);
+                             cluster);
     }
 
-    if (!res &&
-        matroska->current_cluster_num_blocks <
-        matroska->current_cluster.blocks.nb_elem) {
-        blocks_list = &matroska->current_cluster.blocks;
-        blocks      = blocks_list->elem;
+    if (!res && block->bin.size > 0) {
+            int is_keyframe = block->non_simple ? block->reference == INT64_MIN : -1;
+            uint8_t* additional = block->additional.size > 0 ?
+                                    block->additional.data : NULL;
 
-        matroska->current_cluster_num_blocks = blocks_list->nb_elem;
-        i                                    = blocks_list->nb_elem - 1;
-        if (blocks[i].bin.size > 0 && blocks[i].bin.data) {
-            int is_keyframe = blocks[i].non_simple ? blocks[i].reference == INT64_MIN : -1;
-            uint8_t* additional = blocks[i].additional.size > 0 ?
-                                    blocks[i].additional.data : NULL;
-
-            res = matroska_parse_block(matroska, blocks[i].bin.buf, blocks[i].bin.data,
-                                       blocks[i].bin.size, blocks[i].bin.pos,
+            res = matroska_parse_block(matroska, block->bin.buf, block->bin.data,
+                                       block->bin.size, block->bin.pos,
                                        matroska->current_cluster.timecode,
-                                       blocks[i].duration, is_keyframe,
-                                       additional, blocks[i].additional_id,
-                                       blocks[i].additional.size,
-                                       matroska->current_cluster_pos,
-                                       blocks[i].discard_padding);
-        }
+                                       block->duration, is_keyframe,
+                                       additional, block->additional_id,
+                                       block->additional.size,
+                                       cluster->pos,
+                                       block->discard_padding);
     }
 
+    ebml_free(matroska_blockgroup, block);
+    memset(block, 0, sizeof(*block));
+
     return res;
 }
 
@@ -3600,7 +3590,6 @@ static int matroska_read_close(AVFormatContext *s)
     for (n = 0; n < matroska->tracks.nb_elem; n++)
         if (tracks[n].type == MATROSKA_TRACK_TYPE_AUDIO)
             av_freep(&tracks[n].audio.buf);
-    ebml_free(matroska_cluster_parsing, &matroska->current_cluster);
     ebml_free(matroska_segment, matroska);
 
     return 0;