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