From e3196b686233bed3009248cb1ab7f0628ede6a2f Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Wed, 19 Oct 2016 14:35:20 +0200 Subject: avformat/mxfdec: Detect field_order based on video_line_map Read video_line_map from MXF generic picture essence descriptor and use it to derive the coded field order. Use field_dominance to derive the display field order from coded field order. If field_dominance is not available the default value "1" is used as defined in SMPTE S377-1. Fixes field_order detection for a bunch of DV/DVCPRO files. The heuristic for deriving coded field order from video_line_map is inspired by MediaInfo. Signed-off-by: Tobias Rapp Signed-off-by: Michael Niedermayer --- libavformat/mxfdec.c | 75 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 15 deletions(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 1939761b67..8332362ccf 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -173,8 +173,10 @@ typedef struct MXFDescriptor { int width; int height; /* Field height, not frame height */ int frame_layout; /* See MXFFrameLayout enum */ -#define MXF_TFF 1 -#define MXF_BFF 2 + int video_line_map[2]; +#define MXF_FIELD_DOMINANCE_DEFAULT 0 +#define MXF_FIELD_DOMINANCE_FF 1 /* coded first, displayed first */ +#define MXF_FIELD_DOMINANCE_FL 2 /* coded first, displayed last */ int field_dominance; int channels; int bits_per_sample; @@ -968,6 +970,8 @@ static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor) static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFDescriptor *descriptor = arg; + int entry_count, entry_size; + switch(tag) { case 0x3F01: return mxf_read_strong_ref_array(pb, &descriptor->sub_descriptors_refs, @@ -996,6 +1000,21 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int case 0x320C: descriptor->frame_layout = avio_r8(pb); break; + case 0x320D: + entry_count = avio_rb32(pb); + entry_size = avio_rb32(pb); + if (entry_size == 4) { + if (entry_count > 0) + descriptor->video_line_map[0] = avio_rb32(pb); + else + descriptor->video_line_map[0] = 0; + if (entry_count > 1) + descriptor->video_line_map[1] = avio_rb32(pb); + else + descriptor->video_line_map[1] = 0; + } else + av_log(NULL, AV_LOG_WARNING, "VideoLineMap element size %d currently not supported\n", entry_size); + break; case 0x320E: descriptor->aspect_ratio.num = avio_rb32(pb); descriptor->aspect_ratio.den = avio_rb32(pb); @@ -2044,19 +2063,45 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) case SegmentedFrame: st->codecpar->field_order = AV_FIELD_PROGRESSIVE; case SeparateFields: - switch (descriptor->field_dominance) { - case MXF_TFF: - st->codecpar->field_order = AV_FIELD_TT; - break; - case MXF_BFF: - st->codecpar->field_order = AV_FIELD_BB; - break; - default: - avpriv_request_sample(mxf->fc, - "Field dominance %d support", - descriptor->field_dominance); - case 0: // we already have many samples with field_dominance == unknown - break; + av_log(mxf->fc, AV_LOG_DEBUG, "video_line_map: (%d, %d), field_dominance: %d\n", + descriptor->video_line_map[0], descriptor->video_line_map[1], + descriptor->field_dominance); + if ((descriptor->video_line_map[0] > 0) && (descriptor->video_line_map[1] > 0)) { + /* Detect coded field order from VideoLineMap: + * (even, even) => bottom field coded first + * (even, odd) => top field coded first + * (odd, even) => top field coded first + * (odd, odd) => bottom field coded first + */ + if ((descriptor->video_line_map[0] + descriptor->video_line_map[1]) % 2) { + switch (descriptor->field_dominance) { + case MXF_FIELD_DOMINANCE_DEFAULT: + case MXF_FIELD_DOMINANCE_FF: + st->codecpar->field_order = AV_FIELD_TT; + break; + case MXF_FIELD_DOMINANCE_FL: + st->codecpar->field_order = AV_FIELD_TB; + break; + default: + avpriv_request_sample(mxf->fc, + "Field dominance %d support", + descriptor->field_dominance); + } + } else { + switch (descriptor->field_dominance) { + case MXF_FIELD_DOMINANCE_DEFAULT: + case MXF_FIELD_DOMINANCE_FF: + st->codecpar->field_order = AV_FIELD_BB; + break; + case MXF_FIELD_DOMINANCE_FL: + st->codecpar->field_order = AV_FIELD_BT; + break; + default: + avpriv_request_sample(mxf->fc, + "Field dominance %d support", + descriptor->field_dominance); + } + } } /* Turn field height into frame height. */ st->codecpar->height *= 2; -- cgit v1.2.3