35#define CHECK_CU(x) FF_CUDA_CHECK_DL(ctx, s->hwctx->internal->cuda_dl, x)
37#define HIST_SIZE (3*256)
38#define DIV_UP(a, b) ( ((a) + (b) - 1) / (b) )
81#define OFFSET(x) offsetof(ThumbnailCudaContext, x)
82#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
98 "Allocation failure, try to lower the number of frames\n");
114 double err, sum_sq_err = 0;
118 sum_sq_err += err*err;
127 int i, j, best_frame_idx = 0;
128 int nb_frames =
s->n;
129 double avg_hist[
HIST_SIZE] = {0}, sq_err, min_sq_err = -1;
133 for (
i = 0;
i < nb_frames;
i++)
134 avg_hist[j] += (
double)
s->frames[
i].histogram[j];
135 avg_hist[j] /= nb_frames;
139 for (
i = 0;
i < nb_frames;
i++) {
141 if (
i == 0 || sq_err < min_sq_err)
142 best_frame_idx =
i, min_sq_err = sq_err;
146 for (
i = 0;
i < nb_frames;
i++) {
147 memset(
s->frames[
i].histogram, 0,
sizeof(
s->frames[
i].histogram));
148 if (
i != best_frame_idx)
154 picref =
s->frames[best_frame_idx].buf;
156 "from a set of %d images\n", best_frame_idx,
158 s->frames[best_frame_idx].buf =
NULL;
164 int *
histogram, uint8_t *src_dptr,
int src_width,
int src_height,
int src_pitch,
int pixel_size)
168 CudaFunctions *cu =
s->hwctx->internal->cuda_dl;
170 void *args[] = { &tex, &
histogram, &src_width, &src_height };
172 CUDA_TEXTURE_DESC tex_desc = {
173 .filterMode = CU_TR_FILTER_MODE_LINEAR,
174 .flags = CU_TRSF_READ_AS_INTEGER,
177 CUDA_RESOURCE_DESC res_desc = {
178 .resType = CU_RESOURCE_TYPE_PITCH2D,
179 .res.pitch2D.format = pixel_size == 1 ?
180 CU_AD_FORMAT_UNSIGNED_INT8 :
181 CU_AD_FORMAT_UNSIGNED_INT16,
182 .res.pitch2D.numChannels =
channels,
183 .res.pitch2D.width = src_width,
184 .res.pitch2D.height = src_height,
185 .res.pitch2D.pitchInBytes = src_pitch,
186 .res.pitch2D.devPtr = (CUdeviceptr)src_dptr,
189 ret =
CHECK_CU(cu->cuTexObjectCreate(&tex, &res_desc, &tex_desc,
NULL));
198 CHECK_CU(cu->cuTexObjectDestroy(tex));
260 CudaFunctions *cu =
s->hwctx->internal->cuda_dl;
262 int *hist =
s->frames[
s->n].histogram;
265 CUDA_MEMCPY2D cpy = { 0 };
271 ret =
CHECK_CU(cu->cuCtxPushCurrent(
s->hwctx->cuda_ctx));
279 cpy.srcMemoryType = CU_MEMORYTYPE_DEVICE;
280 cpy.dstMemoryType = CU_MEMORYTYPE_HOST;
281 cpy.srcDevice =
s->data;
285 cpy.WidthInBytes =
HIST_SIZE *
sizeof(int);
288 ret =
CHECK_CU(cu->cuMemcpy2DAsync(&cpy,
s->cu_stream));
298 hist[
i] = 4 * hist[
i];
307 if (
s->n <
s->n_frames)
318 CudaFunctions *cu =
s->hwctx->internal->cuda_dl;
326 CHECK_CU(cu->cuModuleUnload(
s->cu_module));
332 for (
int i = 0;
i <
s->n_frames &&
s->frames[
i].buf;
i++)
377 extern const unsigned char ff_vf_thumbnail_cuda_ptx_data[];
378 extern const unsigned int ff_vf_thumbnail_cuda_ptx_len;
380 s->hwctx = device_hwctx;
381 s->cu_stream =
s->hwctx->stream;
383 ret =
CHECK_CU(cu->cuCtxPushCurrent(cuda_ctx));
387 ret =
ff_cuda_load_module(
ctx, device_hwctx, &
s->cu_module, ff_vf_thumbnail_cuda_ptx_data, ff_vf_thumbnail_cuda_ptx_len);
391 ret =
CHECK_CU(cu->cuModuleGetFunction(&
s->cu_func_uchar,
s->cu_module,
"Thumbnail_uchar"));
395 ret =
CHECK_CU(cu->cuModuleGetFunction(&
s->cu_func_uchar2,
s->cu_module,
"Thumbnail_uchar2"));
399 ret =
CHECK_CU(cu->cuModuleGetFunction(&
s->cu_func_ushort,
s->cu_module,
"Thumbnail_ushort"));
403 ret =
CHECK_CU(cu->cuModuleGetFunction(&
s->cu_func_ushort2,
s->cu_module,
"Thumbnail_ushort2"));
447 .p.name =
"thumbnail_cuda",
448 .p.description =
NULL_IF_CONFIG_SMALL(
"Select the most representative frame in a given sequence of consecutive frames using CUDA."),
449 .p.priv_class = &thumbnail_cuda_class,
static int request_frame(AVFilterLink *outlink)
const FFFilter ff_vf_thumbnail_cuda
static AVFormatContext * ctx
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
int(* init)(AVBSFContext *ctx)
@ AV_OPT_TYPE_INT
Underlying C type is int.
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
#define AVERROR_EOF
End of file.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static double av_q2d(AVRational a)
Convert an AVRational to a double.
FFmpeg internal API for CUDA.
static av_cold void uninit(AVBitStreamFilterContext *ctx)
int(* func)(AVBPrint *dst, const char *in, const char *arg)
#define FILTER_INPUTS(array)
#define FILTER_OUTPUTS(array)
#define FF_FILTER_FLAG_HWFRAME_AWARE
The filter is aware of hardware frames, and any hardware frame context should not be automatically pr...
static FilterLink * ff_filter_link(AVFilterLink *link)
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
#define AVFILTER_DEFINE_CLASS(fname)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
int ff_cuda_load_module(void *avctx, AVCUDADeviceContext *hwctx, CUmodule *cu_module, const unsigned char *data, const unsigned int length)
Loads a CUDA module and applies any decompression, if necessary.
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
#define AV_PIX_FMT_YUV444P12MSB
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
@ AV_PIX_FMT_P010LE
like NV12, with 10bpp per component, data in the high bits, zeros in the low bits,...
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
@ AV_PIX_FMT_P016LE
like NV12, with 16bpp per component, little-endian
@ AV_PIX_FMT_P012LE
like NV12, with 12bpp per component, data in the high bits, zeros in the low bits,...
@ AV_PIX_FMT_CUDA
HW acceleration through CUDA.
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
#define AV_PIX_FMT_YUV444P16
#define AV_PIX_FMT_YUV444P10MSB
#define FF_ARRAY_ELEMS(a)
static int config_props(AVBitStreamFilterLink *link)
A reference to a data buffer.
uint8_t * data
The data buffer.
This struct is allocated as AVHWDeviceContext.hwctx.
AVCUDADeviceContextInternal * internal
Describe the class of an AVClass context structure.
A link between two filters.
AVFilterContext * src
source filter
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link.
AVFilterContext * dst
dest filter
A filter pad used for either input or output.
This structure describes decoded (raw) audio or video data.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
This struct describes a set or pool of "hardware" frames (i.e.
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Rational number (pair of numerator and denominator).
Link properties exposed to filter code, but not external callers.
AVBufferRef * hw_frames_ctx
For hwaccel pixel formats, this should be a reference to the AVHWFramesContext describing the frames.
CUfunction cu_func_ushort2
CUfunction cu_func_ushort
AVRational tb
copy of the input timebase to ease access
AVCUDADeviceContext * hwctx
AVBufferRef * hw_frames_ctx
struct thumb_frame * frames
the n_frames frames
CUfunction cu_func_uchar2
int n_frames
number of frames for analysis
AVFrame * buf
cached frame
int histogram[HIST_SIZE]
RGB color distribution histogram of the frame.
static enum AVPixelFormat supported_formats[]
static AVFrame * get_best_frame(AVFilterContext *ctx)
static const AVFilterPad thumbnail_cuda_outputs[]
static const AVOption thumbnail_cuda_options[]
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
static int request_frame(AVFilterLink *link)
static int format_is_supported(enum AVPixelFormat fmt)
static int thumbnail(AVFilterContext *ctx, int *histogram, AVFrame *in)
static int thumbnail_kernel(AVFilterContext *ctx, CUfunction func, int channels, int *histogram, uint8_t *src_dptr, int src_width, int src_height, int src_pitch, int pixel_size)
static int config_props(AVFilterLink *inlink)
static av_cold void uninit(AVFilterContext *ctx)
static double frame_sum_square_err(const int *hist, const double *median)
Compute Sum-square deviation to estimate "closeness".
static const AVFilterPad thumbnail_cuda_inputs[]