mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-24 13:56:33 +02:00
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 <t.rapp@noa-archive.com> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
parent
ee5f0f1d35
commit
e3196b6862
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user