00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "libavutil/eval.h"
00027 #include "libavutil/fifo.h"
00028 #include "libavutil/internal.h"
00029 #include "avfilter.h"
00030 #include "formats.h"
00031 #include "internal.h"
00032 #include "video.h"
00033
00034 #if CONFIG_AVCODEC
00035 #include "libavcodec/dsputil.h"
00036 #endif
00037
00038 static const char *const var_names[] = {
00039 "TB",
00040
00041 "pts",
00042 "start_pts",
00043 "prev_pts",
00044 "prev_selected_pts",
00045
00046 "t",
00047 "start_t",
00048 "prev_t",
00049 "prev_selected_t",
00050
00051 "pict_type",
00052 "I",
00053 "P",
00054 "B",
00055 "S",
00056 "SI",
00057 "SP",
00058 "BI",
00059
00060 "interlace_type",
00061 "PROGRESSIVE",
00062 "TOPFIRST",
00063 "BOTTOMFIRST",
00064
00065 "n",
00066 "selected_n",
00067 "prev_selected_n",
00068
00069 "key",
00070 "pos",
00071
00072 "scene",
00073
00074 NULL
00075 };
00076
00077 enum var_name {
00078 VAR_TB,
00079
00080 VAR_PTS,
00081 VAR_START_PTS,
00082 VAR_PREV_PTS,
00083 VAR_PREV_SELECTED_PTS,
00084
00085 VAR_T,
00086 VAR_START_T,
00087 VAR_PREV_T,
00088 VAR_PREV_SELECTED_T,
00089
00090 VAR_PICT_TYPE,
00091 VAR_PICT_TYPE_I,
00092 VAR_PICT_TYPE_P,
00093 VAR_PICT_TYPE_B,
00094 VAR_PICT_TYPE_S,
00095 VAR_PICT_TYPE_SI,
00096 VAR_PICT_TYPE_SP,
00097 VAR_PICT_TYPE_BI,
00098
00099 VAR_INTERLACE_TYPE,
00100 VAR_INTERLACE_TYPE_P,
00101 VAR_INTERLACE_TYPE_T,
00102 VAR_INTERLACE_TYPE_B,
00103
00104 VAR_N,
00105 VAR_SELECTED_N,
00106 VAR_PREV_SELECTED_N,
00107
00108 VAR_KEY,
00109 VAR_POS,
00110
00111 VAR_SCENE,
00112
00113 VAR_VARS_NB
00114 };
00115
00116 #define FIFO_SIZE 8
00117
00118 typedef struct {
00119 AVExpr *expr;
00120 double var_values[VAR_VARS_NB];
00121 int do_scene_detect;
00122 #if CONFIG_AVCODEC
00123 AVCodecContext *avctx;
00124 DSPContext c;
00125 double prev_mafd;
00126 #endif
00127 AVFilterBufferRef *prev_picref;
00128 double select;
00129 int cache_frames;
00130 AVFifoBuffer *pending_frames;
00131 } SelectContext;
00132
00133 static av_cold int init(AVFilterContext *ctx, const char *args)
00134 {
00135 SelectContext *select = ctx->priv;
00136 int ret;
00137
00138 if ((ret = av_expr_parse(&select->expr, args ? args : "1",
00139 var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
00140 av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", args);
00141 return ret;
00142 }
00143
00144 select->pending_frames = av_fifo_alloc(FIFO_SIZE*sizeof(AVFilterBufferRef*));
00145 if (!select->pending_frames) {
00146 av_log(ctx, AV_LOG_ERROR, "Failed to allocate pending frames buffer.\n");
00147 return AVERROR(ENOMEM);
00148 }
00149
00150 select->do_scene_detect = args && strstr(args, "scene");
00151 if (select->do_scene_detect && !CONFIG_AVCODEC) {
00152 av_log(ctx, AV_LOG_ERROR, "Scene detection is not available without libavcodec.\n");
00153 return AVERROR(EINVAL);
00154 }
00155 return 0;
00156 }
00157
00158 #define INTERLACE_TYPE_P 0
00159 #define INTERLACE_TYPE_T 1
00160 #define INTERLACE_TYPE_B 2
00161
00162 static int config_input(AVFilterLink *inlink)
00163 {
00164 SelectContext *select = inlink->dst->priv;
00165
00166 select->var_values[VAR_N] = 0.0;
00167 select->var_values[VAR_SELECTED_N] = 0.0;
00168
00169 select->var_values[VAR_TB] = av_q2d(inlink->time_base);
00170
00171 select->var_values[VAR_PREV_PTS] = NAN;
00172 select->var_values[VAR_PREV_SELECTED_PTS] = NAN;
00173 select->var_values[VAR_PREV_SELECTED_T] = NAN;
00174 select->var_values[VAR_START_PTS] = NAN;
00175 select->var_values[VAR_START_T] = NAN;
00176
00177 select->var_values[VAR_PICT_TYPE_I] = AV_PICTURE_TYPE_I;
00178 select->var_values[VAR_PICT_TYPE_P] = AV_PICTURE_TYPE_P;
00179 select->var_values[VAR_PICT_TYPE_B] = AV_PICTURE_TYPE_B;
00180 select->var_values[VAR_PICT_TYPE_SI] = AV_PICTURE_TYPE_SI;
00181 select->var_values[VAR_PICT_TYPE_SP] = AV_PICTURE_TYPE_SP;
00182
00183 select->var_values[VAR_INTERLACE_TYPE_P] = INTERLACE_TYPE_P;
00184 select->var_values[VAR_INTERLACE_TYPE_T] = INTERLACE_TYPE_T;
00185 select->var_values[VAR_INTERLACE_TYPE_B] = INTERLACE_TYPE_B;
00186
00187 if (CONFIG_AVCODEC && select->do_scene_detect) {
00188 select->avctx = avcodec_alloc_context3(NULL);
00189 if (!select->avctx)
00190 return AVERROR(ENOMEM);
00191 dsputil_init(&select->c, select->avctx);
00192 }
00193 return 0;
00194 }
00195
00196 #if CONFIG_AVCODEC
00197 static double get_scene_score(AVFilterContext *ctx, AVFilterBufferRef *picref)
00198 {
00199 double ret = 0;
00200 SelectContext *select = ctx->priv;
00201 AVFilterBufferRef *prev_picref = select->prev_picref;
00202
00203 if (prev_picref &&
00204 picref->video->h == prev_picref->video->h &&
00205 picref->video->w == prev_picref->video->w &&
00206 picref->linesize[0] == prev_picref->linesize[0]) {
00207 int x, y, nb_sad = 0;
00208 int64_t sad = 0;
00209 double mafd, diff;
00210 uint8_t *p1 = picref->data[0];
00211 uint8_t *p2 = prev_picref->data[0];
00212 const int linesize = picref->linesize[0];
00213
00214 for (y = 0; y < picref->video->h - 8; y += 8) {
00215 for (x = 0; x < picref->video->w*3 - 8; x += 8) {
00216 sad += select->c.sad[1](select, p1 + x, p2 + x,
00217 linesize, 8);
00218 nb_sad += 8 * 8;
00219 }
00220 p1 += 8 * linesize;
00221 p2 += 8 * linesize;
00222 }
00223 emms_c();
00224 mafd = nb_sad ? sad / nb_sad : 0;
00225 diff = fabs(mafd - select->prev_mafd);
00226 ret = av_clipf(FFMIN(mafd, diff) / 100., 0, 1);
00227 select->prev_mafd = mafd;
00228 avfilter_unref_buffer(prev_picref);
00229 }
00230 select->prev_picref = avfilter_ref_buffer(picref, ~0);
00231 return ret;
00232 }
00233 #endif
00234
00235 #define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
00236 #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
00237
00238 static int select_frame(AVFilterContext *ctx, AVFilterBufferRef *picref)
00239 {
00240 SelectContext *select = ctx->priv;
00241 AVFilterLink *inlink = ctx->inputs[0];
00242 double res;
00243
00244 if (CONFIG_AVCODEC && select->do_scene_detect) {
00245 char buf[32];
00246 select->var_values[VAR_SCENE] = get_scene_score(ctx, picref);
00247
00248 snprintf(buf, sizeof(buf), "%f", select->var_values[VAR_SCENE]);
00249 av_dict_set(&picref->metadata, "lavfi.scene_score", buf, 0);
00250 }
00251 if (isnan(select->var_values[VAR_START_PTS]))
00252 select->var_values[VAR_START_PTS] = TS2D(picref->pts);
00253 if (isnan(select->var_values[VAR_START_T]))
00254 select->var_values[VAR_START_T] = TS2D(picref->pts) * av_q2d(inlink->time_base);
00255
00256 select->var_values[VAR_PTS] = TS2D(picref->pts);
00257 select->var_values[VAR_T ] = TS2D(picref->pts) * av_q2d(inlink->time_base);
00258 select->var_values[VAR_POS] = picref->pos == -1 ? NAN : picref->pos;
00259 select->var_values[VAR_PREV_PTS] = TS2D(picref ->pts);
00260
00261 select->var_values[VAR_INTERLACE_TYPE] =
00262 !picref->video->interlaced ? INTERLACE_TYPE_P :
00263 picref->video->top_field_first ? INTERLACE_TYPE_T : INTERLACE_TYPE_B;
00264 select->var_values[VAR_PICT_TYPE] = picref->video->pict_type;
00265
00266 res = av_expr_eval(select->expr, select->var_values, NULL);
00267 av_log(inlink->dst, AV_LOG_DEBUG,
00268 "n:%d pts:%d t:%f pos:%d interlace_type:%c key:%d pict_type:%c "
00269 "-> select:%f\n",
00270 (int)select->var_values[VAR_N],
00271 (int)select->var_values[VAR_PTS],
00272 select->var_values[VAR_T],
00273 (int)select->var_values[VAR_POS],
00274 select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_P ? 'P' :
00275 select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_T ? 'T' :
00276 select->var_values[VAR_INTERLACE_TYPE] == INTERLACE_TYPE_B ? 'B' : '?',
00277 (int)select->var_values[VAR_KEY],
00278 av_get_picture_type_char(select->var_values[VAR_PICT_TYPE]),
00279 res);
00280
00281 select->var_values[VAR_N] += 1.0;
00282
00283 if (res) {
00284 select->var_values[VAR_PREV_SELECTED_N] = select->var_values[VAR_N];
00285 select->var_values[VAR_PREV_SELECTED_PTS] = select->var_values[VAR_PTS];
00286 select->var_values[VAR_PREV_SELECTED_T] = select->var_values[VAR_T];
00287 select->var_values[VAR_SELECTED_N] += 1.0;
00288 }
00289 return res;
00290 }
00291
00292 static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
00293 {
00294 SelectContext *select = inlink->dst->priv;
00295
00296 select->select = select_frame(inlink->dst, frame);
00297 if (select->select) {
00298
00299 if (select->cache_frames) {
00300 if (!av_fifo_space(select->pending_frames)) {
00301 av_log(inlink->dst, AV_LOG_ERROR,
00302 "Buffering limit reached, cannot cache more frames\n");
00303 avfilter_unref_bufferp(&frame);
00304 } else
00305 av_fifo_generic_write(select->pending_frames, &frame,
00306 sizeof(frame), NULL);
00307 return 0;
00308 }
00309 return ff_filter_frame(inlink->dst->outputs[0], frame);
00310 }
00311
00312 avfilter_unref_bufferp(&frame);
00313 return 0;
00314 }
00315
00316 static int request_frame(AVFilterLink *outlink)
00317 {
00318 AVFilterContext *ctx = outlink->src;
00319 SelectContext *select = ctx->priv;
00320 AVFilterLink *inlink = outlink->src->inputs[0];
00321 select->select = 0;
00322
00323 if (av_fifo_size(select->pending_frames)) {
00324 AVFilterBufferRef *picref;
00325
00326 av_fifo_generic_read(select->pending_frames, &picref, sizeof(picref), NULL);
00327 return ff_filter_frame(outlink, picref);
00328 }
00329
00330 while (!select->select) {
00331 int ret = ff_request_frame(inlink);
00332 if (ret < 0)
00333 return ret;
00334 }
00335
00336 return 0;
00337 }
00338
00339 static int poll_frame(AVFilterLink *outlink)
00340 {
00341 SelectContext *select = outlink->src->priv;
00342 AVFilterLink *inlink = outlink->src->inputs[0];
00343 int count, ret;
00344
00345 if (!av_fifo_size(select->pending_frames)) {
00346 if ((count = ff_poll_frame(inlink)) <= 0)
00347 return count;
00348
00349 select->cache_frames = 1;
00350 while (count-- && av_fifo_space(select->pending_frames)) {
00351 ret = ff_request_frame(inlink);
00352 if (ret < 0)
00353 break;
00354 }
00355 select->cache_frames = 0;
00356 }
00357
00358 return av_fifo_size(select->pending_frames)/sizeof(AVFilterBufferRef *);
00359 }
00360
00361 static av_cold void uninit(AVFilterContext *ctx)
00362 {
00363 SelectContext *select = ctx->priv;
00364 AVFilterBufferRef *picref;
00365
00366 av_expr_free(select->expr);
00367 select->expr = NULL;
00368
00369 while (select->pending_frames &&
00370 av_fifo_generic_read(select->pending_frames, &picref, sizeof(picref), NULL) == sizeof(picref))
00371 avfilter_unref_buffer(picref);
00372 av_fifo_free(select->pending_frames);
00373 select->pending_frames = NULL;
00374
00375 if (select->do_scene_detect) {
00376 avfilter_unref_bufferp(&select->prev_picref);
00377 if (select->avctx) {
00378 avcodec_close(select->avctx);
00379 av_freep(&select->avctx);
00380 }
00381 }
00382 }
00383
00384 static int query_formats(AVFilterContext *ctx)
00385 {
00386 SelectContext *select = ctx->priv;
00387
00388 if (!select->do_scene_detect) {
00389 return ff_default_query_formats(ctx);
00390 } else {
00391 static const enum AVPixelFormat pix_fmts[] = {
00392 AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
00393 AV_PIX_FMT_NONE
00394 };
00395 ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
00396 }
00397 return 0;
00398 }
00399
00400 static const AVFilterPad avfilter_vf_select_inputs[] = {
00401 {
00402 .name = "default",
00403 .type = AVMEDIA_TYPE_VIDEO,
00404 .get_video_buffer = ff_null_get_video_buffer,
00405 .min_perms = AV_PERM_PRESERVE,
00406 .config_props = config_input,
00407 .filter_frame = filter_frame,
00408 },
00409 { NULL }
00410 };
00411
00412 static const AVFilterPad avfilter_vf_select_outputs[] = {
00413 {
00414 .name = "default",
00415 .type = AVMEDIA_TYPE_VIDEO,
00416 .poll_frame = poll_frame,
00417 .request_frame = request_frame,
00418 },
00419 { NULL }
00420 };
00421
00422 AVFilter avfilter_vf_select = {
00423 .name = "select",
00424 .description = NULL_IF_CONFIG_SMALL("Select frames to pass in output."),
00425 .init = init,
00426 .uninit = uninit,
00427 .query_formats = query_formats,
00428
00429 .priv_size = sizeof(SelectContext),
00430
00431 .inputs = avfilter_vf_select_inputs,
00432 .outputs = avfilter_vf_select_outputs,
00433 };