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
99 - arls filter
1010 - ffmpeg CLI new option: -readrate_initial_burst
1111 - zoneplate video source filter
12+- command support in the setpts and asetpts filters
1213
1314 version 6.0:
1415 - 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
2964429644 @item TB
2964529645 The timebase of the input timestamps.
2964629646
29647+@item T_CHANGE
29648+Time of the first frame after command was applied or time of the first frame if no commands.
29649+
2964729650 @end table
2964829651
2964929652 @subsection Examples
@@ -29699,6 +29702,10 @@ asetpts=N/SR/TB · 49 unmodified lines
2969929702
2970029703 @end itemize
2970129704
29705+@subsection Commands
29706+
29707+Both filters support all above options as @ref{commands}.
29708+
2970229709 @section setrange
2970329710
2970429711 Force 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
6363 "S", // Number of samples in the current frame
6464 "SR", // Audio sample rate
6565 "FR", ///< defined only for constant frame-rate video
66+ "T_CHANGE", ///< time of first frame after latest command was applied
6667 NULL
6768 };
6869
@@ -90,7 +91,8 @@ enum var_name { · 21 unmodified lines
9091 VAR_S,
9192 VAR_SR,
9293 VAR_FR,
93− VAR_VARS_NB
94+ VAR_T_CHANGE,
95+ VAR_VARS_NB,
9496 };
9597
9698 typedef struct SetPTSContext {
@@ -120,6 +122,7 @@ static av_cold int init(AVFilterContext *ctx) · 23 unmodified lines
120122 setpts->var_values[VAR_PREV_OUTT] = NAN;
121123 setpts->var_values[VAR_STARTPTS] = NAN;
122124 setpts->var_values[VAR_STARTT] = NAN;
125+ setpts->var_values[VAR_T_CHANGE] = NAN;
123126 return 0;
124127 }
125128
@@ -163,6 +166,9 @@ static double eval_pts(SetPTSContext *setpts, AVFilterLink *inlink, AVFrame *fra · 37 unmodified lines
163166 setpts->var_values[VAR_STARTPTS] = TS2D(pts);
164167 setpts->var_values[VAR_STARTT ] = TS2T(pts, inlink->time_base);
165168 }
169+ if (isnan(setpts->var_values[VAR_T_CHANGE])) {
170+ setpts->var_values[VAR_T_CHANGE] = TS2T(pts, inlink->time_base);
171+ }
166172 setpts->var_values[VAR_PTS ] = TS2D(pts);
167173 setpts->var_values[VAR_T ] = TS2T(pts, inlink->time_base);
168174 #if FF_API_FRAME_PKT
@@ -269,14 +275,45 @@ static av_cold void uninit(AVFilterContext *ctx) · 100 unmodified lines
269275 setpts->expr = NULL;
270276 }
271277
278+static 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+
272308 #define OFFSET(x) offsetof(SetPTSContext, x)
273309 #define V AV_OPT_FLAG_VIDEO_PARAM
274310 #define A AV_OPT_FLAG_AUDIO_PARAM
311+#define R AV_OPT_FLAG_RUNTIME_PARAM
275312 #define F AV_OPT_FLAG_FILTERING_PARAM
276313
277314 #if CONFIG_SETPTS_FILTER
278315 static 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 },
280317 { NULL }
281318 };
282319 AVFILTER_DEFINE_CLASS(setpts);
@@ -297,12 +334,13 @@ static const AVFilterPad avfilter_vf_setpts_outputs[] = { · 14 unmodified lines
297334 };
298335
299336 const AVFilter ff_vf_setpts = {
300− .name = "setpts",
301− .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."),
302− .init = init,
303− .activate = activate,
304− .uninit = uninit,
305− .flags = AVFILTER_FLAG_METADATA_ONLY,
337+ .name = "setpts",
338+ .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."),
339+ .init = init,
340+ .activate = activate,
341+ .uninit = uninit,
342+ .process_command = process_command,
343+ .flags = AVFILTER_FLAG_METADATA_ONLY,
306344
307345 .priv_size = sizeof(SetPTSContext),
308346 .priv_class = &setpts_class,
@@ -315,7 +353,7 @@ const AVFilter ff_vf_setpts = { · 6 unmodified lines
315353 #if CONFIG_ASETPTS_FILTER
316354
317355 static 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 },
319357 { NULL }
320358 };
321359 AVFILTER_DEFINE_CLASS(asetpts);
@@ -336,14 +374,15 @@ static const AVFilterPad asetpts_outputs[] = { · 14 unmodified lines
336374 };
337375
338376 const AVFilter ff_af_asetpts = {
339− .name = "asetpts",
340− .description = NULL_IF_CONFIG_SMALL("Set PTS for the output audio frame."),
341− .init = init,
342− .activate = activate,
343− .uninit = uninit,
344− .priv_size = sizeof(SetPTSContext),
345− .priv_class = &asetpts_class,
346− .flags = AVFILTER_FLAG_METADATA_ONLY,
377+ .name = "asetpts",
378+ .description = NULL_IF_CONFIG_SMALL("Set PTS for the output audio frame."),
379+ .init = init,
380+ .activate = activate,
381+ .uninit = uninit,
382+ .process_command = process_command,
383+ .priv_size = sizeof(SetPTSContext),
384+ .priv_class = &asetpts_class,
385+ .flags = AVFILTER_FLAG_METADATA_ONLY,
347386 FILTER_INPUTS(asetpts_inputs),
348387 FILTER_OUTPUTS(asetpts_outputs),
349388 };

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