summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorMark Reid <mindmark@gmail.com>2014-10-04 17:42:51 -0700
committerMichael Niedermayer <michaelni@gmx.at>2014-10-07 03:13:06 +0200
commit5c50214eed19d039a162c5e16d6ee14bdf21500b (patch)
tree915db64f026b57cb729a35fd6957126f6ba30900 /libavformat
parent3726d07a2af8d57f5af57be339c94fe902853e10 (diff)
avformat/mxfdec: read reel_name and source timecode from physical source package
Reviewed-by: Tomas Härdin <tomas.hardin@codemill.se> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/mxfdec.c120
1 files changed, 99 insertions, 21 deletions
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];