|
|
|
@ -188,6 +188,7 @@ typedef struct { |
|
|
|
|
int tracks_count; |
|
|
|
|
MXFDescriptor *descriptor; /* only one */ |
|
|
|
|
UID descriptor_ref; |
|
|
|
|
char *name; |
|
|
|
|
} MXFPackage; |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
@ -731,6 +732,27 @@ static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mxf_read_utf16_string(AVIOContext *pb, int size, char** str) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
|
size_t buf_size; |
|
|
|
|
|
|
|
|
|
if (size < 0) |
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
|
|
|
|
|
buf_size = size + size / 2 + 1; |
|
|
|
|
*str = av_malloc(buf_size); |
|
|
|
|
if (!*str) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
|
|
if ((ret = avio_get_str16be(pb, size, *str, buf_size)) < 0) { |
|
|
|
|
av_freep(str); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mxf_read_source_package(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) |
|
|
|
|
{ |
|
|
|
|
MXFPackage *package = arg; |
|
|
|
@ -751,6 +773,8 @@ static int mxf_read_source_package(void *arg, AVIOContext *pb, int tag, int size |
|
|
|
|
case 0x4701: |
|
|
|
|
avio_read(pb, package->descriptor_ref, 16); |
|
|
|
|
break; |
|
|
|
|
case 0x4402: |
|
|
|
|
return mxf_read_utf16_string(pb, size, &package->name); |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
@ -1374,6 +1398,78 @@ static int mxf_add_timecode_metadata(AVDictionary **pm, const char *key, AVTimec |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
AVTimecode tc; |
|
|
|
|
int flags; |
|
|
|
|
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) |
|
|
|
|
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) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
/* the name of physical source package is name of the reel or tape */ |
|
|
|
|
if (physical_package->name[0]) |
|
|
|
|
av_dict_set(&st->metadata, "reel_name", physical_package->name, 0); |
|
|
|
|
|
|
|
|
|
/* the source timecode is calculated by adding the start_position of the sourceclip from the file source package track
|
|
|
|
|
* to the start_frame of the timecode component located on one of the tracks of the physical source package. |
|
|
|
|
*/ |
|
|
|
|
for (j = 0; j < physical_package->tracks_count; j++) { |
|
|
|
|
if (!(physical_track = mxf_resolve_strong_ref(mxf, &physical_package->tracks_refs[j], Track))) { |
|
|
|
|
av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track strong ref\n"); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!(physical_track->sequence = mxf_resolve_strong_ref(mxf, &physical_track->sequence_ref, Sequence))) { |
|
|
|
|
av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track sequence strong ref\n"); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (k = 0; k < physical_track->sequence->structural_components_count; k++) { |
|
|
|
|
component = mxf_resolve_strong_ref(mxf, &physical_track->sequence->structural_components_refs[k], TimecodeComponent); |
|
|
|
|
if (!component) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
mxf_tc = (MXFTimecodeComponent*)component; |
|
|
|
|
flags = mxf_tc->drop_frame == 1 ? AV_TIMECODE_FLAG_DROPFRAME : 0; |
|
|
|
|
/* scale sourceclip start_position to match physical track edit rate */ |
|
|
|
|
start_position = av_rescale_q(sourceclip->start_position, |
|
|
|
|
physical_track->edit_rate, |
|
|
|
|
source_track->edit_rate); |
|
|
|
|
|
|
|
|
|
if (av_timecode_init(&tc, mxf_tc->rate, flags, start_position + mxf_tc->start_frame, mxf->fc) == 0) { |
|
|
|
|
mxf_add_timecode_metadata(&st->metadata, "timecode", &tc); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mxf_parse_structural_metadata(MXFContext *mxf) |
|
|
|
|
{ |
|
|
|
|
MXFPackage *material_package = NULL; |
|
|
|
@ -1571,6 +1667,8 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) |
|
|
|
|
} |
|
|
|
|
av_log(mxf->fc, AV_LOG_VERBOSE, "\n"); |
|
|
|
|
|
|
|
|
|
mxf_parse_physical_source_package(mxf, source_track, st); |
|
|
|
|
|
|
|
|
|
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { |
|
|
|
|
source_track->intra_only = mxf_is_intra_only(descriptor); |
|
|
|
|
container_ul = mxf_get_codec_ul(mxf_picture_essence_container_uls, essence_container_ul); |
|
|
|
@ -1706,27 +1804,6 @@ fail_and_free: |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mxf_read_utf16_string(AVIOContext *pb, int size, char** str) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
|
size_t buf_size; |
|
|
|
|
|
|
|
|
|
if (size < 0) |
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
|
|
|
|
|
buf_size = size + size / 2 + 1; |
|
|
|
|
*str = av_malloc(buf_size); |
|
|
|
|
if (!*str) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
|
|
if ((ret = avio_get_str16be(pb, size, *str, buf_size)) < 0) { |
|
|
|
|
av_freep(str); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int mxf_uid_to_str(UID uid, char **str) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
@ -2544,6 +2621,7 @@ static int mxf_read_close(AVFormatContext *s) |
|
|
|
|
case SourcePackage: |
|
|
|
|
case MaterialPackage: |
|
|
|
|
av_freep(&((MXFPackage *)mxf->metadata_sets[i])->tracks_refs); |
|
|
|
|
av_freep(&((MXFPackage *)mxf->metadata_sets[i])->name); |
|
|
|
|
break; |
|
|
|
|
case IndexTableSegment: |
|
|
|
|
seg = (MXFIndexTableSegment *)mxf->metadata_sets[i]; |
|
|
|
|