22#include "config_components.h"
47#if !NVDECAPI_CHECK_VERSION(9, 0)
48#define cudaVideoSurfaceFormat_YUV444 2
49#define cudaVideoSurfaceFormat_YUV444_16Bit 3
52#if NVDECAPI_CHECK_VERSION(11, 0)
53#define CUVID_HAS_AV1_SUPPORT
56#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
57typedef struct CuvidDecoderCleanup {
58 CUvideodecoder cudecoder;
59 CUarray *cuarray_surfaces;
60 int cuarray_num_surfaces;
126#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
127 CUarray *cuarray_surfaces;
128 int cuarray_num_surfaces;
131 CuvidDecoderCleanup *decoder_cleanup;
142#define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, ctx->cudl, x)
145#define CUVID_MAX_DISPLAY_DELAY (4)
148#define CUVID_DEFAULT_NUM_SURFACES (CUVID_MAX_DISPLAY_DELAY + 1)
155 if (
ctx->zero_copy) {
158 "zero_copy requires cuarray output format; "
159 "overriding -output_format %s -> cuarray\n",
171#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
175 "CUARRAY output requires Video Codec SDK 13.1 or later\n");
180 "Unsupported cuvid output format: %s\n",
201 "ff_get_format returned %s, overriding to explicitly requested %s\n",
203 selected = requested;
219#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
220typedef struct CuvidSurfaceRelease {
221 AVBufferRef *in_use_ref;
223} CuvidSurfaceRelease;
225static void cuvid_cuarray_buf_free(
void *opaque, uint8_t *
data)
227 CuvidSurfaceRelease *rel = opaque;
234static void cuvid_decoder_cleanup_free(
void *opaque, uint8_t *
data)
236 CuvidDecoderCleanup *
cleanup = opaque;
244 cudl->cuCtxPushCurrent(device_hwctx->
cuda_ctx);
249 if (
cleanup->cuarray_surfaces) {
250 for (
int i = 0;
i <
cleanup->cuarray_num_surfaces;
i++)
251 cudl->cuArrayDestroy(
cleanup->cuarray_surfaces[
i]);
254 cudl->cuCtxPopCurrent(&
dummy);
260 cuvid_free_functions(&
cleanup->cvdl);
274 CUVIDDECODECAPS *caps =
NULL;
275 CUVIDDECODECREATEINFO cuinfo;
278 int old_nb_surfaces, old_opaque_output =
ctx->opaque_output;
279 int fifo_size_inc, fifo_size_mul = 1;
282 int old_width = avctx->
width;
283 int old_height = avctx->
height;
289 memset(&cuinfo, 0,
sizeof(cuinfo));
291 ctx->internal_error = 0;
294 if (surface_fmt < 0) {
295 ctx->internal_error = surface_fmt;
303 cuinfo.display_area.left =
format->display_area.left +
ctx->crop.left;
304 cuinfo.display_area.top =
format->display_area.top +
ctx->crop.top;
305 cuinfo.display_area.right =
format->display_area.right -
ctx->crop.right;
306 cuinfo.display_area.bottom =
format->display_area.bottom -
ctx->crop.bottom;
309 if (
ctx->resize_expr) {
313 avctx->
width = cuinfo.display_area.right - cuinfo.display_area.left;
314 avctx->
height = cuinfo.display_area.bottom - cuinfo.display_area.top;
321 cuinfo.ulTargetWidth = (avctx->
width + 1) & ~1;
322 cuinfo.ulTargetHeight = (avctx->
height + 1) & ~1;
323 if (
format->chroma_format == cudaVideoChromaFormat_420 ||
324 format->chroma_format == cudaVideoChromaFormat_422) {
325 avctx->
width = cuinfo.ulTargetWidth;
326 avctx->
height = cuinfo.ulTargetHeight;
330 cuinfo.target_rect.left = 0;
331 cuinfo.target_rect.top = 0;
332 cuinfo.target_rect.right = cuinfo.ulTargetWidth;
333 cuinfo.target_rect.bottom = cuinfo.ulTargetHeight;
335 chroma_444 =
format->chroma_format == cudaVideoChromaFormat_444;
337 switch (
format->bit_depth_luma_minus8) {
341#ifdef NVDEC_HAVE_422_SUPPORT
342 }
else if (
format->chroma_format == cudaVideoChromaFormat_422) {
353#ifdef NVDEC_HAVE_422_SUPPORT
354 }
else if (
format->chroma_format == cudaVideoChromaFormat_422) {
365#ifdef NVDEC_HAVE_422_SUPPORT
366 }
else if (
format->chroma_format == cudaVideoChromaFormat_422) {
378 if (!caps || !caps->bIsSupported) {
380 format->bit_depth_luma_minus8 + 8);
388 if (surface_fmt < 0) {
395 requested_hw_format);
407 if (
ctx->opaque_output) {
433 ctx->deint_mode_current =
format->progressive_sequence
434 ? cudaVideoDeinterlaceMode_Weave
437 ctx->progressive_sequence =
format->progressive_sequence;
439 if (!
format->progressive_sequence &&
ctx->deint_mode_current == cudaVideoDeinterlaceMode_Weave)
444 if (
format->video_signal_description.video_full_range_flag)
449 if (
format->video_signal_description.color_primaries)
451 if (
format->video_signal_description.transfer_characteristics)
452 avctx->
color_trc =
format->video_signal_description.transfer_characteristics;
453 if (
format->video_signal_description.matrix_coefficients)
459 if (
format->frame_rate.numerator &&
format->frame_rate.denominator) {
464 if (
ctx->cudecoder &&
ctx->opaque_output != old_opaque_output) {
466 "Changing between opaque and non-opaque output is not supported\n");
474 && avctx->
width == old_width
475 && avctx->
height == old_height
476 &&
ctx->chroma_format ==
format->chroma_format
480 if (
ctx->cudecoder) {
483 if (
ctx->internal_error < 0)
488 if (hwframe_ctx->
pool && (
491 hwframe_ctx->
format != internal_hw_format ||
493 av_log(avctx,
AV_LOG_ERROR,
"AVHWFramesContext is already initialized with incompatible parameters\n");
504 ctx->chroma_format =
format->chroma_format;
506 cuinfo.CodecType =
ctx->codec_type =
format->codec;
507 cuinfo.ChromaFormat =
format->chroma_format;
511 cuinfo.OutputFormat = cudaVideoSurfaceFormat_NV12;
516 cuinfo.OutputFormat = cudaVideoSurfaceFormat_P016;
518#ifdef NVDEC_HAVE_422_SUPPORT
520 cuinfo.OutputFormat = cudaVideoSurfaceFormat_NV16;
525 cuinfo.OutputFormat = cudaVideoSurfaceFormat_P216;
547#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
548 if (
ctx->opaque_output) {
549 switch (cuinfo.OutputFormat) {
550 case cudaVideoSurfaceFormat_NV12: cuinfo.OutputFormat = cudaVideoSurfaceFormat_NV12_Opaque;
break;
551 case cudaVideoSurfaceFormat_P016: cuinfo.OutputFormat = cudaVideoSurfaceFormat_P016_Opaque;
break;
552#ifdef NVDEC_HAVE_422_SUPPORT
553 case cudaVideoSurfaceFormat_NV16: cuinfo.OutputFormat = cudaVideoSurfaceFormat_NV16_Opaque;
break;
554 case cudaVideoSurfaceFormat_P216: cuinfo.OutputFormat = cudaVideoSurfaceFormat_P216_Opaque;
break;
563 if (
ctx->deint_mode_current != cudaVideoDeinterlaceMode_Weave && !
ctx->drop_second_field) {
568 old_nb_surfaces =
ctx->nb_surfaces;
572#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
573 if (
ctx->opaque_output &&
ctx->zero_copy)
575 MAX_NUM_REGISTERED_DECODE_SURFACES);
579 if (fifo_size_inc > 0 &&
av_fifo_grow2(
ctx->frame_queue, fifo_size_inc) < 0) {
580 av_log(avctx,
AV_LOG_ERROR,
"Failed to grow frame queue on video sequence callback\n");
586 av_log(avctx,
AV_LOG_ERROR,
"Failed to grow key frame array on video sequence callback\n");
591 cuinfo.ulNumDecodeSurfaces =
ctx->nb_surfaces;
592 cuinfo.ulNumOutputSurfaces =
ctx->opaque_output ? 0 : 1;
593 cuinfo.ulCreationFlags = cudaVideoCreate_PreferCUVID;
594 cuinfo.bitDepthMinus8 =
format->bit_depth_luma_minus8;
595 cuinfo.DeinterlaceMode =
ctx->deint_mode_current;
597 ctx->internal_error =
CHECK_CU(
ctx->cvdl->cuvidCreateDecoder(&
ctx->cudecoder, &cuinfo));
598 if (
ctx->internal_error < 0)
601#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
602 if (
ctx->opaque_output) {
603 CUDA_ARRAY3D_DESCRIPTOR arr_desc;
604 CUVIDREGISTERDECODESURFACESINFO reg_info;
608 ff_nvdec_fill_cuarray_desc(&arr_desc, avctx, cuinfo.OutputFormat);
610 if (
ctx->cuarray_surfaces) {
611 if (
ctx->decoder_cleanup) {
612 ctx->decoder_cleanup->cuarray_surfaces =
NULL;
613 ctx->decoder_cleanup->cuarray_num_surfaces = 0;
614 ctx->decoder_cleanup->cudecoder =
NULL;
617 for (
i = 0;
i <
ctx->cuarray_num_surfaces;
i++)
618 ctx->cudl->cuArrayDestroy(
ctx->cuarray_surfaces[
i]);
623 ctx->cuarray_num_surfaces =
ctx->nb_surfaces;
624 ctx->cuarray_surfaces =
av_calloc(
ctx->cuarray_num_surfaces,
sizeof(CUarray));
625 if (!
ctx->cuarray_surfaces) {
636 if (
ctx->zero_copy) {
646 (uint8_t *)
flags,
ctx->cuarray_num_surfaces *
sizeof(*
flags),
649 if (!
ctx->surface_in_use_ref) {
659 for (
i = 0;
i <
ctx->cuarray_num_surfaces;
i++) {
661 &
ctx->cuarray_surfaces[
i], &arr_desc));
662 if (
ctx->internal_error < 0) {
663 for (
int j = 0; j <
i; j++)
664 ctx->cudl->cuArrayDestroy(
ctx->cuarray_surfaces[j]);
668 ctx->cuarray_num_surfaces = 0;
680 if (
ctx->internal_error < 0)
683 memset(®_info, 0,
sizeof(reg_info));
684 reg_info.ulNumDecodeSurfaces =
ctx->cuarray_num_surfaces;
685 reg_info.pDecodeSurfaces =
ctx->cuarray_surfaces;
687 if (
ctx->cvdl->cuvidRegisterDecodeSurfaces) {
689 ctx->cvdl->cuvidRegisterDecodeSurfaces(
690 ctx->cudecoder, ®_info));
692 av_log(avctx,
AV_LOG_ERROR,
"cuvidRegisterDecodeSurfaces not available in loaded driver\n");
696 if (
ctx->internal_error < 0)
699 if (
ctx->decoder_cleanup) {
700 ctx->decoder_cleanup->cudecoder =
ctx->cudecoder;
701 ctx->decoder_cleanup->cuarray_surfaces =
ctx->cuarray_surfaces;
702 ctx->decoder_cleanup->cuarray_num_surfaces =
ctx->cuarray_num_surfaces;
707 if (!hwframe_ctx->
pool) {
708 hwframe_ctx->
format = internal_hw_format;
713#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
716 ff_nvdec_fill_cuarray_desc(&cuda_hwctx->
cuarray_desc, avctx, cuinfo.OutputFormat);
726 if(
ctx->cuparseinfo.ulMaxNumDecodeSurfaces != cuinfo.ulNumDecodeSurfaces) {
727 ctx->cuparseinfo.ulMaxNumDecodeSurfaces = cuinfo.ulNumDecodeSurfaces;
728 return cuinfo.ulNumDecodeSurfaces;
744 if(picparams->intra_pic_flag)
745 ctx->key_frame[picparams->CurrPicIdx] = picparams->intra_pic_flag;
747#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
748 if (
ctx->opaque_output) {
749 if (
ctx->surface_in_use &&
751 memory_order_acquire)) {
753 "CUARRAY surface %d still in use by the encoder. "
754 "Increase surfaces with -extra_hw_frames or reduce "
755 "encoder buffering (disable lookahead, reduce B-frames).\n",
756 picparams->CurrPicIdx);
761 if (
ctx->cvdl->cuvidDecodePictureAsync)
762 ctx->internal_error =
CHECK_CU(
ctx->cvdl->cuvidDecodePictureAsync(
763 ctx->cudecoder, picparams,
ctx->cuda_stream));
765 ctx->internal_error =
CHECK_CU(
ctx->cvdl->cuvidDecodePicture(
ctx->cudecoder, picparams));
768 ctx->internal_error =
CHECK_CU(
ctx->cvdl->cuvidDecodePicture(
ctx->cudecoder, picparams));
769 if (
ctx->internal_error < 0)
786 ctx->internal_error = 0;
789 parsed_frame.
dispinfo.progressive_frame =
ctx->progressive_sequence;
791 if (
ctx->deint_mode_current == cudaVideoDeinterlaceMode_Weave) {
801 if (!
ctx->drop_second_field) {
817 if (
ctx->deint_mode != cudaVideoDeinterlaceMode_Weave && !
ctx->drop_second_field)
830 CUVIDSOURCEDATAPACKET cupkt;
831 int ret = 0, eret = 0, is_flush =
ctx->decoder_flushing;
838 if (is_flush && avpkt && avpkt->
size)
844 ret =
CHECK_CU(
ctx->cudl->cuCtxPushCurrent(cuda_ctx));
849 memset(&cupkt, 0,
sizeof(cupkt));
851 if (avpkt && avpkt->
size) {
852 cupkt.payload_size = avpkt->
size;
853 cupkt.payload = avpkt->
data;
856 cupkt.flags = CUVID_PKT_TIMESTAMP;
860 cupkt.timestamp = avpkt->
pts;
863 cupkt.flags = CUVID_PKT_ENDOFSTREAM;
864 ctx->decoder_flushing = 1;
870 ret =
CHECK_CU(
ctx->cvdl->cuvidParseVideoData(
ctx->cuparser, &cupkt));
878 if (
ctx->internal_error) {
880 ret =
ctx->internal_error;
904 CUdeviceptr mapped_frame = 0;
905 int ret = 0, eret = 0;
910 if (
ctx->decoder_flushing) {
931 ret =
CHECK_CU(
ctx->cudl->cuCtxPushCurrent(cuda_ctx));
938 unsigned int pitch = 0;
943 params.progressive_frame = parsed_frame.
dispinfo.progressive_frame;
947#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
949 if (
ctx->zero_copy) {
950 int idx = parsed_frame.
dispinfo.picture_index;
952 if (idx < 0 || idx >=
ctx->cuarray_num_surfaces) {
954 idx,
ctx->cuarray_num_surfaces);
966 if (!
frame->hw_frames_ctx) {
972 CuvidSurfaceRelease *rel =
av_malloc(
sizeof(*rel));
978 if (!rel->in_use_ref) {
985 memory_order_release);
987 (uint8_t *)
ctx->cuarray_surfaces[idx], 0,
988 cuvid_cuarray_buf_free, rel,
990 if (!
frame->buf[0]) {
992 memory_order_release);
1000 frame->data[0] = (uint8_t *)
ctx->cuarray_surfaces[idx];
1004 CUDA_ARRAY3D_DESCRIPTOR plane_desc = { 0 };
1005 CUarray plane_array;
1007 CUresult cures =
ctx->cudl->cuArrayGetPlane(
1008 &plane_array,
ctx->cuarray_surfaces[idx], p);
1009 if (cures == CUDA_ERROR_INVALID_VALUE)
1011 if (cures != CUDA_SUCCESS) {
1017 &plane_desc, plane_array));
1022 if (elem_size <= 0) {
1024 "Unknown CUarray element format %d on plane %d\n",
1025 plane_desc.Format, p);
1030 frame->linesize[p] = plane_desc.Width *
1031 plane_desc.NumChannels * elem_size;
1034 int src_idx = parsed_frame.
dispinfo.picture_index;
1037 if (src_idx < 0 || src_idx >=
ctx->cuarray_num_surfaces) {
1038 av_log(avctx,
AV_LOG_ERROR,
"CUARRAY source surface index %d out of range [0, %d)\n",
1039 src_idx,
ctx->cuarray_num_surfaces);
1056 memset(&tmp_frame, 0,
sizeof(tmp_frame));
1058 tmp_frame.
data[0] = (uint8_t *)
ctx->cuarray_surfaces[src_idx];
1094 CUDA_MEMCPY2D cpy = {
1095 .srcMemoryType = CU_MEMORYTYPE_DEVICE,
1096 .dstMemoryType = CU_MEMORYTYPE_DEVICE,
1097 .srcDevice = mapped_frame,
1098 .dstDevice = (CUdeviceptr)
frame->data[
i],
1100 .dstPitch =
frame->linesize[
i],
1116#ifdef NVDEC_HAVE_422_SUPPORT
1153 tmp_frame->
data[
i] = (uint8_t*)mapped_frame +
offset;
1178 if (
ctx->key_frame[parsed_frame.
dispinfo.picture_index])
1182 ctx->key_frame[parsed_frame.
dispinfo.picture_index] = 0;
1192 if (
ctx->prev_pts == INT64_MIN) {
1196 int pts_diff = (
frame->pts -
ctx->prev_pts) / 2;
1198 frame->pts += pts_diff;
1205 frame->duration = 0;
1212 }
else if (
ctx->decoder_flushing ||
1224 eret =
CHECK_CU(
ctx->cvdl->cuvidUnmapVideoFrame(
ctx->cudecoder, mapped_frame));
1246 ctx->cudl->cuCtxPushCurrent(cuda_ctx);
1248#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
1249 if (
ctx->opaque_output)
1250 ctx->cudl->cuCtxSynchronize();
1254 ctx->cvdl->cuvidDestroyVideoParser(
ctx->cuparser);
1255#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
1256 if (
ctx->decoder_cleanup) {
1258 ctx->decoder_cleanup->cvdl =
ctx->cvdl;
1262 ctx->cuarray_num_surfaces = 0;
1270 ctx->cvdl->cuvidDestroyDecoder(
ctx->cudecoder);
1272#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
1273 if (
ctx->cuarray_surfaces) {
1274 for (
int i = 0;
i <
ctx->cuarray_num_surfaces;
i++)
1275 ctx->cudl->cuArrayDestroy(
ctx->cuarray_surfaces[
i]);
1279 ctx->cuarray_num_surfaces = 0;
1284 ctx->cudl->cuCtxPopCurrent(&
dummy);
1295 cuvid_free_functions(&
ctx->cvdl);
1301 const CUVIDPARSERPARAMS *cuparseinfo,
1304 int bit_depth,
int is_yuv422,
int is_yuv444)
1307 CUVIDDECODECAPS *caps;
1308 int res8 = 0, res10 = 0, res12 = 0;
1310 if (!
ctx->cvdl->cuvidGetDecoderCaps) {
1311 av_log(avctx,
AV_LOG_WARNING,
"Used Nvidia driver is too old to perform a capability check.\n");
1313#
if defined(_WIN32) || defined(__CYGWIN__)
1318 ". Continuing blind.\n");
1319 ctx->caps8.bIsSupported =
ctx->caps10.bIsSupported = 1;
1321 ctx->caps12.bIsSupported = 0;
1325 ctx->caps8.eCodecType =
ctx->caps10.eCodecType =
ctx->caps12.eCodecType
1326 = cuparseinfo->CodecType;
1328 ctx->caps8.eChromaFormat =
ctx->caps10.eChromaFormat =
ctx->caps12.eChromaFormat
1329 = is_yuv444 ? cudaVideoChromaFormat_444 :
1330#ifdef NVDEC_HAVE_422_SUPPORT
1331 (is_yuv422 ? cudaVideoChromaFormat_422 : cudaVideoChromaFormat_420);
1333 cudaVideoChromaFormat_420;
1336 ctx->caps8.nBitDepthMinus8 = 0;
1337 ctx->caps10.nBitDepthMinus8 = 2;
1338 ctx->caps12.nBitDepthMinus8 = 4;
1345 av_log(avctx,
AV_LOG_VERBOSE,
"8 bit: supported: %d, min_width: %d, max_width: %d, min_height: %d, max_height: %d\n",
1346 ctx->caps8.bIsSupported,
ctx->caps8.nMinWidth,
ctx->caps8.nMaxWidth,
ctx->caps8.nMinHeight,
ctx->caps8.nMaxHeight);
1347 av_log(avctx,
AV_LOG_VERBOSE,
"10 bit: supported: %d, min_width: %d, max_width: %d, min_height: %d, max_height: %d\n",
1348 ctx->caps10.bIsSupported,
ctx->caps10.nMinWidth,
ctx->caps10.nMaxWidth,
ctx->caps10.nMinHeight,
ctx->caps10.nMaxHeight);
1349 av_log(avctx,
AV_LOG_VERBOSE,
"12 bit: supported: %d, min_width: %d, max_width: %d, min_height: %d, max_height: %d\n",
1350 ctx->caps12.bIsSupported,
ctx->caps12.nMinWidth,
ctx->caps12.nMaxWidth,
ctx->caps12.nMinHeight,
ctx->caps12.nMaxHeight);
1354 caps = &
ctx->caps10;
1359 caps = &
ctx->caps12;
1369 if (!
ctx->caps8.bIsSupported) {
1374 if (!caps->bIsSupported) {
1379 if (probed_width > caps->nMaxWidth || probed_width < caps->nMinWidth) {
1381 probed_width, caps->nMinWidth, caps->nMaxWidth);
1385 if (probed_height > caps->nMaxHeight || probed_height < caps->nMinHeight) {
1387 probed_height, caps->nMinHeight, caps->nMaxHeight);
1391 if ((probed_width * probed_height) / 256 > caps->nMaxMBCount) {
1393 (
int)(probed_width * probed_height) / 256, caps->nMaxMBCount);
1406 CUVIDSOURCEDATAPACKET seq_pkt;
1407 CUcontext cuda_ctx =
NULL;
1418 int probed_bit_depth = 8, is_yuv444 = 0, is_yuv422 = 0;
1422 probed_bit_depth = probe_desc->
comp[0].
depth;
1427#ifdef NVDEC_HAVE_422_SUPPORT
1437 switch (probed_bit_depth) {
1463 requested_hw_format);
1468 if (
ctx->opaque_output) {
1477 if (
ctx->resize_expr && sscanf(
ctx->resize_expr,
"%dx%d",
1478 &
ctx->resize.width, &
ctx->resize.height) != 2) {
1484 if (
ctx->crop_expr && sscanf(
ctx->crop_expr,
"%dx%dx%dx%d",
1485 &
ctx->crop.top, &
ctx->crop.bottom,
1486 &
ctx->crop.left, &
ctx->crop.right) != 4) {
1492 if (
ctx->opaque_output) {
1493 if (
ctx->crop_expr) {
1495 "Cropping is not supported with cuarray output; "
1496 "crop option will be ignored\n");
1497 memset(&
ctx->crop, 0,
sizeof(
ctx->crop));
1499 if (
ctx->resize_expr) {
1501 "Resizing is not supported with cuarray output; "
1502 "resize option will be ignored\n");
1505 if (
ctx->deint_mode != cudaVideoDeinterlaceMode_Weave) {
1507 "Deinterlacing is not supported with cuarray output; "
1508 "deint mode will be forced to weave\n");
1509 ctx->deint_mode = cudaVideoDeinterlaceMode_Weave;
1513 ret = cuvid_load_functions(&
ctx->cvdl, avctx);
1520 if(
ctx->nb_surfaces < 0)
1524 if (!
ctx->frame_queue) {
1531 if (!
ctx->hwframe) {
1539 if (!
ctx->hwdevice) {
1546 if (!
ctx->hwdevice) {
1557 if (!
ctx->hwframe) {
1567 device_hwctx = device_ctx->
hwctx;
1572 ctx->cuda_stream = device_hwctx->
stream;
1574 memset(&
ctx->cuparseinfo, 0,
sizeof(
ctx->cuparseinfo));
1575 memset(&seq_pkt, 0,
sizeof(seq_pkt));
1578#if CONFIG_H264_CUVID_DECODER
1580 ctx->cuparseinfo.CodecType = cudaVideoCodec_H264;
1583#if CONFIG_HEVC_CUVID_DECODER
1585 ctx->cuparseinfo.CodecType = cudaVideoCodec_HEVC;
1588#if CONFIG_MJPEG_CUVID_DECODER
1590 ctx->cuparseinfo.CodecType = cudaVideoCodec_JPEG;
1593#if CONFIG_MPEG1_CUVID_DECODER
1595 ctx->cuparseinfo.CodecType = cudaVideoCodec_MPEG1;
1598#if CONFIG_MPEG2_CUVID_DECODER
1600 ctx->cuparseinfo.CodecType = cudaVideoCodec_MPEG2;
1603#if CONFIG_MPEG4_CUVID_DECODER
1605 ctx->cuparseinfo.CodecType = cudaVideoCodec_MPEG4;
1608#if CONFIG_VP8_CUVID_DECODER
1610 ctx->cuparseinfo.CodecType = cudaVideoCodec_VP8;
1613#if CONFIG_VP9_CUVID_DECODER
1615 ctx->cuparseinfo.CodecType = cudaVideoCodec_VP9;
1618#if CONFIG_VC1_CUVID_DECODER
1620 ctx->cuparseinfo.CodecType = cudaVideoCodec_VC1;
1623#if CONFIG_AV1_CUVID_DECODER && defined(CUVID_HAS_AV1_SUPPORT)
1625 ctx->cuparseinfo.CodecType = cudaVideoCodec_AV1;
1646 extradata_size >= 4 &&
1647 extradata[0] & 0x80) {
1649 extradata_size -= 4;
1653 +
FFMAX(extradata_size - (
int)
sizeof(
ctx->cuparse_ext->raw_seqhdr_data), 0));
1654 if (!
ctx->cuparse_ext) {
1659 if (extradata_size > 0)
1660 memcpy(
ctx->cuparse_ext->raw_seqhdr_data, extradata, extradata_size);
1661 ctx->cuparse_ext->format.seqhdr_data_length = extradata_size;
1663 ctx->cuparseinfo.pExtVideoInfo =
ctx->cuparse_ext;
1666 if (!
ctx->key_frame) {
1671 ctx->cuparseinfo.ulMaxNumDecodeSurfaces = 1;
1673 ctx->cuparseinfo.pUserData = avctx;
1678 ret =
CHECK_CU(
ctx->cudl->cuCtxPushCurrent(cuda_ctx));
1685 probed_bit_depth, is_yuv422, is_yuv444);
1689 ret =
CHECK_CU(
ctx->cvdl->cuvidCreateVideoParser(&
ctx->cuparser, &
ctx->cuparseinfo));
1693 seq_pkt.payload =
ctx->cuparse_ext->raw_seqhdr_data;
1694 seq_pkt.payload_size =
ctx->cuparse_ext->format.seqhdr_data_length;
1696 if (seq_pkt.payload && seq_pkt.payload_size) {
1697 ret =
CHECK_CU(
ctx->cvdl->cuvidParseVideoData(
ctx->cuparser, &seq_pkt));
1706 ctx->prev_pts = INT64_MIN;
1724 CUVIDSOURCEDATAPACKET seq_pkt = { 0 };
1727 ret =
CHECK_CU(
ctx->cudl->cuCtxPushCurrent(cuda_ctx));
1733 if (
ctx->cudecoder) {
1734 ctx->cvdl->cuvidDestroyDecoder(
ctx->cudecoder);
1738 if (
ctx->cuparser) {
1739 ctx->cvdl->cuvidDestroyVideoParser(
ctx->cuparser);
1743 ret =
CHECK_CU(
ctx->cvdl->cuvidCreateVideoParser(&
ctx->cuparser, &
ctx->cuparseinfo));
1747 seq_pkt.payload =
ctx->cuparse_ext->raw_seqhdr_data;
1748 seq_pkt.payload_size =
ctx->cuparse_ext->format.seqhdr_data_length;
1750 if (seq_pkt.payload && seq_pkt.payload_size) {
1751 ret =
CHECK_CU(
ctx->cvdl->cuvidParseVideoData(
ctx->cuparser, &seq_pkt));
1760 ctx->prev_pts = INT64_MIN;
1761 ctx->decoder_flushing = 0;
1768#define OFFSET(x) offsetof(CuvidContext, x)
1769#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
1771 {
"deint",
"Set deinterlacing mode",
OFFSET(deint_mode),
AV_OPT_TYPE_INT, { .i64 = cudaVideoDeinterlaceMode_Weave }, cudaVideoDeinterlaceMode_Weave, cudaVideoDeinterlaceMode_Adaptive,
VD, .unit =
"deint" },
1772 {
"weave",
"Weave deinterlacing (do nothing)", 0,
AV_OPT_TYPE_CONST, { .i64 = cudaVideoDeinterlaceMode_Weave }, 0, 0,
VD, .unit =
"deint" },
1773 {
"bob",
"Bob deinterlacing", 0,
AV_OPT_TYPE_CONST, { .i64 = cudaVideoDeinterlaceMode_Bob }, 0, 0,
VD, .unit =
"deint" },
1774 {
"adaptive",
"Adaptive deinterlacing", 0,
AV_OPT_TYPE_CONST, { .i64 = cudaVideoDeinterlaceMode_Adaptive }, 0, 0,
VD, .unit =
"deint" },
1777 {
"drop_second_field",
"Drop second field when deinterlacing",
OFFSET(drop_second_field),
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
VD },
1783#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
1785 {
"zero_copy",
"Enable zero-copy opaque decode output (forces output_format=cuarray)",
OFFSET(zero_copy),
AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
VD },
1801#ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
1816#define DEFINE_CUVID_CODEC(x, X, bsf_name) \
1817 static const AVClass x##_cuvid_class = { \
1818 .class_name = #x "_cuvid", \
1819 .item_name = av_default_item_name, \
1820 .option = options, \
1821 .version = LIBAVUTIL_VERSION_INT, \
1823 const FFCodec ff_##x##_cuvid_decoder = { \
1824 .p.name = #x "_cuvid", \
1825 CODEC_LONG_NAME("Nvidia CUVID " #X " decoder"), \
1826 .p.type = AVMEDIA_TYPE_VIDEO, \
1827 .p.id = AV_CODEC_ID_##X, \
1828 .priv_data_size = sizeof(CuvidContext), \
1829 .p.priv_class = &x##_cuvid_class, \
1830 .init = cuvid_decode_init, \
1831 .close = cuvid_decode_end, \
1832 FF_CODEC_RECEIVE_FRAME_CB(cuvid_output_frame), \
1833 .flush = cuvid_flush, \
1835 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
1836 .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | \
1837 FF_CODEC_CAP_SETS_FRAME_PROPS, \
1838 .hw_configs = cuvid_hw_configs, \
1839 .p.wrapper_name = "cuvid", \
1842#if CONFIG_AV1_CUVID_DECODER && defined(CUVID_HAS_AV1_SUPPORT)
1846#if CONFIG_HEVC_CUVID_DECODER
1850#if CONFIG_H264_CUVID_DECODER
1854#if CONFIG_MJPEG_CUVID_DECODER
1858#if CONFIG_MPEG1_CUVID_DECODER
1862#if CONFIG_MPEG2_CUVID_DECODER
1866#if CONFIG_MPEG4_CUVID_DECODER
1870#if CONFIG_VP8_CUVID_DECODER
1874#if CONFIG_VP9_CUVID_DECODER
1878#if CONFIG_VC1_CUVID_DECODER
SwsAArch64OpImplParams params
static const char *const format[]
static void bit_depth(AudioStatsContext *s, const uint64_t *const mask, uint8_t *depth)
static AVFormatContext * ctx
Libavcodec external API header.
refcounted data buffer API
#define flags(name, subs,...)
#define i(width, name, range_min, range_max)
static av_always_inline const FFCodec * ffcodec(const AVCodec *codec)
static int cuvid_decode_packet(AVCodecContext *avctx, const AVPacket *avpkt)
static int CUDAAPI cuvid_handle_picture_decode(void *opaque, CUVIDPICPARAMS *picparams)
static const AVCodecHWConfigInternal *const cuvid_hw_configs[]
static int cuvid_output_frame(AVCodecContext *avctx, AVFrame *frame)
static av_cold int cuvid_decode_end(AVCodecContext *avctx)
static int cuvid_output_format_is_forced(const CuvidContext *ctx)
static enum AVPixelFormat cuvid_apply_forced_output_format(AVCodecContext *avctx, const CuvidContext *ctx, enum AVPixelFormat selected, enum AVPixelFormat requested)
#define CUVID_MAX_DISPLAY_DELAY
#define cudaVideoSurfaceFormat_YUV444
static void cuvid_prepare_format_list(enum AVPixelFormat *pix_fmts, enum AVPixelFormat hw_format, enum AVPixelFormat sw_format)
static int CUDAAPI cuvid_handle_picture_display(void *opaque, CUVIDPARSERDISPINFO *dispinfo)
static int cuvid_get_requested_hw_format(AVCodecContext *avctx, CuvidContext *ctx, enum AVPixelFormat *fmt)
static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT *format)
static av_cold int cuvid_decode_init(AVCodecContext *avctx)
static int cuvid_test_capabilities(AVCodecContext *avctx, const CUVIDPARSERPARAMS *cuparseinfo, int probed_width, int probed_height, int bit_depth, int is_yuv422, int is_yuv444)
#define DEFINE_CUVID_CODEC(x, X, bsf_name)
#define CUVID_DEFAULT_NUM_SURFACES
#define cudaVideoSurfaceFormat_YUV444_16Bit
static int cuvid_is_buffer_full(AVCodecContext *avctx)
static void cuvid_flush(AVCodecContext *avctx)
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
Set various frame properties from the codec context / packet data.
int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
Called by decoders to get the next packet for decoding.
int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
Select the (possibly hardware accelerated) pixel format.
int ff_set_sar(AVCodecContext *avctx, AVRational sar)
Check that the provided sample aspect ratio is valid and set it on the codec context.
#define atomic_load_explicit(object, order)
#define atomic_store_explicit(object, desired, order)
static char * output_format
static av_cold void cleanup(FlashSV2Context *s)
#define AV_OPT_FLAG_DEPRECATED
Set if option is deprecated, users should refer to AVOption.help text for more information.
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ 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...
#define AV_CODEC_FLAG_INTERLACED_DCT
Use interlaced DCT.
#define AV_CODEC_FLAG_LOW_DELAY
Force low delay.
@ AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX
The codec supports this format via the hw_frames_ctx interface.
@ AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX
The codec supports this format via the hw_device_ctx interface.
@ AV_CODEC_HW_CONFIG_METHOD_INTERNAL
The codec supports this format by some internal method.
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
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 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.
#define AVERROR_EXTERNAL
Generic error in an external library.
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
#define AVERROR_EOF
End of file.
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
void av_fifo_reset2(AVFifo *f)
size_t av_fifo_can_write(const AVFifo *f)
size_t av_fifo_can_read(const AVFifo *f)
int av_fifo_grow2(AVFifo *f, size_t inc)
Enlarge an AVFifo.
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
#define AV_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#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.
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
AVRational av_div_q(AVRational b, AVRational c)
Divide one rational by another.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate an array through a pointer to a pointer.
#define AV_NOPTS_VALUE
Undefined timestamp value.
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
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_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
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.
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 int shift(int a, int b)
common internal api header.
static enum AVPixelFormat pix_fmts[]
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.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
@ AVCOL_RANGE_JPEG
Full range content.
#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_YUV444P16
#define AV_PIX_FMT_YUV444P10MSB
#define FF_ARRAY_ELEMS(a)
AVCodecParameters * par_out
Parameters of the output stream.
A reference to a data buffer.
This struct is allocated as AVHWDeviceContext.hwctx.
AVCUDADeviceContextInternal * internal
This struct is allocated as AVHWFramesContext.hwctx.
CUDA_ARRAY3D_DESCRIPTOR cuarray_desc
CUDA_ARRAY3D_DESCRIPTOR CUarrays will be initialized with.
Describe the class of an AVClass context structure.
main external API structure.
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
int width
picture width / height.
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
enum AVColorRange color_range
MPEG vs JPEG YUV range.
AVRational pkt_timebase
Timebase in which pkt_dts/pts and AVPacket.dts/pts are expressed.
enum AVColorPrimaries color_primaries
Chromaticity coordinates of the source primaries.
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
int64_t bit_rate
the average bitrate
const struct AVCodec * codec
enum AVColorSpace colorspace
YUV colorspace type.
enum AVColorTransferCharacteristic color_trc
Color Transfer Characteristic.
int flags
AV_CODEC_FLAG_*.
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
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.
AVPacket * in_pkt
This packet is used to hold the packet given to decoders implementing the .decode API; it is unused b...
struct AVBSFContext * bsf
This struct describes the properties of an encoded stream.
int extradata_size
Size of the extradata content in bytes.
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
const char * name
Name of the codec implementation.
int depth
Number of bits in the component.
This structure describes decoded (raw) audio or video data.
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...
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
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.
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 width
The allocated dimensions of the frames in this pool.
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
This structure stores compressed data.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
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.
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
uint8_t nb_components
The number of components each pixel has, (1-4)
Rational number (pair of numerator and denominator).
struct CuvidContext::@006255247064232322304150030351010216270027246216 resize
enum AVPixelFormat output_format
cudaVideoCodec codec_type
cudaVideoChromaFormat chroma_format
struct CuvidContext::@133300314247370073362260244350264314175314272354 crop
CUVIDPARSERPARAMS cuparseinfo
CUVIDEOFORMATEX * cuparse_ext
CUVIDPARSERDISPINFO dispinfo
const char * bsfs
Decoding only, a comma-separated list of bitstream filters to apply to packets before decoding.
static void error(const char *err)