76#define DIV_UP(a, b) ( ((a) + (b) - 1) / (b) )
80#define CHECK_CU(x) FF_CUDA_CHECK_DL(ctx, s->hwctx->internal->cuda_dl, x)
182 cu->cuMemFree(
filter->weights);
184 cu->cuMemFree(
filter->offsets);
192 cu->cuTexObjectDestroy(t->
tex[
i]);
194 cu->cuMemFree(t->
data[
i]);
197 memset(t, 0,
sizeof(*t));
205 CudaFunctions *cu =
s->hwctx->internal->cuda_dl;
208 CHECK_CU(cu->cuCtxPushCurrent(
s->hwctx->cuda_ctx));
217 CHECK_CU(cu->cuModuleUnload(
s->cu_module));
258 s->frames_ctx = out_ref;
269 CudaFunctions *cu =
s->hwctx->internal->cuda_dl;
276 .crop_width = out_width,
277 .crop_height = in_height,
278 .log2_chroma_w =
s->out_desc->log2_chroma_w,
279 .log2_chroma_h =
s->in_desc->log2_chroma_h,
282 for (
int i = 0;
i <
s->in_planes;
i++) {
283 const int is_chroma =
i == 1 ||
i == 2;
284 const int sub_x = is_chroma ?
s->inter_tex.log2_chroma_w : 0;
285 const int sub_y = is_chroma ?
s->inter_tex.log2_chroma_h : 0;
288 const int sizeof_pixel = (
s->in_plane_depths[
i] <= 8 ? 1 : 2) *
289 s->in_plane_channels[
i];
292 ret =
CHECK_CU(cu->cuMemAllocPitch(&
s->inter_tex.data[
i], &pitch,
293 (
size_t) plane_w * sizeof_pixel,
297 s->inter_tex.linesize[
i] = pitch;
299 CUDA_TEXTURE_DESC tex_desc = {
301 .filterMode = CU_TR_FILTER_MODE_POINT,
304 CUDA_RESOURCE_DESC res_desc = {
305 .resType = CU_RESOURCE_TYPE_PITCH2D,
306 .res.pitch2D.format =
s->in_plane_depths[
i] <= 8 ?
307 CU_AD_FORMAT_UNSIGNED_INT8 :
308 CU_AD_FORMAT_UNSIGNED_INT16,
309 .res.pitch2D.numChannels =
s->in_plane_channels[
i],
310 .res.pitch2D.devPtr =
s->inter_tex.data[
i],
311 .res.pitch2D.pitchInBytes = pitch,
312 .res.pitch2D.width = plane_w,
313 .res.pitch2D.height = plane_h,
316 ret =
CHECK_CU(cu->cuTexObjectCreate(&
s->inter_tex.tex[
i], &res_desc,
350 s->in_fmt = in_format;
351 s->out_fmt = out_format;
362 for (
i = 0;
i <
s->in_desc->nb_components;
i++) {
363 d = (
s->in_desc->comp[
i].depth + 7) / 8;
364 p =
s->in_desc->comp[
i].plane;
365 s->in_plane_channels[p] =
FFMAX(
s->in_plane_channels[p],
s->in_desc->comp[
i].step / d);
367 s->in_plane_depths[p] =
s->in_desc->comp[
i].depth;
372 int out_width,
int out_height)
406 if (
s->passthrough && in_width == out_width && in_height == out_height && in_format == out_format) {
417 if (in_width == out_width && in_height == out_height &&
423 }
else if (
s->use_filters < 0 && (out_width < in_width || out_height < in_height))
425 else if (
s->use_filters < 0)
439 CUcontext
dummy, cuda_ctx =
s->hwctx->cuda_ctx;
440 CudaFunctions *cu =
s->hwctx->internal->cuda_dl;
447 const char *function_infix =
"";
449 extern const unsigned char ff_vf_scale_cuda_ptx_data[];
450 extern const unsigned int ff_vf_scale_cuda_ptx_len;
452 if (
s->use_filters) {
456 function_infix = inlink->
h == outlink->
h ?
"Generic_h" :
"Generic_v";
457 s->interp_use_linear = 0;
458 s->interp_as_integer = 0;
460 switch(
s->interp_algo) {
462 function_infix =
"Nearest";
463 s->interp_use_linear = 0;
464 s->interp_as_integer = 1;
467 function_infix =
"Bilinear";
468 s->interp_use_linear = 1;
469 s->interp_as_integer = 1;
473 function_infix =
"Bicubic";
474 s->interp_use_linear = 0;
475 s->interp_as_integer = 0;
478 function_infix =
"Lanczos";
479 s->interp_use_linear = 0;
480 s->interp_as_integer = 0;
488 ret =
CHECK_CU(cu->cuCtxPushCurrent(cuda_ctx));
493 ff_vf_scale_cuda_ptx_data, ff_vf_scale_cuda_ptx_len);
497 snprintf(buf,
sizeof(buf),
"Subsample_%s_%s_%s", function_infix, in_fmt_name, out_fmt_name);
506 snprintf(buf,
sizeof(buf),
"Subsample_%s_%s_%s_uv", function_infix, in_fmt_name, out_fmt_name);
512 if (
s->use_filters) {
514 snprintf(buf,
sizeof(buf),
"Subsample_Generic_h_%s_%s", in_fmt_name, in_fmt_name);
519 snprintf(buf,
sizeof(buf),
"Subsample_Generic_h_%s_%s_uv", in_fmt_name, in_fmt_name);
533 int src_size,
int dst_size,
537 CudaFunctions *cu =
s->hwctx->internal->cuda_dl;
541 .src_size = src_size,
542 .dst_size = dst_size,
543 .virtual_size = virtual_size,
546 switch (
s->interp_algo) {
553 params.scaler_params[0] =
params.scaler_params[1] = 0.0;
555 params.scaler_params[1] =
s->param;
564 "currently supported by the CUDA scaler (%d).\n",
575 for (
size_t i = 0;
i <
weights->num_weights;
i++)
578 f->filter_size =
weights->filter_size;
579 f->dst_size = dst_size;
581 const size_t weights_size =
weights->num_weights *
sizeof(*tmp);
582 ret =
CHECK_CU(cu->cuMemAlloc(&
f->weights, weights_size));
585 ret =
CHECK_CU(cu->cuMemcpyHtoD(
f->weights,
tmp, weights_size));
589 const size_t offsets_size = dst_size *
sizeof(*
weights->offsets);
590 ret =
CHECK_CU(cu->cuMemAlloc(&
f->offsets, offsets_size));
593 ret =
CHECK_CU(cu->cuMemcpyHtoD(
f->offsets,
weights->offsets, offsets_size));
598 f->filter_size,
weights->name, src_size, dst_size);
613 CudaFunctions *cu =
s->hwctx->internal->cuda_dl;
617 const int in_sub_x =
s->in_desc->log2_chroma_w;
618 const int in_sub_y =
s->in_desc->log2_chroma_h;
619 const int out_sub_x =
s->out_desc->log2_chroma_w;
620 const int out_sub_y =
s->out_desc->log2_chroma_h;
622 ret =
CHECK_CU(cu->cuCtxPushCurrent(
s->hwctx->cuda_ctx));
626 int pass_x = -1, pass_y = -1;
627 if (inlink->
w != outlink->
w && inlink->
h != outlink->
h) {
631 }
else if (inlink->
w != outlink->
w) {
633 }
else if (inlink->
h != outlink->
h) {
639 inlink->
w, outlink->
w, 0.0);
642 if (
s->in_planes > 1) {
645 const double virtual_size = (
double) outlink->
w / (1 << out_sub_x);
647 src_size, dst_size, virtual_size);
655 inlink->
h, outlink->
h, 0.0);
658 if (
s->in_planes > 1) {
661 const double virtual_size = (
double) outlink->
h / (1 << out_sub_y);
663 src_size, dst_size, virtual_size);
693 s->w_expr,
s->h_expr,
703 s->force_original_aspect_ratio,
704 s->force_divisible_by, w_adj);
708 if (((
int64_t)
h * inlink->
w) > INT_MAX ||
722 s->hwctx = device_hwctx;
723 s->cu_stream =
s->hwctx->stream;
729 outlink->
w*inlink->
h},
738 s->passthrough ?
" (passthrough)" :
"");
740 if (
s->use_filters) {
758 const int depths[4],
const int channels[4],
762 CudaFunctions *cu =
s->hwctx->internal->cuda_dl;
769 .width =
frame->width,
770 .height =
frame->height,
771 .crop_left =
frame->crop_left,
772 .crop_top =
frame->crop_top,
775 .color_range =
frame->color_range,
776 .log2_chroma_w =
desc->log2_chroma_w,
777 .log2_chroma_h =
desc->log2_chroma_h,
787 CUDA_TEXTURE_DESC tex_desc = {
788 .filterMode =
s->interp_use_linear ?
789 CU_TR_FILTER_MODE_LINEAR :
790 CU_TR_FILTER_MODE_POINT,
791 .flags =
s->interp_as_integer ? CU_TRSF_READ_AS_INTEGER : 0,
794 const int is_chroma =
i == 1 ||
i == 2;
795 const int sub_x = is_chroma ?
desc->log2_chroma_w : 0;
796 const int sub_y = is_chroma ?
desc->log2_chroma_h : 0;
797 CUDA_RESOURCE_DESC res_desc = {
798 .resType = CU_RESOURCE_TYPE_PITCH2D,
799 .res.pitch2D.format = depths[
i] <= 8 ?
800 CU_AD_FORMAT_UNSIGNED_INT8 :
801 CU_AD_FORMAT_UNSIGNED_INT16,
803 .res.pitch2D.pitchInBytes = tex->
linesize[
i],
804 .res.pitch2D.devPtr = tex->
data[
i],
809 int ret =
CHECK_CU(cu->cuTexObjectCreate(&tex->
tex[
i], &res_desc, &tex_desc,
NULL));
820 const CUtexObject src_tex[4],
821 int src_left,
int src_top,
int src_width,
int src_height,
822 const CUdeviceptr out_data[4],
823 int dst_width,
int dst_height,
int dst_pitch,
int mpeg_range,
827 CudaFunctions *cu =
s->hwctx->internal->cuda_dl;
830 .src_tex = {src_tex[0], src_tex[1], src_tex[2], src_tex[3]},
837 .dst_width = dst_width,
838 .dst_height = dst_height,
839 .dst_pitch = dst_pitch,
840 .src_left = src_left,
842 .src_width = src_width,
843 .src_height = src_height,
845 .mpeg_range = mpeg_range,
854 void *args[] = { &
params };
868 int out_planes =
s->out_planes;
870 out_planes =
s->in_planes;
877 out->linesize[0], mpeg_range,
882 if (out_planes > 1) {
892 out->linesize[1], mpeg_range,
893 &
s->filters_uv[pass]);
904 CudaFunctions *cu =
s->hwctx->internal->cuda_dl;
908 CUDATex in_tex = {0}, out_tex = {0};
918 if (
s->use_filters) {
938 s->frame->width = outlink->
w;
939 s->frame->height = outlink->
h;
961 CudaFunctions *cu =
s->hwctx->internal->cuda_dl;
976 ret =
CHECK_CU(cu->cuCtxPushCurrent(
s->hwctx->cuda_ctx));
989 av_reduce(&
out->sample_aspect_ratio.num, &
out->sample_aspect_ratio.den,
1007 return s->passthrough ?
1012#define OFFSET(x) offsetof(CUDAScaleContext, x)
1013#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
1023 {
"passthrough",
"Do not process frames at all if parameters match",
OFFSET(passthrough),
AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1,
FLAGS },
1024 {
"use_filters",
"Use generic filters instead of fixed function kernels",
OFFSET(use_filters),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1,
FLAGS, .unit =
"use_filters" },
1027 {
"force_original_aspect_ratio",
"decrease or increase w/h if necessary to keep the original AR",
OFFSET(force_original_aspect_ratio),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0,
SCALE_FORCE_OAR_NB-1,
FLAGS, .unit =
"force_oar" },
1031 {
"force_divisible_by",
"enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used",
OFFSET(force_divisible_by),
AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 256,
FLAGS },
1032 {
"reset_sar",
"reset SAR to 1 and scale to square pixels if scaling proportionally",
OFFSET(reset_sar),
AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1,
FLAGS },
1037 .class_name =
"cudascale",
1061 .p.name =
"scale_cuda",
SwsAArch64OpImplParams params
static const char *const format[]
const FFFilter ff_vf_scale_cuda
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
common internal and external API header
#define AV_CEIL_RSHIFT(a, b)
int ff_sws_filter_generate(void *log, const SwsFilterParams *params, SwsFilterWeights **out)
Generate a filter kernel for the given parameters.
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_PIXEL_FMT
Underlying C type is enum AVPixelFormat.
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
void av_frame_side_data_remove_by_props(AVFrameSideData ***sd, int *nb_sd, int props)
Remove and free all side data instances that match any of the given side data properties.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
@ AV_SIDE_DATA_PROP_SIZE_DEPENDENT
Side data depends on the video dimensions.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const char * av_default_item_name(void *ptr)
Return the context name.
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
#define LIBAVUTIL_VERSION_INT
#define SWS_PARAM_DEFAULT
@ SWS_SCALE_LANCZOS
3-tap sinc/sinc
@ SWS_SCALE_BILINEAR
bilinear filtering
@ SWS_SCALE_BICUBIC
2-tap cubic BC-spline
static const int weights[]
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
FFmpeg internal API for CUDA.
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_)
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
@ SWS_FILTER_SCALE
14-bit coefficients are picked to fit comfortably within int16_t for efficient SIMD processing (e....
static const struct @257111027162314367033347246032313251342043035002 planes[]
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.
Memory handling functions.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
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.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
#define AV_PIX_FMT_0RGB32
#define AV_PIX_FMT_YUV420P10
@ AVCOL_RANGE_JPEG
Full range content.
#define AV_PIX_FMT_YUV422P10
#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_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
@ AV_PIX_FMT_CUDA
HW acceleration through CUDA.
@ AV_PIX_FMT_NV16
interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
@ 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 AV_PIX_FMT_0BGR32
#define AV_PIX_FMT_YUV444P10
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
int ff_scale_adjust_dimensions(AVFilterLink *inlink, int *ret_w, int *ret_h, int force_original_aspect_ratio, int force_divisible_by, double w_adj)
Transform evaluated width and height obtained from ff_scale_eval_dimensions into actual target width ...
int ff_scale_eval_dimensions(void *log_ctx, const char *w_expr, const char *h_expr, AVFilterLink *inlink, AVFilterLink *outlink, int *ret_w, int *ret_h)
Parse and evaluate string expressions for width and height.
@ SCALE_FORCE_OAR_DISABLE
@ SCALE_FORCE_OAR_INCREASE
@ SCALE_FORCE_OAR_DECREASE
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
uint8_t * data
The data buffer.
This struct is allocated as AVHWDeviceContext.hwctx.
Describe the class of an AVClass context structure.
AVFilterLink ** inputs
array of pointers to input links
void * priv
private data for use by the filter
A link between two filters.
int w
agreed upon image width
int h
agreed upon image height
AVFilterContext * src
source filter
AVRational sample_aspect_ratio
agreed upon sample aspect ratio
AVFilterContext * dst
dest filter
A filter pad used for either input or output.
This structure describes decoded (raw) audio or video data.
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
enum AVColorRange color_range
MPEG vs JPEG YUV range.
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 format
The pixel format identifying the underlying HW surface type.
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
int width
The allocated dimensions of the frames in this pool.
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Rational number (pair of numerator and denominator).
CUDAScaleFilter filters_uv[FILTER_NB]
enum AVPixelFormat format
Output sw format.
int force_original_aspect_ratio
const AVPixFmtDescriptor * in_desc
enum AVPixelFormat in_fmt out_fmt
CUfunction cu_func[FILTER_NB]
AVCUDADeviceContext * hwctx
CUDAScaleFilter filters[FILTER_NB]
char * w_expr
width expression string
CUfunction cu_func_uv[FILTER_NB]
const AVPixFmtDescriptor * out_desc
char * h_expr
height expression string
CUdeviceptr weights
float[dst_size][filter_size]
CUdeviceptr offsets
int[dst_size]
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.
Represents a computed filter kernel.
enum AVPixelFormat format
#define av_malloc_array(a, b)
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
static AVFormatContext * ctx
static enum AVPixelFormat supported_formats[]
static av_cold int cudascale_setup_filters(AVFilterContext *ctx)
static av_cold int init_hwframe_ctx(CUDAScaleContext *s, AVBufferRef *device_ctx, int width, int height)
static av_cold void cudascale_uninit(AVFilterContext *ctx)
static int scalecuda_resize(AVFilterContext *ctx, int pass, const CUDATex *out, const CUDATex *in)
static int cudascale_scale(AVFilterContext *ctx, AVFrame *out, AVFrame *in)
static av_cold int cudascale_config_props(AVFilterLink *outlink)
static av_cold int init_processing_chain(AVFilterContext *ctx, int in_width, int in_height, int out_width, int out_height)
static av_cold int cudascale_init(AVFilterContext *ctx)
static const AVClass cudascale_class
static av_cold int cudascale_load_functions(AVFilterContext *ctx)
static const char * get_format_name(enum AVPixelFormat fmt)
static av_cold int cudascale_filter_init(AVFilterContext *ctx, CUDAScaleFilter *f, int src_size, int dst_size, double virtual_size)
static int call_resize_kernel(AVFilterContext *ctx, CUfunction func, const CUtexObject src_tex[4], int src_left, int src_top, int src_width, int src_height, const CUdeviceptr out_data[4], int dst_width, int dst_height, int dst_pitch, int mpeg_range, const CUDAScaleFilter *filter)
static void cuda_tex_uninit(CudaFunctions *cu, CUDATex *t)
static int format_is_supported(enum AVPixelFormat fmt)
static av_cold void set_format_info(AVFilterContext *ctx, enum AVPixelFormat in_format, enum AVPixelFormat out_format)
static AVFrame * cudascale_get_video_buffer(AVFilterLink *inlink, int w, int h)
static void filter_uninit(CudaFunctions *cu, CUDAScaleFilter *filter)
static int cudascale_filter_frame(AVFilterLink *link, AVFrame *in)
static av_cold int inter_buf_init(AVFilterContext *ctx, int out_width, int in_height)
static const AVFilterPad cudascale_outputs[]
static const AVFilterPad cudascale_inputs[]
static int cuda_tex_map_frame(AVFilterContext *ctx, const AVFrame *frame, const int depths[4], const int channels[4], CUDATex *tex)
#define SCALE_CUDA_PARAM_DEFAULT
AVFrame * ff_null_get_video_buffer(AVFilterLink *link, int w, int h)
AVFrame * ff_default_get_video_buffer(AVFilterLink *link, int w, int h)