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.
* libavcodec functions.
*/
struct AVCodecInternal *internal;
+
+ /** Field order
+ * - encoding: set by libavcodec
+ * - decoding: Set by libavcodec
+ */
+ enum AVFieldOrder field_order;
} AVCodecContext;
/**
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;
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)
{
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)
{ 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 },
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);
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 &&