diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index d24d2780e5..2353161e06 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -28,6 +28,7 @@ #include "libavutil/imgutils.h" #include "libavutil/avassert.h" #include "libavutil/mem.h" +#include "libavutil/pixdesc.h" #include "internal.h" #define NVENC_CAP 0x30 @@ -1009,49 +1010,37 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx) return 0; } -static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) +static NV_ENC_BUFFER_FORMAT nvenc_map_buffer_format(enum AVPixelFormat pix_fmt) { - NvencContext *ctx = avctx->priv_data; - NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; - NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; - - NVENCSTATUS nv_status; - NV_ENC_CREATE_BITSTREAM_BUFFER allocOut = { 0 }; - allocOut.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER; - - switch (ctx->data_pix_fmt) { + switch (pix_fmt) { case AV_PIX_FMT_YUV420P: - ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YV12_PL; - break; - + return NV_ENC_BUFFER_FORMAT_YV12_PL; case AV_PIX_FMT_NV12: - ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_NV12_PL; - break; - + return NV_ENC_BUFFER_FORMAT_NV12_PL; case AV_PIX_FMT_P010: - ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV420_10BIT; - break; - + return NV_ENC_BUFFER_FORMAT_YUV420_10BIT; case AV_PIX_FMT_YUV444P: - ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV444_PL; - break; - + return NV_ENC_BUFFER_FORMAT_YUV444_PL; case AV_PIX_FMT_YUV444P16: - ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV444_10BIT; - break; - + return NV_ENC_BUFFER_FORMAT_YUV444_10BIT; case AV_PIX_FMT_0RGB32: - ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_ARGB; - break; - + return NV_ENC_BUFFER_FORMAT_ARGB; case AV_PIX_FMT_0BGR32: - ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_ABGR; - break; - + return NV_ENC_BUFFER_FORMAT_ABGR; default: - av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format\n"); - return AVERROR(EINVAL); + return NV_ENC_BUFFER_FORMAT_UNDEFINED; } +} + +static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) +{ + NvencContext *ctx = avctx->priv_data; + NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; + NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; + + NVENCSTATUS nv_status; + NV_ENC_CREATE_BITSTREAM_BUFFER allocOut = { 0 }; + allocOut.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER; if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { ctx->surfaces[idx].in_ref = av_frame_alloc(); @@ -1059,6 +1048,14 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) return AVERROR(ENOMEM); } else { NV_ENC_CREATE_INPUT_BUFFER allocSurf = { 0 }; + + ctx->surfaces[idx].format = nvenc_map_buffer_format(ctx->data_pix_fmt); + if (ctx->surfaces[idx].format == NV_ENC_BUFFER_FORMAT_UNDEFINED) { + av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format: %s\n", + av_get_pix_fmt_name(ctx->data_pix_fmt)); + return AVERROR(EINVAL); + } + allocSurf.version = NV_ENC_CREATE_INPUT_BUFFER_VER; allocSurf.width = (avctx->width + 31) & ~31; allocSurf.height = (avctx->height + 31) & ~31; @@ -1351,10 +1348,16 @@ static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame) reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR; reg.width = frames_ctx->width; reg.height = frames_ctx->height; - reg.bufferFormat = ctx->surfaces[0].format; reg.pitch = frame->linesize[0]; reg.resourceToRegister = frame->data[0]; + reg.bufferFormat = nvenc_map_buffer_format(frames_ctx->sw_format); + if (reg.bufferFormat == NV_ENC_BUFFER_FORMAT_UNDEFINED) { + av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format: %s\n", + av_get_pix_fmt_name(frames_ctx->sw_format)); + return AVERROR(EINVAL); + } + ret = p_nvenc->nvEncRegisterResource(ctx->nvencoder, ®); if (ret != NV_ENC_SUCCESS) { nvenc_print_error(avctx, ret, "Error registering an input resource");