aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthieu Bouron <matthieu.bouron@smartjog.com>2012-02-23 16:58:01 +0100
committerMichael Niedermayer <michaelni@gmx.at>2012-03-11 08:12:46 +0100
commitad029c24a69add848f8d385d297b180bc1146107 (patch)
tree1da7f11ba0b95ca633ee1b142f70735b60d7b6ed
parentc3c2db49a7b10d0b57594332ee3c2cf4aa7552f2 (diff)
downloadffmpeg-ad029c24a69add848f8d385d297b180bc1146107.tar.gz
mxfdec: add timecode to metadata
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r--doc/general.texi2
-rw-r--r--libavformat/mxfdec.c61
2 files changed, 61 insertions, 2 deletions
diff --git a/doc/general.texi b/doc/general.texi
index b945c0b3f2..7770046132 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -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
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 5808a04fd2..1189f3d2db 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -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"
@@ -116,6 +117,15 @@ typedef struct {
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;
MXFSequence *sequence; /* mandatory, and only one */
UID sequence_ref;
int track_id;
@@ -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 },