diff options
author | Clément Bœsch <clement.boesch@smartjog.com> | 2012-05-30 10:26:53 +0200 |
---|---|---|
committer | Clément Bœsch <ubitux@gmail.com> | 2012-06-04 07:41:22 +0200 |
commit | 6b35f1a2a6432cb79f657ea3fadb86b8e12dddcb (patch) | |
tree | 372b3d3ee1664494f32d1b518caf54fb9c4dd20b | |
parent | 0f0f3bd1e022639eb8e9c02b7b18f37071c21763 (diff) | |
download | ffmpeg-6b35f1a2a6432cb79f657ea3fadb86b8e12dddcb.tar.gz |
timecode: move timecode muxer options to metadata.
Some demuxers set a timecode in the format or streams metadata. The
muxers now make use of this metadata instead of a duplicated private
option.
This makes possible transparent copy of the timecode when transmuxing
and transcoding.
-timecode option for MPEG1/2 codec is also renamed to -gop_timecode. The
global ffmpeg -timecode option will set it anyway so no option change
visible for the user.
-rw-r--r-- | ffmpeg.c | 11 | ||||
-rw-r--r-- | libavcodec/mpeg12enc.c | 3 | ||||
-rw-r--r-- | libavformat/dvenc.c | 26 | ||||
-rw-r--r-- | libavformat/gxfenc.c | 26 | ||||
-rw-r--r-- | libavformat/mxfenc.c | 31 | ||||
-rw-r--r-- | libavutil/timecode.h | 6 |
6 files changed, 35 insertions, 68 deletions
@@ -5618,6 +5618,16 @@ static int opt_deinterlace(const char *opt, const char *arg) return 0; } +static int opt_timecode(OptionsContext *o, const char *opt, const char *arg) +{ + char *tcr = av_asprintf("timecode=%s", arg); + int ret = parse_option(o, "metadata:g", tcr, options); + if (ret >= 0) + ret = opt_default("gop_timecode", arg); + av_free(tcr); + return ret; +} + static void parse_cpuflags(int argc, char **argv, const OptionDef *options) { int idx = locate_option(argc, argv, options, "cpuflags"); @@ -5752,6 +5762,7 @@ static const OptionDef options[] = { { "sameq", OPT_BOOL | OPT_VIDEO, {(void*)&same_quant}, "use same quantizer as source (implies VBR)" }, { "same_quant", OPT_BOOL | OPT_VIDEO, {(void*)&same_quant}, "use same quantizer as source (implies VBR)" }, + { "timecode", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_timecode}, "set initial TimeCode value.", "hh:mm:ss[:;.]ff" }, { "pass", HAS_ARG | OPT_VIDEO, {(void*)opt_pass}, "select the pass number (1 or 2)", "n" }, { "passlogfile", HAS_ARG | OPT_VIDEO, {(void*)&opt_passlogfile}, "select two pass log file name prefix", "prefix" }, { "deinterlace", OPT_EXPERT | OPT_VIDEO, {(void*)opt_deinterlace}, diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 169f15553e..ae71b8ec0b 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -931,8 +931,7 @@ static void mpeg1_encode_block(MpegEncContext *s, #define OFFSET(x) offsetof(MpegEncContext, x) #define VE AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM #define COMMON_OPTS\ - {AV_TIMECODE_OPTION(MpegEncContext, tc_opt_str, \ - AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)},\ + { "gop_timecode", "MPEG GOP Timecode in hh:mm:ss[:;.]ff format", OFFSET(tc_opt_str), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, VE },\ { "intra_vlc", "Use MPEG-2 intra VLC table.", OFFSET(intra_vlc_format), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },\ { "drop_frame_timecode", "Timecode is in drop frame format.", OFFSET(drop_frame_timecode), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE}, \ { "scan_offset", "Reserve space for SVCD scan offset user data.", OFFSET(scan_offset), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE }, diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c index 506225e8eb..f3056f7892 100644 --- a/libavformat/dvenc.c +++ b/libavformat/dvenc.c @@ -52,7 +52,6 @@ struct DVMuxContext { int has_audio; /* frame under contruction has audio */ int has_video; /* frame under contruction has video */ uint8_t frame_buf[DV_MAX_FRAME_SIZE]; /* frame under contruction */ - char *tc_opt_str; /* timecode option string */ AVTimecode tc; /* timecode context */ }; @@ -356,6 +355,7 @@ static int dv_write_header(AVFormatContext *s) { AVRational rate; DVMuxContext *dvc = s->priv_data; + AVDictionaryEntry *tcr = av_dict_get(s->metadata, "timecode", NULL, 0); if (!dv_init_mux(s)) { av_log(s, AV_LOG_ERROR, "Can't initialize DV format!\n" @@ -366,9 +366,16 @@ static int dv_write_header(AVFormatContext *s) } rate.num = dvc->sys->ltc_divisor; rate.den = 1; - if (dvc->tc_opt_str) - return av_timecode_init_from_string(&dvc->tc, rate, - dvc->tc_opt_str, s); + if (!tcr) { // no global timecode, look into the streams + int i; + for (i = 0; i < s->nb_streams; i++) { + tcr = av_dict_get(s->streams[i]->metadata, "timecode", NULL, 0); + if (tcr) + break; + } + } + if (tcr) + return av_timecode_init_from_string(&dvc->tc, rate, tcr->value, s); return av_timecode_init(&dvc->tc, rate, 0, 0, s); } @@ -398,16 +405,6 @@ static int dv_write_trailer(struct AVFormatContext *s) return 0; } -static const AVClass class = { - .class_name = "dv", - .item_name = av_default_item_name, - .version = LIBAVUTIL_VERSION_INT, - .option = (const AVOption[]){ - {AV_TIMECODE_OPTION(DVMuxContext, tc_opt_str, AV_OPT_FLAG_ENCODING_PARAM)}, - {NULL}, - }, -}; - AVOutputFormat ff_dv_muxer = { .name = "dv", .long_name = NULL_IF_CONFIG_SMALL("DV video format"), @@ -418,5 +415,4 @@ AVOutputFormat ff_dv_muxer = { .write_header = dv_write_header, .write_packet = dv_write_packet, .write_trailer = dv_write_trailer, - .priv_class = &class, }; diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c index 089a689402..3c5078ca9f 100644 --- a/libavformat/gxfenc.c +++ b/libavformat/gxfenc.c @@ -41,7 +41,6 @@ typedef struct GXFTimecode{ int ff; int color; int drop; - char *str; } GXFTimecode; typedef struct GXFStreamContext { @@ -655,11 +654,11 @@ static void gxf_init_timecode_track(GXFStreamContext *sc, GXFStreamContext *vsc) sc->fields = vsc->fields; } -static int gxf_init_timecode(AVFormatContext *s, GXFTimecode *tc, int fields) +static int gxf_init_timecode(AVFormatContext *s, GXFTimecode *tc, const char *tcstr, int fields) { char c; - if (sscanf(tc->str, "%d:%d:%d%c%d", &tc->hh, &tc->mm, &tc->ss, &c, &tc->ff) != 5) { + if (sscanf(tcstr, "%d:%d:%d%c%d", &tc->hh, &tc->mm, &tc->ss, &c, &tc->ff) != 5) { av_log(s, AV_LOG_ERROR, "unable to parse timecode, " "syntax: hh:mm:ss[:;.]ff\n"); return -1; @@ -681,6 +680,7 @@ static int gxf_write_header(AVFormatContext *s) GXFStreamContext *vsc = NULL; uint8_t tracks[255] = {0}; int i, media_info = 0; + AVDictionaryEntry *tcr = av_dict_get(s->metadata, "timecode", NULL, 0); if (!pb->seekable) { av_log(s, AV_LOG_ERROR, "gxf muxer does not support streamed output, patch welcome"); @@ -741,6 +741,8 @@ static int gxf_write_header(AVFormatContext *s) "gxf muxer only accepts PAL or NTSC resolutions currently\n"); return -1; } + if (!tcr) + tcr = av_dict_get(st->metadata, "timecode", NULL, 0); avpriv_set_pts_info(st, 64, gxf->time_base.num, gxf->time_base.den); if (gxf_find_lines_index(st) < 0) sc->lines_index = -1; @@ -792,9 +794,8 @@ static int gxf_write_header(AVFormatContext *s) if (ff_audio_interleave_init(s, GXF_samples_per_frame, (AVRational){ 1, 48000 }) < 0) return -1; - if (gxf->tc.str) { - gxf_init_timecode(s, &gxf->tc, vsc->fields); - } + if (tcr) + gxf_init_timecode(s, &gxf->tc, tcr->value, vsc->fields); gxf_init_timecode_track(&gxf->timecode_track, vsc); gxf->flags |= 0x200000; // time code track is non-drop frame @@ -983,18 +984,6 @@ static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pk ff_interleave_packet_per_dts, gxf_compare_field_nb); } -static const AVOption options[] = { - { AV_TIMECODE_OPTION(GXFContext, tc.str, AV_OPT_FLAG_ENCODING_PARAM) }, - { NULL } -}; - -static const AVClass gxf_muxer_class = { - .class_name = "GXF muxer", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - AVOutputFormat ff_gxf_muxer = { .name = "gxf", .long_name = NULL_IF_CONFIG_SMALL("GXF format"), @@ -1006,5 +995,4 @@ AVOutputFormat ff_gxf_muxer = { .write_packet = gxf_write_packet, .write_trailer = gxf_write_trailer, .interleave_packet = gxf_interleave_packet, - .priv_class = &gxf_muxer_class, }; diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index f87a50a80b..b2fe736ff2 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -189,7 +189,6 @@ typedef struct MXFContext { unsigned body_partitions_count; int last_key_index; ///< index of last key frame uint64_t duration; - char *tc_opt_str; ///< timecode option string AVTimecode tc; ///< timecode context AVStream *timecode_track; int timecode_base; ///< rounded time code base (25 or 30) @@ -1403,6 +1402,7 @@ static int mxf_write_header(AVFormatContext *s) const int *samples_per_frame = NULL; AVDictionaryEntry *t; int64_t timestamp = 0; + AVDictionaryEntry *tcr = av_dict_get(s->metadata, "timecode", NULL, 0); if (!s->nb_streams) return -1; @@ -1443,9 +1443,10 @@ static int mxf_write_header(AVFormatContext *s) } rate = (AVRational){mxf->time_base.den, mxf->time_base.num}; avpriv_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den); - if (mxf->tc_opt_str) - ret = av_timecode_init_from_string(&mxf->tc, rate, - mxf->tc_opt_str, s); + if (!tcr) + tcr = av_dict_get(st->metadata, "timecode", NULL, 0); + if (tcr) + ret = av_timecode_init_from_string(&mxf->tc, rate, tcr->value, s); else ret = av_timecode_init(&mxf->tc, rate, 0, 0, s); if (ret < 0) @@ -1877,26 +1878,6 @@ static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int mxf_interleave_get_packet, mxf_compare_timestamps); } -static const AVClass mxf_class = { - .class_name = "mxf", - .item_name = av_default_item_name, - .version = LIBAVUTIL_VERSION_INT, - .option = (const AVOption[]){ - {AV_TIMECODE_OPTION(MXFContext, tc_opt_str, AV_OPT_FLAG_ENCODING_PARAM)}, - {NULL} - }, -}; - -static const AVClass mxf_d10_class = { - .class_name = "mxf_d10", - .item_name = av_default_item_name, - .version = LIBAVUTIL_VERSION_INT, - .option = (const AVOption[]){ - {AV_TIMECODE_OPTION(MXFContext, tc_opt_str, AV_OPT_FLAG_ENCODING_PARAM)}, - {NULL} - }, -}; - AVOutputFormat ff_mxf_muxer = { .name = "mxf", .long_name = NULL_IF_CONFIG_SMALL("Material eXchange Format"), @@ -1910,7 +1891,6 @@ AVOutputFormat ff_mxf_muxer = { .write_trailer = mxf_write_footer, .flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, - .priv_class = &mxf_class, }; AVOutputFormat ff_mxf_d10_muxer = { @@ -1925,5 +1905,4 @@ AVOutputFormat ff_mxf_d10_muxer = { .write_trailer = mxf_write_footer, .flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, - .priv_class = &mxf_d10_class, }; diff --git a/libavutil/timecode.h b/libavutil/timecode.h index 41e56d6bfa..da252c1c17 100644 --- a/libavutil/timecode.h +++ b/libavutil/timecode.h @@ -32,12 +32,6 @@ #define AV_TIMECODE_STR_SIZE 16 -#define AV_TIMECODE_OPTION(ctx, string_field, flags) \ - "timecode", "set timecode value following hh:mm:ss[:;.]ff format, " \ - "use ';' or '.' before frame number for drop frame", \ - offsetof(ctx, string_field), \ - AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, flags - enum AVTimecodeFlag { AV_TIMECODE_FLAG_DROPFRAME = 1<<0, ///< timecode is drop frame AV_TIMECODE_FLAG_24HOURSMAX = 1<<1, ///< timecode wraps after 24 hours |