early-access version 1680

This commit is contained in:
pineappleEA
2021-05-13 11:45:27 +02:00
parent 1434d96e7d
commit 66ed389c6f
311 changed files with 6452 additions and 2597 deletions

View File

@@ -22,6 +22,7 @@
#include "config.h"
#include "nvenc.h"
#include "hevc_sei.h"
#include "libavutil/hwcontext_cuda.h"
#include "libavutil/hwcontext.h"
@@ -30,6 +31,7 @@
#include "libavutil/avassert.h"
#include "libavutil/mem.h"
#include "libavutil/pixdesc.h"
#include "encode.h"
#include "internal.h"
#include "packet_internal.h"
@@ -40,6 +42,12 @@
rc == NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ || \
rc == NV_ENC_PARAMS_RC_CBR_HQ)
#ifdef NVENC_HAVE_NEW_PRESETS
#define IS_SDK10_PRESET(p) ((p) >= PRESET_P1 && (p) <= PRESET_P7)
#else
#define IS_SDK10_PRESET(p) 0
#endif
const enum AVPixelFormat ff_nvenc_pix_fmts[] = {
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NV12,
@@ -143,8 +151,14 @@ static int nvenc_print_error(AVCodecContext *avctx, NVENCSTATUS err,
static void nvenc_print_driver_requirement(AVCodecContext *avctx, int level)
{
#if NVENCAPI_CHECK_VERSION(9, 2)
#if NVENCAPI_CHECK_VERSION(10, 1)
const char *minver = "(unknown)";
#elif NVENCAPI_CHECK_VERSION(10, 0)
# if defined(_WIN32) || defined(__CYGWIN__)
const char *minver = "450.51";
# else
const char *minver = "445.87";
# endif
#elif NVENCAPI_CHECK_VERSION(9, 1)
# if defined(_WIN32) || defined(__CYGWIN__)
const char *minver = "436.15";
@@ -648,6 +662,15 @@ static void nvenc_map_preset(NvencContext *ctx)
PRESET(LOW_LATENCY_HQ, NVENC_LOWLATENCY),
PRESET(LOSSLESS_DEFAULT, NVENC_LOSSLESS),
PRESET(LOSSLESS_HP, NVENC_LOSSLESS),
#ifdef NVENC_HAVE_NEW_PRESETS
PRESET(P1),
PRESET(P2),
PRESET(P3),
PRESET(P4),
PRESET(P5),
PRESET(P6),
PRESET(P7),
#endif
};
GUIDTuple *t = &presets[ctx->preset];
@@ -857,6 +880,12 @@ static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx)
if (avctx->rc_max_rate > 0)
ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
#ifdef NVENC_HAVE_MULTIPASS
ctx->encode_config.rcParams.multiPass = ctx->multipass;
if (ctx->encode_config.rcParams.multiPass != NV_ENC_MULTI_PASS_DISABLED)
ctx->flags |= NVENC_TWO_PASSES;
#endif
if (ctx->rc < 0) {
if (ctx->flags & NVENC_ONE_PASS)
ctx->twopass = 0;
@@ -891,6 +920,11 @@ static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx)
ctx->rc &= ~RC_MODE_DEPRECATED;
}
#ifdef NVENC_HAVE_LDKFS
if (ctx->ldkfs)
ctx->encode_config.rcParams.lowDelayKeyFrameScale = ctx->ldkfs;
#endif
if (ctx->flags & NVENC_LOSSLESS) {
set_lossless(avctx);
} else if (ctx->rc >= 0) {
@@ -1200,10 +1234,27 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
preset_config.version = NV_ENC_PRESET_CONFIG_VER;
preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder,
ctx->init_encode_params.encodeGUID,
ctx->init_encode_params.presetGUID,
&preset_config);
if (IS_SDK10_PRESET(ctx->preset)) {
#ifdef NVENC_HAVE_NEW_PRESETS
ctx->init_encode_params.tuningInfo = ctx->tuning_info;
nv_status = p_nvenc->nvEncGetEncodePresetConfigEx(ctx->nvencoder,
ctx->init_encode_params.encodeGUID,
ctx->init_encode_params.presetGUID,
ctx->init_encode_params.tuningInfo,
&preset_config);
#endif
} else {
#ifdef NVENC_HAVE_NEW_PRESETS
// Turn off tuning info parameter if older presets are on
ctx->init_encode_params.tuningInfo = 0;
#endif
nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder,
ctx->init_encode_params.encodeGUID,
ctx->init_encode_params.presetGUID,
&preset_config);
}
if (nv_status != NV_ENC_SUCCESS)
return nvenc_print_error(avctx, nv_status, "Cannot get the preset configuration");
@@ -1226,6 +1277,17 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
ctx->init_encode_params.enableEncodeAsync = 0;
ctx->init_encode_params.enablePTD = 1;
#ifdef NVENC_HAVE_NEW_PRESETS
/* If lookahead isn't set from CLI, use value from preset.
* P6 & P7 presets may enable lookahead for better quality.
* */
if (ctx->rc_lookahead == 0 && ctx->encode_config.rcParams.enableLookahead)
ctx->rc_lookahead = ctx->encode_config.rcParams.lookaheadDepth;
if (ctx->init_encode_params.tuningInfo == NV_ENC_TUNING_INFO_LOSSLESS)
ctx->flags |= NVENC_LOSSLESS;
#endif
if (ctx->weighted_pred == 1)
ctx->init_encode_params.enableWeightedPrediction = 1;
@@ -1509,6 +1571,8 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx)
av_freep(&ctx->surfaces);
ctx->nb_surfaces = 0;
av_frame_free(&ctx->frame);
if (ctx->nvencoder) {
p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
@@ -1562,6 +1626,10 @@ av_cold int ff_nvenc_encode_init(AVCodecContext *avctx)
ctx->data_pix_fmt = avctx->pix_fmt;
}
ctx->frame = av_frame_alloc();
if (!ctx->frame)
return AVERROR(ENOMEM);
if ((ret = nvenc_load_libraries(avctx)) < 0)
return ret;
@@ -1776,7 +1844,8 @@ static int nvenc_upload_frame(AVCodecContext *avctx, const AVFrame *frame,
static void nvenc_codec_specific_pic_params(AVCodecContext *avctx,
NV_ENC_PIC_PARAMS *params,
NV_ENC_SEI_PAYLOAD *sei_data)
NV_ENC_SEI_PAYLOAD *sei_data,
int sei_count)
{
NvencContext *ctx = avctx->priv_data;
@@ -1786,9 +1855,9 @@ static void nvenc_codec_specific_pic_params(AVCodecContext *avctx,
ctx->encode_config.encodeCodecConfig.h264Config.sliceMode;
params->codecPicParams.h264PicParams.sliceModeData =
ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData;
if (sei_data) {
if (sei_count > 0) {
params->codecPicParams.h264PicParams.seiPayloadArray = sei_data;
params->codecPicParams.h264PicParams.seiPayloadArrayCnt = 1;
params->codecPicParams.h264PicParams.seiPayloadArrayCnt = sei_count;
}
break;
@@ -1797,9 +1866,9 @@ static void nvenc_codec_specific_pic_params(AVCodecContext *avctx,
ctx->encode_config.encodeCodecConfig.hevcConfig.sliceMode;
params->codecPicParams.hevcPicParams.sliceModeData =
ctx->encode_config.encodeCodecConfig.hevcConfig.sliceModeData;
if (sei_data) {
if (sei_count > 0) {
params->codecPicParams.hevcPicParams.seiPayloadArray = sei_data;
params->codecPicParams.hevcPicParams.seiPayloadArrayCnt = 1;
params->codecPicParams.hevcPicParams.seiPayloadArrayCnt = sei_count;
}
break;
@@ -1879,9 +1948,7 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur
goto error;
}
res = pkt->data ?
ff_alloc_packet2(avctx, pkt, lock_params.bitstreamSizeInBytes, lock_params.bitstreamSizeInBytes) :
av_new_packet(pkt, lock_params.bitstreamSizeInBytes);
res = av_new_packet(pkt, lock_params.bitstreamSizeInBytes);
if (res < 0) {
p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface);
@@ -2067,13 +2134,14 @@ static void reconfig_encoder(AVCodecContext *avctx, const AVFrame *frame)
}
}
int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
{
NVENCSTATUS nv_status;
NvencSurface *tmp_out_surf, *in_surf;
int res, res2;
NV_ENC_SEI_PAYLOAD *sei_data = NULL;
size_t sei_size;
NV_ENC_SEI_PAYLOAD sei_data[8];
int sei_count = 0;
int i;
NvencContext *ctx = avctx->priv_data;
NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
@@ -2085,15 +2153,7 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder)
return AVERROR(EINVAL);
if (ctx->encoder_flushing) {
if (avctx->internal->draining)
return AVERROR_EOF;
ctx->encoder_flushing = 0;
av_fifo_reset(ctx->timestamp_list);
}
if (frame) {
if (frame && frame->buf[0]) {
in_surf = get_free_frame(ctx);
if (!in_surf)
return AVERROR(EAGAIN);
@@ -2139,21 +2199,40 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
pic_params.inputTimeStamp = frame->pts;
if (ctx->a53_cc && av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC)) {
if (ff_alloc_a53_sei(frame, sizeof(NV_ENC_SEI_PAYLOAD), (void**)&sei_data, &sei_size) < 0) {
void *a53_data = NULL;
size_t a53_size = 0;
if (ff_alloc_a53_sei(frame, 0, (void**)&a53_data, &a53_size) < 0) {
av_log(ctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n");
}
if (sei_data) {
sei_data->payloadSize = (uint32_t)sei_size;
sei_data->payloadType = 4;
sei_data->payload = (uint8_t*)(sei_data + 1);
if (a53_data) {
sei_data[sei_count].payloadSize = (uint32_t)a53_size;
sei_data[sei_count].payloadType = 4;
sei_data[sei_count].payload = (uint8_t*)a53_data;
sei_count ++;
}
}
nvenc_codec_specific_pic_params(avctx, &pic_params, sei_data);
if (ctx->s12m_tc && av_frame_get_side_data(frame, AV_FRAME_DATA_S12M_TIMECODE)) {
void *tc_data = NULL;
size_t tc_size = 0;
if (ff_alloc_timecode_sei(frame, 0, (void**)&tc_data, &tc_size) < 0) {
av_log(ctx, AV_LOG_ERROR, "Not enough memory for timecode sei, skipping\n");
}
if (tc_data) {
sei_data[sei_count].payloadSize = (uint32_t)tc_size;
sei_data[sei_count].payloadType = HEVC_SEI_TYPE_TIME_CODE;
sei_data[sei_count].payload = (uint8_t*)tc_data;
sei_count ++;
}
}
nvenc_codec_specific_pic_params(avctx, &pic_params, sei_data, sei_count);
} else {
pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
ctx->encoder_flushing = 1;
}
res = nvenc_push_context(avctx);
@@ -2161,7 +2240,9 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
return res;
nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params);
av_free(sei_data);
for ( i = 0; i < sei_count; i++)
av_freep(&sei_data[i].payload);
res = nvenc_pop_context(avctx);
if (res < 0)
@@ -2171,7 +2252,7 @@ int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
nv_status != NV_ENC_ERR_NEED_MORE_INPUT)
return nvenc_print_error(avctx, nv_status, "EncodePicture failed!");
if (frame) {
if (frame && frame->buf[0]) {
av_fifo_generic_write(ctx->output_surface_queue, &in_surf, sizeof(in_surf), NULL);
timestamp_queue_enqueue(ctx->timestamp_list, frame->pts);
}
@@ -2194,10 +2275,25 @@ int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
NvencContext *ctx = avctx->priv_data;
AVFrame *frame = ctx->frame;
if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder)
return AVERROR(EINVAL);
if (output_ready(avctx, ctx->encoder_flushing)) {
if (!frame->buf[0]) {
res = ff_encode_get_frame(avctx, frame);
if (res < 0 && res != AVERROR_EOF)
return res;
}
res = nvenc_send_frame(avctx, frame);
if (res < 0) {
if (res != AVERROR(EAGAIN))
return res;
} else
av_frame_unref(frame);
if (output_ready(avctx, avctx->internal->draining)) {
av_fifo_generic_read(ctx->output_surface_ready_queue, &tmp_out_surf, sizeof(tmp_out_surf), NULL);
res = nvenc_push_context(avctx);
@@ -2214,7 +2310,7 @@ int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
return res;
av_fifo_generic_write(ctx->unused_surface_queue, &tmp_out_surf, sizeof(tmp_out_surf), NULL);
} else if (ctx->encoder_flushing) {
} else if (avctx->internal->draining) {
return AVERROR_EOF;
} else {
return AVERROR(EAGAIN);
@@ -2223,31 +2319,10 @@ int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
return 0;
}
int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
const AVFrame *frame, int *got_packet)
{
NvencContext *ctx = avctx->priv_data;
int res;
if (!ctx->encoder_flushing) {
res = ff_nvenc_send_frame(avctx, frame);
if (res < 0)
return res;
}
res = ff_nvenc_receive_packet(avctx, pkt);
if (res == AVERROR(EAGAIN) || res == AVERROR_EOF) {
*got_packet = 0;
} else if (res < 0) {
return res;
} else {
*got_packet = 1;
}
return 0;
}
av_cold void ff_nvenc_encode_flush(AVCodecContext *avctx)
{
ff_nvenc_send_frame(avctx, NULL);
NvencContext *ctx = avctx->priv_data;
nvenc_send_frame(avctx, NULL);
av_fifo_reset(ctx->timestamp_list);
}