From d32b3f40c716785bb4073aca9bd0877ecac855b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= Date: Mon, 7 Feb 2011 16:07:41 +0100 Subject: [PATCH] mxfdec: parse MXF partitions --- libavformat/mxfdec.c | 108 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index cb2ae86e48..33c931e0e0 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -52,6 +52,35 @@ #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);