Define stream QP ceiling and smooth bitrate feedback controller
This commit is contained in:
1 parent
a51af91718
commit
54b50f4177
2 files changed
+34
No files matched your search
@@ -17,6 +17,7 @@ struct LiveVideoConfig {
|
|||||||
int width = 1280, height = 720, fps = 30, bitrate = 2500000, codec = 1, rotation = 0;
|
int width = 1280, height = 720, fps = 30, bitrate = 2500000, codec = 1, rotation = 0;
|
||||||
LiveVideoProfile profile = LiveVideoProfile::Automatic;
|
LiveVideoProfile profile = LiveVideoProfile::Automatic;
|
||||||
int level = 0, references = 0, vbvBits = 0; // level: AVC level_idc / HEVC general_level_idc; 0 — auto.
|
int level = 0, references = 0, vbvBits = 0; // level: AVC level_idc / HEVC general_level_idc; 0 — auto.
|
||||||
|
int maxQp = -1; // Потолок QP для H.264/H.265: 0..51, -1 — настройки encoder. Профили звонка не используют.
|
||||||
QString backend; // Пусто — проба доступных; непусто — только уже проверенный encoder.
|
QString backend; // Пусто — проба доступных; непусто — только уже проверенный encoder.
|
||||||
bool operator==(const LiveVideoConfig&) const = default;
|
bool operator==(const LiveVideoConfig&) const = default;
|
||||||
};
|
};
|
||||||
@@ -28,6 +29,8 @@ public:
|
|||||||
~LiveVideoEncoder();
|
~LiveVideoEncoder();
|
||||||
bool open(const LiveVideoConfig& config, Backend backend = Backend::Automatic);
|
bool open(const LiveVideoConfig& config, Backend backend = Backend::Automatic);
|
||||||
bool setBitrate(int bitrate); // true — изменение на следующем кадре; false — нужна смена видеоконтекста
|
bool setBitrate(int bitrate); // true — изменение на следующем кадре; false — нужна смена видеоконтекста
|
||||||
|
bool canSetMaxQp() const; // Поддерживается изменение потолка без пересоздания encoder.
|
||||||
|
bool setMaxQp(int qp); // 0..51, применяется при следующей подаче кадра; false — ошибка/нет поддержки.
|
||||||
void close();
|
void close();
|
||||||
bool encode(const QImage& image, uint64_t pts, bool key, QList<LiveEncodedFrame>& output);
|
bool encode(const QImage& image, uint64_t pts, bool key, QList<LiveEncodedFrame>& output);
|
||||||
QString error() const;
|
QString error() const;
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/* Плавно меняет потолок QP по выходному видеобитрейту. Один video worker, время в микросекундах.
|
||||||
|
* reset вызывается при смене пользовательских настроек/encoder. update учитывает только новые encoded bytes.
|
||||||
|
* Выбранный потолок — нижняя граница адаптации: при перерасходе допускается рост до 51, затем возврат. */
|
||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
class StreamQpControl {
|
||||||
|
int m_base = -1, m_limit = -1, m_target = 0;
|
||||||
|
bool m_adaptive = false, m_sampled = false;
|
||||||
|
int64_t m_at = 0;
|
||||||
|
uint64_t m_bytes = 0, m_bitrate = 0;
|
||||||
|
public:
|
||||||
|
void reset(int base, int target, bool adaptive, int64_t now) {
|
||||||
|
m_base = m_limit = base; m_target = target; m_adaptive = adaptive;
|
||||||
|
m_at = now; m_bytes = m_bitrate = 0; m_sampled = false;
|
||||||
|
}
|
||||||
|
int limit() const { return m_limit; }
|
||||||
|
uint64_t bitrate() const { return m_bitrate; } // Сглаженный выходной битрейт, бит/с.
|
||||||
|
int update(uint64_t bytes, int64_t now) {
|
||||||
|
m_bytes += bytes;
|
||||||
|
const int64_t elapsed = now - m_at;
|
||||||
|
if (elapsed < 2000000) return m_limit;
|
||||||
|
const uint64_t measured = m_bytes * 8000000 / elapsed;
|
||||||
|
m_bitrate = m_sampled ? (m_bitrate + measured) / 2 : measured;
|
||||||
|
m_sampled = true; m_bytes = 0; m_at = now;
|
||||||
|
if (!m_adaptive || m_base < 0 || m_target <= 0) return m_limit;
|
||||||
|
if (m_bitrate > uint64_t(m_target) * 108 / 100 && m_limit < 51) ++m_limit;
|
||||||
|
else if (m_bitrate < uint64_t(m_target) * 90 / 100 && m_limit > m_base) --m_limit;
|
||||||
|
return m_limit;
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in new issue
Block a user