} \
} while (0)
+static const struct {
+ NVENCSTATUS nverr;
+ int averr;
+ const char *desc;
+} nvenc_errors[] = {
+ { NV_ENC_SUCCESS, 0, "success" },
+ { NV_ENC_ERR_NO_ENCODE_DEVICE, AVERROR(ENOENT), "no encode device" },
+ { NV_ENC_ERR_UNSUPPORTED_DEVICE, AVERROR(ENOSYS), "unsupported device" },
+ { NV_ENC_ERR_INVALID_ENCODERDEVICE, AVERROR(EINVAL), "invalid encoder device" },
+ { NV_ENC_ERR_INVALID_DEVICE, AVERROR(EINVAL), "invalid device" },
+ { NV_ENC_ERR_DEVICE_NOT_EXIST, AVERROR(EIO), "device does not exist" },
+ { NV_ENC_ERR_INVALID_PTR, AVERROR(EFAULT), "invalid ptr" },
+ { NV_ENC_ERR_INVALID_EVENT, AVERROR(EINVAL), "invalid event" },
+ { NV_ENC_ERR_INVALID_PARAM, AVERROR(EINVAL), "invalid param" },
+ { NV_ENC_ERR_INVALID_CALL, AVERROR(EINVAL), "invalid call" },
+ { NV_ENC_ERR_OUT_OF_MEMORY, AVERROR(ENOMEM), "out of memory" },
+ { NV_ENC_ERR_ENCODER_NOT_INITIALIZED, AVERROR(EINVAL), "encoder not initialized" },
+ { NV_ENC_ERR_UNSUPPORTED_PARAM, AVERROR(ENOSYS), "unsupported param" },
+ { NV_ENC_ERR_LOCK_BUSY, AVERROR(EAGAIN), "lock busy" },
+ { NV_ENC_ERR_NOT_ENOUGH_BUFFER, AVERROR(ENOBUFS), "not enough buffer" },
+ { NV_ENC_ERR_INVALID_VERSION, AVERROR(EINVAL), "invalid version" },
+ { NV_ENC_ERR_MAP_FAILED, AVERROR(EIO), "map failed" },
+ { NV_ENC_ERR_NEED_MORE_INPUT, AVERROR(EAGAIN), "need more input" },
+ { NV_ENC_ERR_ENCODER_BUSY, AVERROR(EAGAIN), "encoder busy" },
+ { NV_ENC_ERR_EVENT_NOT_REGISTERD, AVERROR(EBADF), "event not registered" },
+ { NV_ENC_ERR_GENERIC, AVERROR_UNKNOWN, "generic error" },
+ { NV_ENC_ERR_INCOMPATIBLE_CLIENT_KEY, AVERROR(EINVAL), "incompatible client key" },
+ { NV_ENC_ERR_UNIMPLEMENTED, AVERROR(ENOSYS), "unimplemented" },
+ { NV_ENC_ERR_RESOURCE_REGISTER_FAILED, AVERROR(EIO), "resource register failed" },
+ { NV_ENC_ERR_RESOURCE_NOT_REGISTERED, AVERROR(EBADF), "resource not registered" },
+ { NV_ENC_ERR_RESOURCE_NOT_MAPPED, AVERROR(EBADF), "resource not mapped" },
+};
+
+static int nvenc_map_error(NVENCSTATUS err, const char **desc)
+{
+ int i;
+ for (i = 0; i < FF_ARRAY_ELEMS(nvenc_errors); i++) {
+ if (nvenc_errors[i].nverr == err) {
+ if (desc)
+ *desc = nvenc_errors[i].desc;
+ return nvenc_errors[i].averr;
+ }
+ }
+ if (desc)
+ *desc = "unknown error";
+ return AVERROR_UNKNOWN;
+}
+
+static int nvenc_print_error(void *log_ctx, NVENCSTATUS err,
+ const char *error_string)
+{
+ const char *desc;
+ int ret;
+ ret = nvenc_map_error(err, &desc);
+ av_log(log_ctx, AV_LOG_ERROR, "%s: %s (%d)\n", error_string, desc, err);
+ return ret;
+}
+
static av_cold int nvenc_load_libraries(AVCodecContext *avctx)
{
NVENCContext *ctx = avctx->priv_data;
NVENCLibraryContext *nvel = &ctx->nvel;
PNVENCODEAPICREATEINSTANCE nvenc_create_instance;
+ NVENCSTATUS err;
LOAD_LIBRARY(nvel->cuda, CUDA_LIBNAME);
nvel->nvenc_funcs.version = NV_ENCODE_API_FUNCTION_LIST_VER;
- if ((nvenc_create_instance(&nvel->nvenc_funcs)) != NV_ENC_SUCCESS) {
- av_log(avctx, AV_LOG_ERROR, "Cannot create the NVENC instance");
- return AVERROR_UNKNOWN;
- }
+ err = nvenc_create_instance(&nvel->nvenc_funcs);
+ if (err != NV_ENC_SUCCESS)
+ return nvenc_print_error(avctx, err, "Cannot create the NVENC instance");
return 0;
}
ret = nv->nvEncOpenEncodeSessionEx(¶ms, &ctx->nvenc_ctx);
if (ret != NV_ENC_SUCCESS) {
ctx->nvenc_ctx = NULL;
- av_log(avctx, AV_LOG_ERROR,
- "Cannot open the NVENC Session\n");
- return AVERROR_UNKNOWN;
+ return nvenc_print_error(avctx, ret, "Cannot open the NVENC Session");
}
return 0;
vui->videoFullRangeFlag = avctx->color_range == AVCOL_RANGE_JPEG;
- h264->disableSPSPPS = (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
- h264->repeatSPSPPS = (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
+ h264->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
+ h264->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
h264->maxNumRefFrames = avctx->refs;
h264->idrPeriod = cc->gopLength;
NV_ENC_CONFIG *cc = &ctx->config;
NV_ENC_CONFIG_HEVC *hevc = &cc->encodeCodecConfig.hevcConfig;
- hevc->disableSPSPPS = (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
- hevc->repeatSPSPPS = (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
+ hevc->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
+ hevc->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
hevc->maxNumRefFramesInDPB = avctx->refs;
hevc->idrPeriod = cc->gopLength;
NVENCContext *ctx = avctx->priv_data;
NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs;
NV_ENC_PRESET_CONFIG preset_cfg = { 0 };
+ AVCPBProperties *cpb_props;
int ret;
ctx->params.version = NV_ENC_INITIALIZE_PARAMS_VER;
ctx->params.encodeGUID,
ctx->params.presetGUID,
&preset_cfg);
- if (ret != NV_ENC_SUCCESS) {
- av_log(avctx, AV_LOG_ERROR,
- "Cannot get the preset configuration\n");
- return AVERROR_UNKNOWN;
- }
+ if (ret != NV_ENC_SUCCESS)
+ return nvenc_print_error(avctx, ret, "Cannot get the preset configuration");
memcpy(&ctx->config, &preset_cfg.presetCfg, sizeof(ctx->config));
nvenc_setup_rate_control(avctx);
- if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) {
+ if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
ctx->config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD;
} else {
ctx->config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME;
return ret;
ret = nv->nvEncInitializeEncoder(ctx->nvenc_ctx, &ctx->params);
- if (ret != NV_ENC_SUCCESS) {
- av_log(avctx, AV_LOG_ERROR, "Cannot initialize the decoder");
- return AVERROR_UNKNOWN;
- }
+ if (ret != NV_ENC_SUCCESS)
+ return nvenc_print_error(avctx, ret, "Cannot initialize the decoder");
+
+ cpb_props = ff_add_cpb_side_data(avctx);
+ if (!cpb_props)
+ return AVERROR(ENOMEM);
+ cpb_props->max_bitrate = avctx->rc_max_rate;
+ cpb_props->min_bitrate = avctx->rc_min_rate;
+ cpb_props->avg_bitrate = avctx->bit_rate;
+ cpb_props->buffer_size = avctx->rc_buffer_size;
return 0;
}
}
ret = nv->nvEncCreateInputBuffer(ctx->nvenc_ctx, &in_buffer);
- if (ret != NV_ENC_SUCCESS) {
- av_log(avctx, AV_LOG_ERROR, "CreateInputBuffer failed\n");
- return AVERROR_UNKNOWN;
- }
+ if (ret != NV_ENC_SUCCESS)
+ return nvenc_print_error(avctx, ret, "CreateInputBuffer failed");
ctx->in[idx].in = in_buffer.inputBuffer;
ctx->in[idx].format = in_buffer.bufferFmt;
out_buffer.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_UNCACHED;
ret = nv->nvEncCreateBitstreamBuffer(ctx->nvenc_ctx, &out_buffer);
- if (ret != NV_ENC_SUCCESS) {
- av_log(avctx, AV_LOG_ERROR, "CreateBitstreamBuffer failed\n");
- return AVERROR_UNKNOWN;
- }
+ if (ret != NV_ENC_SUCCESS)
+ return nvenc_print_error(avctx, ret, "CreateBitstreamBuffer failed");
ctx->out[idx].out = out_buffer.bitstreamBuffer;
ctx->out[idx].busy = 0;
NV_ENC_SEQUENCE_PARAM_PAYLOAD payload = { 0 };
int ret;
- avctx->extradata = av_mallocz(EXTRADATA_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
+ avctx->extradata = av_mallocz(EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
if (!avctx->extradata)
return AVERROR(ENOMEM);
payload.outSPSPPSPayloadSize = &avctx->extradata_size;
ret = nv->nvEncGetSequenceParams(ctx->nvenc_ctx, &payload);
- if (ret != NV_ENC_SUCCESS) {
- av_log(avctx, AV_LOG_ERROR, "Cannot get the extradata\n");
- return AVERROR_UNKNOWN;
- }
+ if (ret != NV_ENC_SUCCESS)
+ return nvenc_print_error(avctx, ret, "Cannot get the extradata");
return 0;
}
NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs;
int i;
- av_frame_free(&avctx->coded_frame);
+ av_fifo_free(ctx->timestamps);
+ av_fifo_free(ctx->pending);
+ av_fifo_free(ctx->ready);
if (ctx->in) {
for (i = 0; i < ctx->nb_surfaces; ++i) {
if ((ret = nvenc_setup_surfaces(avctx)) < 0)
return ret;
- if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) {
+ if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
if ((ret = nvenc_setup_extradata(avctx)) < 0)
return ret;
}
- avctx->coded_frame = av_frame_alloc();
- if (!avctx->coded_frame)
- return AVERROR(ENOMEM);
-
return 0;
}
ret = nv->nvEncLockInputBuffer(ctx->nvenc_ctx, ¶ms);
- if (ret != NV_ENC_SUCCESS) {
- av_log(avctx, AV_LOG_ERROR, "Cannot lock the buffer %p.\n",
- in);
- return AVERROR_UNKNOWN;
- }
+ if (ret != NV_ENC_SUCCESS)
+ return nvenc_print_error(avctx, ret, "Cannot lock the buffer");
ret = nvenc_copy_frame(¶ms, frame);
if (ret < 0)
goto fail;
ret = nv->nvEncUnlockInputBuffer(ctx->nvenc_ctx, in->in);
- if (ret != NV_ENC_SUCCESS) {
- av_log(avctx, AV_LOG_ERROR, "Cannot unlock the buffer %p.\n",
- in);
- return AVERROR_UNKNOWN;
- }
+ if (ret != NV_ENC_SUCCESS)
+ return nvenc_print_error(avctx, ret, "Cannot unlock the buffer");
*in_surf = in;
ret = nv->nvEncLockBitstream(ctx->nvenc_ctx, ¶ms);
if (ret < 0)
- return AVERROR_UNKNOWN;
+ return nvenc_print_error(avctx, ret, "Cannot lock the bitstream");
ret = ff_alloc_packet(pkt, params.bitstreamSizeInBytes);
if (ret < 0)
ret = nv->nvEncUnlockBitstream(ctx->nvenc_ctx, out->out);
if (ret < 0)
- return AVERROR_UNKNOWN;
+ return nvenc_print_error(avctx, ret, "Cannot unlock the bitstream");
out->busy = out->in->locked = 0;
switch (params.pictureType) {
case NV_ENC_PIC_TYPE_IDR:
pkt->flags |= AV_PKT_FLAG_KEY;
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
case NV_ENC_PIC_TYPE_INTRA_REFRESH:
case NV_ENC_PIC_TYPE_I:
avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
case NV_ENC_PIC_TYPE_BI:
avctx->coded_frame->pict_type = AV_PICTURE_TYPE_BI;
break;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
}
return 0;
params.outputBitstream = out->out;
params.inputTimeStamp = frame->pts;
- if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) {
+ if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
if (frame->top_field_first)
params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_TOP_BOTTOM;
else
}
ret = nv->nvEncEncodePicture(ctx->nvenc_ctx, ¶ms);
-
if (ret != NV_ENC_SUCCESS &&
- ret != NV_ENC_ERR_NEED_MORE_INPUT) {
-
- return AVERROR_UNKNOWN;
- }
+ ret != NV_ENC_ERR_NEED_MORE_INPUT)
+ return nvenc_print_error(avctx, ret, "Error encoding the frame");
if (out) {
ret = nvenc_enqueue_surface(ctx->pending, out);