summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/ffmpeg.texi24
-rw-r--r--ffmpeg.c31
-rw-r--r--ffmpeg.h3
-rw-r--r--ffmpeg_opt.c16
4 files changed, 72 insertions, 2 deletions
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index e72da8c473..dcc0cfb341 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -1176,6 +1176,30 @@ Try to make the choice automatically, in order to generate a sane output.
Default value is -1.
+@item -enc_time_base[:@var{stream_specifier}] @var{timebase} (@emph{output,per-stream})
+Set the encoder timebase. @var{timebase} is a floating point number,
+and can assume one of the following values:
+
+@table @option
+@item 0
+Assign a default value according to the media type.
+
+For video - use 1/framerate, for audio - use 1/samplerate.
+
+@item -1
+Use the input stream timebase when possible.
+
+If an input stream is not available, the default timebase will be used.
+
+@item >0
+Use the provided number as the timebase.
+
+This field can be provided as a ratio of two integers (e.g. 1:24, 1:48000)
+or as a floating point number (e.g. 0.04166, 2.0833e-5)
+@end table
+
+Default value is 0.
+
@item -shortest (@emph{output})
Finish encoding when the shortest input stream ends.
@item -dts_delta_threshold
diff --git a/ffmpeg.c b/ffmpeg.c
index e798d92277..76bf008c73 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -3234,6 +3234,30 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost,
ost->forced_kf_pts = pts;
}
+static void init_encoder_time_base(OutputStream *ost, AVRational default_time_base)
+{
+ InputStream *ist = get_input_stream(ost);
+ AVCodecContext *enc_ctx = ost->enc_ctx;
+ AVFormatContext *oc;
+
+ if (ost->enc_timebase.num > 0) {
+ enc_ctx->time_base = ost->enc_timebase;
+ return;
+ }
+
+ if (ost->enc_timebase.num < 0) {
+ if (ist) {
+ enc_ctx->time_base = ist->st->time_base;
+ return;
+ }
+
+ oc = output_files[ost->file_index]->ctx;
+ av_log(oc, AV_LOG_WARNING, "Input stream data not available, using default time base\n");
+ }
+
+ enc_ctx->time_base = default_time_base;
+}
+
static int init_output_stream_encode(OutputStream *ost)
{
InputStream *ist = get_input_stream(ost);
@@ -3304,10 +3328,13 @@ static int init_output_stream_encode(OutputStream *ost)
enc_ctx->sample_rate = av_buffersink_get_sample_rate(ost->filter->filter);
enc_ctx->channel_layout = av_buffersink_get_channel_layout(ost->filter->filter);
enc_ctx->channels = av_buffersink_get_channels(ost->filter->filter);
- enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate };
+
+ init_encoder_time_base(ost, av_make_q(1, enc_ctx->sample_rate));
break;
+
case AVMEDIA_TYPE_VIDEO:
- enc_ctx->time_base = av_inv_q(ost->frame_rate);
+ init_encoder_time_base(ost, av_inv_q(ost->frame_rate));
+
if (!(enc_ctx->time_base.num && enc_ctx->time_base.den))
enc_ctx->time_base = av_buffersink_get_time_base(ost->filter->filter);
if ( av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH
diff --git a/ffmpeg.h b/ffmpeg.h
index d34561275a..854ed1924a 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -226,6 +226,8 @@ typedef struct OptionsContext {
int nb_program;
SpecifierOpt *time_bases;
int nb_time_bases;
+ SpecifierOpt *enc_time_bases;
+ int nb_enc_time_bases;
} OptionsContext;
typedef struct InputFilter {
@@ -453,6 +455,7 @@ typedef struct OutputStream {
int64_t last_mux_dts;
// the timebase of the packets sent to the muxer
AVRational mux_timebase;
+ AVRational enc_timebase;
int nb_bitstream_filters;
uint8_t *bsf_extradata_updated;
diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
index ce85f324cf..4720e12269 100644
--- a/ffmpeg_opt.c
+++ b/ffmpeg_opt.c
@@ -1311,6 +1311,17 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
st->time_base = q;
}
+ MATCH_PER_STREAM_OPT(enc_time_bases, str, time_base, oc, st);
+ if (time_base) {
+ AVRational q;
+ if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 ||
+ q.den <= 0) {
+ av_log(NULL, AV_LOG_FATAL, "Invalid time base: %s\n", time_base);
+ exit_program(1);
+ }
+ ost->enc_timebase = q;
+ }
+
ost->max_frames = INT64_MAX;
MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st);
for (i = 0; i<o->nb_max_frames; i++) {
@@ -3629,6 +3640,11 @@ const OptionDef options[] = {
{ "time_base", HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(time_bases) },
"set the desired time base hint for output stream (1:24, 1:48000 or 0.04166, 2.0833e-5)", "ratio" },
+ { "enc_time_base", HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(enc_time_bases) },
+ "set the desired time base for the encoder (1:24, 1:48000 or 0.04166, 2.0833e-5). "
+ "two special values are defined - "
+ "0 = use frame rate (video) or sample rate (audio),"
+ "-1 = match source time base", "ratio" },
{ "bsf", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(bitstream_filters) },
"A comma-separated list of bitstream filters", "bitstream_filters" },