Index: ffmpeg/patches/ugly/41_matroska_cluster_incremental.patch |
diff --git a/ffmpeg/patches/ugly/41_matroska_cluster_incremental.patch b/ffmpeg/patches/ugly/41_matroska_cluster_incremental.patch |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1a0d426e4e4fde5f8adc6d13f68e1394d3fde0cb |
--- /dev/null |
+++ b/ffmpeg/patches/ugly/41_matroska_cluster_incremental.patch |
@@ -0,0 +1,163 @@ |
+Index: libavformat/matroskadec.c |
+=================================================================== |
+--- libavformat/matroskadec.c (revision 105457) |
++++ libavformat/matroskadec.c (working copy) |
+@@ -228,6 +228,11 @@ |
+ } MatroskaLevel; |
+ |
+ typedef struct { |
++ uint64_t timecode; |
++ EbmlList blocks; |
++} MatroskaCluster; |
++ |
++typedef struct { |
+ AVFormatContext *ctx; |
+ |
+ /* EBML stuff */ |
+@@ -262,6 +267,10 @@ |
+ |
+ /* File has a CUES element, but we defer parsing until it is needed. */ |
+ int cues_parsing_deferred; |
++ |
++ int current_cluster_num_blocks; |
++ int64_t current_cluster_pos; |
++ MatroskaCluster current_cluster; |
+ } MatroskaDemuxContext; |
+ |
+ typedef struct { |
+@@ -271,11 +280,6 @@ |
+ EbmlBin bin; |
+ } MatroskaBlock; |
+ |
+-typedef struct { |
+- uint64_t timecode; |
+- EbmlList blocks; |
+-} MatroskaCluster; |
+- |
+ static 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} }, |
+@@ -546,6 +550,38 @@ |
+ { 0 } |
+ }; |
+ |
++static EbmlSyntax matroska_cluster_incremental_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_CLUSTERPOSITION,EBML_NONE }, |
++ { MATROSKA_ID_CLUSTERPREVSIZE,EBML_NONE }, |
++ { MATROSKA_ID_INFO, EBML_NONE }, |
++ { MATROSKA_ID_CUES, EBML_NONE }, |
++ { MATROSKA_ID_TAGS, EBML_NONE }, |
++ { MATROSKA_ID_SEEKHEAD, EBML_NONE }, |
++ { MATROSKA_ID_CLUSTER, EBML_STOP }, |
++ { 0 } |
++}; |
++ |
++static EbmlSyntax matroska_cluster_incremental[] = { |
++ { MATROSKA_ID_CLUSTERTIMECODE,EBML_UINT,0, offsetof(MatroskaCluster,timecode) }, |
++ { MATROSKA_ID_BLOCKGROUP, EBML_STOP }, |
++ { MATROSKA_ID_SIMPLEBLOCK, EBML_STOP }, |
++ { MATROSKA_ID_CLUSTERPOSITION,EBML_NONE }, |
++ { MATROSKA_ID_CLUSTERPREVSIZE,EBML_NONE }, |
++ { 0 } |
++}; |
++ |
++static EbmlSyntax matroska_clusters_incremental[] = { |
++ { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, {.n=matroska_cluster_incremental} }, |
++ { MATROSKA_ID_INFO, EBML_NONE }, |
++ { MATROSKA_ID_CUES, EBML_NONE }, |
++ { MATROSKA_ID_TAGS, EBML_NONE }, |
++ { MATROSKA_ID_SEEKHEAD, EBML_NONE }, |
++ { 0 } |
++}; |
++ |
+ static const char *matroska_doctypes[] = { "matroska", "webm" }; |
+ |
+ /* |
+@@ -1690,6 +1726,7 @@ |
+ sizeof(AVPacket *)); |
+ } else { |
+ av_freep(&matroska->packets); |
++ matroska->prev_pkt = NULL; |
+ } |
+ matroska->num_packets--; |
+ return 0; |
+@@ -1993,6 +2030,59 @@ |
+ return res; |
+ } |
+ |
++static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska) |
++{ |
++ EbmlList *blocks_list; |
++ MatroskaBlock *blocks; |
++ int i, res; |
++ res = ebml_parse(matroska, |
++ matroska_cluster_incremental_parsing, |
++ &matroska->current_cluster); |
++ if (res == 1) { |
++ /* New Cluster */ |
++ if (matroska->current_cluster_pos) |
++ ebml_level_end(matroska); |
++ ebml_free(matroska_cluster, &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); |
++ matroska->prev_pkt = NULL; |
++ /* sizeof the ID which was already read */ |
++ if (matroska->current_id) |
++ matroska->current_cluster_pos -= 4; |
++ res = ebml_parse(matroska, |
++ matroska_clusters_incremental, |
++ &matroska->current_cluster); |
++ /* Try parsing the block agiain. */ |
++ if (res == 1) |
++ res = ebml_parse(matroska, |
++ matroska_cluster_incremental_parsing, |
++ &matroska->current_cluster); |
++ } |
++ |
++ if (!res && |
++ matroska->current_cluster_num_blocks < |
++ matroska->current_cluster.blocks.nb_elem) { |
++ blocks_list = &matroska->current_cluster.blocks; |
++ blocks = blocks_list->elem; |
++ |
++ 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 : -1; |
++ res=matroska_parse_block(matroska, |
++ blocks[i].bin.data, blocks[i].bin.size, |
++ blocks[i].bin.pos, |
++ matroska->current_cluster.timecode, |
++ blocks[i].duration, is_keyframe, |
++ matroska->current_cluster_pos); |
++ } |
++ } |
++ |
++ if (res < 0) matroska->done = 1; |
++ return res; |
++} |
++ |
+ static int matroska_read_packet(AVFormatContext *s, AVPacket *pkt) |
+ { |
+ MatroskaDemuxContext *matroska = s->priv_data; |
+@@ -2001,7 +2091,7 @@ |
+ while (!ret && matroska_deliver_packet(matroska, pkt)) { |
+ if (matroska->done) |
+ return AVERROR_EOF; |
+- ret = matroska_parse_cluster(matroska); |
++ ret = matroska_parse_cluster_incremental(matroska); |
+ } |
+ |
+ return ret; |
+@@ -2075,6 +2165,7 @@ |
+ for (n=0; n < matroska->tracks.nb_elem; n++) |
+ if (tracks[n].type == MATROSKA_TRACK_TYPE_AUDIO) |
+ av_free(tracks[n].audio.buf); |
++ ebml_free(matroska_cluster, &matroska->current_cluster); |
+ ebml_free(matroska_segment, matroska); |
+ |
+ return 0; |