| 
																	
																	
																	
																 | 
																@@ -0,0 +1,243 @@ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																/* | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * Copyright (c) 2011 Smartjog S.A.S, Clément Bœsch <clement.boesch@smartjog.com> | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * This file is part of FFmpeg. | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * FFmpeg is free software; you can redistribute it and/or | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * modify it under the terms of the GNU Lesser General Public | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * License as published by the Free Software Foundation; either | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * version 2.1 of the License, or (at your option) any later version. | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * FFmpeg is distributed in the hope that it will be useful, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * Lesser General Public License for more details. | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * You should have received a copy of the GNU Lesser General Public | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * License along with FFmpeg; if not, write to the Free Software | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 */ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																/** | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * @file | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * Potential thumbnail lookup filter to reduce the risk of an inappropriate | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * selection (such as a black frame) we could get with an absolute seek. | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * Simplified version of algorithm by Vadim Zaliva <lord@crocodile.org>. | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * @url http://notbrainsurgery.livejournal.com/29773.html | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 */ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																#include "avfilter.h" | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																#define HIST_SIZE (3*256) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																struct thumb_frame { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    AVFilterBufferRef *buf;     ///< cached frame | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    int histogram[HIST_SIZE];   ///< RGB color distribution histogram of the frame | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																}; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																typedef struct { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    int n;                      ///< current frame | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    int n_frames;               ///< number of frames for analysis | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    struct thumb_frame *frames; ///< the n_frames frames | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																} ThumbContext; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																{ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    ThumbContext *thumb = ctx->priv; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    if (!args) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        thumb->n_frames = 100; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    } else { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        int n = sscanf(args, "%d", &thumb->n_frames); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        if (n != 1 || thumb->n_frames < 2) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            thumb->n_frames = 0; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            av_log(ctx, AV_LOG_ERROR, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																                   "Invalid number of frames specified (minimum is 2).\n"); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            return AVERROR(ENOMEM); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    thumb->frames = av_calloc(thumb->n_frames, sizeof(*thumb->frames)); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    if (!thumb->frames) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        av_log(ctx, AV_LOG_ERROR, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																               "Allocation failure, try to lower the number of frames\n"); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        return AVERROR(ENOMEM); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    av_log(ctx, AV_LOG_INFO, "batch size: %d frames\n", thumb->n_frames); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    return 0; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																{ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    int i, j; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    AVFilterContext *ctx = inlink->dst; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    ThumbContext *thumb = ctx->priv; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    int *hist = thumb->frames[thumb->n].histogram; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    AVFilterBufferRef *picref = inlink->cur_buf; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    const uint8_t *p = picref->data[0] + y * picref->linesize[0]; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    // update current frame RGB histogram | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    for (j = 0; j < h; j++) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        for (i = 0; i < inlink->w; i++) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            hist[0*256 + p[i*3    ]]++; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            hist[1*256 + p[i*3 + 1]]++; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            hist[2*256 + p[i*3 + 2]]++; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        p += picref->linesize[0]; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																/** | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * @brief        Compute Sum-square deviation to estimate "closeness". | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * @param hist   color distribution histogram | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * @param median average color distribution histogram | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 * @return       sum of squared errors | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																 */ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																static double frame_sum_square_err(const int *hist, const double *median) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																{ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    int i; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    double err, sum_sq_err = 0; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    for (i = 0; i < HIST_SIZE; i++) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        err = median[i] - (double)hist[i]; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        sum_sq_err += err*err; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    return sum_sq_err; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																static void end_frame(AVFilterLink *inlink) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																{ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    int i, j, best_frame_idx = 0; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    double avg_hist[HIST_SIZE] = {0}, sq_err, min_sq_err = -1; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    AVFilterLink *outlink = inlink->dst->outputs[0]; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    ThumbContext *thumb   = inlink->dst->priv; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    AVFilterContext *ctx  = inlink->dst; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    AVFilterBufferRef *picref; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    // keep a reference of each frame | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    thumb->frames[thumb->n].buf = inlink->cur_buf; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    // no selection until the buffer of N frames is filled up | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    if (thumb->n < thumb->n_frames - 1) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        thumb->n++; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        return; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    // average histogram of the N frames | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    for (j = 0; j < FF_ARRAY_ELEMS(avg_hist); j++) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        for (i = 0; i < thumb->n_frames; i++) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            avg_hist[j] += (double)thumb->frames[i].histogram[j]; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        avg_hist[j] /= thumb->n_frames; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    // find the frame closer to the average using the sum of squared errors | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    for (i = 0; i < thumb->n_frames; i++) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        sq_err = frame_sum_square_err(thumb->frames[i].histogram, avg_hist); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        if (i == 0 || sq_err < min_sq_err) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            best_frame_idx = i, min_sq_err = sq_err; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    // free and reset everything (except the best frame buffer) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    for (i = 0; i < thumb->n_frames; i++) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        memset(thumb->frames[i].histogram, 0, sizeof(thumb->frames[i].histogram)); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        if (i == best_frame_idx) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            continue; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        avfilter_unref_buffer(thumb->frames[i].buf); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        thumb->frames[i].buf = NULL; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    thumb->n = 0; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    // raise the chosen one | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    picref = thumb->frames[best_frame_idx].buf; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    av_log(ctx, AV_LOG_INFO, "frame id #%d (pts_time=%f) selected\n", | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																           best_frame_idx, picref->pts * av_q2d(inlink->time_base)); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    avfilter_start_frame(outlink, picref); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    thumb->frames[best_frame_idx].buf = NULL; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    avfilter_draw_slice(outlink, 0, inlink->h, 1); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    avfilter_end_frame(outlink); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																static av_cold void uninit(AVFilterContext *ctx) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																{ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    int i; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    ThumbContext *thumb = ctx->priv; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    for (i = 0; i < thumb->n_frames && thumb->frames[i].buf; i++) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        avfilter_unref_buffer(thumb->frames[i].buf); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        thumb->frames[i].buf = NULL; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    av_freep(&thumb->frames); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																static void null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) { } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																static int request_frame(AVFilterLink *link) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																{ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    ThumbContext *thumb = link->src->priv; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    /* loop until a frame thumbnail is available (when a frame is queued, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																     * thumb->n is reset to zero) */ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    while (thumb->n) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        int ret = avfilter_request_frame(link->src->inputs[0]); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        if (ret < 0) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            return ret; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    return 0; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																static int poll_frame(AVFilterLink *link) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																{ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    ThumbContext *thumb  = link->src->priv; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    AVFilterLink *inlink = link->src->inputs[0]; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    int ret, available_frames = avfilter_poll_frame(inlink); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    /* If the input link is not able to provide any frame, we can't do anything | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																     * at the moment and thus have zero thumbnail available. */ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    if (!available_frames) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        return 0; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    /* Since at least one frame is available and the next frame will allow us | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																     * to compute a thumbnail, we can return 1 frame. */ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    if (thumb->n == thumb->n_frames - 1) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        return 1; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    /* we have some frame(s) available in the input link, but not yet enough to | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																     * output a thumbnail, so we request more */ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    ret = avfilter_request_frame(inlink); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    return ret < 0 ? ret : 0; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																static int query_formats(AVFilterContext *ctx) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																{ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    static const enum PixelFormat pix_fmts[] = { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        PIX_FMT_RGB24, PIX_FMT_BGR24, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        PIX_FMT_NONE | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    }; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    return 0; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
  | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																AVFilter avfilter_vf_thumbnail = { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    .name          = "thumbnail", | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    .description   = NULL_IF_CONFIG_SMALL("Select the most representative frame in a given sequence of consecutive frames."), | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    .priv_size     = sizeof(ThumbContext), | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    .init          = init, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    .uninit        = uninit, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    .query_formats = query_formats, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    .inputs        = (const AVFilterPad[]) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        {   .name             = "default", | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            .type             = AVMEDIA_TYPE_VIDEO, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            .get_video_buffer = avfilter_null_get_video_buffer, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            .start_frame      = null_start_frame, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            .draw_slice       = draw_slice, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            .end_frame        = end_frame, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        },{ .name = NULL } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    }, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    .outputs       = (const AVFilterPad[]) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        {   .name             = "default", | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            .type             = AVMEDIA_TYPE_VIDEO, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            .request_frame    = request_frame, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            .poll_frame       = poll_frame, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																            .rej_perms        = AV_PERM_REUSE2, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																        },{ .name = NULL } | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																    }, | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																}; |