Merge commit '95f1f56a21bc2f824af6fb97ca7ab35cdd0c401e'
[ffmpeg.git] / libavfilter / f_select.c
1 /*
2  * Copyright (c) 2011 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  * filter for selecting which frame passes in the filterchain
24  */
25
26 #include "libavutil/eval.h"
27 #include "libavutil/fifo.h"
28 #include "libavutil/internal.h"
29 #include "libavutil/opt.h"
30 #include "avfilter.h"
31 #include "audio.h"
32 #include "formats.h"
33 #include "internal.h"
34 #include "video.h"
35
36 #if CONFIG_AVCODEC
37 #include "libavcodec/dsputil.h"
38 #endif
39
40 static const char *const var_names[] = {
41     "TB",                ///< timebase
42
43     "pts",               ///< original pts in the file of the frame
44     "start_pts",         ///< first PTS in the stream, expressed in TB units
45     "prev_pts",          ///< previous frame PTS
46     "prev_selected_pts", ///< previous selected frame PTS
47
48     "t",                 ///< first PTS in seconds
49     "start_t",           ///< first PTS in the stream, expressed in seconds
50     "prev_t",            ///< previous frame time
51     "prev_selected_t",   ///< previously selected time
52
53     "pict_type",         ///< the type of picture in the movie
54     "I",
55     "P",
56     "B",
57     "S",
58     "SI",
59     "SP",
60     "BI",
61
62     "interlace_type",    ///< the frame interlace type
63     "PROGRESSIVE",
64     "TOPFIRST",
65     "BOTTOMFIRST",
66
67     "consumed_samples_n",///< number of samples consumed by the filter (only audio)
68     "samples_n",         ///< number of samples in the current frame (only audio)
69     "sample_rate",       ///< sample rate (only audio)
70
71     "n",                 ///< frame number (starting from zero)
72     "selected_n",        ///< selected frame number (starting from zero)
73     "prev_selected_n",   ///< number of the last selected frame
74
75     "key",               ///< tell if the frame is a key frame
76     "pos",               ///< original position in the file of the frame
77
78     "scene",
79
80     NULL
81 };
82
83 enum var_name {
84     VAR_TB,
85
86     VAR_PTS,
87     VAR_START_PTS,
88     VAR_PREV_PTS,
89     VAR_PREV_SELECTED_PTS,
90
91     VAR_T,
92     VAR_START_T,
93     VAR_PREV_T,
94     VAR_PREV_SELECTED_T,
95
96     VAR_PICT_TYPE,
97     VAR_PICT_TYPE_I,
98     VAR_PICT_TYPE_P,
99     VAR_PICT_TYPE_B,
100     VAR_PICT_TYPE_S,
101     VAR_PICT_TYPE_SI,
102     VAR_PICT_TYPE_SP,
103     VAR_PICT_TYPE_BI,
104
105     VAR_INTERLACE_TYPE,
106     VAR_INTERLACE_TYPE_P,
107     VAR_INTERLACE_TYPE_T,
108     VAR_INTERLACE_TYPE_B,
109
110     VAR_CONSUMED_SAMPLES_N,
111     VAR_SAMPLES_N,
112     VAR_SAMPLE_RATE,
113
114     VAR_N,
115     VAR_SELECTED_N,
116     VAR_PREV_SELECTED_N,
117
118     VAR_KEY,
119     VAR_POS,
120
121     VAR_SCENE,
122
123     VAR_VARS_NB
124 };
125
126 typedef struct {
127     const AVClass *class;
128     char *expr_str;
129     AVExpr *expr;
130     double var_values[VAR_VARS_NB];
131     int do_scene_detect;            ///< 1 if the expression requires scene detection variables, 0 otherwise
132 #if CONFIG_AVCODEC
133     AVCodecContext *avctx;          ///< codec context required for the DSPContext (scene detect only)
134     DSPContext c;                   ///< context providing optimized SAD methods   (scene detect only)
135     double prev_mafd;               ///< previous MAFD                             (scene detect only)
136 #endif
137     AVFrame *prev_picref; ///< previous frame                            (scene detect only)
138     double select;
139 } SelectContext;
140
141
142 static av_cold int init(AVFilterContext *ctx, const char *args, const AVClass *class)
143 {
144     SelectContext *select = ctx->priv;
145     int ret;
146
147     if ((ret = av_expr_parse(&select->expr, select->expr_str,
148                              var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
149         av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n",
150                select->expr_str);
151         return ret;
152     }
153     select->do_scene_detect = !!strstr(select->expr_str, "scene");
154
155     return 0;
156 }
157
158 #define INTERLACE_TYPE_P 0
159 #define INTERLACE_TYPE_T 1
160 #define INTERLACE_TYPE_B 2
161
162 static int config_input(AVFilterLink *inlink)
163 {
164     SelectContext *select = inlink->dst->priv;
165
166     select->var_values[VAR_N]          = 0.0;
167     select->var_values[VAR_SELECTED_N] = 0.0;
168
169     select->var_values[VAR_TB] = av_q2d(inlink->time_base);
170
171     select->var_values[VAR_PREV_PTS]          = NAN;
172     select->var_values[VAR_PREV_SELECTED_PTS] = NAN;
173     select->var_values[VAR_PREV_SELECTED_T]   = NAN;
174     select->var_values[VAR_PREV_T]            = NAN;
175     select->var_values[VAR_START_PTS]         = NAN;
176     select->var_values[VAR_START_T]           = NAN;
177
178     select->var_values[VAR_PICT_TYPE_I]  = AV_PICTURE_TYPE_I;
179     select->var_values[VAR_PICT_TYPE_P]  = AV_PICTURE_TYPE_P;
180     select->var_values[VAR_PICT_TYPE_B]  = AV_PICTURE_TYPE_B;
181     select->var_values[VAR_PICT_TYPE_SI] = AV_PICTURE_TYPE_SI;
182     select->var_values[VAR_PICT_TYPE_SP] = AV_PICTURE_TYPE_SP;
183
184     select->var_values[VAR_INTERLACE_TYPE_P] = INTERLACE_TYPE_P;
185     select->var_values[VAR_INTERLACE_TYPE_T] = INTERLACE_TYPE_T;
186     select->var_values[VAR_INTERLACE_TYPE_B] = INTERLACE_TYPE_B;
187
188     select->var_values[VAR_PICT_TYPE]         = NAN;
189     select->var_values[VAR_INTERLACE_TYPE]    = NAN;
190     select->var_values[VAR_SCENE]             = NAN;
191     select->var_values[VAR_CONSUMED_SAMPLES_N] = NAN;
192     select->var_values[VAR_SAMPLES_N]          = NAN;
193
194     select->var_values[VAR_SAMPLE_RATE] =
195         inlink->type == AVMEDIA_TYPE_AUDIO ? inlink->sample_rate : NAN;
196
197 #if CONFIG_AVCODEC
198     if (select->do_scene_detect) {
199         select->avctx = avcodec_alloc_context3(NULL);
200         if (!select->avctx)
201             return AVERROR(ENOMEM);
202         dsputil_init(&select->c, select->avctx);
203     }
204 #endif
205     return 0;
206 }
207
208 #if CONFIG_AVCODEC
209 static double get_scene_score(AVFilterContext *ctx, AVFrame *frame)
210 {
211     double ret = 0;
212     SelectContext *select = ctx->priv;
213     AVFrame *prev_picref = select->prev_picref;
214
215     if (prev_picref &&
216         frame->height    == prev_picref->height &&
217         frame->width    == prev_picref->width &&
218         frame->linesize[0] == prev_picref->linesize[0]) {
219         int x, y, nb_sad = 0;
220         int64_t sad = 0;
221         double mafd, diff;
222         uint8_t *p1 =      frame->data[0];
223         uint8_t *p2 = prev_picref->data[0];
224         const int linesize = frame->linesize[0];
225
226         for (y = 0; y < frame->height - 8; y += 8) {
227             for (x = 0; x < frame->width*3 - 8; x += 8) {
228                 sad += select->c.sad[1](select, p1 + x, p2 + x,
229                                         linesize, 8);
230                 nb_sad += 8 * 8;
231             }
232             p1 += 8 * linesize;
233             p2 += 8 * linesize;
234         }
235         emms_c();
236         mafd = nb_sad ? sad / nb_sad : 0;
237         diff = fabs(mafd - select->prev_mafd);
238         ret  = av_clipf(FFMIN(mafd, diff) / 100., 0, 1);
239         select->prev_mafd = mafd;
240         av_frame_free(&prev_picref);
241     }
242     select->prev_picref = av_frame_clone(frame);
243     return ret;
244 }
245 #endif
246
247 #define D2TS(d)  (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
248 #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
249
250 static int select_frame(AVFilterContext *ctx, AVFrame *frame)
251 {
252     SelectContext *select = ctx->priv;
253     AVFilterLink *inlink = ctx->inputs[0];
254     double res;
255
256     if (isnan(select->var_values[VAR_START_PTS]))
257         select->var_values[VAR_START_PTS] = TS2D(frame->pts);
258     if (isnan(select->var_values[VAR_START_T]))
259         select->var_values[VAR_START_T] = TS2D(frame->pts) * av_q2d(inlink->time_base);
260
261     select->var_values[VAR_PTS] = TS2D(frame->pts);
262     select->var_values[VAR_T  ] = TS2D(frame->pts) * av_q2d(inlink->time_base);
263     select->var_values[VAR_POS] = av_frame_get_pkt_pos(frame) == -1 ? NAN : av_frame_get_pkt_pos(frame);
264
265     switch (inlink->type) {
266     case AVMEDIA_TYPE_AUDIO:
267         select->var_values[VAR_SAMPLES_N] = frame->nb_samples;
268         break;
269
270     case AVMEDIA_TYPE_VIDEO:
271         select->var_values[VAR_INTERLACE_TYPE] =
272             !frame->interlaced_frame ? INTERLACE_TYPE_P :
273         frame->top_field_first ? INTERLACE_TYPE_T : INTERLACE_TYPE_B;
274         select->var_values[VAR_PICT_TYPE] = frame->pict_type;
275 #if CONFIG_AVCODEC
276         if (select->do_scene_detect) {
277             char buf[32];
278             select->var_values[VAR_SCENE] = get_scene_score(ctx, frame);
279             // TODO: document metadata
280             snprintf(buf, sizeof(buf), "%f", select->var_values[VAR_SCENE]);
281             av_dict_set(&frame->metadata, "lavfi.scene_score", buf, 0);
282         }
283 #endif
284         break;
285     }
286
287     res = av_expr_eval(select->expr, select->var_values, NULL);
288     av_log(inlink->dst, AV_LOG_DEBUG,
289            "n:%f pts:%f t:%f key:%d",
290            select->var_values[VAR_N],
291            select->var_values[VAR_PTS],
292            select->var_values[VAR_T],
293            (int)select->var_values[VAR_KEY]);
294
295     switch (inlink->type) {
296     case AVMEDIA_TYPE_VIDEO:
297         av_log(inlink->dst, AV_LOG_DEBUG, " interlace_type:%c pict_type:%c scene:%f",
298                select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_P ? 'P' :
299                select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_T ? 'T' :
300                select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_B ? 'B' : '?',
301                av_get_picture_type_char(select->var_values[VAR_PICT_TYPE]),
302                select->var_values[VAR_SCENE]);
303         break;
304     case AVMEDIA_TYPE_AUDIO:
305         av_log(inlink->dst, AV_LOG_DEBUG, " samples_n:%d consumed_samples_n:%d",
306                (int)select->var_values[VAR_SAMPLES_N],
307                (int)select->var_values[VAR_CONSUMED_SAMPLES_N]);
308         break;
309     }
310
311     av_log(inlink->dst, AV_LOG_DEBUG, " -> select:%f\n", res);
312
313     if (res) {
314         select->var_values[VAR_PREV_SELECTED_N]   = select->var_values[VAR_N];
315         select->var_values[VAR_PREV_SELECTED_PTS] = select->var_values[VAR_PTS];
316         select->var_values[VAR_PREV_SELECTED_T]   = select->var_values[VAR_T];
317         select->var_values[VAR_SELECTED_N] += 1.0;
318         if (inlink->type == AVMEDIA_TYPE_AUDIO)
319             select->var_values[VAR_CONSUMED_SAMPLES_N] += frame->nb_samples;
320     }
321
322     select->var_values[VAR_N] += 1.0;
323     select->var_values[VAR_PREV_PTS] = select->var_values[VAR_PTS];
324     select->var_values[VAR_PREV_T]   = select->var_values[VAR_T];
325
326     return res;
327 }
328
329 static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
330 {
331     SelectContext *select = inlink->dst->priv;
332
333     select->select = select_frame(inlink->dst, frame);
334     if (select->select)
335         return ff_filter_frame(inlink->dst->outputs[0], frame);
336
337     av_frame_free(&frame);
338     return 0;
339 }
340
341 static int request_frame(AVFilterLink *outlink)
342 {
343     AVFilterContext *ctx = outlink->src;
344     SelectContext *select = ctx->priv;
345     AVFilterLink *inlink = outlink->src->inputs[0];
346     select->select = 0;
347
348     do {
349         int ret = ff_request_frame(inlink);
350         if (ret < 0)
351             return ret;
352     } while (!select->select);
353
354     return 0;
355 }
356
357 static av_cold void uninit(AVFilterContext *ctx)
358 {
359     SelectContext *select = ctx->priv;
360
361     av_expr_free(select->expr);
362     select->expr = NULL;
363
364 #if CONFIG_AVCODEC
365     if (select->do_scene_detect) {
366         av_frame_free(&select->prev_picref);
367         if (select->avctx) {
368             avcodec_close(select->avctx);
369             av_freep(&select->avctx);
370         }
371     }
372 #endif
373 }
374
375 static int query_formats(AVFilterContext *ctx)
376 {
377     SelectContext *select = ctx->priv;
378
379     if (!select->do_scene_detect) {
380         return ff_default_query_formats(ctx);
381     } else {
382         static const enum AVPixelFormat pix_fmts[] = {
383             AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
384             AV_PIX_FMT_NONE
385         };
386         ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
387     }
388     return 0;
389 }
390
391 static const char *const shorthand[] = { "expr", NULL };
392
393 #if CONFIG_ASELECT_FILTER
394
395 #define OFFSET(x) offsetof(SelectContext, x)
396 #define AFLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
397 static const AVOption aselect_options[] = {
398     { "expr", "An expression to use for selecting frames", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = AFLAGS },
399     { "e",    "An expression to use for selecting frames", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = AFLAGS },
400     { NULL },
401 };
402 AVFILTER_DEFINE_CLASS(aselect);
403
404 static av_cold int aselect_init(AVFilterContext *ctx, const char *args)
405 {
406     SelectContext *select = ctx->priv;
407     int ret;
408
409     if ((ret = init(ctx, args, &aselect_class)) < 0)
410         return ret;
411
412     if (select->do_scene_detect) {
413         av_log(ctx, AV_LOG_ERROR, "Scene detection is ignored in aselect filter\n");
414         return AVERROR(EINVAL);
415     }
416
417     return 0;
418 }
419
420 static const AVFilterPad avfilter_af_aselect_inputs[] = {
421     {
422         .name             = "default",
423         .type             = AVMEDIA_TYPE_AUDIO,
424         .get_audio_buffer = ff_null_get_audio_buffer,
425         .config_props     = config_input,
426         .filter_frame     = filter_frame,
427     },
428     { NULL }
429 };
430
431 static const AVFilterPad avfilter_af_aselect_outputs[] = {
432     {
433         .name = "default",
434         .type = AVMEDIA_TYPE_AUDIO,
435     },
436     { NULL }
437 };
438
439 AVFilter avfilter_af_aselect = {
440     .name      = "aselect",
441     .description = NULL_IF_CONFIG_SMALL("Select audio frames to pass in output."),
442     .init      = aselect_init,
443     .uninit    = uninit,
444     .priv_size = sizeof(SelectContext),
445     .inputs    = avfilter_af_aselect_inputs,
446     .outputs   = avfilter_af_aselect_outputs,
447     .priv_class = &aselect_class,
448     .shorthand  = shorthand,
449 };
450 #endif /* CONFIG_ASELECT_FILTER */
451
452 #if CONFIG_SELECT_FILTER
453
454 #define OFFSET(x) offsetof(SelectContext, x)
455 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM
456 static const AVOption select_options[] = {
457     { "expr", "An expression to use for selecting frames", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS },
458     { "e",    "An expression to use for selecting frames", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS },
459     { NULL },
460 };
461
462 AVFILTER_DEFINE_CLASS(select);
463
464 static av_cold int select_init(AVFilterContext *ctx, const char *args)
465 {
466     SelectContext *select = ctx->priv;
467     int ret;
468
469     if ((ret = init(ctx, args, &select_class)) < 0)
470         return ret;
471
472     if (select->do_scene_detect && !CONFIG_AVCODEC) {
473         av_log(ctx, AV_LOG_ERROR, "Scene detection is not available without libavcodec.\n");
474         return AVERROR(EINVAL);
475     }
476
477     return 0;
478 }
479
480 static const AVFilterPad avfilter_vf_select_inputs[] = {
481     {
482         .name             = "default",
483         .type             = AVMEDIA_TYPE_VIDEO,
484         .get_video_buffer = ff_null_get_video_buffer,
485         .config_props     = config_input,
486         .filter_frame     = filter_frame,
487     },
488     { NULL }
489 };
490
491 static const AVFilterPad avfilter_vf_select_outputs[] = {
492     {
493         .name          = "default",
494         .type          = AVMEDIA_TYPE_VIDEO,
495         .request_frame = request_frame,
496     },
497     { NULL }
498 };
499
500 AVFilter avfilter_vf_select = {
501     .name      = "select",
502     .description = NULL_IF_CONFIG_SMALL("Select video frames to pass in output."),
503     .init      = select_init,
504     .uninit    = uninit,
505     .query_formats = query_formats,
506
507     .priv_size = sizeof(SelectContext),
508     .priv_class = &select_class,
509
510     .inputs    = avfilter_vf_select_inputs,
511     .outputs   = avfilter_vf_select_outputs,
512 };
513 #endif /* CONFIG_SELECT_FILTER */