X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_thumbnail.c;h=825e536e67a18ab0575e858a556dc94c94fa8e1f;hb=a04ad248a05e7b613abe09b3bb067f555108d794;hp=0effdc91e9a8b8f2ca3420d1fb7d62b41e210463;hpb=b4ca32414ea28ad29b4bd387c298f5a676dace2a;p=ffmpeg diff --git a/libavfilter/vf_thumbnail.c b/libavfilter/vf_thumbnail.c index 0effdc91e9a..825e536e67a 100644 --- a/libavfilter/vf_thumbnail.c +++ b/libavfilter/vf_thumbnail.c @@ -28,6 +28,7 @@ */ #include "libavutil/opt.h" +#include "libavutil/pixdesc.h" #include "avfilter.h" #include "internal.h" @@ -44,6 +45,9 @@ typedef struct ThumbContext { int n_frames; ///< number of frames for analysis struct thumb_frame *frames; ///< the n_frames frames AVRational tb; ///< copy of the input timebase to ease access + + int planewidth[4]; + int planeheight[4]; } ThumbContext; #define OFFSET(x) offsetof(ThumbContext, x) @@ -140,14 +144,55 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) // keep a reference of each frame s->frames[s->n].buf = frame; - // update current frame RGB histogram - for (j = 0; j < inlink->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]]++; + // update current frame histogram + switch (inlink->format) { + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_BGR24: + for (j = 0; j < inlink->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 += frame->linesize[0]; + } + break; + case AV_PIX_FMT_RGB0: + case AV_PIX_FMT_BGR0: + case AV_PIX_FMT_RGBA: + case AV_PIX_FMT_BGRA: + for (j = 0; j < inlink->h; j++) { + for (i = 0; i < inlink->w; i++) { + hist[0*256 + p[i*4 ]]++; + hist[1*256 + p[i*4 + 1]]++; + hist[2*256 + p[i*4 + 2]]++; + } + p += frame->linesize[0]; + } + break; + case AV_PIX_FMT_0RGB: + case AV_PIX_FMT_0BGR: + case AV_PIX_FMT_ARGB: + case AV_PIX_FMT_ABGR: + for (j = 0; j < inlink->h; j++) { + for (i = 0; i < inlink->w; i++) { + hist[0*256 + p[i*4 + 1]]++; + hist[1*256 + p[i*4 + 2]]++; + hist[2*256 + p[i*4 + 3]]++; + } + p += frame->linesize[0]; } - p += frame->linesize[0]; + break; + default: + for (int plane = 0; plane < 3; plane++) { + const uint8_t *p = frame->data[plane]; + for (j = 0; j < s->planeheight[plane]; j++) { + for (i = 0; i < s->planewidth[plane]; i++) + hist[256*plane + p[i]]++; + p += frame->linesize[plane]; + } + } + break; } // no selection until the buffer of N frames is filled up @@ -162,7 +207,7 @@ static av_cold void uninit(AVFilterContext *ctx) { int i; ThumbContext *s = ctx->priv; - for (i = 0; i < s->n_frames && s->frames[i].buf; i++) + for (i = 0; i < s->n_frames && s->frames && s->frames[i].buf; i++) av_frame_free(&s->frames[i].buf); av_freep(&s->frames); } @@ -188,8 +233,14 @@ static int config_props(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; ThumbContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); s->tb = inlink->time_base; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + return 0; } @@ -197,6 +248,18 @@ static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, + AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0, + AV_PIX_FMT_ABGR, AV_PIX_FMT_ARGB, + AV_PIX_FMT_0BGR, AV_PIX_FMT_0RGB, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE }; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); @@ -224,7 +287,7 @@ static const AVFilterPad thumbnail_outputs[] = { { NULL } }; -AVFilter ff_vf_thumbnail = { +const AVFilter ff_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), @@ -234,4 +297,5 @@ AVFilter ff_vf_thumbnail = { .inputs = thumbnail_inputs, .outputs = thumbnail_outputs, .priv_class = &thumbnail_class, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, };