From 5c50214eed19d039a162c5e16d6ee14bdf21500b Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Sat, 4 Oct 2014 17:42:51 -0700 Subject: avformat/mxfdec: read reel_name and source timecode from physical source package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Tomas Härdin Signed-off-by: Michael Niedermayer --- libavformat/mxfdec.c | 120 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 99 insertions(+), 21 deletions(-) (limited to 'libavformat') diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index 7a4633feb6..ef4c4ec8f0 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -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]; -- cgit v1.2.3