Commit 27038693 authored by Philip Langdale's avatar Philip Langdale Committed by Timo Rothenpieler

avcodec/nvenc: Delay identification of underlying format of cuda frames

When input surfaces are cuda frames, we will not know what the actual
underlying format (nv12, p010, etc) is at surface allocation time.

On the other hand, we will know when the input frames are actually
registered and associated with a surface.

So, let's delay format discovery until registration time, which is
actually how we handle other frame properties, such as dimensions.

By itself, this change doesn't allow for transcoding of 10bit
content from cuvid, but it reduces the problem to the hardcoding of
the sw format in ffmpeg_cuvid.c
Signed-off-by: 's avatarPhilip Langdale <philipl@overt.org>
Signed-off-by: 's avatarTimo Rothenpieler <timo@rothenpieler.org>
parent 8cbdaa4b
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"
#include "libavutil/avassert.h" #include "libavutil/avassert.h"
#include "libavutil/mem.h" #include "libavutil/mem.h"
#include "libavutil/pixdesc.h"
#include "internal.h" #include "internal.h"
#define NVENC_CAP 0x30 #define NVENC_CAP 0x30
...@@ -1009,49 +1010,37 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx) ...@@ -1009,49 +1010,37 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
return 0; 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; switch (pix_fmt) {
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) {
case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUV420P:
ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YV12_PL; return NV_ENC_BUFFER_FORMAT_YV12_PL;
break;
case AV_PIX_FMT_NV12: case AV_PIX_FMT_NV12:
ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_NV12_PL; return NV_ENC_BUFFER_FORMAT_NV12_PL;
break;
case AV_PIX_FMT_P010: case AV_PIX_FMT_P010:
ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV420_10BIT; return NV_ENC_BUFFER_FORMAT_YUV420_10BIT;
break;
case AV_PIX_FMT_YUV444P: case AV_PIX_FMT_YUV444P:
ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV444_PL; return NV_ENC_BUFFER_FORMAT_YUV444_PL;
break;
case AV_PIX_FMT_YUV444P16: case AV_PIX_FMT_YUV444P16:
ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV444_10BIT; return NV_ENC_BUFFER_FORMAT_YUV444_10BIT;
break;
case AV_PIX_FMT_0RGB32: case AV_PIX_FMT_0RGB32:
ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_ARGB; return NV_ENC_BUFFER_FORMAT_ARGB;
break;
case AV_PIX_FMT_0BGR32: case AV_PIX_FMT_0BGR32:
ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_ABGR; return NV_ENC_BUFFER_FORMAT_ABGR;
break;
default: default:
av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format\n"); return NV_ENC_BUFFER_FORMAT_UNDEFINED;
return AVERROR(EINVAL);
} }
}
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) { if (avctx->pix_fmt == AV_PIX_FMT_CUDA) {
ctx->surfaces[idx].in_ref = av_frame_alloc(); ctx->surfaces[idx].in_ref = av_frame_alloc();
...@@ -1059,6 +1048,14 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) ...@@ -1059,6 +1048,14 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
} else { } else {
NV_ENC_CREATE_INPUT_BUFFER allocSurf = { 0 }; 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.version = NV_ENC_CREATE_INPUT_BUFFER_VER;
allocSurf.width = (avctx->width + 31) & ~31; allocSurf.width = (avctx->width + 31) & ~31;
allocSurf.height = (avctx->height + 31) & ~31; allocSurf.height = (avctx->height + 31) & ~31;
...@@ -1351,10 +1348,16 @@ static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame) ...@@ -1351,10 +1348,16 @@ static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame)
reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR; reg.resourceType = NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR;
reg.width = frames_ctx->width; reg.width = frames_ctx->width;
reg.height = frames_ctx->height; reg.height = frames_ctx->height;
reg.bufferFormat = ctx->surfaces[0].format;
reg.pitch = frame->linesize[0]; reg.pitch = frame->linesize[0];
reg.resourceToRegister = frame->data[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, &reg); ret = p_nvenc->nvEncRegisterResource(ctx->nvencoder, &reg);
if (ret != NV_ENC_SUCCESS) { if (ret != NV_ENC_SUCCESS) {
nvenc_print_error(avctx, ret, "Error registering an input resource"); nvenc_print_error(avctx, ret, "Error registering an input resource");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment