|
|
|
@ -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); |
|
|
|
|