annotate ffmpeg/libavfilter/f_select.c @ 13:844d341cf643 tip

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