Update live x264 bitrate and exclude encoders without forced key support

This commit is contained in:
evgeny committed 2026-10-14 12:32:33 +02:00
1 parent e4f9a48c2c
commit 7ad0aa61af
3 files changed
+36 -6

No files matched your search

+21 -5
View File
@@ -47,7 +47,8 @@ QList<QByteArray> encoders(int codec) {
case STREAM_MEDIA_H264: return {"h264_nvenc", "h264_qsv", "h264_amf", "h264_vaapi", "libx264", "libopenh264"};
case STREAM_MEDIA_H265: return {"hevc_nvenc", "hevc_qsv", "hevc_amf", "hevc_vaapi", "libx265"};
case STREAM_MEDIA_VP9: return {"vp9_qsv", "vp9_vaapi", "libvpx-vp9"};
case STREAM_MEDIA_AV1: return {"av1_nvenc", "av1_qsv", "av1_amf", "av1_vaapi", "libsvtav1", "libaom-av1"};
// FFmpeg/SVT не принимает произвольный KEY при GOP>1; libaom поддерживает нужный live-контракт.
case STREAM_MEDIA_AV1: return {"av1_nvenc", "av1_qsv", "av1_amf", "av1_vaapi", "libaom-av1"};
case STREAM_MEDIA_H266: return {"libvvenc"};
default: return {};
}
@@ -120,9 +121,6 @@ bool StreamVideoEncoder::open(const StreamVideoConfig& config) {
} else if (name == "libvpx-vp9" || name == "libaom-av1") {
av_dict_set(&options, "deadline", "realtime", 0); av_dict_set(&options, "cpu-used", "8", 0);
av_dict_set(&options, "lag-in-frames", "0", 0); av_dict_set(&options, "row-mt", "1", 0);
} else if (name == "libsvtav1") {
c->rc_max_rate = 0;
av_dict_set(&options, "preset", "11", 0); av_dict_set(&options, "svtav1-params", "pred-struct=1:lookahead=0:lp=2", 0);
} else if (name.endsWith("_qsv")) {
av_dict_set(&options, "async_depth", "1", 0); av_dict_set(&options, "look_ahead", "0", 0);
} else if (name.endsWith("_vaapi")) {
@@ -194,7 +192,8 @@ bool StreamVideoEncoder::encode(const QImage& image, uint64_t pts, bool key, QLi
if (result >= 0) {
const int* coefficients = sws_getCoefficients(SWS_CS_ITU709);
sws_setColorspaceDetails(m->scale, coefficients, 1, coefficients, 0, 0, 1 << 16, 1 << 16);
const uint8_t* input[] = {canvas.constBits()}; int stride[] = {static_cast<int>(canvas.bytesPerLine())};
const uint8_t* input[4] = {canvas.constBits(), nullptr, nullptr, nullptr};
int stride[4] = {static_cast<int>(canvas.bytesPerLine()), 0, 0, 0};
result = sws_scale(m->scale, input, stride, 0, canvas.height(), m->frame->data, m->frame->linesize);
}
m->frame->pts = static_cast<int64_t>(pts); m->frame->pict_type = key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_NONE;
@@ -250,8 +249,25 @@ bool StreamVideoEncoder::encode(const QImage& image, uint64_t pts, bool key, QLi
QList<int> StreamVideoEncoder::available() {
QList<int> result;
for (int codec = 1; codec <= 5; codec++) {
#ifdef HAVE_FFMPEG
bool installed = false;
for (const auto& name : encoders(codec)) if (avcodec_find_encoder_by_name(name.constData())) { installed = true; break; }
if (!installed) { DEBUG_DEBUG(DEBUG_CATEGORY_VIDEO, "desktop codec has no installed encoder codec=%d", codec); continue; }
#endif
StreamVideoEncoder encoder; StreamVideoConfig config; config.width = 320; config.height = 180; config.codec = codec;
if (encoder.open(config)) result.push_back(codec);
}
return result;
}
bool StreamVideoEncoder::setBitrate(int bitrate) {
if (bitrate < 64000 || bitrate > 16000000) { DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "desktop live bitrate invalid value=%d", bitrate); return false; }
#ifdef HAVE_FFMPEG
// libx264 перечитывает эти три значения через reconfig_encoder при подаче следующего кадра.
if (m->codec && m->name == "libx264") {
m->codec->bit_rate = m->codec->rc_max_rate = bitrate; m->codec->rc_buffer_size = bitrate / 4; m->config.bitrate = bitrate;
DEBUG_INFO(DEBUG_CATEGORY_VIDEO, "desktop encoder bitrate updated in place name=libx264 bitrate=%d", bitrate); return true;
}
#endif
DEBUG_DEBUG(DEBUG_CATEGORY_VIDEO, "desktop bitrate needs encoder replacement name=%s", qPrintable(m->name)); return false;
}