aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Cunningham <chcunningham@chromium.org>2017-02-03 14:42:44 -0800
committerMichael Niedermayer <michael@niedermayer.cc>2017-02-08 21:17:51 +0100
commitb3ae6cfe1104add473e09a5a18b2dfe6d06c1576 (patch)
tree52be9ca7d2d2fbc6b64731e8ebb411a9957b4887
parentd053b25b59ccfe51f19e61202313d8388a45922a (diff)
downloadffmpeg-b3ae6cfe1104add473e09a5a18b2dfe6d06c1576.tar.gz
lavf/matroskadec: fix is_keyframe for early Blocks
Blocks are marked as key frames whenever the "reference" field is zero. This breaks for non-keyframe Blocks with a reference timestamp of zero. The likelihood of reference timestamp being zero is increased by a longstanding bug in muxing that encodes reference timestamp as the absolute time of the referenced frame (rather than relative to the current Block timestamp, as described in MKV spec). Now using INT64_MIN to denote "no reference". Reported to chromium at http://crbug.com/497889 (contains sample) (cherry picked from commit ac25840ee32888f0c13118edeb9404a123cd3a79) Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r--libavformat/matroskadec.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index a52c4f0f56..4e12c840b0 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -85,6 +85,7 @@ typedef const struct EbmlSyntax {
int list_elem_size;
int data_offset;
union {
+ int64_t i;
uint64_t u;
double f;
const char *s;
@@ -600,7 +601,7 @@ static const EbmlSyntax matroska_blockgroup[] = {
{ MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, offsetof(MatroskaBlock, bin) },
{ MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, offsetof(MatroskaBlock, duration) },
{ MATROSKA_ID_DISCARDPADDING, EBML_SINT, 0, offsetof(MatroskaBlock, discard_padding) },
- { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 0, offsetof(MatroskaBlock, reference) },
+ { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 0, offsetof(MatroskaBlock, reference), { .i = INT64_MIN } },
{ MATROSKA_ID_CODECSTATE, EBML_NONE },
{ 1, EBML_UINT, 0, offsetof(MatroskaBlock, non_simple), { .u = 1 } },
{ 0 }
@@ -971,6 +972,9 @@ static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax,
for (i = 0; syntax[i].id; i++)
switch (syntax[i].type) {
+ case EBML_SINT:
+ *(int64_t *) ((char *) data + syntax[i].data_offset) = syntax[i].def.i;
+ break;
case EBML_UINT:
*(uint64_t *) ((char *) data + syntax[i].data_offset) = syntax[i].def.u;
break;
@@ -2983,7 +2987,7 @@ static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska)
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;
+ 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;
if (!blocks[i].non_simple)
@@ -3021,7 +3025,7 @@ static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
blocks = blocks_list->elem;
for (i = 0; i < blocks_list->nb_elem; i++)
if (blocks[i].bin.size > 0 && blocks[i].bin.data) {
- int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1;
+ int is_keyframe = blocks[i].non_simple ? blocks[i].reference == INT64_MIN : -1;
res = matroska_parse_block(matroska, blocks[i].bin.data,
blocks[i].bin.size, blocks[i].bin.pos,
cluster.timecode, blocks[i].duration,