diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 4343c4e627..0d34d64f0c 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -69,6 +69,7 @@ typedef enum { OP3b, OP3c, OPAtom, + OPSONYOpt, /* FATE sample, violates the spec in places */ } MXFOP; typedef struct { @@ -81,6 +82,10 @@ typedef struct { int64_t this_partition; int64_t essence_offset; /* absolute offset of essence */ int64_t essence_length; + int32_t kag_size; + int64_t header_byte_count; + int64_t index_byte_count; + int pack_length; } MXFPartition; typedef struct { @@ -203,7 +208,8 @@ enum MXFWrappingScheme { Clip, }; -typedef int MXFMetadataReadFunc(void *arg, AVIOContext *pb, int tag, int size, UID uid); +/* NOTE: klv_offset is not set (-1) for local keys */ +typedef int MXFMetadataReadFunc(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset); typedef struct { const UID key; @@ -416,7 +422,7 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR_EOF; } -static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid) +static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFContext *mxf = arg; int item_num = avio_rb32(pb); @@ -436,7 +442,7 @@ 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) +static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFContext *mxf = arg; MXFPartition *partition; @@ -464,6 +470,7 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size memset(partition, 0, sizeof(*partition)); mxf->partitions_count++; + partition->pack_length = avio_tell(pb) - klv_offset + size; switch(uid[13]) { case 2: @@ -483,11 +490,13 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size /* 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, 8); + avio_skip(pb, 4); + partition->kag_size = avio_rb32(pb); partition->this_partition = avio_rb64(pb); partition->previous_partition = avio_rb64(pb); footer_partition = avio_rb64(pb); - avio_skip(pb, 16); + partition->header_byte_count = avio_rb64(pb); + partition->index_byte_count = avio_rb64(pb); partition->index_sid = avio_rb32(pb); avio_skip(pb, 8); partition->body_sid = avio_rb32(pb); @@ -519,8 +528,22 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size 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]); + else if (op[12] == 64&& op[13] == 1) mxf->op = OPSONYOpt; + else { + av_log(mxf->fc, AV_LOG_ERROR, "unknown operational pattern: %02xh %02xh - guessing OP1a\n", op[12], op[13]); + mxf->op = OP1a; + } + + if (partition->kag_size <= 0 || partition->kag_size > (1 << 20)) { + av_log(mxf->fc, AV_LOG_WARNING, "invalid KAGSize %i - guessing ", partition->kag_size); + + if (mxf->op == OPSONYOpt) + partition->kag_size = 512; + else + partition->kag_size = 1; + + av_log(mxf->fc, AV_LOG_WARNING, "%i\n", partition->kag_size); + } return 0; } @@ -537,7 +560,7 @@ static int mxf_add_metadata_set(MXFContext *mxf, void *metadata_set) return 0; } -static int mxf_read_cryptographic_context(void *arg, AVIOContext *pb, int tag, int size, UID uid) +static int mxf_read_cryptographic_context(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFCryptoContext *cryptocontext = arg; if (size != 16) @@ -547,7 +570,7 @@ static int mxf_read_cryptographic_context(void *arg, AVIOContext *pb, int tag, i return 0; } -static int mxf_read_content_storage(void *arg, AVIOContext *pb, int tag, int size, UID uid) +static int mxf_read_content_storage(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFContext *mxf = arg; switch (tag) { @@ -565,7 +588,7 @@ static int mxf_read_content_storage(void *arg, AVIOContext *pb, int tag, int siz return 0; } -static int mxf_read_source_clip(void *arg, AVIOContext *pb, int tag, int size, UID uid) +static int mxf_read_source_clip(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFStructuralComponent *source_clip = arg; switch(tag) { @@ -587,7 +610,7 @@ static int mxf_read_source_clip(void *arg, AVIOContext *pb, int tag, int size, U return 0; } -static int mxf_read_material_package(void *arg, AVIOContext *pb, int tag, int size, UID uid) +static int mxf_read_material_package(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFPackage *package = arg; switch(tag) { @@ -605,7 +628,7 @@ static int mxf_read_material_package(void *arg, AVIOContext *pb, int tag, int si return 0; } -static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid) +static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFTrack *track = arg; switch(tag) { @@ -626,7 +649,7 @@ static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid return 0; } -static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID uid) +static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFSequence *sequence = arg; switch(tag) { @@ -650,7 +673,7 @@ static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID return 0; } -static int mxf_read_source_package(void *arg, AVIOContext *pb, int tag, int size, UID uid) +static int mxf_read_source_package(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFPackage *package = arg; switch(tag) { @@ -729,7 +752,7 @@ static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *seg return 0; } -static int mxf_read_index_table_segment(void *arg, AVIOContext *pb, int tag, int size, UID uid) +static int mxf_read_index_table_segment(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFIndexTableSegment *segment = arg; switch(tag) { @@ -792,7 +815,7 @@ static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor) ff_mxf_decode_pixel_layout(layout, &descriptor->pix_fmt); } -static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid) +static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) { MXFDescriptor *descriptor = arg; switch(tag) { @@ -1321,7 +1344,7 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF } if (ctx_size && tag == 0x3C0A) avio_read(pb, ctx->uid, 16); - else if (read_child(ctx, pb, tag, size, uid) < 0) + else if (read_child(ctx, pb, tag, size, uid, -1) < 0) return -1; avio_seek(pb, next, SEEK_SET); @@ -1531,7 +1554,7 @@ static int mxf_read_header(AVFormatContext *s, AVFormatParameters *ap) res = mxf_read_local_tags(mxf, &klv, metadata->read, metadata->ctx_size, metadata->type); } else { uint64_t next = avio_tell(s->pb) + klv.length; - res = metadata->read(mxf, s->pb, 0, 0, klv.key); + res = metadata->read(mxf, s->pb, 0, klv.length, klv.key, klv.offset); avio_seek(s->pb, next, SEEK_SET); } if (res < 0) {