|
|
|
|
@ -141,6 +141,7 @@ bool LiveVideoEncoder::open(const LiveVideoConfig& config, Backend backend) {
|
|
|
|
|
|| config.width % 2 || config.height % 2 || config.fps < 1 || config.fps > 60 |
|
|
|
|
|| config.bitrate < 64000 || config.bitrate > 16000000 || config.codec < 1 || config.codec > 5 |
|
|
|
|
|| config.vbvBits < 0 || config.vbvBits > 16000000 || config.references < 0 || config.references > 16 |
|
|
|
|
|| config.maxQp < -1 || config.maxQp > 51 || (config.maxQp >= 0 && (constrained || config.codec > STREAM_MEDIA_H265)) |
|
|
|
|
|| (constrained && (config.level <= 0 || config.level > 255 || config.references != 1 || !config.vbvBits |
|
|
|
|
|| !((config.codec == 1 && config.profile == LiveVideoProfile::H264ConstrainedBaseline) |
|
|
|
|
|| (config.codec == 2 && config.profile == LiveVideoProfile::H265Main))))) { |
|
|
|
|
@ -162,6 +163,7 @@ bool LiveVideoEncoder::open(const LiveVideoConfig& config, Backend backend) {
|
|
|
|
|
c->width = config.width; c->height = config.height; c->time_base = {1, 1000000}; c->framerate = {config.fps, 1}; |
|
|
|
|
if (constrained && name.endsWith("_qsv")) c->time_base = {1, 90000}; |
|
|
|
|
c->bit_rate = config.bitrate; c->rc_max_rate = config.bitrate; |
|
|
|
|
if (config.maxQp >= 0) { c->qmin = 0; c->qmax = config.maxQp; } |
|
|
|
|
c->rc_buffer_size = config.vbvBits ? config.vbvBits : config.bitrate / 4; |
|
|
|
|
c->gop_size = config.fps; c->max_b_frames = 0; c->thread_count = 2; |
|
|
|
|
if (config.references) c->refs = config.references; |
|
|
|
|
@ -356,9 +358,10 @@ bool LiveVideoEncoder::open(const LiveVideoConfig& config, Backend backend) {
|
|
|
|
|
c->qmin, c->qmax, c->time_base.num, c->time_base.den, c->framerate.num, c->framerate.den); |
|
|
|
|
} |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_VIDEO, |
|
|
|
|
"desktop encoder ready name=%s codec=%d size=%dx%d fps=%d bitrate=%d level=%d refs=%d vbv=%d profile_verified=%d forced_keys=%d", |
|
|
|
|
"desktop encoder ready name=%s codec=%d size=%dx%d fps=%d bitrate=%d level=%d refs=%d vbv=%d profile_verified=%d " |
|
|
|
|
"forced_keys=%d max_qp=%d dynamic_qp=%d", |
|
|
|
|
name.constData(), config.codec, config.width, config.height, config.fps, config.bitrate, |
|
|
|
|
config.level, config.references, c->rc_buffer_size, constrained, m->forcedKeys); |
|
|
|
|
config.level, config.references, c->rc_buffer_size, constrained, m->forcedKeys, config.maxQp, canSetMaxQp()); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -569,3 +572,33 @@ bool LiveVideoEncoder::setBitrate(int bitrate) {
|
|
|
|
|
#endif |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_VIDEO, "desktop bitrate needs encoder replacement name=%s", qPrintable(m->name)); return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool LiveVideoEncoder::canSetMaxQp() const { |
|
|
|
|
#ifdef HAVE_FFMPEG |
|
|
|
|
if (!m->codec || m->config.profile != LiveVideoProfile::Automatic || m->config.codec > STREAM_MEDIA_H265) return false; |
|
|
|
|
return m->name.endsWith("_qsv") || (m->name.endsWith("_amf") |
|
|
|
|
&& av_opt_find(m->codec->priv_data, "utun_qp_max", nullptr, 0, 0)); |
|
|
|
|
#else |
|
|
|
|
return false; |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool LiveVideoEncoder::setMaxQp(int qp) { |
|
|
|
|
if (qp < 0 || qp > 51 || !canSetMaxQp()) { |
|
|
|
|
m->error = "Live QP adjustment is unavailable"; |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "desktop live QP ceiling unavailable name=%s qp=%d", qPrintable(m->name), qp); return false; |
|
|
|
|
} |
|
|
|
|
#ifdef HAVE_FFMPEG |
|
|
|
|
int result = m->name.endsWith("_amf") ? av_opt_set_int(m->codec->priv_data, "utun_qp_max", qp, 0) : 0; |
|
|
|
|
if (result < 0) { |
|
|
|
|
m->error = ffError(result); |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "desktop live QP ceiling failed name=%s qp=%d error=%s", |
|
|
|
|
qPrintable(m->name), qp, qPrintable(m->error)); return false; |
|
|
|
|
} |
|
|
|
|
m->codec->qmin = 0; m->codec->qmax = qp; |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "desktop live QP ceiling requested name=%s qp=%d", qPrintable(m->name), qp); |
|
|
|
|
return true; |
|
|
|
|
#else |
|
|
|
|
return false; |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|