Диагностика задержек программного видео на desktop
This commit is contained in:
1 parent
03ff431d78
commit
5a55bcb500
3 files changed
+51
-11
No files matched your search
@@ -1,5 +1,6 @@
|
||||
#include "live_video_encoder.h"
|
||||
#include "debug_config.h"
|
||||
#include <QElapsedTimer>
|
||||
#include <QPainter>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
@@ -18,6 +19,9 @@ struct LiveVideoEncoder::Impl {
|
||||
QString error, name;
|
||||
LiveVideoConfig config;
|
||||
int64_t submittedFrames = 0;
|
||||
QElapsedTimer reportTimer;
|
||||
unsigned inputs = 0, outputs = 0, keys = 0;
|
||||
qint64 prepareMax = 0, submitMax = 0, drainMax = 0, keyMax = 0, deltaMax = 0;
|
||||
#ifdef HAVE_FFMPEG
|
||||
AVCodecContext* codec = nullptr;
|
||||
AVBSFContext* filter = nullptr;
|
||||
@@ -297,6 +301,9 @@ bool LiveVideoEncoder::encode(const QImage& image, uint64_t pts, bool key, QList
|
||||
if (!m->codec || !m->frame || image.isNull() || pts > INT64_MAX) {
|
||||
m->error = "Invalid video frame"; DEBUG_ERROR(DEBUG_CATEGORY_VIDEO, "desktop encode invalid frame/state"); return false;
|
||||
}
|
||||
QElapsedTimer timer; timer.start();
|
||||
if (!m->reportTimer.isValid()) m->reportTimer.start();
|
||||
const auto outputBase = output.size();
|
||||
QImage canvas(m->config.width, m->config.height, QImage::Format_RGB32); canvas.fill(Qt::black);
|
||||
QSize fitted = image.size().scaled(canvas.size(), Qt::KeepAspectRatio);
|
||||
{ QPainter painter(&canvas); painter.drawImage(QRect(QPoint((canvas.width() - fitted.width()) / 2,
|
||||
@@ -325,7 +332,9 @@ bool LiveVideoEncoder::encode(const QImage& image, uint64_t pts, bool key, QList
|
||||
if (result >= 0) result = av_hwframe_transfer_data(hardware, m->frame, 0);
|
||||
if (result >= 0) result = av_frame_copy_props(hardware, m->frame);
|
||||
}
|
||||
const qint64 preparedUs = timer.nsecsElapsed() / 1000;
|
||||
if (result >= 0) result = avcodec_send_frame(m->codec, hardware ? hardware : m->frame);
|
||||
const qint64 submittedUs = timer.nsecsElapsed() / 1000;
|
||||
if (result >= 0) m->submittedFrames++;
|
||||
av_frame_free(&hardware);
|
||||
AVPacket* packet = av_packet_alloc();
|
||||
@@ -355,6 +364,27 @@ bool LiveVideoEncoder::encode(const QImage& image, uint64_t pts, bool key, QList
|
||||
}
|
||||
av_packet_free(&packet);
|
||||
if (result == AVERROR(EAGAIN) || result == AVERROR_EOF) {
|
||||
// Сводка по этапам отличает конвертацию, синхронный encoder и получение/упаковку пакета.
|
||||
const qint64 totalUs = timer.nsecsElapsed() / 1000;
|
||||
++m->inputs; m->outputs += output.size() - outputBase;
|
||||
bool producedKey = false;
|
||||
for (auto i = outputBase; i < output.size(); ++i) if (output[i].key) { ++m->keys; producedKey = true; }
|
||||
m->prepareMax = std::max(m->prepareMax, preparedUs);
|
||||
m->submitMax = std::max(m->submitMax, submittedUs - preparedUs);
|
||||
m->drainMax = std::max(m->drainMax, totalUs - submittedUs);
|
||||
auto& frameMax = producedKey ? m->keyMax : m->deltaMax;
|
||||
frameMax = std::max(frameMax, totalUs);
|
||||
if (m->reportTimer.elapsed() >= 1000) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG,
|
||||
"video encoder flow name=%s size=%dx%d bitrate=%d interval_us=%lld inputs=%u outputs=%u keys=%u "
|
||||
"prepare_max_us=%lld submit_max_us=%lld drain_max_us=%lld key_max_us=%lld delta_max_us=%lld pts=%llu",
|
||||
qPrintable(m->name), m->config.width, m->config.height, m->config.bitrate,
|
||||
(long long)(m->reportTimer.nsecsElapsed() / 1000), m->inputs, m->outputs, m->keys,
|
||||
(long long)m->prepareMax, (long long)m->submitMax, (long long)m->drainMax,
|
||||
(long long)m->keyMax, (long long)m->deltaMax, (unsigned long long)pts);
|
||||
m->reportTimer.restart(); m->inputs = m->outputs = m->keys = 0;
|
||||
m->prepareMax = m->submitMax = m->drainMax = m->keyMax = m->deltaMax = 0;
|
||||
}
|
||||
if (key && output.isEmpty()) DEBUG_DEBUG(DEBUG_CATEGORY_VIDEO, "desktop requested KEY buffered name=%s PTS=%llu",
|
||||
qPrintable(m->name), (unsigned long long)pts);
|
||||
return true;
|
||||
|
||||
Reference in new issue
Block a user