FFmpeg
Loading...
Searching...
No Matches
vf_scale_cuda.c
Go to the documentation of this file.
1/*
2* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
3*
4* Permission is hereby granted, free of charge, to any person obtaining a
5* copy of this software and associated documentation files (the "Software"),
6* to deal in the Software without restriction, including without limitation
7* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8* and/or sell copies of the Software, and to permit persons to whom the
9* Software is furnished to do so, subject to the following conditions:
10*
11* The above copyright notice and this permission notice shall be included in
12* all copies or substantial portions of the Software.
13*
14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20* DEALINGS IN THE SOFTWARE.
21*/
22
23#include <float.h>
24#include <stdio.h>
25#include <string.h>
26
27#include "libavutil/common.h"
28#include "libavutil/hwcontext.h"
31#include "libavutil/internal.h"
32#include "libavutil/mem.h"
33#include "libavutil/opt.h"
34#include "libavutil/pixdesc.h"
35#include "libavutil/refstruct.h"
36
37#include "libswscale/filters.h"
38
39#include "avfilter.h"
40#include "filters.h"
41#include "scale_eval.h"
42#include "video.h"
43
44#include "cuda/load_helper.h"
45#include "vf_scale_cuda.h"
46
49 char name[13];
50};
51
52static const struct format_entry supported_formats[] = {
53 {AV_PIX_FMT_YUV420P, "planar8"},
54 {AV_PIX_FMT_YUV422P, "planar8"},
55 {AV_PIX_FMT_YUV444P, "planar8"},
56 {AV_PIX_FMT_YUV420P10,"planar10"},
57 {AV_PIX_FMT_YUV422P10,"planar10"},
58 {AV_PIX_FMT_YUV444P10,"planar10"},
59 {AV_PIX_FMT_YUV444P10MSB,"planar16"},
60 {AV_PIX_FMT_YUV444P12MSB,"planar16"},
61 {AV_PIX_FMT_YUV444P16,"planar16"},
62 {AV_PIX_FMT_NV12, "semiplanar8"},
63 {AV_PIX_FMT_NV16, "semiplanar8"},
64 {AV_PIX_FMT_P010, "semiplanar10"},
65 {AV_PIX_FMT_P210, "semiplanar10"},
66 {AV_PIX_FMT_P012, "semiplanar16"},
67 {AV_PIX_FMT_P212, "semiplanar16"},
68 {AV_PIX_FMT_P016, "semiplanar16"},
69 {AV_PIX_FMT_P216, "semiplanar16"},
70 {AV_PIX_FMT_0RGB32, "bgr0"},
71 {AV_PIX_FMT_0BGR32, "rgb0"},
72 {AV_PIX_FMT_RGB32, "bgra"},
73 {AV_PIX_FMT_BGR32, "rgba"},
74};
75
76#define DIV_UP(a, b) ( ((a) + (b) - 1) / (b) )
77#define BLOCKX 32
78#define BLOCKY 16
79
80#define CHECK_CU(x) FF_CUDA_CHECK_DL(ctx, s->hwctx->internal->cuda_dl, x)
81
82enum {
84
89
91};
92
93enum {
97};
98
99typedef struct CUDAScaleFilter {
100 CUdeviceptr weights; ///< float[dst_size][filter_size]
101 CUdeviceptr offsets; ///< int[dst_size]
105
116
117typedef struct CUDAScaleContext {
118 const AVClass *class;
119
121
122 enum AVPixelFormat in_fmt, out_fmt;
127
130
133
134 /**
135 * Output sw format. AV_PIX_FMT_NONE for no conversion.
136 */
138
139 char *w_expr; ///< width expression string
140 char *h_expr; ///< height expression string
141
145
146 CUcontext cu_ctx;
147 CUmodule cu_module;
148 CUfunction cu_func[FILTER_NB];
150 CUstream cu_stream;
151
155
159 int use_filters; /* -1 for auto */
161
162 float param;
164
166{
167 CUDAScaleContext *s = ctx->priv;
168
169 s->frame = av_frame_alloc();
170 if (!s->frame)
171 return AVERROR(ENOMEM);
172
173 s->tmp_frame = av_frame_alloc();
174 if (!s->tmp_frame)
175 return AVERROR(ENOMEM);
176
177 return 0;
178}
179
180static void filter_uninit(CudaFunctions *cu, CUDAScaleFilter *filter)
181{
182 if (filter->weights)
183 cu->cuMemFree(filter->weights);
184 if (filter->offsets)
185 cu->cuMemFree(filter->offsets);
186 memset(filter, 0, sizeof(*filter));
187}
188
189static void cuda_tex_uninit(CudaFunctions *cu, CUDATex *t)
190{
191 for (int i = 0; i < FF_ARRAY_ELEMS(t->tex); i++) {
192 if (t->tex[i])
193 cu->cuTexObjectDestroy(t->tex[i]);
194 if (t->data[i] && !t->external_data)
195 cu->cuMemFree(t->data[i]);
196 }
197
198 memset(t, 0, sizeof(*t));
199}
200
202{
203 CUDAScaleContext *s = ctx->priv;
204
205 if (s->hwctx) {
206 CudaFunctions *cu = s->hwctx->internal->cuda_dl;
207 CUcontext dummy;
208
209 CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx));
210
211 cuda_tex_uninit(cu, &s->inter_tex);
212 for (int i = 0; i < FF_ARRAY_ELEMS(s->filters); i++) {
213 filter_uninit(cu, &s->filters[i]);
214 filter_uninit(cu, &s->filters_uv[i]);
215 }
216
217 if (s->cu_module) {
218 CHECK_CU(cu->cuModuleUnload(s->cu_module));
219 s->cu_module = NULL;
220 }
221
222 CHECK_CU(cu->cuCtxPopCurrent(&dummy));
223 }
224
225 av_frame_free(&s->frame);
226 av_buffer_unref(&s->frames_ctx);
227 av_frame_free(&s->tmp_frame);
228}
229
231{
232 AVBufferRef *out_ref = NULL;
233 AVHWFramesContext *out_ctx;
234 int ret;
235
236 out_ref = av_hwframe_ctx_alloc(device_ctx);
237 if (!out_ref)
238 return AVERROR(ENOMEM);
239 out_ctx = (AVHWFramesContext*)out_ref->data;
240
241 out_ctx->format = AV_PIX_FMT_CUDA;
242 out_ctx->sw_format = s->out_fmt;
243 out_ctx->width = FFALIGN(width, 32);
244 out_ctx->height = FFALIGN(height, 32);
245
246 ret = av_hwframe_ctx_init(out_ref);
247 if (ret < 0)
248 goto fail;
249
250 av_frame_unref(s->frame);
251 ret = av_hwframe_get_buffer(out_ref, s->frame, 0);
252 if (ret < 0)
253 goto fail;
254
255 s->frame->width = width;
256 s->frame->height = height;
257
258 av_buffer_unref(&s->frames_ctx);
259 s->frames_ctx = out_ref;
260
261 return 0;
262fail:
263 av_buffer_unref(&out_ref);
264 return ret;
265}
266
267static av_cold int inter_buf_init(AVFilterContext *ctx, int out_width, int in_height)
268{
269 CUDAScaleContext *s = ctx->priv;
270 CudaFunctions *cu = s->hwctx->internal->cuda_dl;
271 int ret = 0;
272
273 cuda_tex_uninit(cu, &s->inter_tex);
274 s->inter_tex = (CUDATex) {
275 .width = out_width,
276 .height = in_height,
277 .crop_width = out_width,
278 .crop_height = in_height,
279 .log2_chroma_w = s->out_desc->log2_chroma_w,
280 .log2_chroma_h = s->in_desc->log2_chroma_h,
281 };
282
283 for (int i = 0; i < s->in_planes; i++) {
284 const int is_chroma = i == 1 || i == 2;
285 const int sub_x = is_chroma ? s->inter_tex.log2_chroma_w : 0;
286 const int sub_y = is_chroma ? s->inter_tex.log2_chroma_h : 0;
287 const int plane_w = AV_CEIL_RSHIFT(out_width, sub_x);
288 const int plane_h = AV_CEIL_RSHIFT(in_height, sub_y);
289 const int sizeof_pixel = (s->in_plane_depths[i] <= 8 ? 1 : 2) *
290 s->in_plane_channels[i];
291
292 size_t pitch;
293 ret = CHECK_CU(cu->cuMemAllocPitch(&s->inter_tex.data[i], &pitch,
294 (size_t) plane_w * sizeof_pixel,
295 plane_h, 16));
296 if (ret < 0)
297 goto fail;
298 s->inter_tex.linesize[i] = pitch;
299
300 CUDA_TEXTURE_DESC tex_desc = {
301 /* inter tex is always read as float */
302 .filterMode = CU_TR_FILTER_MODE_POINT,
303 };
304
305 CUDA_RESOURCE_DESC res_desc = {
306 .resType = CU_RESOURCE_TYPE_PITCH2D,
307 .res.pitch2D.format = s->in_plane_depths[i] <= 8 ?
308 CU_AD_FORMAT_UNSIGNED_INT8 :
309 CU_AD_FORMAT_UNSIGNED_INT16,
310 .res.pitch2D.numChannels = s->in_plane_channels[i],
311 .res.pitch2D.devPtr = s->inter_tex.data[i],
312 .res.pitch2D.pitchInBytes = pitch,
313 .res.pitch2D.width = plane_w,
314 .res.pitch2D.height = plane_h,
315 };
316
317 ret = CHECK_CU(cu->cuTexObjectCreate(&s->inter_tex.tex[i], &res_desc,
318 &tex_desc, NULL));
319 if (ret < 0)
320 goto fail;
321 }
322
323 return 0;
324
325fail:
326 cuda_tex_uninit(cu, &s->inter_tex);
327 return ret;
328}
329
331{
332 for (int i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++)
333 if (supported_formats[i].format == fmt)
334 return 1;
335 return 0;
336}
337
338static const char* get_format_name(enum AVPixelFormat fmt)
339{
340 for (int i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++)
341 if (supported_formats[i].format == fmt)
342 return supported_formats[i].name;
343 return NULL;
344}
345
346static av_cold void set_format_info(AVFilterContext *ctx, enum AVPixelFormat in_format, enum AVPixelFormat out_format)
347{
348 CUDAScaleContext *s = ctx->priv;
349 int i, p, d;
350
351 s->in_fmt = in_format;
352 s->out_fmt = out_format;
353
354 s->in_desc = av_pix_fmt_desc_get(s->in_fmt);
355 s->out_desc = av_pix_fmt_desc_get(s->out_fmt);
356 s->in_planes = av_pix_fmt_count_planes(s->in_fmt);
357 s->out_planes = av_pix_fmt_count_planes(s->out_fmt);
358
359 // find maximum step of each component of each plane
360 // For our subset of formats, this should accurately tell us how many channels CUDA needs
361 // i.e. 1 for Y plane, 2 for UV plane of NV12, 4 for single plane of RGB0 formats
362
363 for (i = 0; i < s->in_desc->nb_components; i++) {
364 d = (s->in_desc->comp[i].depth + 7) / 8;
365 p = s->in_desc->comp[i].plane;
366 s->in_plane_channels[p] = FFMAX(s->in_plane_channels[p], s->in_desc->comp[i].step / d);
367
368 s->in_plane_depths[p] = s->in_desc->comp[i].depth;
369 }
370}
371
373{
374 CUDAScaleContext *s = ctx->priv;
375 AVFilterLink *inlink = ctx->inputs[0];
376 AVFilterLink *outlink = ctx->outputs[0];
377
378 s->pass_x = s->pass_y = -1;
379 if (!s->use_filters)
380 return;
381
382 const int scale_x = inlink->w != outlink->w ||
383 s->in_desc->log2_chroma_w != s->out_desc->log2_chroma_w;
384 const int scale_y = inlink->h != outlink->h ||
385 s->in_desc->log2_chroma_h != s->out_desc->log2_chroma_h;
386
387 if (scale_x && scale_y) {
388 /* Always perform the horizontal scaling pass first */
389 s->pass_x = FILTER_TMP;
390 s->pass_y = FILTER_OUT;
391 } else if (scale_x) {
392 s->pass_x = FILTER_OUT;
393 } else {
394 s->pass_y = FILTER_OUT;
395 }
396}
397
398static av_cold int init_processing_chain(AVFilterContext *ctx, int in_width, int in_height,
399 int out_width, int out_height)
400{
401 CUDAScaleContext *s = ctx->priv;
402 FilterLink *inl = ff_filter_link(ctx->inputs[0]);
403 FilterLink *outl = ff_filter_link(ctx->outputs[0]);
404
405 AVHWFramesContext *in_frames_ctx;
406
407 enum AVPixelFormat in_format;
408 enum AVPixelFormat out_format;
409 int ret;
410
411 /* check that we have a hw context */
412 if (!inl->hw_frames_ctx) {
413 av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n");
414 return AVERROR(EINVAL);
415 }
416 in_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
417 in_format = in_frames_ctx->sw_format;
418 out_format = (s->format == AV_PIX_FMT_NONE) ? in_format : s->format;
419
420 if (!format_is_supported(in_format)) {
421 av_log(ctx, AV_LOG_ERROR, "Unsupported input format: %s\n",
422 av_get_pix_fmt_name(in_format));
423 return AVERROR(ENOSYS);
424 }
425 if (!format_is_supported(out_format)) {
426 av_log(ctx, AV_LOG_ERROR, "Unsupported output format: %s\n",
427 av_get_pix_fmt_name(out_format));
428 return AVERROR(ENOSYS);
429 }
430
431 set_format_info(ctx, in_format, out_format);
432
433 if (s->passthrough && in_width == out_width && in_height == out_height && in_format == out_format) {
434 s->frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
435 if (!s->frames_ctx)
436 return AVERROR(ENOMEM);
437
438 s->use_filters = 0;
439 } else {
440 s->passthrough = 0;
441
442 ret = init_hwframe_ctx(s, in_frames_ctx->device_ref, out_width, out_height);
443 if (ret < 0)
444 return ret;
445
446 if (in_width == out_width && in_height == out_height &&
447 in_format == out_format && s->interp_algo == INTERP_ALGO_DEFAULT)
448 s->interp_algo = INTERP_ALGO_NEAREST;
449
450 if (s->interp_algo == INTERP_ALGO_NEAREST) {
451 s->use_filters = 0;
452 } else if (s->use_filters < 0 && (
453 out_width < in_width || out_height < in_height ||
454 AV_CEIL_RSHIFT(out_width, s->out_desc->log2_chroma_w) < AV_CEIL_RSHIFT(in_width, s->in_desc->log2_chroma_w) ||
455 AV_CEIL_RSHIFT(out_height, s->out_desc->log2_chroma_h) < AV_CEIL_RSHIFT(in_height, s->in_desc->log2_chroma_h)
456 ))
457 s->use_filters = 1; /* downscaling; needed for anti-aliasing */
458 else if (s->use_filters < 0)
459 s->use_filters = 0;
460 }
461
462 outl->hw_frames_ctx = av_buffer_ref(s->frames_ctx);
463 if (!outl->hw_frames_ctx)
464 return AVERROR(ENOMEM);
465
467
468 return 0;
469}
470
472{
473 CUDAScaleContext *s = ctx->priv;
474 CUcontext dummy, cuda_ctx = s->hwctx->cuda_ctx;
475 CudaFunctions *cu = s->hwctx->internal->cuda_dl;
476 char buf[128];
477 int ret;
478
479 const char *in_fmt_name = get_format_name(s->in_fmt);
480 const char *out_fmt_name = get_format_name(s->out_fmt);
481
482 const char *function_infix = "";
483
484 extern const unsigned char ff_vf_scale_cuda_ptx_data[];
485 extern const unsigned int ff_vf_scale_cuda_ptx_len;
486
487 if (s->use_filters) {
488 /* Final pass is always vertical unless not vertically scaling */
489 function_infix = s->pass_y == FILTER_OUT ? "Generic_v" : "Generic_h";
490 s->interp_use_linear = 0;
491 s->interp_as_integer = 0;
492 } else {
493 switch(s->interp_algo) {
495 function_infix = "Nearest";
496 s->interp_use_linear = 0;
497 s->interp_as_integer = 1;
498 break;
500 function_infix = "Bilinear";
501 s->interp_use_linear = 1;
502 s->interp_as_integer = 1;
503 break;
506 function_infix = "Bicubic";
507 s->interp_use_linear = 0;
508 s->interp_as_integer = 0;
509 break;
511 function_infix = "Lanczos";
512 s->interp_use_linear = 0;
513 s->interp_as_integer = 0;
514 break;
515 default:
516 av_log(ctx, AV_LOG_ERROR, "Unknown interpolation algorithm\n");
517 return AVERROR_BUG;
518 }
519 }
520
521 ret = CHECK_CU(cu->cuCtxPushCurrent(cuda_ctx));
522 if (ret < 0)
523 return ret;
524
525 ret = ff_cuda_load_module(ctx, s->hwctx, &s->cu_module,
526 ff_vf_scale_cuda_ptx_data, ff_vf_scale_cuda_ptx_len);
527 if (ret < 0)
528 goto fail;
529
530 snprintf(buf, sizeof(buf), "Subsample_%s_%s_%s", function_infix, in_fmt_name, out_fmt_name);
531 ret = CHECK_CU(cu->cuModuleGetFunction(&s->cu_func[FILTER_OUT], s->cu_module, buf));
532 if (ret < 0) {
533 av_log(ctx, AV_LOG_FATAL, "Unsupported conversion: %s -> %s\n", in_fmt_name, out_fmt_name);
534 ret = AVERROR(ENOSYS);
535 goto fail;
536 }
537 av_log(ctx, AV_LOG_DEBUG, "Luma filter: %s (%s -> %s)\n", buf, av_get_pix_fmt_name(s->in_fmt), av_get_pix_fmt_name(s->out_fmt));
538
539 snprintf(buf, sizeof(buf), "Subsample_%s_%s_%s_uv", function_infix, in_fmt_name, out_fmt_name);
540 ret = CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_uv[FILTER_OUT], s->cu_module, buf));
541 if (ret < 0)
542 goto fail;
543 av_log(ctx, AV_LOG_DEBUG, "Chroma filter: %s (%s -> %s)\n", buf, av_get_pix_fmt_name(s->in_fmt), av_get_pix_fmt_name(s->out_fmt));
544
545 if (s->use_filters) {
546 /* Intermediate pass is always horizontal */
547 snprintf(buf, sizeof(buf), "Subsample_Generic_h_%s_%s", in_fmt_name, in_fmt_name);
548 ret = CHECK_CU(cu->cuModuleGetFunction(&s->cu_func[FILTER_TMP], s->cu_module, buf));
549 if (ret < 0)
550 goto fail;
551
552 snprintf(buf, sizeof(buf), "Subsample_Generic_h_%s_%s_uv", in_fmt_name, in_fmt_name);
553 ret = CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_uv[FILTER_TMP], s->cu_module, buf));
554 if (ret < 0)
555 goto fail;
556 }
557
558fail:
559 CHECK_CU(cu->cuCtxPopCurrent(&dummy));
560
561 return ret;
562}
563
566 int src_size, int dst_size,
567 double virtual_size)
568{
569 CUDAScaleContext *s = ctx->priv;
570 CudaFunctions *cu = s->hwctx->internal->cuda_dl;
571
573 .scaler_params = { SWS_PARAM_DEFAULT, SWS_PARAM_DEFAULT },
574 .src_size = src_size,
575 .dst_size = dst_size,
576 .virtual_size = virtual_size,
577 };
578
579 switch (s->interp_algo) {
580 case INTERP_ALGO_NEAREST: return 0; /* no weights needed */
581 case INTERP_ALGO_BILINEAR: params.scaler = SWS_SCALE_BILINEAR; break;
582 case INTERP_ALGO_LANCZOS: params.scaler = SWS_SCALE_LANCZOS; break;
585 params.scaler = SWS_SCALE_BICUBIC;
586 params.scaler_params[0] = params.scaler_params[1] = 0.0;
587 if (s->param != SCALE_CUDA_PARAM_DEFAULT)
588 params.scaler_params[1] = s->param;
589 break;
590 }
591
594 if (ret < 0) {
595 if (ret == AVERROR(ENOTSUP)) {
596 av_log(ctx, AV_LOG_ERROR, "Filter size exceeds the maximum "
597 "currently supported by the CUDA scaler (%d).\n",
599 }
600 return ret;
601 }
602
603 float *tmp = av_malloc_array(weights->num_weights, sizeof(*tmp));
604 if (!tmp) {
605 ret = AVERROR(ENOMEM);
606 goto fail;
607 }
608 for (size_t i = 0; i < weights->num_weights; i++)
609 tmp[i] = weights->weights[i] / (float) SWS_FILTER_SCALE;
610
611 f->filter_size = weights->filter_size;
612 f->dst_size = dst_size;
613
614 const size_t weights_size = weights->num_weights * sizeof(*tmp);
615 ret = CHECK_CU(cu->cuMemAlloc(&f->weights, weights_size));
616 if (ret < 0)
617 goto fail;
618 ret = CHECK_CU(cu->cuMemcpyHtoD(f->weights, tmp, weights_size));
619 if (ret < 0)
620 goto fail;
621
622 const size_t offsets_size = dst_size * sizeof(*weights->offsets);
623 ret = CHECK_CU(cu->cuMemAlloc(&f->offsets, offsets_size));
624 if (ret < 0)
625 goto fail;
626 ret = CHECK_CU(cu->cuMemcpyHtoD(f->offsets, weights->offsets, offsets_size));
627 if (ret < 0)
628 goto fail;
629
630 av_log(ctx, AV_LOG_VERBOSE, " using %d tap '%s' filter: %d -> %d\n",
631 f->filter_size, weights->name, src_size, dst_size);
632
633 ret = 0;
634
635fail:
636 av_free(tmp);
638 return ret;
639}
640
642{
643 CUDAScaleContext *s = ctx->priv;
644 AVFilterLink *inlink = ctx->inputs[0];
645 AVFilterLink *outlink = ctx->outputs[0];
646 CudaFunctions *cu = s->hwctx->internal->cuda_dl;
647 CUcontext dummy;
648 int ret;
649
650 const int in_sub_x = s->in_desc->log2_chroma_w;
651 const int in_sub_y = s->in_desc->log2_chroma_h;
652 const int out_sub_x = s->out_desc->log2_chroma_w;
653 const int out_sub_y = s->out_desc->log2_chroma_h;
654
655 ret = CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx));
656 if (ret < 0)
657 return ret;
658
659 if (s->pass_x >= 0) {
660 ret = cudascale_filter_init(ctx, &s->filters[s->pass_x],
661 inlink->w, outlink->w, 0.0);
662 if (ret < 0)
663 goto fail;
664 if (s->in_planes > 1) {
665 const int src_size = AV_CEIL_RSHIFT(inlink->w, in_sub_x);
666 const int dst_size = AV_CEIL_RSHIFT(outlink->w, out_sub_x);
667 const double virtual_size = (double) outlink->w / (1 << out_sub_x);
668 ret = cudascale_filter_init(ctx, &s->filters_uv[s->pass_x],
669 src_size, dst_size, virtual_size);
670 if (ret < 0)
671 goto fail;
672 }
673 }
674
675 if (s->pass_y >= 0) {
676 ret = cudascale_filter_init(ctx, &s->filters[s->pass_y],
677 inlink->h, outlink->h, 0.0);
678 if (ret < 0)
679 goto fail;
680 if (s->in_planes > 1) {
681 const int src_size = AV_CEIL_RSHIFT(inlink->h, in_sub_y);
682 const int dst_size = AV_CEIL_RSHIFT(outlink->h, out_sub_y);
683 const double virtual_size = (double) outlink->h / (1 << out_sub_y);
684 ret = cudascale_filter_init(ctx, &s->filters_uv[s->pass_y],
685 src_size, dst_size, virtual_size);
686 if (ret < 0)
687 goto fail;
688 }
689 }
690
691 if (s->pass_x == FILTER_TMP) {
692 ret = inter_buf_init(ctx, outlink->w, inlink->h);
693 if (ret < 0)
694 goto fail;
695 }
696
697 ret = 0;
698
699fail:
700 CHECK_CU(cu->cuCtxPopCurrent(&dummy));
701 return ret;
702}
703
705{
706 AVFilterContext *ctx = outlink->src;
707 AVFilterLink *inlink = outlink->src->inputs[0];
708 FilterLink *inl = ff_filter_link(inlink);
709 CUDAScaleContext *s = ctx->priv;
710 AVHWFramesContext *frames_ctx;
711 AVCUDADeviceContext *device_hwctx;
712 int w, h;
713 double w_adj = 1.0;
714 int ret;
715
716 if ((ret = ff_scale_eval_dimensions(s,
717 s->w_expr, s->h_expr,
718 inlink, outlink,
719 &w, &h)) < 0)
720 goto fail;
721
722 if (s->reset_sar)
723 w_adj = inlink->sample_aspect_ratio.num ?
725
726 ret = ff_scale_adjust_dimensions(inlink, &w, &h,
727 s->force_original_aspect_ratio,
728 s->force_divisible_by, w_adj);
729 if (ret < 0)
730 goto fail;
731
732 if (((int64_t)h * inlink->w) > INT_MAX ||
733 ((int64_t)w * inlink->h) > INT_MAX)
734 av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n");
735
736 outlink->w = w;
737 outlink->h = h;
738
739 ret = init_processing_chain(ctx, inlink->w, inlink->h, w, h);
740 if (ret < 0)
741 return ret;
742
743 frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
744 device_hwctx = frames_ctx->device_ctx->hwctx;
745
746 s->hwctx = device_hwctx;
747 s->cu_stream = s->hwctx->stream;
748
749 if (s->reset_sar)
750 outlink->sample_aspect_ratio = (AVRational){1, 1};
751 else if (inlink->sample_aspect_ratio.num) {
752 outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h*inlink->w,
753 outlink->w*inlink->h},
754 inlink->sample_aspect_ratio);
755 } else {
756 outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
757 }
758
759 av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s -> w:%d h:%d fmt:%s%s\n",
760 inlink->w, inlink->h, av_get_pix_fmt_name(s->in_fmt),
761 outlink->w, outlink->h, av_get_pix_fmt_name(s->out_fmt),
762 s->passthrough ? " (passthrough)" : "");
763
764 if (s->use_filters) {
766 if (ret < 0)
767 return ret;
768 }
769
771 if (ret < 0)
772 return ret;
773
774 return 0;
775
776fail:
777 return ret;
778}
779
780/* if depths/channels are NULL, only maps pointers without creating textures */
782 const int depths[4], const int channels[4],
783 CUDATex *tex)
784{
785 CUDAScaleContext *s = ctx->priv;
786 CudaFunctions *cu = s->hwctx->internal->cuda_dl;
787
788 const AVHWFramesContext *fctx = (const AVHWFramesContext*)frame->hw_frames_ctx->data;
790 const int planes = av_pix_fmt_count_planes(fctx->sw_format);
791
792 *tex = (CUDATex) {
793 .width = frame->width,
794 .height = frame->height,
795 .crop_left = frame->crop_left,
796 .crop_top = frame->crop_top,
797 .crop_width = (frame->width - frame->crop_right) - frame->crop_left,
798 .crop_height = (frame->height - frame->crop_bottom) - frame->crop_top,
799 .color_range = frame->color_range,
800 .log2_chroma_w = desc->log2_chroma_w,
801 .log2_chroma_h = desc->log2_chroma_h,
802 .external_data = 1,
803 };
804
805 for (int i = 0; i < planes; i++) {
806 tex->data[i] = (CUdeviceptr)frame->data[i];
807 tex->linesize[i] = frame->linesize[i];
808 if (!depths || !channels)
809 continue;
810
811 CUDA_TEXTURE_DESC tex_desc = {
812 .filterMode = s->interp_use_linear ?
813 CU_TR_FILTER_MODE_LINEAR :
814 CU_TR_FILTER_MODE_POINT,
815 .flags = s->interp_as_integer ? CU_TRSF_READ_AS_INTEGER : 0,
816 };
817
818 const int is_chroma = i == 1 || i == 2;
819 const int sub_x = is_chroma ? desc->log2_chroma_w : 0;
820 const int sub_y = is_chroma ? desc->log2_chroma_h : 0;
821 CUDA_RESOURCE_DESC res_desc = {
822 .resType = CU_RESOURCE_TYPE_PITCH2D,
823 .res.pitch2D.format = depths[i] <= 8 ?
824 CU_AD_FORMAT_UNSIGNED_INT8 :
825 CU_AD_FORMAT_UNSIGNED_INT16,
826 .res.pitch2D.numChannels = channels[i],
827 .res.pitch2D.pitchInBytes = tex->linesize[i],
828 .res.pitch2D.devPtr = tex->data[i],
829 .res.pitch2D.width = AV_CEIL_RSHIFT(frame->width, sub_x),
830 .res.pitch2D.height = AV_CEIL_RSHIFT(frame->height, sub_y),
831 };
832
833 int ret = CHECK_CU(cu->cuTexObjectCreate(&tex->tex[i], &res_desc, &tex_desc, NULL));
834 if (ret < 0) {
835 cuda_tex_uninit(cu, tex);
836 return ret;
837 }
838 }
839
840 return 0;
841}
842
844 const CUtexObject src_tex[4],
845 int src_left, int src_top, int src_width, int src_height,
846 const CUdeviceptr out_data[4],
847 int dst_width, int dst_height, int dst_pitch, int mpeg_range,
848 const CUDAScaleFilter *filter)
849{
850 CUDAScaleContext *s = ctx->priv;
851 CudaFunctions *cu = s->hwctx->internal->cuda_dl;
852
854 .src_tex = {src_tex[0], src_tex[1], src_tex[2], src_tex[3]},
855 .dst = {
856 out_data[0],
857 out_data[1],
858 out_data[2],
859 out_data[3]
860 },
861 .dst_width = dst_width,
862 .dst_height = dst_height,
863 .dst_pitch = dst_pitch,
864 .src_left = src_left,
865 .src_top = src_top,
866 .src_width = src_width,
867 .src_height = src_height,
868 .param = s->param,
869 .mpeg_range = mpeg_range,
870 };
871
872 if (filter) {
873 params.weights = filter->weights;
874 params.offsets = filter->offsets;
875 params.filter_size = filter->filter_size;
876 }
877
878 void *args[] = { &params };
879
880 return CHECK_CU(cu->cuLaunchKernel(func,
881 DIV_UP(dst_width, BLOCKX), DIV_UP(dst_height, BLOCKY), 1,
882 BLOCKX, BLOCKY, 1, 0, s->cu_stream, args, NULL));
883}
884
886 const CUDATex *out, const CUDATex *in)
887{
888 CUDAScaleContext *s = ctx->priv;
889 int mpeg_range = in->color_range != AVCOL_RANGE_JPEG;
890 int ret;
891
892 int out_planes = s->out_planes;
893 if (pass == FILTER_TMP)
894 out_planes = s->in_planes;
895
896 // scale primary plane(s). Usually Y (and A), or single plane of RGB frames.
897 ret = call_resize_kernel(ctx, s->cu_func[pass],
898 in->tex, in->crop_left, in->crop_top,
899 in->crop_width, in->crop_height,
900 out->data, out->width, out->height,
901 out->linesize[0], mpeg_range,
902 &s->filters[pass]);
903 if (ret < 0)
904 return ret;
905
906 if (out_planes > 1) {
907 // scale UV plane. Scale function sets both U and V plane, or singular interleaved plane.
908 ret = call_resize_kernel(ctx, s->cu_func_uv[pass], in->tex,
913 out->data,
914 AV_CEIL_RSHIFT(out->width, out->log2_chroma_w),
915 AV_CEIL_RSHIFT(out->height, out->log2_chroma_h),
916 out->linesize[1], mpeg_range,
917 &s->filters_uv[pass]);
918 if (ret < 0)
919 return ret;
920 }
921
922 return 0;
923}
924
926{
927 CUDAScaleContext *s = ctx->priv;
928 CudaFunctions *cu = s->hwctx->internal->cuda_dl;
929 AVFilterLink *outlink = ctx->outputs[0];
930 int ret = 0;
931
932 CUDATex in_tex = {0}, out_tex = {0};
933 ret = cuda_tex_map_frame(ctx, in, s->in_plane_depths, s->in_plane_channels, &in_tex);
934 if (ret < 0)
935 goto fail;
936
937 ret = cuda_tex_map_frame(ctx, s->frame, NULL, NULL, &out_tex);
938 if (ret < 0)
939 goto fail;
940
941 const CUDATex *src = &in_tex;
942 if (s->pass_x == FILTER_TMP) {
943 /* Handle first pass separately */
944 s->inter_tex.color_range = in->color_range;
945 ret = scalecuda_resize(ctx, FILTER_TMP, &s->inter_tex, src);
946 if (ret < 0)
947 goto fail;
948 src = &s->inter_tex;
949 }
950
951 ret = scalecuda_resize(ctx, FILTER_OUT, &out_tex, src);
952 if (ret < 0)
953 goto fail;
954
955 ret = av_hwframe_get_buffer(s->frame->hw_frames_ctx, s->tmp_frame, 0);
956 if (ret < 0)
957 goto fail;
958
959 av_frame_move_ref(out, s->frame);
960 av_frame_move_ref(s->frame, s->tmp_frame);
961
962 s->frame->width = outlink->w;
963 s->frame->height = outlink->h;
964
965 ret = av_frame_copy_props(out, in);
966 if (ret < 0)
967 goto fail;
968
969 if (out->width != in->width || out->height != in->height) {
970 av_frame_side_data_remove_by_props(&out->side_data, &out->nb_side_data,
972 }
973
974fail:
975 cuda_tex_uninit(cu, &in_tex);
976 cuda_tex_uninit(cu, &out_tex);
977 return ret;
978}
979
981{
982 AVFilterContext *ctx = link->dst;
983 CUDAScaleContext *s = ctx->priv;
984 AVFilterLink *outlink = ctx->outputs[0];
985 CudaFunctions *cu = s->hwctx->internal->cuda_dl;
986
987 AVFrame *out = NULL;
988 CUcontext dummy;
989 int ret = 0;
990
991 if (s->passthrough)
992 return ff_filter_frame(outlink, in);
993
995 if (!out) {
996 ret = AVERROR(ENOMEM);
997 goto fail;
998 }
999
1000 ret = CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx));
1001 if (ret < 0)
1002 goto fail;
1003
1004 ret = cudascale_scale(ctx, out, in);
1005
1006 CHECK_CU(cu->cuCtxPopCurrent(&dummy));
1007 if (ret < 0)
1008 goto fail;
1009
1010 if (s->reset_sar) {
1011 out->sample_aspect_ratio = (AVRational){1, 1};
1012 } else {
1013 av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den,
1014 (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w,
1015 (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h,
1016 INT_MAX);
1017 }
1018
1019 av_frame_free(&in);
1020 return ff_filter_frame(outlink, out);
1021fail:
1022 av_frame_free(&in);
1024 return ret;
1025}
1026
1028{
1029 CUDAScaleContext *s = inlink->dst->priv;
1030
1031 return s->passthrough ?
1032 ff_null_get_video_buffer (inlink, w, h) :
1034}
1035
1036#define OFFSET(x) offsetof(CUDAScaleContext, x)
1037#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
1038static const AVOption options[] = {
1039 { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str = "iw" }, .flags = FLAGS },
1040 { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS },
1041 { "interp_algo", "Interpolation algorithm used for resizing", OFFSET(interp_algo), AV_OPT_TYPE_INT, { .i64 = INTERP_ALGO_DEFAULT }, 0, INTERP_ALGO_COUNT - 1, FLAGS, .unit = "interp_algo" },
1042 { "nearest", "nearest neighbour", 0, AV_OPT_TYPE_CONST, { .i64 = INTERP_ALGO_NEAREST }, 0, 0, FLAGS, .unit = "interp_algo" },
1043 { "bilinear", "bilinear", 0, AV_OPT_TYPE_CONST, { .i64 = INTERP_ALGO_BILINEAR }, 0, 0, FLAGS, .unit = "interp_algo" },
1044 { "bicubic", "bicubic", 0, AV_OPT_TYPE_CONST, { .i64 = INTERP_ALGO_BICUBIC }, 0, 0, FLAGS, .unit = "interp_algo" },
1045 { "lanczos", "lanczos", 0, AV_OPT_TYPE_CONST, { .i64 = INTERP_ALGO_LANCZOS }, 0, 0, FLAGS, .unit = "interp_algo" },
1046 { "format", "Output video pixel format", OFFSET(format), AV_OPT_TYPE_PIXEL_FMT, { .i64 = AV_PIX_FMT_NONE }, INT_MIN, INT_MAX, .flags=FLAGS },
1047 { "passthrough", "Do not process frames at all if parameters match", OFFSET(passthrough), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
1048 { "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" },
1049 { "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, FLAGS, .unit = "use_filters" },
1050 { "param", "Algorithm-Specific parameter", OFFSET(param), AV_OPT_TYPE_FLOAT, { .dbl = SCALE_CUDA_PARAM_DEFAULT }, -FLT_MAX, FLT_MAX, FLAGS },
1051 { "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" },
1052 { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_FORCE_OAR_DISABLE }, 0, 0, FLAGS, .unit = "force_oar" },
1053 { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_FORCE_OAR_DECREASE }, 0, 0, FLAGS, .unit = "force_oar" },
1054 { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_FORCE_OAR_INCREASE }, 0, 0, FLAGS, .unit = "force_oar" },
1055 { "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 },
1056 { "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 },
1057 { NULL },
1058};
1059
1060static const AVClass cudascale_class = {
1061 .class_name = "cudascale",
1062 .item_name = av_default_item_name,
1063 .option = options,
1064 .version = LIBAVUTIL_VERSION_INT,
1065};
1066
1068 {
1069 .name = "default",
1070 .type = AVMEDIA_TYPE_VIDEO,
1071 .filter_frame = cudascale_filter_frame,
1072 .get_buffer.video = cudascale_get_video_buffer,
1073 },
1074};
1075
1077 {
1078 .name = "default",
1079 .type = AVMEDIA_TYPE_VIDEO,
1080 .config_props = cudascale_config_props,
1081 },
1082};
1083
1085 .p.name = "scale_cuda",
1086 .p.description = NULL_IF_CONFIG_SMALL("GPU accelerated video resizer"),
1087
1088 .p.priv_class = &cudascale_class,
1089
1090 .init = cudascale_init,
1091 .uninit = cudascale_uninit,
1092
1093 .priv_size = sizeof(CUDAScaleContext),
1094
1097
1099
1100 .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
1101};
SwsAArch64OpImplParams params
Definition ops.c:51
static const char *const format[]
Definition af_aiir.c:444
const FFFilter ff_vf_scale_cuda
static FILE * out
static AVFormatContext * ctx
channels
Definition aptx.h:31
@ FILTER_NB
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define f(width, name)
Definition cbs_vp8.c:236
#define s(width, name)
Definition cbs_vp9.c:198
#define FLAGS
Definition cmdutils.c:598
common internal and external API header
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static AVFrame * frame
static int dummy
Definition ffplay.c:3754
int ff_sws_filter_generate(void *log, const SwsFilterParams *params, SwsFilterWeights **out)
Generate a filter kernel for the given parameters.
Definition filters.c:187
#define fail
Definition test.h:479
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_PIXEL_FMT
Underlying C type is enum AVPixelFormat.
Definition opt.h:306
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
Definition opt.h:270
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
@ 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...
Definition opt.h:275
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:139
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition buffer.c:103
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR(e)
Definition error.h:45
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition frame.c:496
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
Definition frame.c:523
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.
Definition side_data.c:123
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition frame.c:599
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:52
@ AV_SIDE_DATA_PROP_SIZE_DEPENDENT
Side data depends on the video dimensions.
Definition frame.h:354
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
Definition log.h:204
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition rational.c:80
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition rational.c:35
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
#define SWS_PARAM_DEFAULT
Definition swscale.h:456
@ SWS_SCALE_LANCZOS
3-tap sinc/sinc
Definition swscale.h:104
@ SWS_SCALE_BILINEAR
bilinear filtering
Definition swscale.h:98
@ SWS_SCALE_BICUBIC
2-tap cubic BC-spline
Definition swscale.h:99
static const int weights[]
Definition hevc_pel.c:32
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition hwcontext.c:337
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition hwcontext.c:263
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition hwcontext.c:506
FFmpeg internal API for CUDA.
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition jacosubdec.c:66
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define FF_FILTER_FLAG_HWFRAME_AWARE
The filter is aware of hardware frames, and any hardware frame context should not be automatically pr...
Definition filters.h:208
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
Definition filters.h:254
#define av_cold
Definition attributes.h:117
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
const char * desc
Definition libsvtav1.c:83
@ SWS_FILTER_SIZE_MAX
Definition filters.h:41
@ SWS_FILTER_SCALE
14-bit coefficients are picked to fit comfortably within int16_t for efficient SIMD processing (e....
Definition filters.h:40
static const struct @257111027162314367033347246032313251342043035002 planes[]
uint8_t w
Definition llvidencdsp.c:39
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.
Definition load_helper.c:34
#define FFMAX(a, b)
Definition macros.h:47
#define FFALIGN(x, a)
Definition macros.h:78
Memory handling functions.
AVOptions.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3500
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.
Definition pixdesc.c:3380
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_0RGB32
Definition pixfmt.h:521
#define AV_PIX_FMT_P212
Definition pixfmt.h:624
#define AV_PIX_FMT_YUV420P10
Definition pixfmt.h:545
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:783
#define AV_PIX_FMT_P210
Definition pixfmt.h:622
#define AV_PIX_FMT_P012
Definition pixfmt.h:609
#define AV_PIX_FMT_P216
Definition pixfmt.h:626
#define AV_PIX_FMT_P010
Definition pixfmt.h:608
#define AV_PIX_FMT_P016
Definition pixfmt.h:610
#define AV_PIX_FMT_YUV422P10
Definition pixfmt.h:546
#define AV_PIX_FMT_YUV444P12MSB
Definition pixfmt.h:561
#define AV_PIX_FMT_BGR32
Definition pixfmt.h:519
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ 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...
Definition pixfmt.h:96
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_CUDA
HW acceleration through CUDA.
Definition pixfmt.h:260
@ AV_PIX_FMT_NV16
interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:198
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition pixfmt.h:78
#define AV_PIX_FMT_YUV444P16
Definition pixfmt.h:558
#define AV_PIX_FMT_YUV444P10MSB
Definition pixfmt.h:560
#define AV_PIX_FMT_0BGR32
Definition pixfmt.h:522
#define AV_PIX_FMT_RGB32
Definition pixfmt.h:517
#define AV_PIX_FMT_YUV444P10
Definition pixfmt.h:548
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition refstruct.c:120
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 ...
Definition scale_eval.c:123
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.
Definition scale_eval.c:58
@ SCALE_FORCE_OAR_DISABLE
Definition scale_eval.h:25
@ SCALE_FORCE_OAR_NB
Definition scale_eval.h:28
@ SCALE_FORCE_OAR_INCREASE
Definition scale_eval.h:27
@ SCALE_FORCE_OAR_DECREASE
Definition scale_eval.h:26
#define FF_ARRAY_ELEMS(a)
#define snprintf
Definition snprintf.h:34
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
This struct is allocated as AVHWDeviceContext.hwctx.
Describe the class of an AVClass context structure.
Definition log.h:76
An instance of a filter.
Definition avfilter.h:273
AVFilterLink ** inputs
array of pointers to input links
Definition avfilter.h:281
void * priv
private data for use by the filter
Definition avfilter.h:288
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
int width
Definition frame.h:544
int height
Definition frame.h:544
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
Definition frame.h:569
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition frame.h:723
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition hwcontext.h:88
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition hwcontext.h:200
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition hwcontext.h:129
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
int width
The allocated dimensions of the frames in this pool.
Definition hwcontext.h:220
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition hwcontext.h:137
AVOption.
Definition opt.h:428
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
CUDAScaleFilter filters_uv[FILTER_NB]
enum AVPixelFormat format
Output sw format.
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
AVBufferRef * frames_ctx
CUdeviceptr weights
float[dst_size][filter_size]
CUdeviceptr offsets
int[dst_size]
int external_data
CUtexObject tex[4]
CUdeviceptr data[4]
int color_range
int log2_chroma_h
int linesize[4]
int crop_height
int log2_chroma_w
Represents a computed filter kernel.
Definition filters.h:85
enum AVPixelFormat format
char name[13]
#define av_free(p)
#define av_malloc_array(a, b)
#define av_log(a,...)
static uint8_t tmp[40]
Definition aes_ctr.c:52
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition h263dsp.c:29
#define src
Definition vp8dsp.c:248
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
static enum AVPixelFormat supported_formats[]
#define DIV_UP(a, b)
#define BLOCKX
#define BLOCKY
static av_cold void cudascale_setup_passes(AVFilterContext *ctx)
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)
#define DIV_UP(a, b)
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)
@ INTERP_ALGO_LANCZOS
@ INTERP_ALGO_BICUBIC
@ INTERP_ALGO_DEFAULT
@ INTERP_ALGO_BILINEAR
@ INTERP_ALGO_COUNT
@ INTERP_ALGO_NEAREST
static void cuda_tex_uninit(CudaFunctions *cu, CUDATex *t)
static int format_is_supported(enum AVPixelFormat fmt)
#define CHECK_CU(x)
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)
#define OFFSET(x)
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[]
@ FILTER_NB
@ FILTER_OUT
@ FILTER_TMP
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)
Definition video.c:44
AVFrame * ff_default_get_video_buffer(AVFilterLink *link, int w, int h)
Definition video.c:84