24#include "config_components.h"
44#if !NVDECAPI_CHECK_VERSION(9, 0)
45#define cudaVideoSurfaceFormat_YUV444 2
46#define cudaVideoSurfaceFormat_YUV444_16Bit 3
63#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
74#define CHECK_CU(x) FF_CUDA_CHECK_DL(logctx, decoder->cudl, x)
79#if CONFIG_AV1_NVDEC_HWACCEL
98 int shift_h = 0, shift_v = 0;
101 return cudaVideoChromaFormat_Monochrome;
105 if (shift_h == 1 && shift_v == 1)
106 return cudaVideoChromaFormat_420;
107 else if (shift_h == 1 && shift_v == 0)
108 return cudaVideoChromaFormat_422;
109 else if (shift_h == 0 && shift_v == 0)
110 return cudaVideoChromaFormat_444;
116 CUVIDDECODECREATEINFO *
params,
void *logctx)
119 CUVIDDECODECAPS caps = { 0 };
121 caps.eCodecType =
params->CodecType;
122 caps.eChromaFormat =
params->ChromaFormat;
123 caps.nBitDepthMinus8 =
params->bitDepthMinus8;
125 if (!
decoder->cvdl->cuvidGetDecoderCaps) {
126 av_log(logctx,
AV_LOG_WARNING,
"Used Nvidia driver is too old to perform a capability check.\n");
128#
if defined(_WIN32) || defined(__CYGWIN__)
133 ". Continuing blind.\n");
143 caps.bIsSupported ?
"yes" :
"no", caps.nMaxMBCount);
145 caps.nMinWidth, caps.nMaxWidth);
147 caps.nMinHeight, caps.nMaxHeight);
149 if (!caps.bIsSupported) {
154 if (
params->ulWidth > caps.nMaxWidth ||
params->ulWidth < caps.nMinWidth) {
156 (
int)
params->ulWidth, caps.nMinWidth, caps.nMaxWidth);
160 if (
params->ulHeight > caps.nMaxHeight ||
params->ulHeight < caps.nMinHeight) {
162 (
int)
params->ulHeight, caps.nMinHeight, caps.nMaxHeight);
166 if ((
params->ulWidth *
params->ulHeight) / 256 > caps.nMaxMBCount) {
168 (
int)(
params->ulWidth *
params->ulHeight) / 256, caps.nMaxMBCount);
183#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
195 decoder->cudl->cuCtxSynchronize();
198 for (
int i = 0;
i <
decoder->num_surfaces;
i++)
200 memory_order_acquire) != 0;
203 "%d CUarray surface(s) unexpectedly still in use at "
204 "decoder teardown; destroying anyway\n", busy);
212#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
219 cuvid_free_functions(&
decoder->cvdl);
223 CUVIDDECODECREATEINFO *
params,
void *logctx)
247 ret = cuvid_load_functions(&
decoder->cvdl, logctx);
282 unsigned int *intp = obj;
303 ctx->bitstream_len = 0;
304 ctx->bitstream_allocated = 0;
308 ctx->slice_offsets_allocated = 0;
347 if (!frames_ctx->
pool) {
365#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
366void ff_nvdec_fill_cuarray_desc(CUDA_ARRAY3D_DESCRIPTOR *
desc,
370 CUarray_format arr_fmt;
373 case cudaVideoSurfaceFormat_NV12:
374 case cudaVideoSurfaceFormat_NV12_Opaque: arr_fmt = CU_AD_FORMAT_NV12;
break;
375 case cudaVideoSurfaceFormat_P016:
376 case cudaVideoSurfaceFormat_P016_Opaque: arr_fmt = CU_AD_FORMAT_P016;
break;
377 case cudaVideoSurfaceFormat_NV16:
378 case cudaVideoSurfaceFormat_NV16_Opaque: arr_fmt = CU_AD_FORMAT_NV16;
break;
379 case cudaVideoSurfaceFormat_P216:
380 case cudaVideoSurfaceFormat_P216_Opaque: arr_fmt = CU_AD_FORMAT_P216;
break;
382 case cudaVideoSurfaceFormat_YUV444_Opaque: arr_fmt = CU_AD_FORMAT_YUV444_8BIT_SEMIPLANAR;
break;
384 case cudaVideoSurfaceFormat_YUV444_16Bit_Opaque: arr_fmt = CU_AD_FORMAT_YUV444_16BIT_SEMIPLANAR;
break;
396 desc->Format = arr_fmt;
397 desc->NumChannels = 3;
398 desc->Flags = CUDA_ARRAY3D_SURFACE_LDST |
399 CUDA_ARRAY3D_VIDEO_ENCODE_DECODE;
415 CUVIDDECODECREATEINFO
params = { 0 };
418 int cuvid_codec_type, cuvid_chroma_format, chroma_444;
420 int need_real_hwframes = 0;
424 int opaque_output = 0;
425 int decode_pool_size;
432 if (cuvid_codec_type < 0) {
438 if (cuvid_chroma_format < 0) {
442 chroma_444 =
ctx->supports_444 && cuvid_chroma_format == cudaVideoChromaFormat_444;
448 need_real_hwframes = 1;
453#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
460 "CUarray opaque output requires Video Codec SDK 13.1 or later\n");
466#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
470 av_log(avctx,
AV_LOG_VERBOSE,
"unsafe_output + cuarray: %d decode surfaces (pool=%d, max=%d)\n",
471 decode_pool_size, frames_ctx->
initial_pool_size, MAX_NUM_REGISTERED_DECODE_SURFACES);
474 av_log(avctx,
AV_LOG_VERBOSE,
"Opaque copy mode: %d decode surfaces, %d extra surfaces reserved for output pool\n",
484#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
485 if (opaque_output)
output_format = cudaVideoSurfaceFormat_YUV444_Opaque;
487#ifdef NVDEC_HAVE_422_SUPPORT
488 }
else if (cuvid_chroma_format == cudaVideoChromaFormat_422) {
490#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
491 if (opaque_output)
output_format = cudaVideoSurfaceFormat_NV16_Opaque;
496#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
497 if (opaque_output)
output_format = cudaVideoSurfaceFormat_NV12_Opaque;
505#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
506 if (opaque_output)
output_format = cudaVideoSurfaceFormat_YUV444_16Bit_Opaque;
508#ifdef NVDEC_HAVE_422_SUPPORT
509 }
else if (cuvid_chroma_format == cudaVideoChromaFormat_422) {
511#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
512 if (opaque_output)
output_format = cudaVideoSurfaceFormat_P216_Opaque;
517#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
518 if (opaque_output)
output_format = cudaVideoSurfaceFormat_P016_Opaque;
527 if (need_real_hwframes) {
529#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
535 &real_hw_frames_ref);
542 cuda_priv = real_ctx->
hwctx;
553 if (!decode_hw_frames_ref) {
560 &decode_hw_frames_ref);
567 cuda_priv = real_ctx->
hwctx;
583 if (!real_hw_frames_ref)
586#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
596 &decode_hw_frames_ref);
603 cuda_priv = real_ctx->
hwctx;
612 if (!decode_hw_frames_ref) {
626 params.CodecType = cuvid_codec_type;
627 params.ChromaFormat = cuvid_chroma_format;
628 params.ulNumDecodeSurfaces =
FFMIN(decode_pool_size, 32);
633 if (
params.ulNumDecodeSurfaces > 32) {
634 av_log(avctx,
AV_LOG_WARNING,
"Using more than 32 (%d) decode surfaces might cause nvdec to fail.\n",
635 (
int)
params.ulNumDecodeSurfaces);
643 decoder->unsafe_output = unsafe_output;
644 decoder->opaque_output = opaque_output;
646#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
648 void *logctx = avctx;
651 CUVIDREGISTERDECODESURFACESINFO reg_info = { 0 };
654 if (!
decoder->cvdl->cuvidRegisterDecodeSurfaces) {
665 (
unsigned)decode_pool_size);
672 decoder->num_surfaces = reg_info.ulNumDecodeSurfaces;
674 sizeof(*
decoder->surface_in_use));
675 if (!
decoder->surface_in_use) {
682 decoder->decode_hw_frames_ref = decode_hw_frames_ref;
683 decode_hw_frames_ref =
NULL;
684 decoder->real_hw_frames_ref = real_hw_frames_ref;
685 real_hw_frames_ref =
NULL;
697 if (!
ctx->decoder_pool) {
732 void *logctx =
decoder->hw_device_ref->data;
733 CUdeviceptr devptr = (CUdeviceptr)opaque;
752#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
753typedef struct NVDECOpaqueRelease {
756 unsigned int *idx_ref;
759static void nvdec_opaque_release_slot(
void *opaque, uint8_t *
data)
761 NVDECOpaqueRelease *
r = (NVDECOpaqueRelease *)opaque;
762 if (
r->decoder->surface_in_use)
764 memory_order_release);
779 CUVIDPROCPARAMS vpp = { 0 };
785 unsigned int pitch,
i;
787 int shift_h = 0, shift_v = 0;
790#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
797 "NVDEC opaque surface index %u out of range (%d surfaces)\n",
805 NVDECOpaqueRelease *rel;
814 nvdec_opaque_release_slot, rel,
831 memory_order_release);
835 ?
decoder->decode_hw_frames_ref
836 :
decoder->real_hw_frames_ref);
843 frame->buf[0] = buf0;
844 frame->data[0] = (uint8_t *)arr;
853 CUDA_ARRAY3D_DESCRIPTOR plane_desc = { 0 };
856 CUresult cures =
decoder->cudl->cuArrayGetPlane(&plane_array, arr, p);
857 if (cures == CUDA_ERROR_INVALID_VALUE)
859 if (cures != CUDA_SUCCESS) {
863 ret =
CHECK_CU(
decoder->cudl->cuArray3DGetDescriptor(&plane_desc, plane_array));
871 frame->linesize[p] = plane_desc.Width * plane_desc.NumChannels * elem_size;
886 vpp.progressive_frame = 1;
887 vpp.output_stream =
decoder->stream;
908 if (!
frame->buf[1]) {
917 unmap_data->
idx = cf->
idx;
921 for (
i = 0;
frame->linesize[
i];
i++) {
923 frame->linesize[
i] = pitch;
930 if (!
frame->buf[1]) {
940 if (ret < 0 || decoder->unsafe_output)
953 ctx->bitstream_len = 0;
1018 void *logctx = avctx;
1019 CUVIDPICPARAMS *pp = &
ctx->pic_params;
1025 pp->nBitstreamDataLen =
ctx->bitstream_len;
1026 pp->pBitstreamData =
ctx->bitstream;
1027 pp->nNumSlices =
ctx->nb_slices;
1028 pp->pSliceDataOffsets =
ctx->slice_offsets;
1034#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
1035 if (
decoder->opaque_output &&
decoder->cvdl->cuvidDecodePictureAsync)
1056 ctx->bitstream_len = 0;
1068 (
ctx->nb_slices + 1) *
sizeof(*
ctx->slice_offsets));
1071 ctx->slice_offsets =
tmp;
1073 if (!
ctx->bitstream)
1091 int cuvid_codec_type, cuvid_chroma_format, chroma_444;
1105 if (cuvid_codec_type < 0) {
1111 if (cuvid_chroma_format < 0) {
1115 chroma_444 = supports_444 && cuvid_chroma_format == cudaVideoChromaFormat_444;
1117 frames_ctx->
format = hw_format;
1122 if (cuvid_chroma_format == cudaVideoChromaFormat_420 ||
1123 cuvid_chroma_format == cudaVideoChromaFormat_422) {
1141#ifdef NVDEC_HAVE_422_SUPPORT
1142 }
else if (cuvid_chroma_format == cudaVideoChromaFormat_422) {
1153#ifdef NVDEC_HAVE_422_SUPPORT
1154 }
else if (cuvid_chroma_format == cudaVideoChromaFormat_422) {
1165#ifdef NVDEC_HAVE_422_SUPPORT
1166 }
else if (cuvid_chroma_format == cudaVideoChromaFormat_422) {
1188 fdd =
frame->private_ref;
SwsAArch64OpImplParams params
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Libavcodec external API header.
#define i(width, name, range_min, range_max)
common internal and external API header
#define cudaVideoSurfaceFormat_YUV444
#define cudaVideoSurfaceFormat_YUV444_16Bit
static DecodeContext * decode_ctx(AVCodecInternal *avci)
static enum AVPixelFormat pix_fmt
#define atomic_load_explicit(object, order)
#define atomic_store_explicit(object, desired, order)
static char * output_format
AVCodecID
Identify the syntax and semantics of the bitstream.
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, AVBufferRef *device_ref, enum AVPixelFormat hw_pix_fmt, AVBufferRef **out_frames_ref)
Create and return a AVHWFramesContext with values adequate for hardware decoding.
#define AV_HWACCEL_FLAG_UNSAFE_OUTPUT
Some hardware decoders (namely nvdec) can either output direct decoder surfaces, or make an on-device...
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
int av_buffer_replace(AVBufferRef **pdst, const AVBufferRef *src)
Ensure dst refers to the same data as src.
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
AVBufferPool * av_buffer_pool_init(size_t size, AVBufferRef *(*alloc)(size_t size))
Allocate and initialize a buffer pool.
#define AVERROR_EXTERNAL
Generic error in an external library.
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
int av_frame_make_writable(AVFrame *frame)
Ensure that the frame data is writable, avoiding data copy if possible.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
static AVBufferRef * hw_device_ctx
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
FFmpeg internal API for CUDA.
static int ff_cuda_cuarray_elem_size(CUarray_format fmt)
Return the element size in bytes for a CUarray_format, or 0 for unknown.
static const chunk_decoder decoder[8]
common internal api header.
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
int ff_nvdec_start_frame_sep_ref(AVCodecContext *avctx, AVFrame *frame, int has_sep_ref)
static int nvdec_decoder_create(NVDECDecoder **out, AVBufferRef *hw_device_ref, CUVIDDECODECREATEINFO *params, void *logctx)
int ff_nvdec_simple_end_frame(AVCodecContext *avctx)
int ff_nvdec_simple_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
static int map_chroma_format(enum AVPixelFormat pix_fmt)
static void nvdec_decoder_frame_pool_free(AVRefStructOpaque opaque)
int ff_nvdec_decode_init(AVCodecContext *avctx)
static void nvdec_free_dummy(struct AVHWFramesContext *ctx)
int ff_nvdec_get_ref_idx(AVFrame *frame)
static void nvdec_decoder_free(AVRefStructOpaque unused, void *obj)
int ff_nvdec_end_frame(AVCodecContext *avctx)
static void nvdec_unmap_mapped_frame(void *opaque, uint8_t *data)
int ff_nvdec_start_frame(AVCodecContext *avctx, AVFrame *frame)
static int nvdec_init_hwframes(AVCodecContext *avctx, AVBufferRef **out_frames_ref, int dummy)
static int nvdec_test_capabilities(NVDECDecoder *decoder, CUVIDDECODECREATEINFO *params, void *logctx)
static int nvdec_decoder_frame_init(AVRefStructOpaque opaque, void *obj)
static int map_avcodec_id(enum AVCodecID id)
static int nvdec_retrieve_data(void *logctx, AVFrame *frame)
static void nvdec_fdd_priv_free(void *priv)
int ff_nvdec_decode_uninit(AVCodecContext *avctx)
int ff_nvdec_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx, enum AVPixelFormat hw_format, int dpb_size, int supports_444)
static AVBufferRef * nvdec_alloc_dummy(size_t size)
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
int av_pix_fmt_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift)
Utility function to access log2_chroma_w log2_chroma_h from the pixel format AVPixFmtDescriptor.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
#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_CUDA
HW acceleration through CUDA.
@ AV_PIX_FMT_NV24
planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
@ 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)
@ AV_PIX_FMT_CUARRAY
hardware decoding through openharmony
#define AV_PIX_FMT_YUV444P10MSB
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
void * av_refstruct_pool_get(AVRefStructPool *pool)
Get an object from the pool, reusing an old one from the pool when available.
void * av_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
static void * av_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, void(*free_cb)(AVRefStructOpaque opaque, void *obj))
A wrapper around av_refstruct_alloc_ext_c() for the common case of a non-const qualified opaque.
static AVRefStructPool * av_refstruct_pool_alloc_ext(size_t size, unsigned flags, void *opaque, int(*init_cb)(AVRefStructOpaque opaque, void *obj), void(*reset_cb)(AVRefStructOpaque opaque, void *obj), void(*free_entry_cb)(AVRefStructOpaque opaque, void *obj), void(*free_cb)(AVRefStructOpaque opaque))
A wrapper around av_refstruct_pool_alloc_ext_c() for the common case of a non-const qualified opaque.
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
uint8_t * data
The data buffer.
This struct is allocated as AVHWDeviceContext.hwctx.
AVCUDADeviceContextInternal * internal
This struct is allocated as AVHWFramesContext.hwctx.
CUarray * cuarray_surfaces
If cuarray_num_surfaces is >0, this contains the array of pre-allocated surfaces.
CUDA_ARRAY3D_DESCRIPTOR cuarray_desc
CUDA_ARRAY3D_DESCRIPTOR CUarrays will be initialized with.
int cuarray_num_surfaces
If >0, pre-allocate a fixed pool of surfaces.
main external API structure.
int hwaccel_flags
Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated decoding (if active).
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
const struct AVHWAccel * hwaccel
Hardware accelerator in use.
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
int extra_hw_frames
Video decoding only.
int coded_width
Bitstream width / height, may be different from width/height e.g.
struct AVCodecInternal * internal
Private context used for internal data.
void * hwaccel_priv_data
hwaccel-specific private data
int depth
Number of bits in the component.
This structure describes decoded (raw) audio or video data.
enum AVPixelFormat pix_fmt
Supported pixel format.
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
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.
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
int initial_pool_size
Initial size of the frame pool.
int width
The allocated dimensions of the frames in this pool.
void(* free)(struct AVHWFramesContext *ctx)
This field may be set by the caller before calling av_hwframe_ctx_init().
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
This struct stores per-frame lavc-internal data and is attached to it via private_ref.
void(* hwaccel_priv_free)(void *priv)
int(* hwaccel_priv_post_process)(void *logctx, AVFrame *frame)
Per-frame private data for hwaccels.
AVBufferRef * decode_hw_frames_ref
AVBufferRef * real_hw_frames_ref
AVBufferRef * hw_device_ref
unsigned int nb_allocated
struct NVDECDecoder * decoder
RefStruct reference.
unsigned int * ref_idx_ref
RefStruct reference.
unsigned int * idx_ref
RefStruct reference.
static AVFormatContext * ctx
RefStruct is an API for creating reference-counted objects with minimal overhead.