Commit 5c50214e authored by Mark Reid's avatar Mark Reid Committed by Michael Niedermayer

avformat/mxfdec: read reel_name and source timecode from physical source package

Reviewed-by: 's avatarTomas Härdin <tomas.hardin@codemill.se>
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 3726d07a
......@@ -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];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment