FFmpeg
nvdec.c
Go to the documentation of this file.
1 /*
2  * HW decode acceleration through NVDEC
3  *
4  * Copyright (c) 2016 Anton Khirnov
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "config.h"
24 #include "config_components.h"
25 
26 #include <stdatomic.h>
27 
28 #include "libavutil/avassert.h"
29 #include "libavutil/common.h"
30 #include "libavutil/error.h"
31 #include "libavutil/hwcontext.h"
33 #include "libavutil/cuda_check.h"
34 #include "libavutil/mem.h"
35 #include "libavutil/pixdesc.h"
36 #include "libavutil/pixfmt.h"
37 
38 #include "avcodec.h"
39 #include "decode.h"
40 #include "nvdec.h"
41 #include "internal.h"
42 #include "libavutil/refstruct.h"
43 
44 #if !NVDECAPI_CHECK_VERSION(9, 0)
45 #define cudaVideoSurfaceFormat_YUV444 2
46 #define cudaVideoSurfaceFormat_YUV444_16Bit 3
47 #endif
48 
49 typedef struct NVDECDecoder {
50  CUvideodecoder decoder;
51 
55  CUcontext cuda_ctx;
56  CUstream stream;
57 
58  CudaFunctions *cudl;
59  CuvidFunctions *cvdl;
60 
63 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
64  atomic_int *surface_in_use;
65  int num_surfaces;
66 #endif
67 } NVDECDecoder;
68 
69 typedef struct NVDECFramePool {
70  unsigned int dpb_size;
71  unsigned int nb_allocated;
73 
74 #define CHECK_CU(x) FF_CUDA_CHECK_DL(logctx, decoder->cudl, x)
75 
76 static int map_avcodec_id(enum AVCodecID id)
77 {
78  switch (id) {
79 #if CONFIG_AV1_NVDEC_HWACCEL
80  case AV_CODEC_ID_AV1: return cudaVideoCodec_AV1;
81 #endif
82  case AV_CODEC_ID_H264: return cudaVideoCodec_H264;
83  case AV_CODEC_ID_HEVC: return cudaVideoCodec_HEVC;
84  case AV_CODEC_ID_MJPEG: return cudaVideoCodec_JPEG;
85  case AV_CODEC_ID_MPEG1VIDEO: return cudaVideoCodec_MPEG1;
86  case AV_CODEC_ID_MPEG2VIDEO: return cudaVideoCodec_MPEG2;
87  case AV_CODEC_ID_MPEG4: return cudaVideoCodec_MPEG4;
88  case AV_CODEC_ID_VC1: return cudaVideoCodec_VC1;
89  case AV_CODEC_ID_VP8: return cudaVideoCodec_VP8;
90  case AV_CODEC_ID_VP9: return cudaVideoCodec_VP9;
91  case AV_CODEC_ID_WMV3: return cudaVideoCodec_VC1;
92  }
93  return -1;
94 }
95 
97 {
98  int shift_h = 0, shift_v = 0;
99 
101  return cudaVideoChromaFormat_Monochrome;
102 
103  av_pix_fmt_get_chroma_sub_sample(pix_fmt, &shift_h, &shift_v);
104 
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;
111 
112  return -1;
113 }
114 
116  CUVIDDECODECREATEINFO *params, void *logctx)
117 {
118  int ret;
119  CUVIDDECODECAPS caps = { 0 };
120 
121  caps.eCodecType = params->CodecType;
122  caps.eChromaFormat = params->ChromaFormat;
123  caps.nBitDepthMinus8 = params->bitDepthMinus8;
124 
125  if (!decoder->cvdl->cuvidGetDecoderCaps) {
126  av_log(logctx, AV_LOG_WARNING, "Used Nvidia driver is too old to perform a capability check.\n");
127  av_log(logctx, AV_LOG_WARNING, "The minimum required version is "
128 #if defined(_WIN32) || defined(__CYGWIN__)
129  "378.66"
130 #else
131  "378.13"
132 #endif
133  ". Continuing blind.\n");
134  return 0;
135  }
136 
137  ret = CHECK_CU(decoder->cvdl->cuvidGetDecoderCaps(&caps));
138  if (ret < 0)
139  return ret;
140 
141  av_log(logctx, AV_LOG_VERBOSE, "NVDEC capabilities:\n");
142  av_log(logctx, AV_LOG_VERBOSE, "format supported: %s, max_mb_count: %d\n",
143  caps.bIsSupported ? "yes" : "no", caps.nMaxMBCount);
144  av_log(logctx, AV_LOG_VERBOSE, "min_width: %d, max_width: %d\n",
145  caps.nMinWidth, caps.nMaxWidth);
146  av_log(logctx, AV_LOG_VERBOSE, "min_height: %d, max_height: %d\n",
147  caps.nMinHeight, caps.nMaxHeight);
148 
149  if (!caps.bIsSupported) {
150  av_log(logctx, AV_LOG_ERROR, "Hardware is lacking required capabilities\n");
151  return AVERROR(EINVAL);
152  }
153 
154  if (params->ulWidth > caps.nMaxWidth || params->ulWidth < caps.nMinWidth) {
155  av_log(logctx, AV_LOG_ERROR, "Video width %d not within range from %d to %d\n",
156  (int)params->ulWidth, caps.nMinWidth, caps.nMaxWidth);
157  return AVERROR(EINVAL);
158  }
159 
160  if (params->ulHeight > caps.nMaxHeight || params->ulHeight < caps.nMinHeight) {
161  av_log(logctx, AV_LOG_ERROR, "Video height %d not within range from %d to %d\n",
162  (int)params->ulHeight, caps.nMinHeight, caps.nMaxHeight);
163  return AVERROR(EINVAL);
164  }
165 
166  if ((params->ulWidth * params->ulHeight) / 256 > caps.nMaxMBCount) {
167  av_log(logctx, AV_LOG_ERROR, "Video macroblock count %d exceeds maximum of %d\n",
168  (int)(params->ulWidth * params->ulHeight) / 256, caps.nMaxMBCount);
169  return AVERROR(EINVAL);
170  }
171 
172  return 0;
173 }
174 
175 static void nvdec_decoder_free(AVRefStructOpaque unused, void *obj)
176 {
177  NVDECDecoder *decoder = obj;
178  void *logctx = decoder->hw_device_ref ? decoder->hw_device_ref->data : NULL;
179 
180  if (decoder->decoder) {
181  CUcontext dummy;
182  CHECK_CU(decoder->cudl->cuCtxPushCurrent(decoder->cuda_ctx));
183 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
184  if (decoder->opaque_output) {
185  /*
186  * Every opaque output frame holds a reference to this decoder
187  * (NVDECOpaqueRelease.decoder, attached as frame->buf[0]) and only
188  * clears its surface_in_use slot when that buffer is released. This
189  * RefStruct free callback therefore cannot run until all surfaces
190  * have been handed back, so the decoder always outlives its
191  * surfaces and is safe to destroy unconditionally. The check below
192  * is purely a guard against a future regression of that invariant;
193  * it must never defer destruction (which would leak the decoder).
194  */
195  decoder->cudl->cuCtxSynchronize();
196  if (decoder->surface_in_use) {
197  int busy = 0;
198  for (int i = 0; i < decoder->num_surfaces; i++)
199  busy += atomic_load_explicit(&decoder->surface_in_use[i],
200  memory_order_acquire) != 0;
201  if (busy)
202  av_log(logctx, AV_LOG_ERROR,
203  "%d CUarray surface(s) unexpectedly still in use at "
204  "decoder teardown; destroying anyway\n", busy);
205  }
206  }
207 #endif
208  CHECK_CU(decoder->cvdl->cuvidDestroyDecoder(decoder->decoder));
209  CHECK_CU(decoder->cudl->cuCtxPopCurrent(&dummy));
210  }
211 
212 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
213  av_freep(&decoder->surface_in_use);
214 #endif
215  av_buffer_unref(&decoder->decode_hw_frames_ref);
216  av_buffer_unref(&decoder->real_hw_frames_ref);
217  av_buffer_unref(&decoder->hw_device_ref);
218 
219  cuvid_free_functions(&decoder->cvdl);
220 }
221 
222 static int nvdec_decoder_create(NVDECDecoder **out, AVBufferRef *hw_device_ref,
223  CUVIDDECODECREATEINFO *params, void *logctx)
224 {
226  AVCUDADeviceContext *device_hwctx = hw_device_ctx->hwctx;
227 
229 
230  CUcontext dummy;
231  int ret;
232 
233  decoder = av_refstruct_alloc_ext(sizeof(*decoder), 0,
235  if (!decoder)
236  return AVERROR(ENOMEM);
237 
238  decoder->hw_device_ref = av_buffer_ref(hw_device_ref);
239  if (!decoder->hw_device_ref) {
240  ret = AVERROR(ENOMEM);
241  goto fail;
242  }
243  decoder->cuda_ctx = device_hwctx->cuda_ctx;
244  decoder->cudl = device_hwctx->internal->cuda_dl;
245  decoder->stream = device_hwctx->stream;
246 
247  ret = cuvid_load_functions(&decoder->cvdl, logctx);
248  if (ret < 0) {
249  av_log(logctx, AV_LOG_ERROR, "Failed loading nvcuvid.\n");
250  goto fail;
251  }
252 
253  ret = CHECK_CU(decoder->cudl->cuCtxPushCurrent(decoder->cuda_ctx));
254  if (ret < 0)
255  goto fail;
256 
257  ret = nvdec_test_capabilities(decoder, params, logctx);
258  if (ret < 0) {
259  CHECK_CU(decoder->cudl->cuCtxPopCurrent(&dummy));
260  goto fail;
261  }
262 
263  ret = CHECK_CU(decoder->cvdl->cuvidCreateDecoder(&decoder->decoder, params));
264 
265  CHECK_CU(decoder->cudl->cuCtxPopCurrent(&dummy));
266 
267  if (ret < 0) {
268  goto fail;
269  }
270 
271  *out = decoder;
272 
273  return 0;
274 fail:
276  return ret;
277 }
278 
279 static int nvdec_decoder_frame_init(AVRefStructOpaque opaque, void *obj)
280 {
281  NVDECFramePool *pool = opaque.nc;
282  unsigned int *intp = obj;
283 
284  if (pool->nb_allocated >= pool->dpb_size)
285  return AVERROR(ENOMEM);
286 
287  *intp = pool->nb_allocated++;
288 
289  return 0;
290 }
291 
293 {
294  av_free(opaque.nc);
295 }
296 
298 {
300 
301  av_freep(&ctx->bitstream_internal);
302  ctx->bitstream = NULL;
303  ctx->bitstream_len = 0;
304  ctx->bitstream_allocated = 0;
305 
306  av_freep(&ctx->slice_offsets);
307  ctx->nb_slices = 0;
308  ctx->slice_offsets_allocated = 0;
309 
310  av_refstruct_unref(&ctx->decoder);
311  av_refstruct_pool_uninit(&ctx->decoder_pool);
312 
313  return 0;
314 }
315 
317 {
318  av_buffer_pool_uninit(&ctx->pool);
319 }
320 
322 {
323  return av_buffer_create(NULL, 0, NULL, NULL, 0);
324 }
325 
326 static int nvdec_init_hwframes(AVCodecContext *avctx, AVBufferRef **out_frames_ref, int dummy)
327 {
328  AVHWFramesContext *frames_ctx;
329  int ret;
330 
332  avctx->hw_device_ctx,
333  avctx->hwaccel->pix_fmt,
334  out_frames_ref);
335  if (ret < 0)
336  return ret;
337 
338  frames_ctx = (AVHWFramesContext*)(*out_frames_ref)->data;
339 
340  if (dummy) {
341  // Copied from ff_decode_get_hw_frames_ctx for compatibility
342  frames_ctx->initial_pool_size += 3;
343 
344  frames_ctx->free = nvdec_free_dummy;
345  frames_ctx->pool = av_buffer_pool_init(0, nvdec_alloc_dummy);
346 
347  if (!frames_ctx->pool) {
348  av_buffer_unref(out_frames_ref);
349  return AVERROR(ENOMEM);
350  }
351  } else {
352  // This is normally not used to actually allocate frames from
353  frames_ctx->initial_pool_size = 0;
354  }
355 
356  ret = av_hwframe_ctx_init(*out_frames_ref);
357  if (ret < 0) {
358  av_buffer_unref(out_frames_ref);
359  return ret;
360  }
361 
362  return 0;
363 }
364 
365 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
366 void ff_nvdec_fill_cuarray_desc(CUDA_ARRAY3D_DESCRIPTOR *desc,
367  AVCodecContext *avctx,
368  cudaVideoSurfaceFormat output_format)
369 {
370  CUarray_format arr_fmt;
371 
372  switch (output_format) {
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;
385  default:
386  /* The caller's bit-depth/chroma switch only ever yields the formats
387  * handled above (and errors out otherwise), so this is unreachable;
388  * assert rather than silently producing a wrong descriptor. */
389  av_assert0(0);
390  }
391 
392  memset(desc, 0, sizeof(*desc));
393  desc->Width = avctx->coded_width;
394  desc->Height = avctx->coded_height;
395  desc->Depth = 0;
396  desc->Format = arr_fmt;
397  desc->NumChannels = 3;
398  desc->Flags = CUDA_ARRAY3D_SURFACE_LDST |
399  CUDA_ARRAY3D_VIDEO_ENCODE_DECODE;
400 }
401 
402 #endif
403 
405 {
407 
409  AVBufferRef *decode_hw_frames_ref = NULL;
410  AVBufferRef *real_hw_frames_ref = NULL;
411  NVDECFramePool *pool;
412  AVHWFramesContext *frames_ctx;
413  const AVPixFmtDescriptor *sw_desc;
414 
415  CUVIDDECODECREATEINFO params = { 0 };
416 
417  cudaVideoSurfaceFormat output_format;
418  int cuvid_codec_type, cuvid_chroma_format, chroma_444;
419  int ret = 0;
420  int need_real_hwframes = 0;
421 
422  int unsafe_output = !!(avctx->hwaccel_flags & AV_HWACCEL_FLAG_UNSAFE_OUTPUT);
423 
424  int opaque_output = 0;
425  int decode_pool_size;
426 
427  sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
428  if (!sw_desc)
429  return AVERROR_BUG;
430 
431  cuvid_codec_type = map_avcodec_id(avctx->codec_id);
432  if (cuvid_codec_type < 0) {
433  av_log(avctx, AV_LOG_ERROR, "Unsupported codec ID\n");
434  return AVERROR_BUG;
435  }
436 
437  cuvid_chroma_format = map_chroma_format(avctx->sw_pix_fmt);
438  if (cuvid_chroma_format < 0) {
439  av_log(avctx, AV_LOG_ERROR, "Unsupported chroma format\n");
440  return AVERROR(ENOSYS);
441  }
442  chroma_444 = ctx->supports_444 && cuvid_chroma_format == cudaVideoChromaFormat_444;
443 
444  if (!avctx->hw_frames_ctx) {
445  ret = nvdec_init_hwframes(avctx, &avctx->hw_frames_ctx, 1);
446  if (ret < 0)
447  return ret;
448  need_real_hwframes = 1;
449  }
450 
451  frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
452 
453 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
454  if (frames_ctx->format == AV_PIX_FMT_CUARRAY) {
455  opaque_output = 1;
456  }
457 #else
458  if (frames_ctx->format == AV_PIX_FMT_CUARRAY) {
459  av_log(avctx, AV_LOG_ERROR,
460  "CUarray opaque output requires Video Codec SDK 13.1 or later\n");
461  return AVERROR(ENOSYS);
462  }
463 #endif
464 
465  decode_pool_size = frames_ctx->initial_pool_size;
466 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
467  if (opaque_output) {
468  if (unsafe_output) {
469  decode_pool_size = FFMIN(frames_ctx->initial_pool_size + 16, MAX_NUM_REGISTERED_DECODE_SURFACES);
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);
472  } else if (avctx->extra_hw_frames > 0) {
473  decode_pool_size = FFMAX(frames_ctx->initial_pool_size - avctx->extra_hw_frames, 1);
474  av_log(avctx, AV_LOG_VERBOSE, "Opaque copy mode: %d decode surfaces, %d extra surfaces reserved for output pool\n",
475  decode_pool_size, avctx->extra_hw_frames);
476  }
477  }
478 #endif
479 
480  switch (sw_desc->comp[0].depth) {
481  case 8:
482  if (chroma_444) {
484 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
485  if (opaque_output) output_format = cudaVideoSurfaceFormat_YUV444_Opaque;
486 #endif
487 #ifdef NVDEC_HAVE_422_SUPPORT
488  } else if (cuvid_chroma_format == cudaVideoChromaFormat_422) {
489  output_format = cudaVideoSurfaceFormat_NV16;
490 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
491  if (opaque_output) output_format = cudaVideoSurfaceFormat_NV16_Opaque;
492 #endif
493 #endif
494  } else {
495  output_format = cudaVideoSurfaceFormat_NV12;
496 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
497  if (opaque_output) output_format = cudaVideoSurfaceFormat_NV12_Opaque;
498 #endif
499  }
500  break;
501  case 10:
502  case 12:
503  if (chroma_444) {
505 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
506  if (opaque_output) output_format = cudaVideoSurfaceFormat_YUV444_16Bit_Opaque;
507 #endif
508 #ifdef NVDEC_HAVE_422_SUPPORT
509  } else if (cuvid_chroma_format == cudaVideoChromaFormat_422) {
510  output_format = cudaVideoSurfaceFormat_P216;
511 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
512  if (opaque_output) output_format = cudaVideoSurfaceFormat_P216_Opaque;
513 #endif
514 #endif
515  } else {
516  output_format = cudaVideoSurfaceFormat_P016;
517 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
518  if (opaque_output) output_format = cudaVideoSurfaceFormat_P016_Opaque;
519 #endif
520  }
521  break;
522  default:
523  av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth\n");
524  return AVERROR(ENOSYS);
525  }
526 
527  if (need_real_hwframes) {
528  if (frames_ctx->format == AV_PIX_FMT_CUARRAY) {
529 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
530  AVHWFramesContext *real_ctx;
531  AVCUDAFramesContext *cuda_priv;
532 
534  avctx->hwaccel->pix_fmt,
535  &real_hw_frames_ref);
536  if (ret < 0)
537  goto fail;
538 
539  real_ctx = (AVHWFramesContext*)real_hw_frames_ref->data;
540  real_ctx->initial_pool_size = 0;
541 
542  cuda_priv = real_ctx->hwctx;
543  ff_nvdec_fill_cuarray_desc(&cuda_priv->cuarray_desc, avctx, output_format);
544  cuda_priv->cuarray_num_surfaces = unsafe_output ? decode_pool_size
545  : frames_ctx->initial_pool_size;
546 
547  ret = av_hwframe_ctx_init(real_hw_frames_ref);
548  if (ret < 0)
549  goto fail;
550 
551  if (unsafe_output) {
552  decode_hw_frames_ref = av_buffer_ref(real_hw_frames_ref);
553  if (!decode_hw_frames_ref) {
554  ret = AVERROR(ENOMEM);
555  goto fail;
556  }
557  } else {
559  avctx->hwaccel->pix_fmt,
560  &decode_hw_frames_ref);
561  if (ret < 0)
562  goto fail;
563 
564  real_ctx = (AVHWFramesContext*)decode_hw_frames_ref->data;
565  real_ctx->initial_pool_size = 0;
566 
567  cuda_priv = real_ctx->hwctx;
568  ff_nvdec_fill_cuarray_desc(&cuda_priv->cuarray_desc, avctx, output_format);
569  cuda_priv->cuarray_num_surfaces = decode_pool_size;
570 
571  ret = av_hwframe_ctx_init(decode_hw_frames_ref);
572  if (ret < 0)
573  goto fail;
574  }
575 #endif
576  } else {
577  ret = nvdec_init_hwframes(avctx, &real_hw_frames_ref, 0);
578  if (ret < 0)
579  goto fail;
580  }
581  } else {
582  real_hw_frames_ref = av_buffer_ref(avctx->hw_frames_ctx);
583  if (!real_hw_frames_ref)
584  return AVERROR(ENOMEM);
585 
586 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
587  if (frames_ctx->format == AV_PIX_FMT_CUARRAY) {
588  if (unsafe_output) {
589  decode_hw_frames_ref = av_buffer_ref(real_hw_frames_ref);
590  } else {
591  AVHWFramesContext *real_ctx;
592  AVCUDAFramesContext *cuda_priv;
593 
594  ret = avcodec_get_hw_frames_parameters(avctx, frames_ctx->device_ref,
595  avctx->hwaccel->pix_fmt,
596  &decode_hw_frames_ref);
597  if (ret < 0)
598  goto fail;
599 
600  real_ctx = (AVHWFramesContext*)decode_hw_frames_ref->data;
601  real_ctx->initial_pool_size = 0;
602 
603  cuda_priv = real_ctx->hwctx;
604  ff_nvdec_fill_cuarray_desc(&cuda_priv->cuarray_desc, avctx, output_format);
605  cuda_priv->cuarray_num_surfaces = decode_pool_size;
606 
607  ret = av_hwframe_ctx_init(decode_hw_frames_ref);
608  if (ret < 0)
609  goto fail;
610  }
611 
612  if (!decode_hw_frames_ref) {
613  av_buffer_unref(&real_hw_frames_ref);
614  return AVERROR(ENOMEM);
615  }
616  }
617 #endif
618  }
619 
620  params.ulWidth = avctx->coded_width;
621  params.ulHeight = avctx->coded_height;
622  params.ulTargetWidth = avctx->coded_width;
623  params.ulTargetHeight = avctx->coded_height;
624  params.bitDepthMinus8 = sw_desc->comp[0].depth - 8;
625  params.OutputFormat = output_format;
626  params.CodecType = cuvid_codec_type;
627  params.ChromaFormat = cuvid_chroma_format;
628  params.ulNumDecodeSurfaces = FFMIN(decode_pool_size, 32);
629  params.ulNumOutputSurfaces = opaque_output ? 0 : (unsafe_output ? FFMIN(frames_ctx->initial_pool_size, 64) : 1);
630 
631  ret = nvdec_decoder_create(&ctx->decoder, frames_ctx->device_ref, &params, avctx);
632  if (ret < 0) {
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);
636  av_log(avctx, AV_LOG_WARNING, "Try lowering the amount of threads. Using %d right now.\n",
637  avctx->thread_count);
638  }
639  goto fail;
640  }
641 
642  decoder = ctx->decoder;
643  decoder->unsafe_output = unsafe_output;
644  decoder->opaque_output = opaque_output;
645 
646 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
647  if (opaque_output) {
648  void *logctx = avctx;
649  AVHWFramesContext *real_ctx = (AVHWFramesContext*)decode_hw_frames_ref->data;
650  AVCUDAFramesContext *cuda_priv = real_ctx->hwctx;
651  CUVIDREGISTERDECODESURFACESINFO reg_info = { 0 };
652  CUcontext dummy;
653 
654  if (!decoder->cvdl->cuvidRegisterDecodeSurfaces) {
655  av_log(logctx, AV_LOG_ERROR, "Driver lacking CUarray output support.\n");
656  ret = AVERROR(ENOSYS);
657  goto fail;
658  }
659 
660  ret = CHECK_CU(decoder->cudl->cuCtxPushCurrent(decoder->cuda_ctx));
661  if (ret < 0)
662  goto fail;
663 
664  reg_info.ulNumDecodeSurfaces = FFMIN(cuda_priv->cuarray_num_surfaces,
665  (unsigned)decode_pool_size);
666  reg_info.pDecodeSurfaces = cuda_priv->cuarray_surfaces;
667  ret = CHECK_CU(decoder->cvdl->cuvidRegisterDecodeSurfaces(decoder->decoder, &reg_info));
668  CHECK_CU(decoder->cudl->cuCtxPopCurrent(&dummy));
669  if (ret < 0)
670  goto fail;
671 
672  decoder->num_surfaces = reg_info.ulNumDecodeSurfaces;
673  decoder->surface_in_use = av_calloc(decoder->num_surfaces,
674  sizeof(*decoder->surface_in_use));
675  if (!decoder->surface_in_use) {
676  ret = AVERROR(ENOMEM);
677  goto fail;
678  }
679  }
680 #endif
681 
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;
686 
687  pool = av_mallocz(sizeof(*pool));
688  if (!pool) {
689  ret = AVERROR(ENOMEM);
690  goto fail;
691  }
692  pool->dpb_size = FFMIN(decode_pool_size, 32);
693 
694  ctx->decoder_pool = av_refstruct_pool_alloc_ext(sizeof(unsigned int), 0, pool,
697  if (!ctx->decoder_pool) {
698  ret = AVERROR(ENOMEM);
699  goto fail;
700  }
701 
702  ret = 0;
703 
704 fail:
705  av_buffer_unref(&decode_hw_frames_ref);
706  av_buffer_unref(&real_hw_frames_ref);
707 
708  if (ret < 0)
709  ff_nvdec_decode_uninit(avctx);
710 
711  return ret;
712 }
713 
714 static void nvdec_fdd_priv_free(void *priv)
715 {
716  NVDECFrame *cf = priv;
717 
718  if (!cf)
719  return;
720 
724 
725  av_freep(&priv);
726 }
727 
728 static void nvdec_unmap_mapped_frame(void *opaque, uint8_t *data)
729 {
730  NVDECFrame *unmap_data = (NVDECFrame*)data;
731  NVDECDecoder *decoder = unmap_data->decoder;
732  void *logctx = decoder->hw_device_ref->data;
733  CUdeviceptr devptr = (CUdeviceptr)opaque;
734  int ret;
735  CUcontext dummy;
736 
737  ret = CHECK_CU(decoder->cudl->cuCtxPushCurrent(decoder->cuda_ctx));
738  if (ret < 0)
739  goto finish;
740 
741  CHECK_CU(decoder->cvdl->cuvidUnmapVideoFrame(decoder->decoder, devptr));
742 
743  CHECK_CU(decoder->cudl->cuCtxPopCurrent(&dummy));
744 
745 finish:
746  av_refstruct_unref(&unmap_data->idx_ref);
747  av_refstruct_unref(&unmap_data->ref_idx_ref);
748  av_refstruct_unref(&unmap_data->decoder);
749  av_free(unmap_data);
750 }
751 
752 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
753 typedef struct NVDECOpaqueRelease {
755  int idx;
756  unsigned int *idx_ref; ///< RefStruct reference keeping the surface index locked
757 } NVDECOpaqueRelease;
758 
759 static void nvdec_opaque_release_slot(void *opaque, uint8_t *data)
760 {
761  NVDECOpaqueRelease *r = (NVDECOpaqueRelease *)opaque;
762  if (r->decoder->surface_in_use)
763  atomic_store_explicit(&r->decoder->surface_in_use[r->idx], 0,
764  memory_order_release);
765  av_refstruct_unref(&r->idx_ref);
766  av_refstruct_unref(&r->decoder);
767  av_free(r);
768 }
769 #endif
770 
771 static int nvdec_retrieve_data(void *logctx, AVFrame *frame)
772 {
773  FrameDecodeData *fdd = frame->private_ref;
774  NVDECFrame *cf = (NVDECFrame*)fdd->hwaccel_priv;
776 
777  AVHWFramesContext *hwctx = (AVHWFramesContext *)frame->hw_frames_ctx->data;
778 
779  CUVIDPROCPARAMS vpp = { 0 };
780  NVDECFrame *unmap_data = NULL;
781 
782  CUcontext dummy;
783  CUdeviceptr devptr;
784 
785  unsigned int pitch, i;
786  unsigned int offset = 0;
787  int shift_h = 0, shift_v = 0;
788  int ret = 0;
789 
790 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
791  if (decoder->opaque_output) {
792  AVHWFramesContext *decode_ctx = (AVHWFramesContext *)decoder->decode_hw_frames_ref->data;
793  AVCUDAFramesContext *cuda_priv = decode_ctx->hwctx;
794 
795  if (cf->idx >= (unsigned)cuda_priv->cuarray_num_surfaces) {
796  av_log(logctx, AV_LOG_ERROR,
797  "NVDEC opaque surface index %u out of range (%d surfaces)\n",
798  cf->idx, cuda_priv->cuarray_num_surfaces);
799  return AVERROR_BUG;
800  }
801 
802  {
803  CUarray arr = cuda_priv->cuarray_surfaces[cf->idx];
804  AVBufferRef *buf0;
805  NVDECOpaqueRelease *rel;
806 
807  rel = av_malloc(sizeof(*rel));
808  if (!rel)
809  return AVERROR(ENOMEM);
810  rel->decoder = av_refstruct_ref(decoder);
811  rel->idx = cf->idx;
812  rel->idx_ref = av_refstruct_ref(cf->idx_ref);
813  buf0 = av_buffer_create((uint8_t *)arr, 0,
814  nvdec_opaque_release_slot, rel,
816  if (!buf0) {
817  av_refstruct_unref(&rel->idx_ref);
818  av_refstruct_unref(&rel->decoder);
819  av_free(rel);
820  return AVERROR(ENOMEM);
821  }
822 
823  /*
824  * Mark the surface in use only now that buf0 owns rel:
825  * nvdec_opaque_release_slot (buf0's free callback) is the sole path
826  * that clears the flag, so deferring the set until buf0 exists keeps
827  * every set paired with a clear, even on a later error return.
828  */
829  if (decoder->surface_in_use)
830  atomic_store_explicit(&decoder->surface_in_use[cf->idx], 1,
831  memory_order_release);
832 
833  ret = av_buffer_replace(&frame->hw_frames_ctx,
834  decoder->unsafe_output
835  ? decoder->decode_hw_frames_ref
836  : decoder->real_hw_frames_ref);
837  if (ret < 0) {
838  av_buffer_unref(&buf0);
839  return ret;
840  }
841 
842  av_buffer_unref(&frame->buf[0]);
843  frame->buf[0] = buf0;
844  frame->data[0] = (uint8_t *)arr;
845 
846  {
847  CUcontext dummy;
848  ret = CHECK_CU(decoder->cudl->cuCtxPushCurrent(decoder->cuda_ctx));
849  if (ret < 0) {
850  return ret;
851  }
852  for (int p = 0; p < FF_ARRAY_ELEMS(frame->linesize); p++) {
853  CUDA_ARRAY3D_DESCRIPTOR plane_desc = { 0 };
854  CUarray plane_array;
855  int elem_size;
856  CUresult cures = decoder->cudl->cuArrayGetPlane(&plane_array, arr, p);
857  if (cures == CUDA_ERROR_INVALID_VALUE)
858  break;
859  if (cures != CUDA_SUCCESS) {
860  CHECK_CU(decoder->cudl->cuCtxPopCurrent(&dummy));
861  return AVERROR_EXTERNAL;
862  }
863  ret = CHECK_CU(decoder->cudl->cuArray3DGetDescriptor(&plane_desc, plane_array));
864  if (ret < 0) {
865  CHECK_CU(decoder->cudl->cuCtxPopCurrent(&dummy));
866  return ret;
867  }
868  elem_size = ff_cuda_cuarray_elem_size(plane_desc.Format);
869  if (elem_size <= 0)
870  elem_size = 1;
871  frame->linesize[p] = plane_desc.Width * plane_desc.NumChannels * elem_size;
872  }
873  CHECK_CU(decoder->cudl->cuCtxPopCurrent(&dummy));
874  }
875 
876  frame->format = AV_PIX_FMT_CUARRAY;
877 
878  if (decoder->unsafe_output)
879  return 0;
880 
882  }
883  }
884 #endif
885 
886  vpp.progressive_frame = 1;
887  vpp.output_stream = decoder->stream;
888 
889  ret = CHECK_CU(decoder->cudl->cuCtxPushCurrent(decoder->cuda_ctx));
890  if (ret < 0)
891  return ret;
892 
893  ret = CHECK_CU(decoder->cvdl->cuvidMapVideoFrame(decoder->decoder,
894  cf->idx, &devptr,
895  &pitch, &vpp));
896  if (ret < 0)
897  goto finish;
898 
899  unmap_data = av_mallocz(sizeof(*unmap_data));
900  if (!unmap_data) {
901  ret = AVERROR(ENOMEM);
902  goto copy_fail;
903  }
904 
905  frame->buf[1] = av_buffer_create((uint8_t *)unmap_data, sizeof(*unmap_data),
906  nvdec_unmap_mapped_frame, (void*)devptr,
908  if (!frame->buf[1]) {
909  ret = AVERROR(ENOMEM);
910  goto copy_fail;
911  }
912 
913  ret = av_buffer_replace(&frame->hw_frames_ctx, decoder->real_hw_frames_ref);
914  if (ret < 0)
915  goto copy_fail;
916 
917  unmap_data->idx = cf->idx;
918  unmap_data->decoder = av_refstruct_ref(cf->decoder);
919 
920  av_pix_fmt_get_chroma_sub_sample(hwctx->sw_format, &shift_h, &shift_v);
921  for (i = 0; frame->linesize[i]; i++) {
922  frame->data[i] = (uint8_t*)(devptr + offset);
923  frame->linesize[i] = pitch;
924  offset += pitch * (frame->height >> (i ? shift_v : 0));
925  }
926 
927  goto finish;
928 
929 copy_fail:
930  if (!frame->buf[1]) {
931  CHECK_CU(decoder->cvdl->cuvidUnmapVideoFrame(decoder->decoder, devptr));
932  av_freep(&unmap_data);
933  } else {
934  av_buffer_unref(&frame->buf[1]);
935  }
936 
937 finish:
938  CHECK_CU(decoder->cudl->cuCtxPopCurrent(&dummy));
939 
940  if (ret < 0 || decoder->unsafe_output)
941  return ret;
942 
944 }
945 
947 {
949  FrameDecodeData *fdd = frame->private_ref;
950  NVDECFrame *cf = NULL;
951  int ret;
952 
953  ctx->bitstream_len = 0;
954  ctx->nb_slices = 0;
955 
956  if (fdd->hwaccel_priv)
957  return 0;
958 
959  cf = av_mallocz(sizeof(*cf));
960  if (!cf)
961  return AVERROR(ENOMEM);
962 
963  cf->decoder = av_refstruct_ref(ctx->decoder);
964 
965  cf->idx_ref = av_refstruct_pool_get(ctx->decoder_pool);
966  if (!cf->idx_ref) {
967  av_log(avctx, AV_LOG_ERROR, "No decoder surfaces left\n");
968  ret = AVERROR(ENOMEM);
969  goto fail;
970  }
971  cf->ref_idx = cf->idx = *cf->idx_ref;
972 
973  fdd->hwaccel_priv = cf;
976 
977  return 0;
978 fail:
980  return ret;
981 
982 }
983 
985 {
987  FrameDecodeData *fdd = frame->private_ref;
988  NVDECFrame *cf;
989  int ret;
990 
991  ret = ff_nvdec_start_frame(avctx, frame);
992  if (ret < 0)
993  return ret;
994 
995  cf = fdd->hwaccel_priv;
996 
997  if (has_sep_ref) {
998  if (!cf->ref_idx_ref) {
999  cf->ref_idx_ref = av_refstruct_pool_get(ctx->decoder_pool);
1000  if (!cf->ref_idx_ref) {
1001  av_log(avctx, AV_LOG_ERROR, "No decoder surfaces left\n");
1002  return AVERROR(ENOMEM);
1003  }
1004  }
1005  cf->ref_idx = *cf->ref_idx_ref;
1006  } else {
1008  cf->ref_idx = cf->idx;
1009  }
1010 
1011  return 0;
1012 }
1013 
1015 {
1017  NVDECDecoder *decoder = ctx->decoder;
1018  void *logctx = avctx;
1019  CUVIDPICPARAMS *pp = &ctx->pic_params;
1020 
1021  CUcontext dummy;
1022 
1023  int ret = 0;
1024 
1025  pp->nBitstreamDataLen = ctx->bitstream_len;
1026  pp->pBitstreamData = ctx->bitstream;
1027  pp->nNumSlices = ctx->nb_slices;
1028  pp->pSliceDataOffsets = ctx->slice_offsets;
1029 
1030  ret = CHECK_CU(decoder->cudl->cuCtxPushCurrent(decoder->cuda_ctx));
1031  if (ret < 0)
1032  return ret;
1033 
1034 #ifdef NVDEC_HAVE_OPAQUE_OUTPUT_SUPPORT
1035  if (decoder->opaque_output && decoder->cvdl->cuvidDecodePictureAsync)
1036  ret = CHECK_CU(decoder->cvdl->cuvidDecodePictureAsync(decoder->decoder, &ctx->pic_params, decoder->stream));
1037  else
1038  ret = CHECK_CU(decoder->cvdl->cuvidDecodePicture(decoder->decoder, &ctx->pic_params));
1039 #else
1040  ret = CHECK_CU(decoder->cvdl->cuvidDecodePicture(decoder->decoder, &ctx->pic_params));
1041 #endif
1042  if (ret < 0)
1043  goto finish;
1044 
1045 finish:
1046  CHECK_CU(decoder->cudl->cuCtxPopCurrent(&dummy));
1047 
1048  return ret;
1049 }
1050 
1052 {
1054  int ret = ff_nvdec_end_frame(avctx);
1055  ctx->bitstream = NULL;
1056  ctx->bitstream_len = 0;
1057  ctx->nb_slices = 0;
1058  return ret;
1059 }
1060 
1062  uint32_t size)
1063 {
1065  void *tmp;
1066 
1067  tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated,
1068  (ctx->nb_slices + 1) * sizeof(*ctx->slice_offsets));
1069  if (!tmp)
1070  return AVERROR(ENOMEM);
1071  ctx->slice_offsets = tmp;
1072 
1073  if (!ctx->bitstream)
1074  ctx->bitstream = buffer;
1075 
1076  ctx->slice_offsets[ctx->nb_slices] = buffer - ctx->bitstream;
1077  ctx->bitstream_len += size;
1078  ctx->nb_slices++;
1079 
1080  return 0;
1081 }
1082 
1084  AVBufferRef *hw_frames_ctx,
1085  int dpb_size,
1086  int supports_444)
1087 {
1088  AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
1089  const AVPixFmtDescriptor *sw_desc;
1090  int cuvid_codec_type, cuvid_chroma_format, chroma_444;
1091 
1092  sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);
1093  if (!sw_desc)
1094  return AVERROR_BUG;
1095 
1096  cuvid_codec_type = map_avcodec_id(avctx->codec_id);
1097  if (cuvid_codec_type < 0) {
1098  av_log(avctx, AV_LOG_ERROR, "Unsupported codec ID\n");
1099  return AVERROR_BUG;
1100  }
1101 
1102  cuvid_chroma_format = map_chroma_format(avctx->sw_pix_fmt);
1103  if (cuvid_chroma_format < 0) {
1104  av_log(avctx, AV_LOG_VERBOSE, "Unsupported chroma format\n");
1105  return AVERROR(EINVAL);
1106  }
1107  chroma_444 = supports_444 && cuvid_chroma_format == cudaVideoChromaFormat_444;
1108 
1109  frames_ctx->format = (avctx->hwaccel->pix_fmt == AV_PIX_FMT_CUARRAY)
1111  // NVDEC target dimensions must be even-aligned for internal surface allocation.
1112  // For chroma-subsampled formats (420/422), the output dimensions must also be
1113  // even. For monochrome/444, keep the original output dimensions and only
1114  // even-align the NVDEC target — the frame copy will crop to avctx dimensions.
1115  if (cuvid_chroma_format == cudaVideoChromaFormat_420 ||
1116  cuvid_chroma_format == cudaVideoChromaFormat_422) {
1117  frames_ctx->width = (avctx->coded_width + 1) & ~1;
1118  frames_ctx->height = (avctx->coded_height + 1) & ~1;
1119  } else {
1120  frames_ctx->width = avctx->coded_width;
1121  frames_ctx->height = avctx->coded_height;
1122  }
1123  /*
1124  * We add two extra frames to the pool to account for deinterlacing filters
1125  * holding onto their frames.
1126  */
1127  frames_ctx->initial_pool_size = dpb_size + 2;
1128 
1129  switch (sw_desc->comp[0].depth) {
1130  case 8:
1131  if (chroma_444) {
1132  frames_ctx->sw_format = (frames_ctx->format == AV_PIX_FMT_CUARRAY)
1134 #ifdef NVDEC_HAVE_422_SUPPORT
1135  } else if (cuvid_chroma_format == cudaVideoChromaFormat_422) {
1136  frames_ctx->sw_format = AV_PIX_FMT_NV16;
1137 #endif
1138  } else {
1139  frames_ctx->sw_format = AV_PIX_FMT_NV12;
1140  }
1141  break;
1142  case 10:
1143  if (chroma_444) {
1144  frames_ctx->sw_format = (frames_ctx->format == AV_PIX_FMT_CUARRAY)
1146 #ifdef NVDEC_HAVE_422_SUPPORT
1147  } else if (cuvid_chroma_format == cudaVideoChromaFormat_422) {
1148  frames_ctx->sw_format = AV_PIX_FMT_P210;
1149 #endif
1150  } else {
1151  frames_ctx->sw_format = AV_PIX_FMT_P010;
1152  }
1153  break;
1154  case 12:
1155  if (chroma_444) {
1156  frames_ctx->sw_format = (frames_ctx->format == AV_PIX_FMT_CUARRAY)
1158 #ifdef NVDEC_HAVE_422_SUPPORT
1159  } else if (cuvid_chroma_format == cudaVideoChromaFormat_422) {
1160  frames_ctx->sw_format = AV_PIX_FMT_P212;
1161 #endif
1162  } else {
1163  frames_ctx->sw_format = AV_PIX_FMT_P012;
1164  }
1165  break;
1166  default:
1167  return AVERROR(EINVAL);
1168  }
1169 
1170  return 0;
1171 }
1172 
1174 {
1175  FrameDecodeData *fdd;
1176  NVDECFrame *cf;
1177 
1178  if (!frame || !frame->private_ref)
1179  return -1;
1180 
1181  fdd = frame->private_ref;
1182  cf = (NVDECFrame*)fdd->hwaccel_priv;
1183  if (!cf)
1184  return -1;
1185 
1186  return cf->ref_idx;
1187 }
AVCodecContext::hwaccel
const struct AVHWAccel * hwaccel
Hardware accelerator in use.
Definition: avcodec.h:1423
av_buffer_pool_init
AVBufferPool * av_buffer_pool_init(size_t size, AVBufferRef *(*alloc)(size_t size))
Allocate and initialize a buffer pool.
Definition: buffer.c:283
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
AV_PIX_FMT_CUDA
@ AV_PIX_FMT_CUDA
HW acceleration through CUDA.
Definition: pixfmt.h:260
ff_cuda_cuarray_elem_size
static int ff_cuda_cuarray_elem_size(CUarray_format fmt)
Return the element size in bytes for a CUarray_format, or 0 for unknown.
Definition: hwcontext_cuda_internal.h:44
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
r
const char * r
Definition: vf_curves.c:127
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
map_avcodec_id
static int map_avcodec_id(enum AVCodecID id)
Definition: nvdec.c:76
hwcontext_cuda_internal.h
out
static FILE * out
Definition: movenc.c:55
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3460
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
AVRefStructOpaque
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition: refstruct.h:58
map_chroma_format
static int map_chroma_format(enum AVPixelFormat pix_fmt)
Definition: nvdec.c:96
NVDECFramePool
Definition: nvdec.c:69
AVHWFramesContext::format
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:200
NVDECDecoder::stream
CUstream stream
Definition: nvdec.c:56
AV_PIX_FMT_YUV444P10MSB
#define AV_PIX_FMT_YUV444P10MSB
Definition: pixfmt.h:560
AVRefStructOpaque::nc
void * nc
Definition: refstruct.h:59
ff_nvdec_get_ref_idx
int ff_nvdec_get_ref_idx(AVFrame *frame)
Definition: nvdec.c:1173
AV_CODEC_ID_MPEG4
@ AV_CODEC_ID_MPEG4
Definition: codec_id.h:62
FrameDecodeData
This struct stores per-frame lavc-internal data and is attached to it via private_ref.
Definition: decode.h:33
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:337
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:472
av_frame_make_writable
int av_frame_make_writable(AVFrame *frame)
Ensure that the frame data is writable, avoiding data copy if possible.
Definition: frame.c:552
pixdesc.h
internal.h
AVHWFramesContext::free
void(* free)(struct AVHWFramesContext *ctx)
This field may be set by the caller before calling av_hwframe_ctx_init().
Definition: hwcontext.h:161
AVComponentDescriptor::depth
int depth
Number of bits in the component.
Definition: pixdesc.h:57
NVDECDecoder::unsafe_output
int unsafe_output
Definition: nvdec.c:61
data
const char data[16]
Definition: mxf.c:149
atomic_int
intptr_t atomic_int
Definition: stdatomic.h:55
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
FrameDecodeData::hwaccel_priv_free
void(* hwaccel_priv_free)(void *priv)
Definition: decode.h:55
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
NVDECDecoder::decoder
CUvideodecoder decoder
Definition: nvdec.c:50
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:220
decode_ctx
static DecodeContext * decode_ctx(AVCodecInternal *avci)
Definition: decode.c:112
NVDECDecoder::cvdl
CuvidFunctions * cvdl
Definition: nvdec.c:59
dummy
static int dummy
Definition: ffplay.c:3751
AV_PIX_FMT_P212
#define AV_PIX_FMT_P212
Definition: pixfmt.h:624
AV_PIX_FMT_YUV444P12MSB
#define AV_PIX_FMT_YUV444P12MSB
Definition: pixfmt.h:561
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3500
decoder
static const chunk_decoder decoder[8]
Definition: dfa.c:331
finish
static void finish(void)
Definition: movenc.c:374
NVDECFrame::idx_ref
unsigned int * idx_ref
RefStruct reference.
Definition: nvdec.h:57
ff_nvdec_start_frame
int ff_nvdec_start_frame(AVCodecContext *avctx, AVFrame *frame)
Definition: nvdec.c:946
NVDECFrame::ref_idx
unsigned int ref_idx
Definition: nvdec.h:56
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1579
av_pix_fmt_get_chroma_sub_sample
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.
Definition: pixdesc.c:3488
AVCodecContext::coded_height
int coded_height
Definition: avcodec.h:619
refstruct.h
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:63
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
cudaVideoSurfaceFormat_YUV444
#define cudaVideoSurfaceFormat_YUV444
Definition: nvdec.c:45
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
AV_HWACCEL_FLAG_UNSAFE_OUTPUT
#define AV_HWACCEL_FLAG_UNSAFE_OUTPUT
Some hardware decoders (namely nvdec) can either output direct decoder surfaces, or make an on-device...
Definition: avcodec.h:2034
AVHWFramesContext::height
int height
Definition: hwcontext.h:220
AVHWFramesContext::pool
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
Definition: hwcontext.h:181
ff_nvdec_start_frame_sep_ref
int ff_nvdec_start_frame_sep_ref(AVCodecContext *avctx, AVFrame *frame, int has_sep_ref)
Definition: nvdec.c:984
av_fast_realloc
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.
Definition: mem.c:495
nvdec_decoder_free
static void nvdec_decoder_free(AVRefStructOpaque unused, void *obj)
Definition: nvdec.c:175
FrameDecodeData::hwaccel_priv_post_process
int(* hwaccel_priv_post_process)(void *logctx, AVFrame *frame)
Per-frame private data for hwaccels.
Definition: decode.h:53
AV_BUFFER_FLAG_READONLY
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:114
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
AV_CODEC_ID_VP9
@ AV_CODEC_ID_VP9
Definition: codec_id.h:217
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:42
av_refstruct_alloc_ext
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.
Definition: refstruct.h:94
NVDECFrame
Definition: nvdec.h:54
AVCUDAFramesContext::cuarray_num_surfaces
int cuarray_num_surfaces
If >0, pre-allocate a fixed pool of surfaces.
Definition: hwcontext_cuda.h:98
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
decode.h
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:77
tmp
static uint8_t tmp[40]
Definition: aes_ctr.c:52
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition: avcodec.h:453
NVDECDecoder::cudl
CudaFunctions * cudl
Definition: nvdec.c:58
dpb_size
int dpb_size
Definition: h264_levels.c:111
if
if(ret)
Definition: filter_design.txt:179
AV_CODEC_ID_WMV3
@ AV_CODEC_ID_WMV3
Definition: codec_id.h:121
fail
#define fail
Definition: test.h:478
ff_nvdec_simple_end_frame
int ff_nvdec_simple_end_frame(AVCodecContext *avctx)
Definition: nvdec.c:1051
NULL
#define NULL
Definition: coverity.c:32
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:213
av_buffer_unref
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
AV_CODEC_ID_AV1
@ AV_CODEC_ID_AV1
Definition: codec_id.h:275
ff_nvdec_decode_init
int ff_nvdec_decode_init(AVCodecContext *avctx)
Definition: nvdec.c:404
AVHWFramesContext::device_ref
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:129
NVDECDecoder::hw_device_ref
AVBufferRef * hw_device_ref
Definition: nvdec.c:52
AVCodecContext::internal
struct AVCodecInternal * internal
Private context used for internal data.
Definition: avcodec.h:478
nvdec_decoder_frame_init
static int nvdec_decoder_frame_init(AVRefStructOpaque opaque, void *obj)
Definition: nvdec.c:279
AV_PIX_FMT_P410
#define AV_PIX_FMT_P410
Definition: pixfmt.h:623
av_buffer_pool_uninit
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:328
av_refstruct_pool_alloc_ext
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.
Definition: refstruct.h:258
av_refstruct_pool_get
void * av_refstruct_pool_get(AVRefStructPool *pool)
Get an object from the pool, reusing an old one from the pool when available.
Definition: refstruct.c:297
nvdec_decoder_create
static int nvdec_decoder_create(NVDECDecoder **out, AVBufferRef *hw_device_ref, CUVIDDECODECREATEINFO *params, void *logctx)
Definition: nvdec.c:222
atomic_load_explicit
#define atomic_load_explicit(object, order)
Definition: stdatomic.h:96
AV_CODEC_ID_MPEG1VIDEO
@ AV_CODEC_ID_MPEG1VIDEO
Definition: codec_id.h:51
av_buffer_create
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.
Definition: buffer.c:55
error.h
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:47
cudaVideoSurfaceFormat_YUV444_16Bit
#define cudaVideoSurfaceFormat_YUV444_16Bit
Definition: nvdec.c:46
nvdec_alloc_dummy
static AVBufferRef * nvdec_alloc_dummy(size_t size)
Definition: nvdec.c:321
CHECK_CU
#define CHECK_CU(x)
Definition: nvdec.c:74
NVDECDecoder::real_hw_frames_ref
AVBufferRef * real_hw_frames_ref
Definition: nvdec.c:54
AVCodecContext::extra_hw_frames
int extra_hw_frames
Video decoding only.
Definition: avcodec.h:1516
AV_PIX_FMT_P012
#define AV_PIX_FMT_P012
Definition: pixfmt.h:609
AVCodecInternal::hwaccel_priv_data
void * hwaccel_priv_data
hwaccel-specific private data
Definition: internal.h:130
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
NVDECFrame::ref_idx_ref
unsigned int * ref_idx_ref
RefStruct reference.
Definition: nvdec.h:58
NVDECFrame::idx
unsigned int idx
Definition: nvdec.h:55
NVDECDecoder::decode_hw_frames_ref
AVBufferRef * decode_hw_frames_ref
Definition: nvdec.c:53
nvdec_decoder_frame_pool_free
static void nvdec_decoder_frame_pool_free(AVRefStructOpaque opaque)
Definition: nvdec.c:292
size
int size
Definition: twinvq_data.h:10344
AV_PIX_FMT_NV16
@ AV_PIX_FMT_NV16
interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:198
av_refstruct_ref
void * av_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
Definition: refstruct.c:140
nvdec_test_capabilities
static int nvdec_test_capabilities(NVDECDecoder *decoder, CUVIDDECODECREATEINFO *params, void *logctx)
Definition: nvdec.c:115
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
nvdec.h
nvdec_free_dummy
static void nvdec_free_dummy(struct AVHWFramesContext *ctx)
Definition: nvdec.c:316
AV_PIX_FMT_P210
#define AV_PIX_FMT_P210
Definition: pixfmt.h:622
ff_nvdec_decode_uninit
int ff_nvdec_decode_uninit(AVCodecContext *avctx)
Definition: nvdec.c:297
av_refstruct_unref
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
AV_CODEC_ID_MJPEG
@ AV_CODEC_ID_MJPEG
Definition: codec_id.h:57
NVDECFrame::decoder
struct NVDECDecoder * decoder
RefStruct reference.
Definition: nvdec.h:59
av_malloc
#define av_malloc(s)
Definition: ops_asmgen.c:44
AVCUDAFramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_cuda.h:79
AV_PIX_FMT_CUARRAY
@ AV_PIX_FMT_CUARRAY
hardware decoding through openharmony
Definition: pixfmt.h:506
hw_device_ctx
static AVBufferRef * hw_device_ctx
Definition: hw_decode.c:45
NVDECDecoder::cuda_ctx
CUcontext cuda_ctx
Definition: nvdec.c:55
AV_PIX_FMT_NV24
@ 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...
Definition: pixfmt.h:371
nvdec_fdd_priv_free
static void nvdec_fdd_priv_free(void *priv)
Definition: nvdec.c:714
ff_nvdec_end_frame
int ff_nvdec_end_frame(AVCodecContext *avctx)
Definition: nvdec.c:1014
common.h
AVCodecContext::hwaccel_flags
int hwaccel_flags
Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated decoding (if active).
Definition: avcodec.h:1502
atomic_store_explicit
#define atomic_store_explicit(object, desired, order)
Definition: stdatomic.h:90
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:223
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AVCodecContext::hw_device_ctx
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
Definition: avcodec.h:1493
AV_CODEC_ID_VC1
@ AV_CODEC_ID_VC1
Definition: codec_id.h:120
av_buffer_replace
int av_buffer_replace(AVBufferRef **pdst, const AVBufferRef *src)
Ensure dst refers to the same data as src.
Definition: buffer.c:233
NVDECDecoder
Definition: nvdec.c:49
NVDECDecoder::opaque_output
int opaque_output
Definition: nvdec.c:62
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
AVCodecContext::hw_frames_ctx
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
Definition: avcodec.h:1471
avcodec.h
nvdec_retrieve_data
static int nvdec_retrieve_data(void *logctx, AVFrame *frame)
Definition: nvdec.c:771
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:118
AVCUDADeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_cuda.h:44
avcodec_get_hw_frames_parameters
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.
Definition: decode.c:1120
ret
ret
Definition: filter_design.txt:187
pixfmt.h
AV_PIX_FMT_NV12
@ 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
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:265
cuda_check.h
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:153
NVDECFramePool::dpb_size
unsigned int dpb_size
Definition: nvdec.c:70
nvdec_init_hwframes
static int nvdec_init_hwframes(AVCodecContext *avctx, AVBufferRef **out_frames_ref, int dummy)
Definition: nvdec.c:326
NVDECFramePool::nb_allocated
unsigned int nb_allocated
Definition: nvdec.c:71
AVCodecContext
main external API structure.
Definition: avcodec.h:443
ff_nvdec_simple_decode_slice
int ff_nvdec_simple_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
Definition: nvdec.c:1061
nvdec_unmap_mapped_frame
static void nvdec_unmap_mapped_frame(void *opaque, uint8_t *data)
Definition: nvdec.c:728
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
ff_nvdec_frame_params
int ff_nvdec_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx, int dpb_size, int supports_444)
Definition: nvdec.c:1083
output_format
static char * output_format
Definition: ffprobe.c:145
AVPixFmtDescriptor::comp
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:105
Windows::Graphics::DirectX::Direct3D11::p
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
Definition: vsrc_gfxcapture_winrt.hpp:53
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:78
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:608
AVCodecContext::coded_width
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:619
AVHWFramesContext::initial_pool_size
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:190
desc
const char * desc
Definition: libsvtav1.c:83
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
av_refstruct_pool_uninit
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
Definition: refstruct.h:292
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
FrameDecodeData::hwaccel_priv
void * hwaccel_priv
Definition: decode.h:54
AV_CODEC_ID_VP8
@ AV_CODEC_ID_VP8
Definition: codec_id.h:190
hwcontext.h
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AV_PIX_FMT_P412
#define AV_PIX_FMT_P412
Definition: pixfmt.h:625
AVCodecContext::sw_pix_fmt
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:650
NVDECContext
Definition: nvdec.h:62
AV_CODEC_ID_MPEG2VIDEO
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
Definition: codec_id.h:52
AVCUDAFramesContext::cuarray_desc
CUDA_ARRAY3D_DESCRIPTOR cuarray_desc
CUDA_ARRAY3D_DESCRIPTOR CUarrays will be initialized with.
Definition: hwcontext_cuda.h:89
AVHWAccel::pix_fmt
enum AVPixelFormat pix_fmt
Supported pixel format.
Definition: avcodec.h:1975