FFmpeg  4.4.6
settb.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010 Stefano Sabatini
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file
23  * Set timebase for the output link.
24  */
25 
26 #include <inttypes.h>
27 #include <stdio.h>
28 
29 #include "libavutil/avstring.h"
30 #include "libavutil/eval.h"
31 #include "libavutil/internal.h"
32 #include "libavutil/mathematics.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/rational.h"
35 #include "audio.h"
36 #include "avfilter.h"
37 #include "filters.h"
38 #include "internal.h"
39 #include "video.h"
40 
41 static const char *const var_names[] = {
42  "AVTB", /* default timebase 1/AV_TIME_BASE */
43  "intb", /* input timebase */
44  "sr", /* sample rate */
45  NULL
46 };
47 
48 enum var_name {
53 };
54 
55 typedef struct SetTBContext {
56  const AVClass *class;
57  char *tb_expr;
59 } SetTBContext;
60 
61 #define OFFSET(x) offsetof(SetTBContext, x)
62 #define DEFINE_OPTIONS(filt_name, filt_type) \
63 static const AVOption filt_name##_options[] = { \
64  { "expr", "set expression determining the output timebase", OFFSET(tb_expr), AV_OPT_TYPE_STRING, {.str="intb"}, \
65  .flags=AV_OPT_FLAG_##filt_type##_PARAM|AV_OPT_FLAG_FILTERING_PARAM }, \
66  { "tb", "set expression determining the output timebase", OFFSET(tb_expr), AV_OPT_TYPE_STRING, {.str="intb"}, \
67  .flags=AV_OPT_FLAG_##filt_type##_PARAM|AV_OPT_FLAG_FILTERING_PARAM }, \
68  { NULL } \
69 }
70 
71 static int config_output_props(AVFilterLink *outlink)
72 {
73  AVFilterContext *ctx = outlink->src;
74  SetTBContext *settb = ctx->priv;
75  AVFilterLink *inlink = ctx->inputs[0];
76  AVRational time_base;
77  int ret;
78  double res;
79 
81  settb->var_values[VAR_INTB] = av_q2d(inlink->time_base);
82  settb->var_values[VAR_SR] = inlink->sample_rate;
83 
84  outlink->w = inlink->w;
85  outlink->h = inlink->h;
86 
87  if ((ret = av_expr_parse_and_eval(&res, settb->tb_expr, var_names, settb->var_values,
88  NULL, NULL, NULL, NULL, NULL, 0, NULL)) < 0) {
89  av_log(ctx, AV_LOG_ERROR, "Invalid expression '%s' for timebase.\n", settb->tb_expr);
90  return ret;
91  }
92  time_base = av_d2q(res, INT_MAX);
93  if (time_base.num <= 0 || time_base.den <= 0) {
95  "Invalid non-positive values for the timebase num:%d or den:%d.\n",
96  time_base.num, time_base.den);
97  return AVERROR(EINVAL);
98  }
99 
100  outlink->time_base = time_base;
101  av_log(outlink->src, AV_LOG_VERBOSE, "tb:%d/%d -> tb:%d/%d\n",
102  inlink ->time_base.num, inlink ->time_base.den,
103  outlink->time_base.num, outlink->time_base.den);
104 
105  return 0;
106 }
107 
108 static int64_t rescale_pts(AVFilterLink *inlink, AVFilterLink *outlink, int64_t orig_pts)
109 {
110  AVFilterContext *ctx = inlink->dst;
111  int64_t new_pts = orig_pts;
112 
113  if (av_cmp_q(inlink->time_base, outlink->time_base)) {
114  new_pts = av_rescale_q(orig_pts, inlink->time_base, outlink->time_base);
115  av_log(ctx, AV_LOG_DEBUG, "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n",
116  inlink ->time_base.num, inlink ->time_base.den, orig_pts,
117  outlink->time_base.num, outlink->time_base.den, new_pts);
118  }
119 
120  return new_pts;
121 }
122 
123 static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
124 {
125  AVFilterContext *ctx = inlink->dst;
126  AVFilterLink *outlink = ctx->outputs[0];
127 
128  frame->pts = rescale_pts(inlink, outlink, frame->pts);
129 
130  return ff_filter_frame(outlink, frame);
131 }
132 
134 {
135  AVFilterLink *inlink = ctx->inputs[0];
136  AVFilterLink *outlink = ctx->outputs[0];
137  AVFrame *in;
138  int status;
139  int64_t pts;
140  int ret;
141 
142  FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
143 
144  ret = ff_inlink_consume_frame(inlink, &in);
145  if (ret < 0)
146  return ret;
147  if (ret > 0)
148  return filter_frame(inlink, in);
149 
150  if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
151  ff_outlink_set_status(outlink, status, rescale_pts(inlink, outlink, pts));
152  return 0;
153  }
154 
155  FF_FILTER_FORWARD_WANTED(outlink, inlink);
156 
157  return FFERROR_NOT_READY;
158 }
159 
160 #if CONFIG_SETTB_FILTER
161 
162 DEFINE_OPTIONS(settb, VIDEO);
163 AVFILTER_DEFINE_CLASS(settb);
164 
165 static const AVFilterPad avfilter_vf_settb_inputs[] = {
166  {
167  .name = "default",
168  .type = AVMEDIA_TYPE_VIDEO,
169  },
170  { NULL }
171 };
172 
173 static const AVFilterPad avfilter_vf_settb_outputs[] = {
174  {
175  .name = "default",
176  .type = AVMEDIA_TYPE_VIDEO,
177  .config_props = config_output_props,
178  },
179  { NULL }
180 };
181 
183  .name = "settb",
184  .description = NULL_IF_CONFIG_SMALL("Set timebase for the video output link."),
185  .priv_size = sizeof(SetTBContext),
186  .priv_class = &settb_class,
187  .inputs = avfilter_vf_settb_inputs,
188  .outputs = avfilter_vf_settb_outputs,
189  .activate = activate,
190 };
191 #endif /* CONFIG_SETTB_FILTER */
192 
193 #if CONFIG_ASETTB_FILTER
194 
195 DEFINE_OPTIONS(asettb, AUDIO);
196 AVFILTER_DEFINE_CLASS(asettb);
197 
198 static const AVFilterPad avfilter_af_asettb_inputs[] = {
199  {
200  .name = "default",
201  .type = AVMEDIA_TYPE_AUDIO,
202  },
203  { NULL }
204 };
205 
206 static const AVFilterPad avfilter_af_asettb_outputs[] = {
207  {
208  .name = "default",
209  .type = AVMEDIA_TYPE_AUDIO,
210  .config_props = config_output_props,
211  },
212  { NULL }
213 };
214 
216  .name = "asettb",
217  .description = NULL_IF_CONFIG_SMALL("Set timebase for the audio output link."),
218  .priv_size = sizeof(SetTBContext),
219  .inputs = avfilter_af_asettb_inputs,
220  .outputs = avfilter_af_asettb_outputs,
221  .priv_class = &asettb_class,
222  .activate = activate,
223 };
224 #endif /* CONFIG_ASETTB_FILTER */
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
AVFilter ff_af_asettb
AVFilter ff_vf_settb
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition: avfilter.c:1449
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1096
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition: avfilter.c:1494
Main libavfilter public API header.
#define NULL
Definition: coverity.c:32
long long int64_t
Definition: coverity.c:34
static AVFrame * frame
int av_expr_parse_and_eval(double *d, const char *s, const char *const *const_names, const double *const_values, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), void *opaque, int log_offset, void *log_ctx)
Parse and evaluate an expression.
Definition: eval.c:776
simple arithmetic expression evaluator
#define FF_FILTER_FORWARD_WANTED(outlink, inlink)
Forward the frame_wanted_out flag from an output link to an input link.
Definition: filters.h:254
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition: filters.h:189
#define FFERROR_NOT_READY
Filters implementation helper functions.
Definition: filters.h:34
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition: filters.h:199
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
AVRational av_d2q(double d, int max)
Convert a double precision floating point number to a rational.
Definition: rational.c:106
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
#define AVFILTER_DEFINE_CLASS(fname)
Definition: internal.h:288
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
AVOptions.
Utilties for rational number calculation.
@ VAR_INTB
Definition: settb.c:50
@ VAR_AVTB
Definition: settb.c:49
@ VAR_VARS_NB
Definition: settb.c:52
@ VAR_SR
Definition: settb.c:51
static int64_t rescale_pts(AVFilterLink *inlink, AVFilterLink *outlink, int64_t orig_pts)
Definition: settb.c:108
#define DEFINE_OPTIONS(filt_name, filt_type)
Definition: settb.c:62
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
Definition: settb.c:123
static int config_output_props(AVFilterLink *outlink)
Definition: settb.c:71
static const char *const var_names[]
Definition: settb.c:41
static int activate(AVFilterContext *ctx)
Definition: settb.c:133
var_name
Definition: setts_bsf.c:50
Describe the class of an AVClass context structure.
Definition: log.h:67
An instance of a filter.
Definition: avfilter.h:341
A filter pad used for either input or output.
Definition: internal.h:54
const char * name
Pad name.
Definition: internal.h:60
Filter definition.
Definition: avfilter.h:145
const char * name
Filter name.
Definition: avfilter.h:149
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:411
Rational number (pair of numerator and denominator).
Definition: rational.h:58
int num
Numerator.
Definition: rational.h:59
int den
Denominator.
Definition: rational.h:60
char * tb_expr
Definition: settb.c:57
double var_values[VAR_VARS_NB]
Definition: settb.c:58
#define av_log(a,...)
AVFormatContext * ctx
Definition: movenc.c:48
static int64_t pts