|
|
|
@ -133,6 +133,14 @@ typedef struct { |
|
|
|
|
UID input_segment_ref; |
|
|
|
|
} MXFPulldownComponent; |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
UID uid; |
|
|
|
|
enum MXFMetadataSetType type; |
|
|
|
|
UID *structural_components_refs; |
|
|
|
|
int structural_components_count; |
|
|
|
|
int64_t duration; |
|
|
|
|
} MXFEssenceGroup; |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
UID uid; |
|
|
|
|
enum MXFMetadataSetType type; |
|
|
|
@ -161,6 +169,7 @@ typedef struct { |
|
|
|
|
int field_dominance; |
|
|
|
|
int channels; |
|
|
|
|
int bits_per_sample; |
|
|
|
|
int64_t duration; /* ContainerDuration optional property */ |
|
|
|
|
unsigned int component_depth; |
|
|
|
|
unsigned int horiz_subsampling; |
|
|
|
|
unsigned int vert_subsampling; |
|
|
|
@ -742,6 +751,25 @@ static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mxf_read_essence_group(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) |
|
|
|
|
{ |
|
|
|
|
MXFEssenceGroup *essence_group = arg; |
|
|
|
|
switch (tag) { |
|
|
|
|
case 0x0202: |
|
|
|
|
essence_group->duration = avio_rb64(pb); |
|
|
|
|
break; |
|
|
|
|
case 0x0501: |
|
|
|
|
essence_group->structural_components_count = avio_rb32(pb); |
|
|
|
|
essence_group->structural_components_refs = av_calloc(essence_group->structural_components_count, sizeof(UID)); |
|
|
|
|
if (!essence_group->structural_components_refs) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */ |
|
|
|
|
avio_read(pb, (uint8_t *)essence_group->structural_components_refs, essence_group->structural_components_count * sizeof(UID)); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mxf_read_utf16_string(AVIOContext *pb, int size, char** str) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
@ -872,7 +900,6 @@ static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor) |
|
|
|
|
static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) |
|
|
|
|
{ |
|
|
|
|
MXFDescriptor *descriptor = arg; |
|
|
|
|
descriptor->pix_fmt = AV_PIX_FMT_NONE; |
|
|
|
|
switch(tag) { |
|
|
|
|
case 0x3F01: |
|
|
|
|
descriptor->sub_descriptors_count = avio_rb32(pb); |
|
|
|
@ -882,6 +909,9 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int |
|
|
|
|
avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */ |
|
|
|
|
avio_read(pb, (uint8_t *)descriptor->sub_descriptors_refs, descriptor->sub_descriptors_count * sizeof(UID)); |
|
|
|
|
break; |
|
|
|
|
case 0x3002: /* ContainerDuration */ |
|
|
|
|
descriptor->duration = avio_rb64(pb); |
|
|
|
|
break; |
|
|
|
|
case 0x3004: |
|
|
|
|
avio_read(pb, descriptor->essence_container_ul, 16); |
|
|
|
|
break; |
|
|
|
@ -994,6 +1024,7 @@ static const MXFCodecUL mxf_picture_essence_container_uls[] = { |
|
|
|
|
{ { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MPEG-ES Frame wrapped */ |
|
|
|
|
{ { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14, AV_CODEC_ID_DVVIDEO }, /* DV 625 25mbps */ |
|
|
|
|
{ { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14, AV_CODEC_ID_RAWVIDEO }, /* Uncompressed Picture */ |
|
|
|
|
{ { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4f }, 14, AV_CODEC_ID_RAWVIDEO }, /* Legacy ?? Uncompressed Picture */ |
|
|
|
|
{ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -1457,12 +1488,75 @@ static MXFTimecodeComponent* mxf_resolve_timecode_component(MXFContext *mxf, UID |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static MXFPackage* mxf_resolve_source_package(MXFContext *mxf, UID package_uid) |
|
|
|
|
{ |
|
|
|
|
MXFPackage *package = NULL; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < mxf->packages_count; i++) { |
|
|
|
|
package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[i], SourcePackage); |
|
|
|
|
if (!package) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
if (!memcmp(package->package_uid, package_uid, 16)) |
|
|
|
|
return package; |
|
|
|
|
} |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static MXFStructuralComponent* mxf_resolve_essence_group_choice(MXFContext *mxf, MXFEssenceGroup *essence_group) |
|
|
|
|
{ |
|
|
|
|
MXFStructuralComponent *component = NULL; |
|
|
|
|
MXFPackage *package = NULL; |
|
|
|
|
MXFDescriptor *descriptor = NULL; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
if (!essence_group || !essence_group->structural_components_count) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
/* essence groups contains multiple representations of the same media,
|
|
|
|
|
this return the first components with a valid Descriptor typically index 0 */ |
|
|
|
|
for (i =0; i < essence_group->structural_components_count; i++){ |
|
|
|
|
component = mxf_resolve_strong_ref(mxf, &essence_group->structural_components_refs[i], SourceClip); |
|
|
|
|
if (!component) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
if (!(package = mxf_resolve_source_package(mxf, component->source_package_uid))) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
descriptor = mxf_resolve_strong_ref(mxf, &package->descriptor_ref, Descriptor); |
|
|
|
|
if (descriptor){ |
|
|
|
|
/* HACK: force the duration of the component to match the duration of the descriptor */ |
|
|
|
|
if (descriptor->duration != AV_NOPTS_VALUE) |
|
|
|
|
component->duration = descriptor->duration; |
|
|
|
|
return component; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static MXFStructuralComponent* mxf_resolve_sourceclip(MXFContext *mxf, UID *strong_ref) |
|
|
|
|
{ |
|
|
|
|
MXFStructuralComponent *component = NULL; |
|
|
|
|
|
|
|
|
|
component = mxf_resolve_strong_ref(mxf, strong_ref, AnyType); |
|
|
|
|
if (!component) |
|
|
|
|
return NULL; |
|
|
|
|
switch (component->type) { |
|
|
|
|
case SourceClip: |
|
|
|
|
return component; |
|
|
|
|
case EssenceGroup: |
|
|
|
|
return mxf_resolve_essence_group_choice(mxf, (MXFEssenceGroup*) component); |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_track, AVStream *st) |
|
|
|
|
{ |
|
|
|
|
MXFPackage *temp_package = NULL; |
|
|
|
|
MXFPackage *physical_package = NULL; |
|
|
|
|
MXFTrack *physical_track = NULL; |
|
|
|
|
MXFStructuralComponent *component = NULL; |
|
|
|
|
MXFStructuralComponent *sourceclip = NULL; |
|
|
|
|
MXFTimecodeComponent *mxf_tc = NULL; |
|
|
|
|
int i, j, k; |
|
|
|
@ -1471,21 +1565,11 @@ static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_t |
|
|
|
|
int64_t start_position; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < source_track->sequence->structural_components_count; i++) { |
|
|
|
|
component = mxf_resolve_strong_ref(mxf, &source_track->sequence->structural_components_refs[i], SourceClip); |
|
|
|
|
if (!component) |
|
|
|
|
sourceclip = mxf_resolve_strong_ref(mxf, &source_track->sequence->structural_components_refs[i], SourceClip); |
|
|
|
|
if (!sourceclip) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
for (j = 0; j < mxf->packages_count; j++) { |
|
|
|
|
temp_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[j], SourcePackage); |
|
|
|
|
if (!temp_package) |
|
|
|
|
continue; |
|
|
|
|
if (!memcmp(temp_package->package_uid, component->source_package_uid, 16)){ |
|
|
|
|
physical_package = temp_package; |
|
|
|
|
sourceclip = component; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (!physical_package) |
|
|
|
|
if (!(physical_package = mxf_resolve_source_package(mxf, sourceclip->source_package_uid))) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
mxf_add_uid_metadata(&st->metadata, "reel_uid", physical_package->package_uid); |
|
|
|
@ -1532,7 +1616,6 @@ static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_t |
|
|
|
|
static int mxf_parse_structural_metadata(MXFContext *mxf) |
|
|
|
|
{ |
|
|
|
|
MXFPackage *material_package = NULL; |
|
|
|
|
MXFPackage *temp_package = NULL; |
|
|
|
|
int i, j, k, ret; |
|
|
|
|
|
|
|
|
|
av_dlog(mxf->fc, "metadata sets count %d\n", mxf->metadata_sets_count); |
|
|
|
@ -1599,19 +1682,11 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) |
|
|
|
|
|
|
|
|
|
/* TODO: handle multiple source clips */ |
|
|
|
|
for (j = 0; j < material_track->sequence->structural_components_count; j++) { |
|
|
|
|
component = mxf_resolve_strong_ref(mxf, &material_track->sequence->structural_components_refs[j], SourceClip); |
|
|
|
|
component = mxf_resolve_sourceclip(mxf, &material_track->sequence->structural_components_refs[j]); |
|
|
|
|
if (!component) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
for (k = 0; k < mxf->packages_count; k++) { |
|
|
|
|
temp_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[k], SourcePackage); |
|
|
|
|
if (!temp_package) |
|
|
|
|
continue; |
|
|
|
|
if (!memcmp(temp_package->package_uid, component->source_package_uid, 16)) { |
|
|
|
|
source_package = temp_package; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
source_package = mxf_resolve_source_package(mxf, component->source_package_uid); |
|
|
|
|
if (!source_package) { |
|
|
|
|
av_dlog(mxf->fc, "material track %d: no corresponding source package found\n", material_track->track_id); |
|
|
|
|
break; |
|
|
|
@ -1976,6 +2051,7 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = { |
|
|
|
|
{ { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_package, sizeof(MXFPackage), SourcePackage }, |
|
|
|
|
{ { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_package, sizeof(MXFPackage), MaterialPackage }, |
|
|
|
|
{ { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0f,0x00 }, mxf_read_sequence, sizeof(MXFSequence), Sequence }, |
|
|
|
|
{ { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x05,0x00 }, mxf_read_essence_group, sizeof(MXFEssenceGroup), EssenceGroup}, |
|
|
|
|
{ { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_source_clip, sizeof(MXFStructuralComponent), SourceClip }, |
|
|
|
|
{ { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x44,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), MultipleDescriptor }, |
|
|
|
|
{ { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Generic Sound */ |
|
|
|
@ -1996,6 +2072,20 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = { |
|
|
|
|
{ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL, 0, AnyType }, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static int mxf_metadataset_init(MXFMetadataSet *ctx, enum MXFMetadataSetType type) |
|
|
|
|
{ |
|
|
|
|
switch (type){ |
|
|
|
|
case MultipleDescriptor: |
|
|
|
|
case Descriptor: |
|
|
|
|
((MXFDescriptor*)ctx)->pix_fmt = AV_PIX_FMT_NONE; |
|
|
|
|
((MXFDescriptor*)ctx)->duration = AV_NOPTS_VALUE; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadFunc *read_child, int ctx_size, enum MXFMetadataSetType type) |
|
|
|
|
{ |
|
|
|
|
AVIOContext *pb = mxf->fc->pb; |
|
|
|
@ -2004,6 +2094,7 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF |
|
|
|
|
|
|
|
|
|
if (!ctx) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
mxf_metadataset_init(ctx, type); |
|
|
|
|
while (avio_tell(pb) + 4 < klv_end && !avio_feof(pb)) { |
|
|
|
|
int ret; |
|
|
|
|
int tag = avio_rb16(pb); |
|
|
|
@ -2741,6 +2832,9 @@ static int mxf_read_close(AVFormatContext *s) |
|
|
|
|
case Sequence: |
|
|
|
|
av_freep(&((MXFSequence *)mxf->metadata_sets[i])->structural_components_refs); |
|
|
|
|
break; |
|
|
|
|
case EssenceGroup: |
|
|
|
|
av_freep(&((MXFEssenceGroup *)mxf->metadata_sets[i])->structural_components_refs); |
|
|
|
|
break; |
|
|
|
|
case SourcePackage: |
|
|
|
|
case MaterialPackage: |
|
|
|
|
av_freep(&((MXFPackage *)mxf->metadata_sets[i])->tracks_refs); |
|
|
|
|