Browse Source

Apply configured QP ceilings and expose live encoder adjustment capability

stream-multiview
evgeny 6 days ago
parent
commit
0070221045
  1. 37
      tools/chatgui/src/live_video_encoder.cpp
  2. 2
      tools/chatgui/src/stream_publish_engine.h

37
tools/chatgui/src/live_video_encoder.cpp

@ -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
}

2
tools/chatgui/src/stream_publish_engine.h

@ -36,6 +36,7 @@ struct StreamPublishConfig {
bool audio = true;
bool showCursor = true;
bool nativeSize = false, automaticBitrate = false;
bool adaptiveQp = false; // При перерасходе битрейта плавно повышать потолок выше video.maxQp, затем возвращать.
};
class StreamPublishEngine : public QObject {
Q_OBJECT
@ -50,6 +51,7 @@ public:
uint64_t group() const;
StreamPublishConfig config() const;
uint64_t videoBitrate() const; // Фактический выход video encoder за последний интервал около секунды, бит/с; читать в GUI-потоке.
int videoMaxQp() const; // Текущий потолок QP с учётом адаптации; -1 — настройки encoder.
QVariant previewFrame() const;
QList<int> codecs() const;
static QList<StreamVideoSource> sources();

Loading…
Cancel
Save