summaryrefslogtreecommitdiff
path: root/libavformat/mov.c
diff options
context:
space:
mode:
authorAlex Converse <alex.converse@gmail.com>2011-12-13 18:49:06 -0800
committerAlex Converse <alex.converse@gmail.com>2011-12-21 22:04:37 -0800
commit4bf3c8f226252e18de8051fd0d417c1d39857b67 (patch)
treef2b1bccb16202512c24bc080a683a092c8c4174f /libavformat/mov.c
parentf264d336fe61c12ce9607c3060aa5d3dca947c61 (diff)
mov: Don't stick the QuickTime field ordering atom in extradata.
The 'fiel' atoms can be found in H.264 tracks clobbering the extradata. MJPEG supports non field based extradata, and this data should be preserved when copying.
Diffstat (limited to 'libavformat/mov.c')
-rw-r--r--libavformat/mov.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/libavformat/mov.c b/libavformat/mov.c
index d9fb8fb991..d3674d9e12 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -841,6 +841,40 @@ static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return 0;
}
+static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+ AVStream *st;
+ unsigned mov_field_order;
+ enum AVFieldOrder decoded_field_order = AV_FIELD_UNKNOWN;
+
+ if (c->fc->nb_streams < 1) // will happen with jp2 files
+ return 0;
+ st = c->fc->streams[c->fc->nb_streams-1];
+ if (atom.size < 2)
+ return AVERROR_INVALIDDATA;
+ mov_field_order = avio_rb16(pb);
+ if ((mov_field_order & 0xFF00) == 0x0100)
+ decoded_field_order = AV_FIELD_PROGRESSIVE;
+ else if ((mov_field_order & 0xFF00) == 0x0200) {
+ switch (mov_field_order & 0xFF) {
+ case 0x01: decoded_field_order = AV_FIELD_TT;
+ break;
+ case 0x06: decoded_field_order = AV_FIELD_BB;
+ break;
+ case 0x09: decoded_field_order = AV_FIELD_TB;
+ break;
+ case 0x0E: decoded_field_order = AV_FIELD_BT;
+ break;
+ }
+ }
+ if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
+ av_log(NULL, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
+ }
+ st->codec->field_order = decoded_field_order;
+
+ return 0;
+}
+
/* FIXME modify qdm2/svq3/h264 decoders to take full atom as extradata */
static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
@@ -908,6 +942,15 @@ static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if ((uint64_t)atom.size > (1<<30))
return -1;
+ if (atom.size >= 10) {
+ // Broken files created by legacy versions of Libav and FFmpeg will
+ // wrap a whole fiel atom inside of a glbl atom.
+ unsigned size = avio_rb32(pb);
+ unsigned type = avio_rl32(pb);
+ avio_seek(pb, -8, SEEK_CUR);
+ if (type == MKTAG('f','i','e','l') && size == atom.size)
+ return mov_read_default(c, pb, atom);
+ }
av_free(st->codec->extradata);
st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE);
if (!st->codec->extradata)
@@ -2331,7 +2374,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG('e','d','t','s'), mov_read_default },
{ MKTAG('e','l','s','t'), mov_read_elst },
{ MKTAG('e','n','d','a'), mov_read_enda },
-{ MKTAG('f','i','e','l'), mov_read_extradata },
+{ MKTAG('f','i','e','l'), mov_read_fiel },
{ MKTAG('f','t','y','p'), mov_read_ftyp },
{ MKTAG('g','l','b','l'), mov_read_glbl },
{ MKTAG('h','d','l','r'), mov_read_hdlr },