From b33ca05b465dcb574d00823226ca0d872799175c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Wed, 6 Jul 2011 16:35:12 +0200 Subject: [PATCH] mxf: add cli option in mxfenc to replace GOP timecode parsing. This is based on the original work by Baptiste Coudurier. --- libavformat/mxfenc.c | 47 +++++++++++++++++++++------------------- tests/lavf-regression.sh | 2 +- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 50d2deda7b..fe7c9676f5 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -35,6 +35,7 @@ #include #include +#include "libavutil/opt.h" #include "libavutil/random_seed.h" #include "libavcodec/bytestream.h" #include "libavcodec/timecode.h" @@ -172,6 +173,7 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = { }; typedef struct MXFContext { + AVClass *av_class; int64_t footer_partition_offset; int essence_container_count; AVRational time_base; @@ -185,10 +187,9 @@ typedef struct MXFContext { unsigned body_partitions_count; int last_key_index; ///< index of last key frame uint64_t duration; + struct ff_timecode tc; AVStream *timecode_track; int timecode_base; ///< rounded time code base (25 or 30) - int timecode_start; ///< frame number computed from mpeg-2 gop header timecode - int timecode_drop_frame; ///< time code use drop frame method frop mpeg-2 essence gop header int edit_unit_byte_count; ///< fixed edit unit byte count uint64_t body_offset; uint32_t instance_number; @@ -666,7 +667,7 @@ static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, enum // Start Time Code mxf_write_local_tag(pb, 8, 0x1501); - avio_wb64(pb, mxf->timecode_start); + avio_wb64(pb, mxf->tc.start); // Rounded Time Code Base mxf_write_local_tag(pb, 2, 0x1502); @@ -674,7 +675,7 @@ static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, enum // Drop Frame mxf_write_local_tag(pb, 1, 0x1503); - avio_w8(pb, mxf->timecode_drop_frame); + avio_w8(pb, mxf->tc.drop); } static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, enum MXFMetadataSetType type) @@ -1310,7 +1311,6 @@ static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt, MXFIndexEntry *e) { MXFStreamContext *sc = st->priv_data; - MXFContext *mxf = s->priv_data; uint32_t c = -1; int i; @@ -1330,21 +1330,6 @@ static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st, if (e->flags & 0x40) // sequence header present e->flags |= 0x80; // random access } - if (!mxf->header_written) { - unsigned hours = (pkt->data[i+1]>>2) & 0x1f; - unsigned minutes = ((pkt->data[i+1] & 0x03) << 4) | (pkt->data[i+2]>>4); - unsigned seconds = ((pkt->data[i+2] & 0x07) << 3) | (pkt->data[i+3]>>5); - unsigned frames = ((pkt->data[i+3] & 0x1f) << 1) | (pkt->data[i+4]>>7); - mxf->timecode_drop_frame = !!(pkt->data[i+1] & 0x80); - mxf->timecode_start = (hours*3600 + minutes*60 + seconds) * - mxf->timecode_base + frames; - if (mxf->timecode_drop_frame) { - unsigned tminutes = 60 * hours + minutes; - mxf->timecode_start -= 2 * (tminutes - tminutes / 10); - } - av_log(s, AV_LOG_DEBUG, "frame %d %d:%d:%d%c%d\n", mxf->timecode_start, - hours, minutes, seconds, mxf->timecode_drop_frame ? ';':':', frames); - } } else if (c == 0x1b3) { // seq e->flags |= 0x40; switch ((pkt->data[i+4]>>4) & 0xf) { @@ -1440,6 +1425,12 @@ static int mxf_write_header(AVFormatContext *s) return -1; } av_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den); + if (mxf->tc.str) { + mxf->tc.rate.num = mxf->time_base.den; + mxf->tc.rate.den = mxf->time_base.num; + if (ff_init_smtpe_timecode(s, &mxf->tc) < 0) + return -1; + } if (s->oformat == &ff_mxf_d10_muxer) { if (st->codec->bit_rate == 50000000) if (mxf->time_base.den == 25) sc->index = 3; @@ -1554,7 +1545,7 @@ static void mxf_write_system_item(AVFormatContext *s) unsigned frame; uint32_t time_code; - frame = mxf->timecode_start + mxf->last_indexed_edit_unit + mxf->edit_units_count; + frame = mxf->tc.start + mxf->last_indexed_edit_unit + mxf->edit_units_count; // write system metadata pack avio_write(pb, system_metadata_pack_key, 16); @@ -1576,7 +1567,7 @@ static void mxf_write_system_item(AVFormatContext *s) avio_w8(pb, 0x81); // SMPTE 12M time code time_code = ff_framenum_to_smtpe_timecode(frame, mxf->timecode_base, - mxf->timecode_drop_frame); + mxf->tc.drop); avio_wb32(pb, time_code); avio_wb32(pb, 0); // binary group data avio_wb64(pb, 0); @@ -1873,6 +1864,16 @@ static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int mxf_interleave_get_packet, mxf_compare_timestamps); } +static const AVClass class = { + .class_name = "mxf", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, + .option = (const AVOption[]){ + {TIMECODE_OPT(MXFContext, AV_OPT_FLAG_ENCODING_PARAM)}, + {NULL} + }, +}; + AVOutputFormat ff_mxf_muxer = { .name = "mxf", .long_name = NULL_IF_CONFIG_SMALL("Material eXchange Format"), @@ -1886,6 +1887,7 @@ AVOutputFormat ff_mxf_muxer = { .write_trailer = mxf_write_footer, .flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, + .priv_class = &class, }; AVOutputFormat ff_mxf_d10_muxer = { @@ -1900,4 +1902,5 @@ AVOutputFormat ff_mxf_d10_muxer = { .write_trailer = mxf_write_footer, .flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, + .priv_class = &class, }; diff --git a/tests/lavf-regression.sh b/tests/lavf-regression.sh index 3650ce1b95..0c6a6ba547 100755 --- a/tests/lavf-regression.sh +++ b/tests/lavf-regression.sh @@ -63,7 +63,7 @@ do_lavf mpg fi if [ -n "$do_mxf" ] ; then -do_lavf mxf "-ar 48000 -bf 2 -timecode_frame_start 264363" +do_lavf mxf "-ar 48000 -bf 2 -timecode 02:56:14:13" fi if [ -n "$do_mxf_d10" ]; then