History

avfilter/setpts: add command support

Add support for changing expr on the fly.

Oleg committed 3 years ago

Commit e700d871 parent 6f136883 files · +64 −17Browse files

Unified · Split

3 files
  1. Changelog +1 −0
  2. doc/filters.texi +7 −0
  3. libavfilter/setpts.c +56 −17
Changelog+1−0
@@ -9,6 +9,7 @@ version <next>: · 8 unmodified lines
9- arls filter9- arls filter
10- ffmpeg CLI new option: -readrate_initial_burst10- ffmpeg CLI new option: -readrate_initial_burst
11- zoneplate video source filter11- zoneplate video source filter
12- command support in the setpts and asetpts filters
12 13
13version 6.0:14version 6.0:
14- Radiance HDR image support15- Radiance HDR image support
doc/filters.texi+7−0
@@ -29644,6 +29644,9 @@ The wallclock (RTC) time at the start of the movie in microseconds. · 29643 unmodified lines
29644@item TB29644@item TB
29645The timebase of the input timestamps.29645The timebase of the input timestamps.
29646 29646
29647@item T_CHANGE
29648Time of the first frame after command was applied or time of the first frame if no commands.
29649
29647@end table29650@end table
29648 29651
29649@subsection Examples29652@subsection Examples
@@ -29699,6 +29702,10 @@ asetpts=N/SR/TB · 49 unmodified lines
29699 29702
29700@end itemize29703@end itemize
29701 29704
29705@subsection Commands
29706
29707Both filters support all above options as @ref{commands}.
29708
29702@section setrange29709@section setrange
29703 29710
29704Force color range for the output video frame.29711Force color range for the output video frame.
libavfilter/setpts.c+56−17
@@ -63,6 +63,7 @@ static const char *const var_names[] = { · 62 unmodified lines
63 "S", // Number of samples in the current frame63 "S", // Number of samples in the current frame
64 "SR", // Audio sample rate64 "SR", // Audio sample rate
65 "FR", ///< defined only for constant frame-rate video65 "FR", ///< defined only for constant frame-rate video
66 "T_CHANGE", ///< time of first frame after latest command was applied
66 NULL67 NULL
67};68};
68 69
@@ -90,7 +91,8 @@ enum var_name { · 21 unmodified lines
90 VAR_S,91 VAR_S,
91 VAR_SR,92 VAR_SR,
92 VAR_FR,93 VAR_FR,
93 VAR_VARS_NB94 VAR_T_CHANGE,
95 VAR_VARS_NB,
94};96};
95 97
96typedef struct SetPTSContext {98typedef struct SetPTSContext {
@@ -120,6 +122,7 @@ static av_cold int init(AVFilterContext *ctx) · 23 unmodified lines
120 setpts->var_values[VAR_PREV_OUTT] = NAN;122 setpts->var_values[VAR_PREV_OUTT] = NAN;
121 setpts->var_values[VAR_STARTPTS] = NAN;123 setpts->var_values[VAR_STARTPTS] = NAN;
122 setpts->var_values[VAR_STARTT] = NAN;124 setpts->var_values[VAR_STARTT] = NAN;
125 setpts->var_values[VAR_T_CHANGE] = NAN;
123 return 0;126 return 0;
124}127}
125 128
@@ -163,6 +166,9 @@ static double eval_pts(SetPTSContext *setpts, AVFilterLink *inlink, AVFrame *fra · 37 unmodified lines
163 setpts->var_values[VAR_STARTPTS] = TS2D(pts);166 setpts->var_values[VAR_STARTPTS] = TS2D(pts);
164 setpts->var_values[VAR_STARTT ] = TS2T(pts, inlink->time_base);167 setpts->var_values[VAR_STARTT ] = TS2T(pts, inlink->time_base);
165 }168 }
169 if (isnan(setpts->var_values[VAR_T_CHANGE])) {
170 setpts->var_values[VAR_T_CHANGE] = TS2T(pts, inlink->time_base);
171 }
166 setpts->var_values[VAR_PTS ] = TS2D(pts);172 setpts->var_values[VAR_PTS ] = TS2D(pts);
167 setpts->var_values[VAR_T ] = TS2T(pts, inlink->time_base);173 setpts->var_values[VAR_T ] = TS2T(pts, inlink->time_base);
168#if FF_API_FRAME_PKT174#if FF_API_FRAME_PKT
@@ -269,14 +275,45 @@ static av_cold void uninit(AVFilterContext *ctx) · 100 unmodified lines
269 setpts->expr = NULL;275 setpts->expr = NULL;
270}276}
271 277
278static int process_command(AVFilterContext *ctx, const char *cmd, const char *arg,
279 char *res, int res_len, int flags)
280{
281 SetPTSContext *setpts = ctx->priv;
282 AVExpr *new_expr;
283 int ret;
284
285 ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags);
286
287 if (ret < 0)
288 return ret;
289
290 if (!strcmp(cmd, "expr")) {
291 ret = av_expr_parse(&new_expr, arg, var_names, NULL, NULL, NULL, NULL, 0, ctx);
292 // Only free and replace previous expression if new one succeeds,
293 // otherwise defensively keep everything intact even if reporting an error.
294 if (ret < 0) {
295 av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", arg);
296 } else {
297 av_expr_free(setpts->expr);
298 setpts->expr = new_expr;
299 setpts->var_values[VAR_T_CHANGE] = NAN;
300 }
301 } else {
302 ret = AVERROR(EINVAL);
303 }
304
305 return ret;
306}
307
272#define OFFSET(x) offsetof(SetPTSContext, x)308#define OFFSET(x) offsetof(SetPTSContext, x)
273#define V AV_OPT_FLAG_VIDEO_PARAM309#define V AV_OPT_FLAG_VIDEO_PARAM
274#define A AV_OPT_FLAG_AUDIO_PARAM310#define A AV_OPT_FLAG_AUDIO_PARAM
311#define R AV_OPT_FLAG_RUNTIME_PARAM
275#define F AV_OPT_FLAG_FILTERING_PARAM312#define F AV_OPT_FLAG_FILTERING_PARAM
276 313
277#if CONFIG_SETPTS_FILTER314#if CONFIG_SETPTS_FILTER
278static const AVOption setpts_options[] = {315static const AVOption setpts_options[] = {
279 { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = V|F },316 { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = V|F|R },
280 { NULL }317 { NULL }
281};318};
282AVFILTER_DEFINE_CLASS(setpts);319AVFILTER_DEFINE_CLASS(setpts);
@@ -297,12 +334,13 @@ static const AVFilterPad avfilter_vf_setpts_outputs[] = { · 14 unmodified lines
297};334};
298 335
299const AVFilter ff_vf_setpts = {336const AVFilter ff_vf_setpts = {
300 .name = "setpts",337 .name = "setpts",
301 .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."),338 .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."),
302 .init = init,339 .init = init,
303 .activate = activate,340 .activate = activate,
304 .uninit = uninit,341 .uninit = uninit,
305 .flags = AVFILTER_FLAG_METADATA_ONLY,342 .process_command = process_command,
343 .flags = AVFILTER_FLAG_METADATA_ONLY,
306 344
307 .priv_size = sizeof(SetPTSContext),345 .priv_size = sizeof(SetPTSContext),
308 .priv_class = &setpts_class,346 .priv_class = &setpts_class,
@@ -315,7 +353,7 @@ const AVFilter ff_vf_setpts = { · 6 unmodified lines
315#if CONFIG_ASETPTS_FILTER353#if CONFIG_ASETPTS_FILTER
316 354
317static const AVOption asetpts_options[] = {355static const AVOption asetpts_options[] = {
318 { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = A|F },356 { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = A|F|R },
319 { NULL }357 { NULL }
320};358};
321AVFILTER_DEFINE_CLASS(asetpts);359AVFILTER_DEFINE_CLASS(asetpts);
@@ -336,14 +374,15 @@ static const AVFilterPad asetpts_outputs[] = { · 14 unmodified lines
336};374};
337 375
338const AVFilter ff_af_asetpts = {376const AVFilter ff_af_asetpts = {
339 .name = "asetpts",377 .name = "asetpts",
340 .description = NULL_IF_CONFIG_SMALL("Set PTS for the output audio frame."),378 .description = NULL_IF_CONFIG_SMALL("Set PTS for the output audio frame."),
341 .init = init,379 .init = init,
342 .activate = activate,380 .activate = activate,
343 .uninit = uninit,381 .uninit = uninit,
344 .priv_size = sizeof(SetPTSContext),382 .process_command = process_command,
345 .priv_class = &asetpts_class,383 .priv_size = sizeof(SetPTSContext),
346 .flags = AVFILTER_FLAG_METADATA_ONLY,384 .priv_class = &asetpts_class,
385 .flags = AVFILTER_FLAG_METADATA_ONLY,
347 FILTER_INPUTS(asetpts_inputs),386 FILTER_INPUTS(asetpts_inputs),
348 FILTER_OUTPUTS(asetpts_outputs),387 FILTER_OUTPUTS(asetpts_outputs),
349};388};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t