@ -35,6 +35,11 @@
# include "nvdec.h"
# include "internal.h"
# if !NVDECAPI_CHECK_VERSION(9, 0)
# define cudaVideoSurfaceFormat_YUV444 2
# define cudaVideoSurfaceFormat_YUV444_16Bit 3
# endif
typedef struct NVDECDecoder {
CUvideodecoder decoder ;
@ -274,7 +279,8 @@ int ff_nvdec_decode_init(AVCodecContext *avctx)
CUVIDDECODECREATEINFO params = { 0 } ;
int cuvid_codec_type , cuvid_chroma_format ;
cudaVideoSurfaceFormat output_format ;
int cuvid_codec_type , cuvid_chroma_format , chroma_444 ;
int ret = 0 ;
sw_desc = av_pix_fmt_desc_get ( avctx - > sw_pix_fmt ) ;
@ -292,6 +298,7 @@ int ff_nvdec_decode_init(AVCodecContext *avctx)
av_log ( avctx , AV_LOG_ERROR , " Unsupported chroma format \n " ) ;
return AVERROR ( ENOSYS ) ;
}
chroma_444 = cuvid_chroma_format = = cudaVideoChromaFormat_444 ;
if ( ! avctx - > hw_frames_ctx ) {
ret = ff_decode_get_hw_frames_ctx ( avctx , AV_HWDEVICE_TYPE_CUDA ) ;
@ -299,6 +306,21 @@ int ff_nvdec_decode_init(AVCodecContext *avctx)
return ret ;
}
switch ( sw_desc - > comp [ 0 ] . depth ) {
case 8 :
output_format = chroma_444 ? cudaVideoSurfaceFormat_YUV444 :
cudaVideoSurfaceFormat_NV12 ;
break ;
case 10 :
case 12 :
output_format = chroma_444 ? cudaVideoSurfaceFormat_YUV444_16Bit :
cudaVideoSurfaceFormat_P016 ;
break ;
default :
av_log ( avctx , AV_LOG_ERROR , " Unsupported bit depth \n " ) ;
return AVERROR ( ENOSYS ) ;
}
frames_ctx = ( AVHWFramesContext * ) avctx - > hw_frames_ctx - > data ;
params . ulWidth = avctx - > coded_width ;
@ -306,8 +328,7 @@ int ff_nvdec_decode_init(AVCodecContext *avctx)
params . ulTargetWidth = avctx - > coded_width ;
params . ulTargetHeight = avctx - > coded_height ;
params . bitDepthMinus8 = sw_desc - > comp [ 0 ] . depth - 8 ;
params . OutputFormat = params . bitDepthMinus8 ?
cudaVideoSurfaceFormat_P016 : cudaVideoSurfaceFormat_NV12 ;
params . OutputFormat = output_format ;
params . CodecType = cuvid_codec_type ;
params . ChromaFormat = cuvid_chroma_format ;
params . ulNumDecodeSurfaces = frames_ctx - > initial_pool_size ;
@ -386,6 +407,8 @@ static int nvdec_retrieve_data(void *logctx, AVFrame *frame)
NVDECFrame * cf = ( NVDECFrame * ) fdd - > hwaccel_priv ;
NVDECDecoder * decoder = ( NVDECDecoder * ) cf - > decoder_ref - > data ;
AVHWFramesContext * hwctx = ( AVHWFramesContext * ) frame - > hw_frames_ctx - > data ;
CUVIDPROCPARAMS vpp = { 0 } ;
NVDECFrame * unmap_data = NULL ;
@ -394,6 +417,7 @@ static int nvdec_retrieve_data(void *logctx, AVFrame *frame)
unsigned int pitch , i ;
unsigned int offset = 0 ;
int shift_h = 0 , shift_v = 0 ;
int ret = 0 ;
vpp . progressive_frame = 1 ;
@ -427,10 +451,11 @@ static int nvdec_retrieve_data(void *logctx, AVFrame *frame)
unmap_data - > idx_ref = av_buffer_ref ( cf - > idx_ref ) ;
unmap_data - > decoder_ref = av_buffer_ref ( cf - > decoder_ref ) ;
av_pix_fmt_get_chroma_sub_sample ( hwctx - > sw_format , & shift_h , & shift_v ) ;
for ( i = 0 ; frame - > linesize [ i ] ; i + + ) {
frame - > data [ i ] = ( uint8_t * ) ( devptr + offset ) ;
frame - > linesize [ i ] = pitch ;
offset + = pitch * ( frame - > height > > ( i ? 1 : 0 ) ) ;
offset + = pitch * ( frame - > height > > ( i ? shift_v : 0 ) ) ;
}
goto finish ;
@ -566,7 +591,7 @@ int ff_nvdec_frame_params(AVCodecContext *avctx,
{
AVHWFramesContext * frames_ctx = ( AVHWFramesContext * ) hw_frames_ctx - > data ;
const AVPixFmtDescriptor * sw_desc ;
int cuvid_codec_type , cuvid_chroma_format ;
int cuvid_codec_type , cuvid_chroma_format , chroma_444 ;
sw_desc = av_pix_fmt_desc_get ( avctx - > sw_pix_fmt ) ;
if ( ! sw_desc )
@ -583,6 +608,7 @@ int ff_nvdec_frame_params(AVCodecContext *avctx,
av_log ( avctx , AV_LOG_VERBOSE , " Unsupported chroma format \n " ) ;
return AVERROR ( EINVAL ) ;
}
chroma_444 = cuvid_chroma_format = = cudaVideoChromaFormat_444 ;
frames_ctx - > format = AV_PIX_FMT_CUDA ;
frames_ctx - > width = ( avctx - > coded_width + 1 ) & ~ 1 ;
@ -601,13 +627,13 @@ int ff_nvdec_frame_params(AVCodecContext *avctx,
switch ( sw_desc - > comp [ 0 ] . depth ) {
case 8 :
frames_ctx - > sw_format = AV_PIX_FMT_NV12 ;
frames_ctx - > sw_format = chroma_444 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_NV12 ;
break ;
case 10 :
frames_ctx - > sw_format = AV_PIX_FMT_P010 ;
frames_ctx - > sw_format = chroma_444 ? AV_PIX_FMT_YUV444P16 : AV_PIX_FMT_P010 ;
break ;
case 12 :
frames_ctx - > sw_format = AV_PIX_FMT_P016 ;
frames_ctx - > sw_format = chroma_444 ? AV_PIX_FMT_YUV444P16 : AV_PIX_FMT_P016 ;
break ;
default :
return AVERROR ( EINVAL ) ;