mxfdec: parse MXF partitions
authorTomas Härdin <tomas.hardin@codemill.se>
Mon, 7 Feb 2011 15:07:41 +0000 (16:07 +0100)
committerJanne Grunau <janne-libav@jannau.net>
Sun, 22 Jan 2012 13:40:51 +0000 (14:40 +0100)
libavformat/mxfdec.c

index cb2ae86..33c931e 100644 (file)
 #include "internal.h"
 #include "mxf.h"
 
+typedef enum {
+    Header,
+    BodyPartition,
+    Footer
+} MXFPartitionType;
+
+typedef enum {
+    OP1a,
+    OP1b,
+    OP1c,
+    OP2a,
+    OP2b,
+    OP2c,
+    OP3a,
+    OP3b,
+    OP3c,
+    OPAtom,
+} MXFOP;
+
+typedef struct {
+    int closed;
+    int complete;
+    MXFPartitionType type;
+    uint64_t previous_partition;
+    uint64_t footer_partition;
+    int index_sid;
+    int body_sid;
+} MXFPartition;
+
 typedef struct {
     UID uid;
     enum MXFMetadataSetType type;
@@ -127,6 +156,9 @@ typedef struct {
 } MXFMetadataSet;
 
 typedef struct {
+    MXFPartition *partitions;
+    unsigned partitions_count;
+    MXFOP op;
     UID *packages_refs;
     int packages_count;
     MXFMetadataSet **metadata_sets;
@@ -376,6 +408,69 @@ static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, U
     return 0;
 }
 
+static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid)
+{
+    MXFContext *mxf = arg;
+    MXFPartition *partition;
+    UID op;
+
+    if (mxf->partitions_count+1 >= UINT_MAX / sizeof(*mxf->partitions))
+        return AVERROR(ENOMEM);
+
+    mxf->partitions = av_realloc(mxf->partitions, (mxf->partitions_count + 1) * sizeof(*mxf->partitions));
+    if (!mxf->partitions)
+        return AVERROR(ENOMEM);
+
+    partition = &mxf->partitions[mxf->partitions_count++];
+
+    switch(uid[13]) {
+    case 2:
+        partition->type = Header;
+        break;
+    case 3:
+        partition->type = BodyPartition;
+        break;
+    case 4:
+        partition->type = Footer;
+        break;
+    default:
+        av_log(mxf->fc, AV_LOG_ERROR, "unknown partition type %i\n", uid[13]);
+        return AVERROR_INVALIDDATA;
+    }
+
+    /* consider both footers to be closed (there is only Footer and CompleteFooter) */
+    partition->closed = partition->type == Footer || !(uid[14] & 1);
+    partition->complete = uid[14] > 2;
+    avio_skip(pb, 16);
+    partition->previous_partition = avio_rb64(pb);
+    partition->footer_partition = avio_rb64(pb);
+    avio_skip(pb, 16);
+    partition->index_sid = avio_rb32(pb);
+    avio_skip(pb, 8);
+    partition->body_sid = avio_rb32(pb);
+    avio_read(pb, op, sizeof(UID));
+
+    av_dlog(mxf->fc, "PartitionPack: PreviousPartition = 0x%lx, "
+            "FooterPartition = 0x%lx, IndexSID = %i, BodySID = %i\n",
+            partition->previous_partition, partition->footer_partition,
+            partition->index_sid, partition->body_sid);
+
+    if      (op[12] == 1 && op[13] == 1) mxf->op = OP1a;
+    else if (op[12] == 1 && op[13] == 2) mxf->op = OP1b;
+    else if (op[12] == 1 && op[13] == 3) mxf->op = OP1c;
+    else if (op[12] == 2 && op[13] == 1) mxf->op = OP2a;
+    else if (op[12] == 2 && op[13] == 2) mxf->op = OP2b;
+    else if (op[12] == 2 && op[13] == 3) mxf->op = OP2c;
+    else if (op[12] == 3 && op[13] == 1) mxf->op = OP3a;
+    else if (op[12] == 3 && op[13] == 2) mxf->op = OP3b;
+    else if (op[12] == 3 && op[13] == 3) mxf->op = OP3c;
+    else if (op[12] == 0x10)             mxf->op = OPAtom;
+    else
+        av_log(mxf->fc, AV_LOG_ERROR, "unknown operational pattern: %02xh %02xh\n", op[12], op[13]);
+
+    return 0;
+}
+
 static int mxf_add_metadata_set(MXFContext *mxf, void *metadata_set)
 {
     if (mxf->metadata_sets_count+1 >= UINT_MAX / sizeof(*mxf->metadata_sets))
@@ -856,6 +951,16 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
 
 static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
     { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x05,0x01,0x00 }, mxf_read_primer_pack },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, mxf_read_partition_pack },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x02,0x00 }, mxf_read_partition_pack },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x03,0x00 }, mxf_read_partition_pack },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x04,0x00 }, mxf_read_partition_pack },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x01,0x00 }, mxf_read_partition_pack },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x02,0x00 }, mxf_read_partition_pack },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x03,0x00 }, mxf_read_partition_pack },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x04,0x00 }, mxf_read_partition_pack },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x02,0x00 }, mxf_read_partition_pack },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x04,0x00 }, mxf_read_partition_pack },
     { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_content_storage, 0, AnyType },
     { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_source_package, sizeof(MXFPackage), SourcePackage },
     { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_material_package, sizeof(MXFPackage), MaterialPackage },
@@ -949,7 +1054,7 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap)
                 if (klv.key[5] == 0x53) {
                     res = mxf_read_local_tags(mxf, &klv, metadata->read, metadata->ctx_size, metadata->type);
                 } else
-                    res = metadata->read(mxf, s->pb, 0, 0, NULL);
+                    res = metadata->read(mxf, s->pb, 0, 0, klv.key);
                 if (res < 0) {
                     av_log(s, AV_LOG_ERROR, "error reading header metadata\n");
                     return res;
@@ -990,6 +1095,7 @@ static int mxf_read_close(AVFormatContext *s)
         }
         av_freep(&mxf->metadata_sets[i]);
     }
+    av_freep(&mxf->partitions);
     av_freep(&mxf->metadata_sets);
     av_freep(&mxf->aesc);
     av_freep(&mxf->local_tags);