>From b3f3ef7ecfc03fb6c501173b50115334f422f81e Mon Sep 17 00:00:00 2001
From: Joseph Artsimovich <joseph@mirriad.com>
Date: Tue, 7 Feb 2012 10:48:43 +0000
Subject: [PATCH 1/2] Fix frame height vs field height confusion in MXF
 decoding.

---
 libavformat/mxf.h    |    8 ++++++++
 libavformat/mxfdec.c |   27 +++++++++++++++++++++++++--
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/libavformat/mxf.h b/libavformat/mxf.h
index 4f5d4c0..88dc94e 100644
--- a/libavformat/mxf.h
+++ b/libavformat/mxf.h
@@ -46,6 +46,14 @@ enum MXFMetadataSetType {
     TypeBottom,// add metadata type before this
 };
 
+enum MXFFrameLayout {
+    FullFrame = 0,
+    MixedFields,
+    OneField,
+    SegmentedFrame,
+    SeparateFields
+};
+
 typedef struct {
     UID key;
     int64_t offset;
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index c927869..28a9d35 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -131,7 +131,8 @@ typedef struct {
     AVRational sample_rate;
     AVRational aspect_ratio;
     int width;
-    int height;
+    int height; /* Field height, not frame height */
+    int frame_layout; /* See MXFFrameLayout enum */
     int channels;
     int bits_per_sample;
     UID *sub_descriptors_refs;
@@ -794,6 +795,9 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int
     case 0x3202:
         descriptor->height = avio_rb32(pb);
         break;
+    case 0x320C:
+        descriptor->frame_layout = avio_r8(pb);
+        break;
     case 0x320E:
         descriptor->aspect_ratio.num = avio_rb32(pb);
         descriptor->aspect_ratio.den = avio_rb32(pb);
@@ -1391,7 +1395,26 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
             if (st->codec->codec_id == CODEC_ID_NONE)
                 st->codec->codec_id = container_ul->id;
             st->codec->width = descriptor->width;
-            st->codec->height = descriptor->height;
+            st->codec->height = descriptor->height; /* Field height, not frame height */
+            switch (descriptor->frame_layout) {
+                case SegmentedFrame:
+                    /* This one is a weird layout I don't fully understand. */
+                    av_log(mxf->fc, AV_LOG_INFO, "SegmentedFrame layout isn't currently supported\n");
+                    break;
+                case FullFrame:
+                    break;
+                case OneField:
+                    /* Every other line is stored and needs to be duplicated. */
+                    av_log(mxf->fc, AV_LOG_INFO, "OneField frame layout isn't currently supported\n");
+                    break; /* The correct thing to do here is fall through, but by breaking we might be
+                    able to decode some streams at half the vertical resolution, rather than not al all.
+                    It's also for compatibility with the old behavior. */
+                case SeparateFields:
+                case MixedFields:
+                    st->codec->height *= 2; /* Turn field height into frame height. */
+                default:
+                    av_log(mxf->fc, AV_LOG_INFO, "Unknown frame layout type: %d\n", descriptor->frame_layout);
+            }
             if (st->codec->codec_id == CODEC_ID_RAWVIDEO)
                 st->codec->pix_fmt = descriptor->pix_fmt;
             st->need_parsing = AVSTREAM_PARSE_HEADERS;
-- 
1.7.5.4

