| 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;
|
|
|