Merge pull request #4344 from jpark37/nvenc-ffmpeg-alignment

obs-ffmpeg: Align both NVENC implementations
This commit is contained in:
Jim
2021-03-16 22:12:36 -07:00
committed by GitHub
2 changed files with 63 additions and 26 deletions
+49 -19
View File
@@ -3,6 +3,7 @@
#include <util/darray.h>
#include <util/dstr.h>
#include <obs-avc.h>
#include <libavutil/rational.h>
#define INITGUID
#include <dxgi.h>
#include <d3d11.h>
@@ -41,15 +42,16 @@ struct nvenc_data {
void *session;
NV_ENC_INITIALIZE_PARAMS params;
NV_ENC_CONFIG config;
size_t buf_count;
size_t output_delay;
size_t buffers_queued;
int rc_lookahead;
int buf_count;
int output_delay;
int buffers_queued;
size_t next_bitstream;
size_t cur_bitstream;
bool encode_started;
bool first_packet;
bool can_change_bitrate;
bool bframes;
int32_t bframes;
DARRAY(struct nv_bitstream) bitstreams;
DARRAY(struct nv_texture) textures;
@@ -408,21 +410,22 @@ static bool init_encoder(struct nvenc_data *enc, obs_data_t *settings)
NV_ENC_CONFIG_H264_VUI_PARAMETERS *vui_params =
&h264_config->h264VUIParameters;
int darWidth, darHeight;
av_reduce(&darWidth, &darHeight, voi->width, voi->height, 1024 * 1024);
memset(params, 0, sizeof(*params));
params->version = NV_ENC_INITIALIZE_PARAMS_VER;
params->encodeGUID = NV_ENC_CODEC_H264_GUID;
params->presetGUID = nv_preset;
params->encodeWidth = voi->width;
params->encodeHeight = voi->height;
params->darWidth = voi->width;
params->darHeight = voi->height;
params->darWidth = darWidth;
params->darHeight = darHeight;
params->frameRateNum = voi->fps_num;
params->frameRateDen = voi->fps_den;
params->enableEncodeAsync = 1;
params->enablePTD = 1;
params->encodeConfig = &enc->config;
params->maxEncodeWidth = voi->width;
params->maxEncodeHeight = voi->height;
config->gopLength = gop_size;
config->frameIntervalP = 1 + bf;
h264_config->idrPeriod = gop_size;
@@ -434,6 +437,11 @@ static bool init_encoder(struct nvenc_data *enc, obs_data_t *settings)
h264_config->outputAUD = 1;
}
h264_config->sliceMode = 3;
h264_config->sliceModeData = 1;
h264_config->useBFramesAsRef = NV_ENC_BFRAME_REF_MODE_DISABLED;
vui_params->videoSignalTypePresentFlag = 1;
vui_params->videoFullRangeFlag = (voi->range == VIDEO_RANGE_FULL);
vui_params->colourDescriptionPresentFlag = 1;
@@ -457,19 +465,45 @@ static bool init_encoder(struct nvenc_data *enc, obs_data_t *settings)
break;
}
enc->bframes = bf > 0;
enc->bframes = bf;
/* lookahead */
if (lookahead && nv_get_cap(enc, NV_ENC_CAPS_SUPPORT_LOOKAHEAD)) {
config->rcParams.lookaheadDepth = 8;
const bool use_profile_lookahead = config->rcParams.enableLookahead;
lookahead = nv_get_cap(enc, NV_ENC_CAPS_SUPPORT_LOOKAHEAD) &&
(lookahead || use_profile_lookahead);
if (lookahead) {
enc->rc_lookahead = use_profile_lookahead
? config->rcParams.lookaheadDepth
: 8;
}
int buf_count = max(4, config->frameIntervalP * 2 * 2);
if (lookahead) {
buf_count = max(buf_count, config->frameIntervalP +
enc->rc_lookahead +
EXTRA_BUFFERS);
}
buf_count = min(64, buf_count);
enc->buf_count = buf_count;
const int output_delay = buf_count - 1;
enc->output_delay = output_delay;
if (lookahead) {
int lkd_bound = output_delay - config->frameIntervalP - 4;
config->rcParams.enableLookahead = 1;
} else {
lookahead = false;
config->rcParams.lookaheadDepth =
max(enc->rc_lookahead, lkd_bound);
config->rcParams.disableIadapt = 0;
config->rcParams.disableBadapt = 0;
}
/* psycho aq */
if (nv_get_cap(enc, NV_ENC_CAPS_SUPPORT_TEMPORAL_AQ)) {
config->rcParams.enableAQ = psycho_aq;
config->rcParams.aqStrength = 8;
config->rcParams.enableTemporalAQ = psycho_aq;
}
@@ -506,6 +540,7 @@ static bool init_encoder(struct nvenc_data *enc, obs_data_t *settings)
h264_config->outputPictureTimingSEI = 1;
config->rcParams.averageBitRate = bitrate * 1000;
config->rcParams.maxBitRate = vbr ? max_bitrate * 1000 : bitrate * 1000;
config->rcParams.vbvBufferSize = bitrate * 1000;
/* -------------------------- */
/* profile */
@@ -525,10 +560,6 @@ static bool init_encoder(struct nvenc_data *enc, obs_data_t *settings)
return false;
}
enc->buf_count = config->frameIntervalP +
config->rcParams.lookaheadDepth + EXTRA_BUFFERS;
enc->output_delay = enc->buf_count - 1;
info("settings:\n"
"\trate_control: %s\n"
"\tbitrate: %d\n"
@@ -904,8 +935,7 @@ static bool nvenc_encode_tex(void *data, uint32_t handle, int64_t pts,
circlebuf_pop_front(&enc->dts_list, &dts, sizeof(dts));
/* subtract bframe delay from dts */
if (enc->bframes)
dts -= packet->timebase_num;
dts -= (int64_t)enc->bframes * packet->timebase_num;
*received_packet = true;
packet->data = enc->packet_data.array;
+14 -7
View File
@@ -173,6 +173,7 @@ static bool nvenc_update(void *data, obs_data_t *settings)
int gpu = (int)obs_data_get_int(settings, "gpu");
bool cbr_override = obs_data_get_bool(settings, "cbr");
int bf = (int)obs_data_get_int(settings, "bf");
bool psycho_aq = obs_data_get_bool(settings, "psycho_aq");
video_t *video = obs_encoder_video(enc->encoder);
const struct video_output_info *voi = video_output_get_info(video);
@@ -220,8 +221,9 @@ static bool nvenc_update(void *data, obs_data_t *settings)
} else if (astrcmpi(rc, "vbr") != 0) { /* CBR by default */
av_opt_set_int(enc->context->priv_data, "cbr", true, 0);
enc->context->rc_max_rate = bitrate * 1000;
enc->context->rc_min_rate = bitrate * 1000;
const int64_t rate = (int64_t)bitrate * 1000;
enc->context->rc_max_rate = rate;
enc->context->rc_min_rate = rate;
cqp = 0;
}
@@ -229,8 +231,12 @@ static bool nvenc_update(void *data, obs_data_t *settings)
av_opt_set_int(enc->context->priv_data, "2pass", twopass, 0);
av_opt_set_int(enc->context->priv_data, "gpu", gpu, 0);
enc->context->bit_rate = bitrate * 1000;
enc->context->rc_buffer_size = bitrate * 1000;
av_opt_set_int(enc->context->priv_data, "spatial-aq", psycho_aq, 0);
av_opt_set_int(enc->context->priv_data, "temporal-aq", psycho_aq, 0);
const int rate = bitrate * 1000;
enc->context->bit_rate = rate;
enc->context->rc_buffer_size = rate;
enc->context->width = obs_encoder_get_width(enc->encoder);
enc->context->height = obs_encoder_get_height(enc->encoder);
enc->context->time_base = (AVRational){voi->fps_den, voi->fps_num};
@@ -291,13 +297,14 @@ static bool nvenc_reconfigure(void *data, obs_data_t *settings)
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 19, 101)
struct nvenc_encoder *enc = data;
int bitrate = (int)obs_data_get_int(settings, "bitrate");
const int64_t bitrate = obs_data_get_int(settings, "bitrate");
const char *rc = obs_data_get_string(settings, "rate_control");
bool cbr = astrcmpi(rc, "CBR") == 0;
bool vbr = astrcmpi(rc, "VBR") == 0;
if (cbr || vbr) {
enc->context->bit_rate = bitrate * 1000;
enc->context->rc_max_rate = bitrate * 1000;
const int64_t rate = bitrate * 1000;
enc->context->bit_rate = rate;
enc->context->rc_max_rate = rate;
}
#endif
return true;