|
|
|
|
@ -2,6 +2,7 @@
|
|
|
|
|
#include "call_video_encoder.h" |
|
|
|
|
#include "call_video_decoder.h" |
|
|
|
|
#include "call_video_cadence.h" |
|
|
|
|
#include "call_video_capture_clock.h" |
|
|
|
|
#include "call_camera_rate.h" |
|
|
|
|
#include "../../../src/call/call_video_port.h" |
|
|
|
|
#include "../../../src/call/call_audio.h" |
|
|
|
|
@ -32,7 +33,8 @@ struct CallVideoEngine::Impl {
|
|
|
|
|
uint64_t id = 0, revision = 1; |
|
|
|
|
bool enabled = false; |
|
|
|
|
int width = 640, height = 480, codec = 0; |
|
|
|
|
int64_t pts = -1, backend = -1, anchor = -1; |
|
|
|
|
int64_t pts = -1; |
|
|
|
|
CallVideoCaptureClock captureClock; |
|
|
|
|
uint64_t captured = 0; |
|
|
|
|
QImage shown; |
|
|
|
|
uint64_t shownSerial = 0, deliveredSerial = 0; |
|
|
|
|
@ -109,7 +111,7 @@ void CallVideoEngine::closeCamera() {
|
|
|
|
|
if (m->camera) { disconnect(m->camera.get(), nullptr, this, nullptr); m->camera->stop(); } |
|
|
|
|
m->cameraRate.restore(); |
|
|
|
|
m->capture.reset(); m->camera.reset(); m->sink.reset(); |
|
|
|
|
{ std::lock_guard<std::mutex> guard(m->lock); m->raw = {}; m->pts = m->backend = m->anchor = -1; } |
|
|
|
|
{ std::lock_guard<std::mutex> guard(m->lock); m->raw = {}; m->pts = -1; m->captureClock = {}; } |
|
|
|
|
#endif |
|
|
|
|
m->previewPts = -1; m->previewVisible = false; m->previewReportAt = nowUs(); m->previewFrames = 0; m->previewMaxUs = 0; |
|
|
|
|
emit localImageChanged({}); |
|
|
|
|
@ -152,15 +154,12 @@ void CallVideoEngine::setVideo(bool enabled, const QByteArray& cameraId, int wid
|
|
|
|
|
if (!frame.isValid() || !m->running) return; |
|
|
|
|
std::lock_guard<std::mutex> guard(m->lock); |
|
|
|
|
if (revision != m->revision) return; |
|
|
|
|
int64_t pts = nowUs(); |
|
|
|
|
if (frame.startTime() >= 0) { |
|
|
|
|
if (m->backend < 0) { |
|
|
|
|
m->backend = frame.startTime(); m->anchor = pts; |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_CALL, "camera clock source=%lld monotonic=%lld calibration=arrival-estimate", |
|
|
|
|
(long long)m->backend, (long long)m->anchor); |
|
|
|
|
} |
|
|
|
|
pts = m->anchor + frame.startTime() - m->backend; |
|
|
|
|
} |
|
|
|
|
const int64_t arrival = nowUs(), source = frame.startTime(); |
|
|
|
|
if (m->pts < 0) DEBUG_INFO(DEBUG_CATEGORY_CALL, "camera clock source=%lld monotonic=%lld calibration=arrival-upper-bound", |
|
|
|
|
(long long)source, (long long)arrival); |
|
|
|
|
if (m->captureClock.source >= 0 && source < m->captureClock.source) |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_CALL, "camera clock reset source=%lld previous=%lld", (long long)source, (long long)m->captureClock.source); |
|
|
|
|
const int64_t pts = m->captureClock.map(source, arrival); |
|
|
|
|
if (pts > m->pts) { m->raw = frame; m->pts = pts; ++m->captured; } |
|
|
|
|
}, Qt::DirectConnection); |
|
|
|
|
connect(m->camera.get(), &QCamera::errorOccurred, this, [this](QCamera::Error, const QString& error) { |
|
|
|
|
@ -201,13 +200,14 @@ void CallVideoEngine::transmit() {
|
|
|
|
|
struct call_video_port_status state{}; |
|
|
|
|
if (call_video_port_status(m->id, &state) < 0) break; |
|
|
|
|
if (state.error) { m->report(tr("Core rejected video format")); break; } |
|
|
|
|
uint64_t revision, captured; bool enabled; int width, height, codec; int64_t pts; |
|
|
|
|
uint64_t revision, captured; bool enabled; int width, height, codec; int64_t pts, clockCorrection; |
|
|
|
|
#ifdef HAVE_STREAM_CAPTURE |
|
|
|
|
QVideoFrame raw; |
|
|
|
|
#endif |
|
|
|
|
{ std::lock_guard<std::mutex> guard(m->lock); |
|
|
|
|
revision = m->revision; enabled = m->enabled; width = m->width; height = m->height; codec = m->codec; pts = m->pts; |
|
|
|
|
captured = m->captured; |
|
|
|
|
clockCorrection = m->captureClock.correction; |
|
|
|
|
#ifdef HAVE_STREAM_CAPTURE |
|
|
|
|
raw = m->raw; |
|
|
|
|
#endif |
|
|
|
|
@ -216,10 +216,10 @@ void CallVideoEngine::transmit() {
|
|
|
|
|
if (now - reportAt >= 1000000) { |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_CALL, |
|
|
|
|
"video capture flow call=%llu interval_us=%lld captured=%llu encoded=%u keys=%u send_busy=%u paced=%u " |
|
|
|
|
"encode_max_us=%lld capture_age_us=%lld pts=%lld", |
|
|
|
|
"encode_max_us=%lld capture_age_us=%lld pts=%lld clock_correction_us=%lld", |
|
|
|
|
(unsigned long long)m->id, (long long)(now - reportAt), (unsigned long long)(captured - captureBase), |
|
|
|
|
encodedCount, keyCount, sendBusy, paced, (long long)encodeMax, |
|
|
|
|
(long long)(pts >= 0 ? now - pts : 0), (long long)pts); |
|
|
|
|
(long long)(pts >= 0 ? now - pts : 0), (long long)pts, (long long)clockCorrection); |
|
|
|
|
reportAt = now; captureBase = captured; encodedCount = keyCount = sendBusy = paced = 0; encodeMax = 0; |
|
|
|
|
} |
|
|
|
|
if (revision != userRevision) { userRevision = revision; excluded = 0; } |
|
|
|
|
|