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 | 21 +++++++++++++++++++++
libavcodec/mjpegdec.c | 9 +++------
libavformat/mov.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
libavformat/movenc.c | 21 ++++++++++++++++++++-
5 files changed, 89 insertions(+), 8 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..27cf0ba 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1235,6 +1235,15 @@ typedef struct AVFrame {
struct AVCodecInternal;
+enum AVFieldOrder {
+ AV_FIELD_UNKNOWN,
+ AV_FIELD_PROGRESSIVE,
+ AV_FIELD_TT, //< Top coded_first, top displayed first
+ AV_FIELD_BB, //< Bottom coded first, bottom displayed first
+ AV_FIELD_TB, //< Top coded first, bottom displayed first
+ AV_FIELD_BT, //< Bottom coded first, top displayed first
+};
+
/**
* main external API structure.
* New fields can be added to the end with minor version bumps.
@@ -3081,6 +3090,18 @@ 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
+ * - encoding: set by libavcodec
+ * - decoding: Set by libavcodec
+ */
+ enum AVFieldOrder field_order;
} AVCodecContext;
/**
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index 17e87ed..058b08f 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -110,12 +110,9 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx)
return AVERROR_INVALIDDATA;
}
}
- 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 == AV_FIELD_BB) { /* 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..d3674d9 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 },
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index d1076c3..da112ff 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -780,6 +780,23 @@ static int mov_write_uuid_tag_ipod(AVIOContext *pb)
return 28;
}
+static const uint16_t fiel_data[] = {
+ 0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
+};
+
+static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track)
+{
+ unsigned mov_field_order = 0;
+ if (track->enc->field_order < FF_ARRAY_ELEMS(fiel_data))
+ mov_field_order = fiel_data[track->enc->field_order];
+ else
+ return 0;
+ avio_wb32(pb, 10);
+ ffio_wfourcc(pb, "fiel");
+ avio_wb16(pb, mov_field_order);
+ return 10;
+}
+
static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track)
{
int64_t pos = avio_tell(pb);
@@ -866,7 +883,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 != AV_FIELD_UNKNOWN)
+ 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
This version no longer decodes this info if it has been copied out of mov/mp4
and into another container.
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel