|
|
|
@ -2,6 +2,7 @@ |
|
|
|
#include "call_camera_protocol.h" |
|
|
|
#include "call_camera_protocol.h" |
|
|
|
#include "call_camera_buffer.h" |
|
|
|
#include "call_camera_buffer.h" |
|
|
|
#include "call_video_capture_clock.h" |
|
|
|
#include "call_video_capture_clock.h" |
|
|
|
|
|
|
|
#include "call_video_cadence.h" |
|
|
|
#include "call_camera_rate.h" |
|
|
|
#include "call_camera_rate.h" |
|
|
|
#include "../../../src/call/call_video_playout.h" |
|
|
|
#include "../../../src/call/call_video_playout.h" |
|
|
|
#include "debug_config.h" |
|
|
|
#include "debug_config.h" |
|
|
|
@ -79,11 +80,12 @@ class CameraWorker : public QObject { |
|
|
|
std::shared_ptr<Pending> pending; |
|
|
|
std::shared_ptr<Pending> pending; |
|
|
|
QMetaObject::Connection captureConnection, errorConnection; |
|
|
|
QMetaObject::Connection captureConnection, errorConnection; |
|
|
|
CallVideoCaptureClock clock; |
|
|
|
CallVideoCaptureClock clock; |
|
|
|
|
|
|
|
CallVideoCadence cadence; |
|
|
|
quint64 generation = 0, inFlight = 0; |
|
|
|
quint64 generation = 0, inFlight = 0; |
|
|
|
bool sending = false; |
|
|
|
bool sending = false; |
|
|
|
int width = 640, height = 480; |
|
|
|
int width = 640, height = 480; |
|
|
|
qint64 lastPts = -1, reportAt = 0, convertMax = 0; |
|
|
|
qint64 lastPts = -1, reportAt = 0, convertMax = 0; |
|
|
|
unsigned frames = 0; |
|
|
|
unsigned frames = 0, paced = 0; |
|
|
|
|
|
|
|
|
|
|
|
void send(const QByteArray& data) { |
|
|
|
void send(const QByteArray& data) { |
|
|
|
if (socket.write(data) != data.size()) { |
|
|
|
if (socket.write(data) != data.size()) { |
|
|
|
@ -113,6 +115,8 @@ class CameraWorker : public QObject { |
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_CALL, "camera skips old frame age_us=%lld pts=%lld last=%lld", |
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_CALL, "camera skips old frame age_us=%lld pts=%lld last=%lld", |
|
|
|
(long long)(started - pts), (long long)pts, (long long)lastPts); return; |
|
|
|
(long long)(started - pts), (long long)pts, (long long)lastPts); return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Ограничиваем поток до дорогой конвертации и IPC; preview и TX получают те же 30 fps.
|
|
|
|
|
|
|
|
if (!cadence.accept(pts)) { ++paced; return; } |
|
|
|
stage(QStringLiteral("convert")); |
|
|
|
stage(QStringLiteral("convert")); |
|
|
|
QImage image = raw.toImage(); |
|
|
|
QImage image = raw.toImage(); |
|
|
|
if (image.isNull()) { |
|
|
|
if (image.isNull()) { |
|
|
|
@ -133,9 +137,9 @@ class CameraWorker : public QObject { |
|
|
|
stage(QStringLiteral("release")); image = {}; raw = {}; stage(QStringLiteral("running")); |
|
|
|
stage(QStringLiteral("release")); image = {}; raw = {}; stage(QStringLiteral("running")); |
|
|
|
convertMax = std::max(convertMax, call_video_playout_now_us() - started); |
|
|
|
convertMax = std::max(convertMax, call_video_playout_now_us() - started); |
|
|
|
if (started - reportAt >= 1000000) { |
|
|
|
if (started - reportAt >= 1000000) { |
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "camera flow frames=%u convert_max_us=%lld age_us=%lld clock_correction_us=%lld", |
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "camera flow frames=%u paced=%u convert_max_us=%lld age_us=%lld clock_correction_us=%lld", |
|
|
|
frames, (long long)convertMax, (long long)(converted - pts), (long long)clock.correction); |
|
|
|
frames, paced, (long long)convertMax, (long long)(converted - pts), (long long)clock.correction); |
|
|
|
reportAt = started; convertMax = 0; frames = 0; |
|
|
|
reportAt = started; convertMax = 0; frames = paced = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
bool receive(quint8 type, quint64 revision, QDataStream& in) { |
|
|
|
bool receive(quint8 type, quint64 revision, QDataStream& in) { |
|
|
|
@ -152,7 +156,7 @@ class CameraWorker : public QObject { |
|
|
|
} else if (type == Configure) { |
|
|
|
} else if (type == Configure) { |
|
|
|
bool enabled = false; QByteArray device; qint32 w = 0, h = 0; in >> enabled >> device >> w >> h; |
|
|
|
bool enabled = false; QByteArray device; qint32 w = 0, h = 0; in >> enabled >> device >> w >> h; |
|
|
|
if (in.status() != QDataStream::Ok || w < 1 || h < 1 || w > 1280 || h > 720 || !pixels) return false; |
|
|
|
if (in.status() != QDataStream::Ok || w < 1 || h < 1 || w > 1280 || h > 720 || !pixels) return false; |
|
|
|
stop(); generation = revision; width = w; height = h; clock = {}; lastPts = -1; |
|
|
|
stop(); generation = revision; width = w; height = h; clock = {}; cadence = {}; lastPts = -1; |
|
|
|
if (!enabled) { stage(QStringLiteral("idle")); return true; } |
|
|
|
if (!enabled) { stage(QStringLiteral("idle")); return true; } |
|
|
|
stage(QStringLiteral("start")); |
|
|
|
stage(QStringLiteral("start")); |
|
|
|
pending = std::make_shared<Pending>(); |
|
|
|
pending = std::make_shared<Pending>(); |
|
|
|
|