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.
---
 avconv.c              |    1 +
 libavcodec/avcodec.h  |   10 ++++++++++
 libavcodec/mjpegdec.c |   10 ++++++----
 libavformat/mov.c     |   24 +++++++++++++++++++++++-
 libavformat/movenc.c  |   12 +++++++++++-
 5 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/avconv.c b/avconv.c
index 90ed00d..3870451 100644
--- a/avconv.c
+++ b/avconv.c
@@ -2068,6 +2068,7 @@ static int transcode_init(OutputFile *output_files,
             codec->bit_rate       = icodec->bit_rate;
             codec->rc_max_rate    = icodec->rc_max_rate;
             codec->rc_buffer_size = icodec->rc_buffer_size;
+            codec->field_order    = icodec->field_order;
             codec->extradata      = av_mallocz(extra_size);
             if (!codec->extradata) {
                 return AVERROR(ENOMEM);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index fe65a6e..23531e1 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -3081,6 +3081,16 @@ typedef struct AVCodecContext {
      * libavcodec functions.
      */
     struct AVCodecInternal *internal;
+
+    /** Field order
+     * 0x0000 - unset
+     * 0x0100 - progressive scan
+     * 0x0201 - top displayed first, top coded first
+     * 0x0206 - bottom displayed first, bottom coded first
+     * 0x0209 - top coded first, bottom displayed first
+     * 0x020E - bottom coded first, top displayed first
+     */
+    unsigned field_order;
 } AVCodecContext;
 
 /**
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index 17e87ed..0d8f7c3 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -112,10 +112,12 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx)
     }
     if (avctx->extradata_size > 9 &&
         AV_RL32(avctx->extradata + 4) == MKTAG('f','i','e','l')) {
-        if (avctx->extradata[9] == 6) { /* quicktime icefloe 019 */
-            s->interlace_polarity = 1; /* bottom field first */
-            av_log(avctx, AV_LOG_DEBUG, "mjpeg bottom field first\n");
-        }
+        if (!avctx->field_order)
+          avctx->field_order = AV_RB16(avctx->extradata + 8);
+    }
+    if ((avctx->field_order & 0xFF) == 6) { /* quicktime icefloe 019 */
+        s->interlace_polarity = 1; /* bottom field first */
+        av_log(avctx, AV_LOG_DEBUG, "mjpeg bottom field first\n");
     }
     if (avctx->codec->id == CODEC_ID_AMV)
         s->flipped = 1;
diff --git a/libavformat/mov.c b/libavformat/mov.c
index d9fb8fb..d556dd2 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -841,6 +841,19 @@ 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;
+
+    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;
+    st->codec->field_order = avio_rb16(pb);
+    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 +921,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 +2353,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 },
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index d1076c3..934cca5 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -780,6 +780,14 @@ static int mov_write_uuid_tag_ipod(AVIOContext *pb)
     return 28;
 }
 
+static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track)
+{
+    avio_wb32(pb, 10);
+    ffio_wfourcc(pb, "fiel");
+    avio_wb16(pb, track->enc->field_order);
+    return 10;
+}
+
 static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track)
 {
     int64_t pos = avio_tell(pb);
@@ -866,7 +874,9 @@ static int mov_write_video_tag(AVIOContext *pb, MOVTrack 
*track)
         mov_write_avcc_tag(pb, track);
         if(track->mode == MODE_IPOD)
             mov_write_uuid_tag_ipod(pb);
-    } else if(track->vosLen > 0)
+    } else if (track->enc->field_order)
+        mov_write_fiel_tag(pb, track);
+    else if(track->vosLen > 0)
         mov_write_glbl_tag(pb, track);
 
     if (track->enc->sample_aspect_ratio.den && 
track->enc->sample_aspect_ratio.num &&
-- 
1.7.3.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to