From: Tomas Härdin <[email protected]>

---
 libavformat/mxfdec.c |   69 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 69 insertions(+), 0 deletions(-)

diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 95e54c7..8402165 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -79,6 +79,8 @@ typedef struct {
     int index_sid;
     int body_sid;
     int64_t this_partition;
+    int64_t essence_offset;         /* absolute offset of essence */
+    int64_t essence_length;
 } MXFPartition;
 
 typedef struct {
@@ -1424,6 +1426,46 @@ static int mxf_parse_handle_partition_or_eof(MXFContext 
*mxf)
     return mxf->parsing_backward ? mxf_seek_to_previous_partition(mxf) : 1;
 }
 
+/**
+ * Figures out the proper offset and length of the essence container in each 
partition
+ */
+static void mxf_compute_essence_containers(MXFContext *mxf)
+{
+    int x;
+
+    /* everything is already correct */
+    if (mxf->op == OPAtom)
+        return;
+
+    for (x = 0; x < mxf->partitions_count; x++) {
+        MXFPartition *p = &mxf->partitions[x];
+
+        if (!p->body_sid)
+            continue;       /* BodySID == 0 -> no essence */
+
+        if (x >= mxf->partitions_count - 1)
+            break;          /* last partition - can't compute length (and we 
don't need to) */
+
+        /* essence container spans to the next partition */
+        p->essence_length = mxf->partitions[x+1].this_partition - 
p->essence_offset;
+
+        if (p->essence_length < 0) {
+            /* next ThisPartition < essence_offset */
+            p->essence_length = 0;
+            av_log(mxf->fc, AV_LOG_ERROR, "partition %i: bad ThisPartition = 
%lx\n",
+                   x+1, mxf->partitions[x+1].this_partition);
+        }
+    }
+}
+
+static int64_t round_to_kag(int64_t position, int kag_size)
+{
+    /* TODO: account for run-in? the spec isn't clear whether KAG should 
account for it */
+    /* NOTE: kag_size may be any integer between 1 - 2^10 */
+    int64_t ret = (position / kag_size) * kag_size;
+    return ret == position ? ret : ret + kag_size;
+}
+
 static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
 {
     MXFContext *mxf = s->priv_data;
@@ -1455,6 +1497,30 @@ static int mxf_read_header(AVFormatContext *s, 
AVFormatParameters *ap)
         if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key) ||
             IS_KLV_KEY(klv.key, mxf_essence_element_key) ||
             IS_KLV_KEY(klv.key, mxf_system_item_key)) {
+            if (!mxf->current_partition->essence_offset) {
+                /* for OP1a we compute essence_offset
+                 * for OPAtom we point essence_offset after the KL (usually 
op1a_essence_offset + 20 or 25)
+                 * TODO: for OP1a we could eliminate this entire if statement, 
always stopping parsing at op1a_essence_offset
+                 *       for OPAtom we still need the actual essence_offset 
though (the KL's length can vary)
+                 */
+                int64_t op1a_essence_offset =
+                    round_to_kag(mxf->current_partition->this_partition +
+                                 mxf->current_partition->pack_length,       
mxf->current_partition->kag_size) +
+                    round_to_kag(mxf->current_partition->header_byte_count, 
mxf->current_partition->kag_size) +
+                    round_to_kag(mxf->current_partition->index_byte_count,  
mxf->current_partition->kag_size);
+
+                if (mxf->op == OPAtom) {
+                    /* point essence_offset to the actual data
+                    * OPAtom has all the essence in one big KLV
+                    */
+                    mxf->current_partition->essence_offset = avio_tell(s->pb);
+                    mxf->current_partition->essence_length = klv.length;
+                } else {
+                    /* NOTE: op1a_essence_offset may be less than to 
klv.offset (C0023S01.mxf)  */
+                    mxf->current_partition->essence_offset = 
op1a_essence_offset;
+                }
+            }
+
         if (IS_KLV_KEY(klv.key, mxf_system_item_key)) {
             mxf->system_item = 1;
         }
@@ -1504,6 +1570,9 @@ static int mxf_read_header(AVFormatContext *s, 
AVFormatParameters *ap)
         return AVERROR_INVALIDDATA;
     }
     avio_seek(s->pb, mxf->essence_offset, SEEK_SET);
+
+    mxf_compute_essence_containers(mxf);
+
     return mxf_parse_structural_metadata(mxf);
 }
 
-- 
1.7.8

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to