History

lavfi: add timeline support.

Flag added in a few simple filters. A bunch of other filters can likely use the feature as well.

Clément Bœsch committed 13 years ago

Commit fdd93ea1 parent b8a5c7621 files · +125 −4Browse files

Unified · Split

21 files
  1. Changelog +1 −0
  2. cmdutils.c +2 −0
  3. doc/filters.texi +32 −0
  4. libavfilter/af_volume.c +1 −0
  5. libavfilter/avfilter.c +50 −0
  6. libavfilter/avfilter.h +24 −1
  7. libavfilter/vf_boxblur.c +1 −0
  8. libavfilter/vf_colormatrix.c +1 −0
  9. libavfilter/vf_cropdetect.c +1 −0
  10. libavfilter/vf_curves.c +1 −0
  11. libavfilter/vf_drawbox.c +1 −0
  12. libavfilter/vf_edgedetect.c +1 −0
  13. libavfilter/vf_gradfun.c +1 −0
  14. libavfilter/vf_histeq.c +1 −0
  15. libavfilter/vf_hqdn3d.c +1 −1
  16. libavfilter/vf_hue.c +1 −0
  17. libavfilter/vf_lut.c +1 −0
  18. libavfilter/vf_noise.c +1 −0
  19. libavfilter/vf_pp.c +1 −1
  20. libavfilter/vf_smartblur.c +1 −0
  21. libavfilter/vf_unsharp.c +1 −1
Changelog+1−0
@@ -30,6 +30,7 @@ version <next>: · 29 unmodified lines
3030 - decent native animated GIF encoding
3131 - asetrate filter
3232 - interleave filter
33+- timeline editing with filters
3334
3435
3536 version 1.2:
cmdutils.c+2−0
@@ -1683,6 +1683,8 @@ static void show_help_filter(const char *name) · 1682 unmodified lines
16831683 if (f->priv_class)
16841684 show_help_children(f->priv_class, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM |
16851685 AV_OPT_FLAG_AUDIO_PARAM);
1686+ if (f->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)
1687+ printf("This filter has support for timeline through the 'enable' option.\n");
16861688 #else
16871689 av_log(NULL, AV_LOG_ERROR, "Build without libavfilter; "
16881690 "can not to satisfy request\n");
doc/filters.texi+32−0
@@ -267,6 +267,36 @@ See the ``Quoting and escaping'' section in the ffmpeg-utils manual · 266 unmodified lines
267267 for more information about the escaping and quoting rules adopted by
268268 FFmpeg.
269269
270+@chapter Timeline editing
271+
272+Some filters support a generic @option{enable} option. For the filters
273+supporting timeline editing, this option can be set to an expression which is
274+evaluated before sending a frame to the filter. If the evaluation is non-zero,
275+the filter will be enabled, otherwise the frame will be sent unchanged to the
276+next filter in the filtergraph.
277+
278+The expression accepts the following values:
279+@table @samp
280+@item t
281+timestamp expressed in seconds, NAN if the input timestamp is unknown
282+
283+@item n
284+sequential number of the input frame, starting from 0
285+
286+@item pos
287+the position in the file of the input frame, NAN if unknown
288+@end table
289+
290+Like any other filtering option, the @option{enable} option follows the same
291+rules.
292+
293+For example, to enable a denoiser filter (@ref{hqdn3d}) from 10 seconds to 3
294+minutes, and a @ref{curves} filter starting at 3 seconds:
295+@example
296+hqdn3d = enable='between(t,10,3*60)',
297+curves = enable='gte(t,3)' : preset=cross_process
298+@end example
299+
270300 @c man end FILTERGRAPH DESCRIPTION
271301
272302 @chapter Audio Filters
@@ -2409,6 +2439,7 @@ indicates never reset and return the largest area encountered during · 2136 unmodified lines
24092439 playback.
24102440 @end table
24112441
2442+@anchor{curves}
24122443 @section curves
24132444
24142445 Apply color adjustments using curves.
@@ -4013,6 +4044,7 @@ ffplay -i input -vf histogram · 1598 unmodified lines
40134044
40144045 @end itemize
40154046
4047+@anchor{hqdn3d}
40164048 @section hqdn3d
40174049
40184050 High precision/quality 3d denoise filter. This filter aims to reduce
libavfilter/af_volume.c+1−0
@@ -296,4 +296,5 @@ AVFilter avfilter_af_volume = { · 295 unmodified lines
296296 .init = init,
297297 .inputs = avfilter_af_volume_inputs,
298298 .outputs = avfilter_af_volume_outputs,
299+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
299300 };
libavfilter/avfilter.c+50−0
@@ -23,6 +23,7 @@ · 22 unmodified lines
2323 #include "libavutil/avstring.h"
2424 #include "libavutil/channel_layout.h"
2525 #include "libavutil/common.h"
26+#include "libavutil/eval.h"
2627 #include "libavutil/imgutils.h"
2728 #include "libavutil/opt.h"
2829 #include "libavutil/pixdesc.h"
@@ -483,12 +484,20 @@ static const AVClass *filter_child_class_next(const AVClass *prev) · 454 unmodified lines
483484 return NULL;
484485 }
485486
487+#define OFFSET(x) offsetof(AVFilterContext, x)
488+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM
489+static const AVOption filters_common_options[] = {
490+ { "enable", "set enable expression", OFFSET(enable_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
491+ { NULL }
492+};
493+
486494 static const AVClass avfilter_class = {
487495 .class_name = "AVFilter",
488496 .item_name = default_filter_name,
489497 .version = LIBAVUTIL_VERSION_INT,
490498 .category = AV_CLASS_CATEGORY_FILTER,
491499 .child_next = filter_child_next,
500+ .option = filters_common_options,
492501 .child_class_next = filter_child_class_next,
493502 };
494503
@@ -618,9 +627,16 @@ void avfilter_free(AVFilterContext *filter) · 123 unmodified lines
618627 while(filter->command_queue){
619628 ff_command_queue_pop(filter);
620629 }
630+ av_opt_free(filter);
631+ av_expr_free(filter->enable);
632+ filter->enable = NULL;
633+ av_freep(&filter->var_values);
621634 av_free(filter);
622635 }
623636
637+static const char *const var_names[] = { "t", "n", "pos", NULL };
638+enum { VAR_T, VAR_N, VAR_POS, VAR_VARS_NB };
639+
624640 static int process_options(AVFilterContext *ctx, AVDictionary **options,
625641 const char *args)
626642 {
@@ -630,6 +646,8 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options, · 3 unmodified lines
630646 const char *key;
631647 int offset= -1;
632648
649+ av_opt_set_defaults(ctx);
650+
633651 if (!args)
634652 return 0;
635653
@@ -665,6 +683,12 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options, · 29 unmodified lines
665683 }
666684
667685 av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value);
686+
687+ if (av_opt_find(ctx, key, NULL, 0, 0)) {
688+ ret = av_opt_set(ctx, key, value, 0);
689+ if (ret < 0)
690+ return ret;
691+ } else {
668692 av_dict_set(options, key, value, 0);
669693 if ((ret = av_opt_set(ctx->priv, key, value, 0)) < 0) {
670694 if (!av_opt_find(ctx->priv, key, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) {
@@ -675,11 +699,27 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options, · 4 unmodified lines
675699 return ret;
676700 }
677701 }
702+ }
678703
679704 av_free(value);
680705 av_free(parsed_key);
681706 count++;
682707 }
708+
709+ if (ctx->enable_str) {
710+ if (!(ctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)) {
711+ av_log(ctx, AV_LOG_ERROR, "Timeline ('enable' option) not supported "
712+ "with filter '%s'\n", ctx->filter->name);
713+ return AVERROR_PATCHWELCOME;
714+ }
715+ ctx->var_values = av_calloc(VAR_VARS_NB, sizeof(*ctx->var_values));
716+ if (!ctx->var_values)
717+ return AVERROR(ENOMEM);
718+ ret = av_expr_parse((AVExpr**)&ctx->enable, ctx->enable_str, var_names,
719+ NULL, NULL, NULL, NULL, 0, ctx->priv);
720+ if (ret < 0)
721+ return ret;
722+ }
683723 return count;
684724 }
685725
@@ -852,6 +892,7 @@ static int default_filter_frame(AVFilterLink *link, AVFrame *frame) · 166 unmodified lines
852892 static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame)
853893 {
854894 int (*filter_frame)(AVFilterLink *, AVFrame *);
895+ AVFilterContext *dstctx = link->dst;
855896 AVFilterPad *dst = link->dstpad;
856897 AVFrame *out;
857898 int ret;
@@ -914,6 +955,15 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame) · 56 unmodified lines
914955 }
915956
916957 pts = out->pts;
958+ if (dstctx->enable_str) {
959+ int64_t pos = av_frame_get_pkt_pos(out);
960+ dstctx->var_values[VAR_N] = link->frame_count;
961+ dstctx->var_values[VAR_T] = pts == AV_NOPTS_VALUE ? NAN : pts * av_q2d(link->time_base);
962+ dstctx->var_values[VAR_POS] = pos == -1 ? NAN : pos;
963+ if (!av_expr_eval(dstctx->enable, dstctx->var_values, NULL))
964+ filter_frame = dst->passthrough_filter_frame ? dst->passthrough_filter_frame
965+ : default_filter_frame;
966+ }
917967 ret = filter_frame(link, out);
918968 link->frame_count++;
919969 link->frame_requested = 0;
libavfilter/avfilter.h+24−1
@@ -385,6 +385,19 @@ struct AVFilterPad { · 384 unmodified lines
385385 int needs_fifo;
386386
387387 int needs_writable;
388+
389+ /**
390+ * Passthrough filtering callback.
391+ *
392+ * If a filter supports timeline editing (in case
393+ * AVFILTER_FLAG_SUPPORT_TIMELINE is enabled) then it can implement a
394+ * custom passthrough callback to update its local context (for example to
395+ * keep a frame reference, or simply send the filter to a custom outlink).
396+ * The filter must not do any change to the frame in this callback.
397+ *
398+ * Input pads only.
399+ */
400+ int (*passthrough_filter_frame)(AVFilterLink *link, AVFrame *frame);
388401 };
389402 #endif
390403
@@ -428,6 +441,12 @@ enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx); · 37 unmodified lines
428441 * the options supplied to it.
429442 */
430443 #define AVFILTER_FLAG_DYNAMIC_OUTPUTS (1 << 1)
444+/**
445+ * Some filters support a generic "enable" expression option that can be used
446+ * to enable or disable a filter in the timeline. Filters supporting this
447+ * option have this flag set.
448+ */
449+#define AVFILTER_FLAG_SUPPORT_TIMELINE (1 << 16)
431450
432451 /**
433452 * Filter definition. This defines the pads a filter contains, and all the
@@ -522,7 +541,7 @@ typedef struct AVFilter { · 88 unmodified lines
522541
523542 /** An instance of a filter */
524543 struct AVFilterContext {
525− const AVClass *av_class; ///< needed for av_log()
544+ const AVClass *av_class; ///< needed for av_log() and filters common options
526545
527546 const AVFilter *filter; ///< the AVFilter of which this is an instance
528547
@@ -547,6 +566,10 @@ struct AVFilterContext { · 18 unmodified lines
547566 struct AVFilterGraph *graph; ///< filtergraph this filter belongs to
548567
549568 struct AVFilterCommand *command_queue;
569+
570+ char *enable_str; ///< enable expression string
571+ void *enable; ///< parsed expression (AVExpr*)
572+ double *var_values; ///< variable values for the enable expression
550573 };
551574
552575 /**
libavfilter/vf_boxblur.c+1−0
@@ -383,4 +383,5 @@ AVFilter avfilter_vf_boxblur = { · 382 unmodified lines
383383
384384 .inputs = avfilter_vf_boxblur_inputs,
385385 .outputs = avfilter_vf_boxblur_outputs,
386+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
386387 };
libavfilter/vf_colormatrix.c+1−0
@@ -385,4 +385,5 @@ AVFilter avfilter_vf_colormatrix = { · 384 unmodified lines
385385 .inputs = colormatrix_inputs,
386386 .outputs = colormatrix_outputs,
387387 .priv_class = &colormatrix_class,
388+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
388389 };
libavfilter/vf_cropdetect.c+1−0
@@ -233,4 +233,5 @@ AVFilter avfilter_vf_cropdetect = { · 232 unmodified lines
233233 .query_formats = query_formats,
234234 .inputs = avfilter_vf_cropdetect_inputs,
235235 .outputs = avfilter_vf_cropdetect_outputs,
236+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
236237 };
libavfilter/vf_curves.c+1−0
@@ -514,4 +514,5 @@ AVFilter avfilter_vf_curves = { · 513 unmodified lines
514514 .inputs = curves_inputs,
515515 .outputs = curves_outputs,
516516 .priv_class = &curves_class,
517+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
517518 };
libavfilter/vf_drawbox.c+1−0
@@ -181,4 +181,5 @@ AVFilter avfilter_vf_drawbox = { · 180 unmodified lines
181181 .query_formats = query_formats,
182182 .inputs = avfilter_vf_drawbox_inputs,
183183 .outputs = avfilter_vf_drawbox_outputs,
184+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
184185 };
libavfilter/vf_edgedetect.c+1−0
@@ -327,4 +327,5 @@ AVFilter avfilter_vf_edgedetect = { · 326 unmodified lines
327327 .inputs = edgedetect_inputs,
328328 .outputs = edgedetect_outputs,
329329 .priv_class = &edgedetect_class,
330+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
330331 };
libavfilter/vf_gradfun.c+1−0
@@ -260,4 +260,5 @@ AVFilter avfilter_vf_gradfun = { · 259 unmodified lines
260260 .query_formats = query_formats,
261261 .inputs = avfilter_vf_gradfun_inputs,
262262 .outputs = avfilter_vf_gradfun_outputs,
263+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
263264 };
libavfilter/vf_histeq.c+1−0
@@ -279,4 +279,5 @@ AVFilter avfilter_vf_histeq = { · 278 unmodified lines
279279 .inputs = histeq_inputs,
280280 .outputs = histeq_outputs,
281281 .priv_class = &histeq_class,
282+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
282283 };
libavfilter/vf_hqdn3d.c+1−1
@@ -355,6 +355,6 @@ AVFilter avfilter_vf_hqdn3d = { · 354 unmodified lines
355355 .query_formats = query_formats,
356356
357357 .inputs = avfilter_vf_hqdn3d_inputs,
358−
359358 .outputs = avfilter_vf_hqdn3d_outputs,
359+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
360360 };
libavfilter/vf_hue.c+1−0
@@ -349,4 +349,5 @@ AVFilter avfilter_vf_hue = { · 348 unmodified lines
349349 .inputs = hue_inputs,
350350 .outputs = hue_outputs,
351351 .priv_class = &hue_class,
352+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
352353 };
libavfilter/vf_lut.c+1−0
@@ -350,6 +350,7 @@ static const AVFilterPad outputs[] = { · 349 unmodified lines
350350 \
351351 .inputs = inputs, \
352352 .outputs = outputs, \
353+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, \
353354 }
354355
355356 #if CONFIG_LUT_FILTER
libavfilter/vf_noise.c+1−0
@@ -471,4 +471,5 @@ AVFilter avfilter_vf_noise = { · 470 unmodified lines
471471 .inputs = noise_inputs,
472472 .outputs = noise_outputs,
473473 .priv_class = &noise_class,
474+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
474475 };
libavfilter/vf_pp.c+1−1
@@ -180,5 +180,5 @@ AVFilter avfilter_vf_pp = { · 179 unmodified lines
180180 .outputs = pp_outputs,
181181 .process_command = pp_process_command,
182182 .priv_class = &pp_class,
183−
183+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
184184 };
libavfilter/vf_smartblur.c+1−0
@@ -301,4 +301,5 @@ AVFilter avfilter_vf_smartblur = { · 300 unmodified lines
301301 .inputs = smartblur_inputs,
302302 .outputs = smartblur_outputs,
303303 .priv_class = &smartblur_class,
304+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
304305 };
libavfilter/vf_unsharp.c+1−1
@@ -299,6 +299,6 @@ AVFilter avfilter_vf_unsharp = { · 298 unmodified lines
299299 .query_formats = query_formats,
300300
301301 .inputs = avfilter_vf_unsharp_inputs,
302−
303302 .outputs = avfilter_vf_unsharp_outputs,
303+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
304304 };

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