... | ... |
@@ -3506,7 +3506,7 @@ scale='min(500\, iw*3/2):-1' |
3506 | 3506 |
@end example |
3507 | 3507 |
@end itemize |
3508 | 3508 |
|
3509 |
-@section select |
|
3509 |
+@section aselect, select |
|
3510 | 3510 |
Select frames to pass in output. |
3511 | 3511 |
|
3512 | 3512 |
It accepts in input an expression, which is evaluated for each input |
... | ... |
@@ -3551,7 +3551,7 @@ the PTS of the first video frame in the video, NAN if undefined |
3551 | 3551 |
@item start_t |
3552 | 3552 |
the time of the first video frame in the video, NAN if undefined |
3553 | 3553 |
|
3554 |
-@item pict_type |
|
3554 |
+@item pict_type @emph{(video only)} |
|
3555 | 3555 |
the type of the filtered frame, can assume one of the following |
3556 | 3556 |
values: |
3557 | 3557 |
@table @option |
... | ... |
@@ -3564,7 +3564,7 @@ values: |
3564 | 3564 |
@item BI |
3565 | 3565 |
@end table |
3566 | 3566 |
|
3567 |
-@item interlace_type |
|
3567 |
+@item interlace_type @emph{(video only)} |
|
3568 | 3568 |
the frame interlace type, can assume one of the following values: |
3569 | 3569 |
@table @option |
3570 | 3570 |
@item PROGRESSIVE |
... | ... |
@@ -3575,6 +3575,15 @@ the frame is top-field-first |
3575 | 3575 |
the frame is bottom-field-first |
3576 | 3576 |
@end table |
3577 | 3577 |
|
3578 |
+@item consumed_sample_n @emph{(audio only)} |
|
3579 |
+the number of selected samples before the current frame |
|
3580 |
+ |
|
3581 |
+@item samples_n @emph{(audio only)} |
|
3582 |
+the number of samples in the current frame |
|
3583 |
+ |
|
3584 |
+@item sample_rate @emph{(audio only)} |
|
3585 |
+the input sample rate |
|
3586 |
+ |
|
3578 | 3587 |
@item key |
3579 | 3588 |
1 if the filtered frame is a key-frame, 0 otherwise |
3580 | 3589 |
|
... | ... |
@@ -3582,7 +3591,7 @@ the frame is bottom-field-first |
3582 | 3582 |
the position in the file of the filtered frame, -1 if the information |
3583 | 3583 |
is not available (e.g. for synthetic video) |
3584 | 3584 |
|
3585 |
-@item scene |
|
3585 |
+@item scene @emph{(video only)} |
|
3586 | 3586 |
value between 0 and 1 to indicate a new scene; a low value reflects a low |
3587 | 3587 |
probability for the current frame to introduce a new scene, while a higher |
3588 | 3588 |
value means the current frame is more likely to be one (see the example below) |
... | ... |
@@ -3617,6 +3626,9 @@ select='gte(t\,10)*lte(t\,20)*eq(pict_type\,I)' |
3617 | 3617 |
|
3618 | 3618 |
# select frames with a minimum distance of 10 seconds |
3619 | 3619 |
select='isnan(prev_selected_t)+gte(t-prev_selected_t\,10)' |
3620 |
+ |
|
3621 |
+# use aselect to select only audio frames with samples number > 100 |
|
3622 |
+aselect='gt(samples_n\,100)' |
|
3620 | 3623 |
@end example |
3621 | 3624 |
|
3622 | 3625 |
Complete example to create a mosaic of the first scenes: |
... | ... |
@@ -54,6 +54,7 @@ OBJS-$(CONFIG_AMERGE_FILTER) += af_amerge.o |
54 | 54 |
OBJS-$(CONFIG_AMIX_FILTER) += af_amix.o |
55 | 55 |
OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o |
56 | 56 |
OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o |
57 |
+OBJS-$(CONFIG_ASELECT_FILTER) += vf_select.o |
|
57 | 58 |
OBJS-$(CONFIG_ASENDCMD_FILTER) += f_sendcmd.o |
58 | 59 |
OBJS-$(CONFIG_ASETNSAMPLES_FILTER) += af_asetnsamples.o |
59 | 60 |
OBJS-$(CONFIG_ASETPTS_FILTER) += f_setpts.o |
... | ... |
@@ -46,6 +46,7 @@ void avfilter_register_all(void) |
46 | 46 |
REGISTER_FILTER (AMIX, amix, af); |
47 | 47 |
REGISTER_FILTER (ANULL, anull, af); |
48 | 48 |
REGISTER_FILTER (ARESAMPLE, aresample, af); |
49 |
+ REGISTER_FILTER (ASELECT, aselect, af); |
|
49 | 50 |
REGISTER_FILTER (ASENDCMD, asendcmd, af); |
50 | 51 |
REGISTER_FILTER (ASETNSAMPLES, asetnsamples, af); |
51 | 52 |
REGISTER_FILTER (ASETPTS, asetpts, af); |
... | ... |
@@ -29,8 +29,8 @@ |
29 | 29 |
#include "libavutil/avutil.h" |
30 | 30 |
|
31 | 31 |
#define LIBAVFILTER_VERSION_MAJOR 3 |
32 |
-#define LIBAVFILTER_VERSION_MINOR 26 |
|
33 |
-#define LIBAVFILTER_VERSION_MICRO 102 |
|
32 |
+#define LIBAVFILTER_VERSION_MINOR 27 |
|
33 |
+#define LIBAVFILTER_VERSION_MICRO 100 |
|
34 | 34 |
|
35 | 35 |
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ |
36 | 36 |
LIBAVFILTER_VERSION_MINOR, \ |
... | ... |
@@ -27,6 +27,7 @@ |
27 | 27 |
#include "libavutil/fifo.h" |
28 | 28 |
#include "libavutil/internal.h" |
29 | 29 |
#include "avfilter.h" |
30 |
+#include "audio.h" |
|
30 | 31 |
#include "formats.h" |
31 | 32 |
#include "internal.h" |
32 | 33 |
#include "video.h" |
... | ... |
@@ -62,6 +63,10 @@ static const char *const var_names[] = { |
62 | 62 |
"TOPFIRST", |
63 | 63 |
"BOTTOMFIRST", |
64 | 64 |
|
65 |
+ "consumed_samples_n",///< number of samples consumed by the filter (only audio) |
|
66 |
+ "samples_n", ///< number of samples in the current frame (only audio) |
|
67 |
+ "sample_rate", ///< sample rate (only audio) |
|
68 |
+ |
|
65 | 69 |
"n", ///< frame number (starting from zero) |
66 | 70 |
"selected_n", ///< selected frame number (starting from zero) |
67 | 71 |
"prev_selected_n", ///< number of the last selected frame |
... | ... |
@@ -101,6 +106,10 @@ enum var_name { |
101 | 101 |
VAR_INTERLACE_TYPE_T, |
102 | 102 |
VAR_INTERLACE_TYPE_B, |
103 | 103 |
|
104 |
+ VAR_CONSUMED_SAMPLES_N, |
|
105 |
+ VAR_SAMPLES_N, |
|
106 |
+ VAR_SAMPLE_RATE, |
|
107 |
+ |
|
104 | 108 |
VAR_N, |
105 | 109 |
VAR_SELECTED_N, |
106 | 110 |
VAR_PREV_SELECTED_N, |
... | ... |
@@ -174,6 +183,9 @@ static int config_input(AVFilterLink *inlink) |
174 | 174 |
select->var_values[VAR_INTERLACE_TYPE_T] = INTERLACE_TYPE_T; |
175 | 175 |
select->var_values[VAR_INTERLACE_TYPE_B] = INTERLACE_TYPE_B; |
176 | 176 |
|
177 |
+ select->var_values[VAR_SAMPLE_RATE] = |
|
178 |
+ inlink->type == AVMEDIA_TYPE_AUDIO ? inlink->sample_rate : NAN; |
|
179 |
+ |
|
177 | 180 |
if (CONFIG_AVCODEC && select->do_scene_detect) { |
178 | 181 |
select->avctx = avcodec_alloc_context3(NULL); |
179 | 182 |
if (!select->avctx) |
... | ... |
@@ -231,13 +243,6 @@ static int select_frame(AVFilterContext *ctx, AVFilterBufferRef *picref) |
231 | 231 |
AVFilterLink *inlink = ctx->inputs[0]; |
232 | 232 |
double res; |
233 | 233 |
|
234 |
- if (CONFIG_AVCODEC && select->do_scene_detect) { |
|
235 |
- char buf[32]; |
|
236 |
- select->var_values[VAR_SCENE] = get_scene_score(ctx, picref); |
|
237 |
- // TODO: document metadata |
|
238 |
- snprintf(buf, sizeof(buf), "%f", select->var_values[VAR_SCENE]); |
|
239 |
- av_dict_set(&picref->metadata, "lavfi.scene_score", buf, 0); |
|
240 |
- } |
|
241 | 234 |
if (isnan(select->var_values[VAR_START_PTS])) |
242 | 235 |
select->var_values[VAR_START_PTS] = TS2D(picref->pts); |
243 | 236 |
if (isnan(select->var_values[VAR_START_T])) |
... | ... |
@@ -248,34 +253,63 @@ static int select_frame(AVFilterContext *ctx, AVFilterBufferRef *picref) |
248 | 248 |
select->var_values[VAR_POS] = picref->pos == -1 ? NAN : picref->pos; |
249 | 249 |
select->var_values[VAR_PREV_PTS] = TS2D(picref ->pts); |
250 | 250 |
|
251 |
- select->var_values[VAR_INTERLACE_TYPE] = |
|
252 |
- !picref->video->interlaced ? INTERLACE_TYPE_P : |
|
251 |
+ switch (inlink->type) { |
|
252 |
+ case AVMEDIA_TYPE_AUDIO: |
|
253 |
+ select->var_values[VAR_SAMPLES_N] = picref->audio->nb_samples; |
|
254 |
+ break; |
|
255 |
+ |
|
256 |
+ case AVMEDIA_TYPE_VIDEO: |
|
257 |
+ select->var_values[VAR_INTERLACE_TYPE] = |
|
258 |
+ !picref->video->interlaced ? INTERLACE_TYPE_P : |
|
253 | 259 |
picref->video->top_field_first ? INTERLACE_TYPE_T : INTERLACE_TYPE_B; |
254 |
- select->var_values[VAR_PICT_TYPE] = picref->video->pict_type; |
|
260 |
+ select->var_values[VAR_PICT_TYPE] = picref->video->pict_type; |
|
261 |
+ if (CONFIG_AVCODEC && select->do_scene_detect) { |
|
262 |
+ char buf[32]; |
|
263 |
+ select->var_values[VAR_SCENE] = get_scene_score(ctx, picref); |
|
264 |
+ // TODO: document metadata |
|
265 |
+ snprintf(buf, sizeof(buf), "%f", select->var_values[VAR_SCENE]); |
|
266 |
+ av_dict_set(&picref->metadata, "lavfi.scene_score", buf, 0); |
|
267 |
+ } |
|
268 |
+ break; |
|
269 |
+ } |
|
255 | 270 |
|
256 | 271 |
res = av_expr_eval(select->expr, select->var_values, NULL); |
257 | 272 |
av_log(inlink->dst, AV_LOG_DEBUG, |
258 |
- "n:%d pts:%d t:%f pos:%d interlace_type:%c key:%d pict_type:%c " |
|
259 |
- "-> select:%f\n", |
|
273 |
+ "n:%d pts:%d t:%f pos:%d key:%d", |
|
260 | 274 |
(int)select->var_values[VAR_N], |
261 | 275 |
(int)select->var_values[VAR_PTS], |
262 | 276 |
select->var_values[VAR_T], |
263 | 277 |
(int)select->var_values[VAR_POS], |
264 |
- select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_P ? 'P' : |
|
265 |
- select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_T ? 'T' : |
|
266 |
- select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_B ? 'B' : '?', |
|
267 |
- (int)select->var_values[VAR_KEY], |
|
268 |
- av_get_picture_type_char(select->var_values[VAR_PICT_TYPE]), |
|
269 |
- res); |
|
278 |
+ (int)select->var_values[VAR_KEY]); |
|
279 |
+ |
|
280 |
+ switch (inlink->type) { |
|
281 |
+ case AVMEDIA_TYPE_VIDEO: |
|
282 |
+ av_log(inlink->dst, AV_LOG_DEBUG, " interlace_type:%c pict_type:%c", |
|
283 |
+ select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_P ? 'P' : |
|
284 |
+ select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_T ? 'T' : |
|
285 |
+ select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_B ? 'B' : '?', |
|
286 |
+ av_get_picture_type_char(select->var_values[VAR_PICT_TYPE])); |
|
287 |
+ break; |
|
288 |
+ case AVMEDIA_TYPE_AUDIO: |
|
289 |
+ av_log(inlink->dst, AV_LOG_DEBUG, " samples_n:%d consumed_samples_n:%d", |
|
290 |
+ (int)select->var_values[VAR_SAMPLES_N], |
|
291 |
+ (int)select->var_values[VAR_CONSUMED_SAMPLES_N]); |
|
292 |
+ break; |
|
293 |
+ } |
|
270 | 294 |
|
271 |
- select->var_values[VAR_N] += 1.0; |
|
295 |
+ av_log(inlink->dst, AV_LOG_DEBUG, " -> select:%f\n", res); |
|
272 | 296 |
|
273 | 297 |
if (res) { |
274 | 298 |
select->var_values[VAR_PREV_SELECTED_N] = select->var_values[VAR_N]; |
275 | 299 |
select->var_values[VAR_PREV_SELECTED_PTS] = select->var_values[VAR_PTS]; |
276 | 300 |
select->var_values[VAR_PREV_SELECTED_T] = select->var_values[VAR_T]; |
277 | 301 |
select->var_values[VAR_SELECTED_N] += 1.0; |
302 |
+ if (inlink->type == AVMEDIA_TYPE_AUDIO) |
|
303 |
+ select->var_values[VAR_CONSUMED_SAMPLES_N] += picref->audio->nb_samples; |
|
278 | 304 |
} |
305 |
+ |
|
306 |
+ select->var_values[VAR_N] += 1.0; |
|
307 |
+ |
|
279 | 308 |
return res; |
280 | 309 |
} |
281 | 310 |
|
... | ... |
@@ -339,6 +373,38 @@ static int query_formats(AVFilterContext *ctx) |
339 | 339 |
return 0; |
340 | 340 |
} |
341 | 341 |
|
342 |
+#if CONFIG_ASELECT_FILTER |
|
343 |
+static const AVFilterPad avfilter_af_aselect_inputs[] = { |
|
344 |
+ { |
|
345 |
+ .name = "default", |
|
346 |
+ .type = AVMEDIA_TYPE_AUDIO, |
|
347 |
+ .get_audio_buffer = ff_null_get_audio_buffer, |
|
348 |
+ .config_props = config_input, |
|
349 |
+ .filter_frame = filter_frame, |
|
350 |
+ }, |
|
351 |
+ { NULL } |
|
352 |
+}; |
|
353 |
+ |
|
354 |
+static const AVFilterPad avfilter_af_aselect_outputs[] = { |
|
355 |
+ { |
|
356 |
+ .name = "default", |
|
357 |
+ .type = AVMEDIA_TYPE_AUDIO, |
|
358 |
+ }, |
|
359 |
+ { NULL } |
|
360 |
+}; |
|
361 |
+ |
|
362 |
+AVFilter avfilter_af_aselect = { |
|
363 |
+ .name = "aselect", |
|
364 |
+ .description = NULL_IF_CONFIG_SMALL("Select audio frames to pass in output."), |
|
365 |
+ .init = init, |
|
366 |
+ .uninit = uninit, |
|
367 |
+ .priv_size = sizeof(SelectContext), |
|
368 |
+ .inputs = avfilter_af_aselect_inputs, |
|
369 |
+ .outputs = avfilter_af_aselect_outputs, |
|
370 |
+}; |
|
371 |
+#endif /* CONFIG_ASELECT_FILTER */ |
|
372 |
+ |
|
373 |
+#if CONFIG_SELECT_FILTER |
|
342 | 374 |
static const AVFilterPad avfilter_vf_select_inputs[] = { |
343 | 375 |
{ |
344 | 376 |
.name = "default", |
... | ... |
@@ -362,7 +428,7 @@ static const AVFilterPad avfilter_vf_select_outputs[] = { |
362 | 362 |
|
363 | 363 |
AVFilter avfilter_vf_select = { |
364 | 364 |
.name = "select", |
365 |
- .description = NULL_IF_CONFIG_SMALL("Select frames to pass in output."), |
|
365 |
+ .description = NULL_IF_CONFIG_SMALL("Select video frames to pass in output."), |
|
366 | 366 |
.init = init, |
367 | 367 |
.uninit = uninit, |
368 | 368 |
.query_formats = query_formats, |
... | ... |
@@ -372,3 +438,4 @@ AVFilter avfilter_vf_select = { |
372 | 372 |
.inputs = avfilter_vf_select_inputs, |
373 | 373 |
.outputs = avfilter_vf_select_outputs, |
374 | 374 |
}; |
375 |
+#endif /* CONFIG_SELECT_FILTER */ |