[1/3] RFC: mov: Parse the dvc1 atom

Message ID 1327694430-19598-1-git-send-email-martin@martin.st
State Deferred
Headers show

Commit Message

Martin Storsjö Jan. 27, 2012, 8 p.m.
Normally, the actual payload data contains sequence headers, too,
and the parser can extract this and set it as extradata. However,
the data in the dvc1 atom is the "official" extradata for the file.

This is required for proper stream copy of vc1 from ismv to ismv.

This makes the early avcodec_open2() in avformat_find_stream_info()
succeed, which used to fail before. The call to avcodec_open2()
sets has_b_frames, which makes the logic in compute_pkt_fields
not to call update_initial_timestamps (this logic has special
case code for H264 which perhaps also should apply to VC1?).
When update_initial_timestamps isn't called, start_time in
AVFormatContext is set based on the audio stream only.

This in turn makes the first video frame to have a timestamp less
than start_time, which makes it be skipped, breaking fate-vc1-ism.

One solution to this breakage is to add -vsync 0 to the fate test,
another solution is to adjust compute_pkt_fields to do the same
as for H264 for VC1, too.
---
 libavformat/mov.c |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)

Patch

diff --git a/libavformat/mov.c b/libavformat/mov.c
index b7d8a55..07665e0 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -971,6 +971,32 @@  static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     return 0;
 }
 
+static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+    AVStream *st;
+    uint8_t profile_level;
+
+    if (c->fc->nb_streams < 1)
+        return 0;
+    st = c->fc->streams[c->fc->nb_streams-1];
+
+    if ((uint64_t)atom.size > (1<<30) || atom.size < 7)
+        return AVERROR_INVALIDDATA;
+
+    profile_level = avio_r8(pb);
+    if (profile_level & 0xf0 != 0xc0)
+        return 0;
+
+    av_free(st->codec->extradata);
+    st->codec->extradata = av_mallocz(atom.size - 7 + FF_INPUT_BUFFER_PADDING_SIZE);
+    if (!st->codec->extradata)
+        return AVERROR(ENOMEM);
+    st->codec->extradata_size = atom.size - 7;
+    avio_seek(pb, 6, SEEK_CUR);
+    avio_read(pb, st->codec->extradata, st->codec->extradata_size);
+    return 0;
+}
+
 /**
  * An strf atom is a BITMAPINFOHEADER struct. This struct is 40 bytes itself,
  * but can have extradata appended at the end after the 40 bytes belonging
@@ -2434,6 +2460,7 @@  static const MOVParseTableEntry mov_default_parse_table[] = {
 { MKTAG('w','f','e','x'), mov_read_wfex },
 { MKTAG('c','m','o','v'), mov_read_cmov },
 { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout */
+{ MKTAG('d','v','c','1'), mov_read_dvc1 },
 { 0, NULL }
 };