mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-03-23 04:24:35 +02:00
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>
This commit is contained in:
parent
3726d07a2a
commit
5c50214eed
@ -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];
|
||||
|
Loading…
x
Reference in New Issue
Block a user