|
|
|
|
@ -4,6 +4,7 @@
|
|
|
|
|
#include "call_audio_engine.h" |
|
|
|
|
#include "call_video_engine.h" |
|
|
|
|
#include "../../../src/call/call_video_port.h" |
|
|
|
|
#include "../../../src/call/call_video_playout.h" |
|
|
|
|
#include "sound_manager.h" |
|
|
|
|
|
|
|
|
|
#include <QVBoxLayout> |
|
|
|
|
@ -46,7 +47,11 @@ public:
|
|
|
|
|
QImage remote, local; |
|
|
|
|
CallVideoEngine* engine = nullptr; |
|
|
|
|
quint64 serial = 0; |
|
|
|
|
quint64 callId = 0; |
|
|
|
|
int64_t requestedAt = 0; // GUI-получение кадра -> начало paintEvent, отдельно от самой работы painter.
|
|
|
|
|
protected: |
|
|
|
|
void moveEvent(QMoveEvent* event) override { ++m_moves; QWidget::moveEvent(event); } |
|
|
|
|
void resizeEvent(QResizeEvent* event) override { ++m_resizes; QWidget::resizeEvent(event); } |
|
|
|
|
void hideEvent(QHideEvent* event) override { presented(); QWidget::hideEvent(event); } |
|
|
|
|
void changeEvent(QEvent* event) override { |
|
|
|
|
QWidget::changeEvent(event); |
|
|
|
|
@ -66,17 +71,47 @@ protected:
|
|
|
|
|
QWidget::mouseDoubleClickEvent(event); |
|
|
|
|
} |
|
|
|
|
void paintEvent(QPaintEvent*) override { |
|
|
|
|
const int64_t started = call_video_playout_now_us(), requestWait = serial && requestedAt ? started - requestedAt : 0; |
|
|
|
|
const bool selected = serial != 0; |
|
|
|
|
QPainter painter(this); painter.fillRect(rect(), Qt::black); painter.setRenderHint(QPainter::SmoothPixmapTransform); |
|
|
|
|
if (remote.isNull()) return; |
|
|
|
|
QSize fitted = remote.size().scaled(size(), Qt::KeepAspectRatio); |
|
|
|
|
QRect videoRect(QPoint((width() - fitted.width()) / 2, (height() - fitted.height()) / 2), fitted); |
|
|
|
|
const int64_t prepared = call_video_playout_now_us(); |
|
|
|
|
painter.drawImage(videoRect, remote); |
|
|
|
|
const int64_t drawn = call_video_playout_now_us(); |
|
|
|
|
if (!local.isNull()) { |
|
|
|
|
QSize preview = local.size().scaled(qMin(200, fitted.width() / 4), qMin(150, fitted.height() / 4), Qt::KeepAspectRatio); |
|
|
|
|
QRect target(QPoint(videoRect.right() - preview.width() - 12, videoRect.top() + 12), preview); |
|
|
|
|
painter.setPen(QPen(Qt::white, 2)); painter.drawRect(target.adjusted(-1, -1, 1, 1)); painter.drawImage(target, local); |
|
|
|
|
} |
|
|
|
|
painter.end(); presented(); |
|
|
|
|
const int64_t overlay = call_video_playout_now_us(); |
|
|
|
|
painter.end(); |
|
|
|
|
const int64_t finished = call_video_playout_now_us(); |
|
|
|
|
presented(); |
|
|
|
|
++m_paints; if (selected) ++m_selectedPaints; |
|
|
|
|
m_requestMax = std::max(m_requestMax, requestWait); m_paintMax = std::max(m_paintMax, finished - started); |
|
|
|
|
m_prepareMax = std::max(m_prepareMax, prepared - started); m_drawMax = std::max(m_drawMax, drawn - prepared); |
|
|
|
|
m_overlayMax = std::max(m_overlayMax, overlay - drawn); m_finishMax = std::max(m_finishMax, finished - overlay); |
|
|
|
|
if (!m_slowReported && (requestWait > 50000 || finished - started > 20000)) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_CALL, "video GUI paint delayed call=%llu request_wait_us=%lld paint_us=%lld " |
|
|
|
|
"prepare_us=%lld draw_us=%lld overlay_us=%lld finish_us=%lld window=%dx%d image=%dx%d dpr_x1000=%d mono_us=%lld", |
|
|
|
|
(unsigned long long)callId, (long long)requestWait, (long long)(finished - started), |
|
|
|
|
(long long)(prepared - started), (long long)(drawn - prepared), (long long)(overlay - drawn), |
|
|
|
|
(long long)(finished - overlay), width(), height(), remote.width(), remote.height(), |
|
|
|
|
int(devicePixelRatioF() * 1000), (long long)finished); |
|
|
|
|
m_slowReported = true; |
|
|
|
|
} |
|
|
|
|
if (!m_reportAt) m_reportAt = started; |
|
|
|
|
if (finished - m_reportAt >= 1000000) { |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "video GUI paint call=%llu interval_us=%lld paints=%u selected=%u moves=%u resizes=%u " |
|
|
|
|
"request_wait_max_us=%lld paint_max_us=%lld prepare_max_us=%lld draw_max_us=%lld overlay_max_us=%lld finish_max_us=%lld", |
|
|
|
|
(unsigned long long)callId, (long long)(finished - m_reportAt), m_paints, m_selectedPaints, m_moves, m_resizes, |
|
|
|
|
(long long)m_requestMax, (long long)m_paintMax, (long long)m_prepareMax, (long long)m_drawMax, |
|
|
|
|
(long long)m_overlayMax, (long long)m_finishMax); |
|
|
|
|
m_reportAt = finished; m_paints = m_selectedPaints = m_moves = m_resizes = 0; |
|
|
|
|
m_requestMax = m_paintMax = m_prepareMax = m_drawMax = m_overlayMax = m_finishMax = 0; m_slowReported = false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
private: |
|
|
|
|
void presented() { |
|
|
|
|
@ -87,6 +122,9 @@ private:
|
|
|
|
|
else { m_geometry = saveGeometry(); showFullScreen(); } |
|
|
|
|
} |
|
|
|
|
QByteArray m_geometry; |
|
|
|
|
int64_t m_reportAt = 0, m_requestMax = 0, m_paintMax = 0, m_prepareMax = 0, m_drawMax = 0, m_overlayMax = 0, m_finishMax = 0; |
|
|
|
|
unsigned m_paints = 0, m_selectedPaints = 0, m_moves = 0, m_resizes = 0; |
|
|
|
|
bool m_slowReported = false; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static QColor colorForName(const QString& name) { |
|
|
|
|
@ -331,7 +369,8 @@ CallWindow::CallWindow(QWidget* parent)
|
|
|
|
|
}); |
|
|
|
|
connect(m_video, &CallVideoEngine::imageChanged, this, [this](const QImage& image, quint64 serial) { |
|
|
|
|
bool changed = m_remoteImage.isNull() != image.isNull(); m_remoteImage = image; |
|
|
|
|
m_videoWindow->remote = image; m_videoWindow->serial = serial; m_videoWindow->update(); |
|
|
|
|
m_videoWindow->remote = image; m_videoWindow->serial = serial; m_videoWindow->callId = m_videoCall; |
|
|
|
|
m_videoWindow->requestedAt = call_video_playout_now_us(); m_videoWindow->update(); |
|
|
|
|
if (changed) updateVideoPresentation(); |
|
|
|
|
// Скрытое окно продолжает принимать поток, не ждёт невозможного paintEvent.
|
|
|
|
|
if (!m_videoWindow->isVisible() || m_videoWindow->isMinimized()) m_video->imagePresented(serial); |
|
|
|
|
|