mxfdec: add timecode to metadata

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Matthieu Bouron 2012-02-23 16:58:01 +01:00 committed by Michael Niedermayer
parent c3c2db49a7
commit ad029c24a6
2 changed files with 61 additions and 2 deletions

View File

@ -883,7 +883,7 @@ performance on systems without hardware floating point support).
@item GXF @tab X @tab X
@item MOV @tab X @tab
@item MPEG1/2 @tab X @tab X
@item MXF @tab @tab X
@item MXF @tab X @tab X
@end multitable
@bye

View File

@ -48,6 +48,7 @@
#include "libavutil/aes.h"
#include "libavutil/mathematics.h"
#include "libavcodec/bytestream.h"
#include "libavutil/timecode.h"
#include "avformat.h"
#include "internal.h"
#include "mxf.h"
@ -113,6 +114,15 @@ typedef struct {
int64_t duration;
} MXFSequence;
typedef struct {
UID uid;
enum MXFMetadataSetType type;
int drop_frame;
int start_frame;
struct AVRational rate;
AVTimecode tc;
} MXFTimecodeComponent;
typedef struct {
UID uid;
enum MXFMetadataSetType type;
@ -626,6 +636,23 @@ static int mxf_read_material_package(void *arg, AVIOContext *pb, int tag, int si
return 0;
}
static int mxf_read_timecode_component(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
MXFTimecodeComponent *mxf_timecode = arg;
switch(tag) {
case 0x1501:
mxf_timecode->start_frame = avio_rb64(pb);
break;
case 0x1502:
mxf_timecode->rate = (AVRational){avio_rb16(pb), 1};
break;
case 0x1503:
mxf_timecode->drop_frame = avio_r8(pb);
break;
}
return 0;
}
static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
MXFTrack *track = arg;
@ -1274,6 +1301,14 @@ static int mxf_is_intra_only(MXFDescriptor *descriptor)
&descriptor->essence_codec_ul)->id != CODEC_ID_NONE;
}
static int mxf_add_timecode_metadata(AVDictionary **pm, const char *key, AVTimecode *tc)
{
char buf[AV_TIMECODE_STR_SIZE];
av_dict_set(pm, key, av_timecode_make_string(tc, buf, 0), 0);
return 0;
}
static int mxf_parse_structural_metadata(MXFContext *mxf)
{
MXFPackage *material_package = NULL;
@ -1298,25 +1333,48 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
MXFTrack *temp_track = NULL;
MXFDescriptor *descriptor = NULL;
MXFStructuralComponent *component = NULL;
MXFTimecodeComponent *mxf_tc = NULL;
UID *essence_container_ul = NULL;
const MXFCodecUL *codec_ul = NULL;
const MXFCodecUL *container_ul = NULL;
const MXFCodecUL *pix_fmt_ul = NULL;
AVStream *st;
AVTimecode tc;
int flags;
if (!(material_track = mxf_resolve_strong_ref(mxf, &material_package->tracks_refs[i], Track))) {
av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track strong ref\n");
continue;
}
if ((component = mxf_resolve_strong_ref(mxf, &material_track->sequence_ref, TimecodeComponent))) {
mxf_tc = (MXFTimecodeComponent*)component;
flags = mxf_tc->drop_frame == 1 ? AV_TIMECODE_FLAG_DROPFRAME : 0;
if (av_timecode_init(&tc, mxf_tc->rate, flags, mxf_tc->start_frame, mxf) == 0) {
mxf_add_timecode_metadata(&mxf->fc->metadata, "timecode", &tc);
}
}
if (!(material_track->sequence = mxf_resolve_strong_ref(mxf, &material_track->sequence_ref, Sequence))) {
av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track sequence strong ref\n");
continue;
}
for (j = 0; j < material_track->sequence->structural_components_count; j++) {
component = mxf_resolve_strong_ref(mxf, &material_track->sequence->structural_components_refs[j], TimecodeComponent);
if (!component)
continue;
mxf_tc = (MXFTimecodeComponent*)component;
flags = mxf_tc->drop_frame == 1 ? AV_TIMECODE_FLAG_DROPFRAME : 0;
if (av_timecode_init(&tc, mxf_tc->rate, flags, mxf_tc->start_frame, mxf) == 0) {
mxf_add_timecode_metadata(&mxf->fc->metadata, "timecode", &tc);
break;
}
}
/* TODO: handle multiple source clips */
for (j = 0; j < material_track->sequence->structural_components_count; j++) {
/* TODO: handle timecode component */
component = mxf_resolve_strong_ref(mxf, &material_track->sequence->structural_components_refs[j], SourceClip);
if (!component)
continue;
@ -1515,6 +1573,7 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
{ { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* AES3 */
{ { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Static Track */
{ { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Generic Track */
{ { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x14,0x00 }, mxf_read_timecode_component, sizeof(MXFTimecodeComponent), TimecodeComponent },
{ { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x04,0x01,0x02,0x02,0x00,0x00 }, mxf_read_cryptographic_context, sizeof(MXFCryptoContext), CryptoContext },
{ { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 }, mxf_read_index_table_segment, sizeof(MXFIndexTableSegment), IndexTableSegment },
{ { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL, 0, AnyType },