ffmpeg: add enc_time_base option

add a per-stream option for setting the encoder timebase.
the following values are allowed:
0 - for video, use 1/frame_rate, for audio use 1/sample_rate (this is
  the default)
-1 - match the input timebase (when possible)
>0 - set the timebase to provided number

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
erankor 2017-05-03 11:50:15 +03:00 committed by Michael Niedermayer
parent 6ce57fb3c2
commit 2b06f2d2e2
4 changed files with 72 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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" },