Clarify GUI ownership and preserve video queue payload lifetime

This commit is contained in:
evgeny committed 2026-10-19 21:16:10 +02:00
1 parent d0232e4c6e
commit 8c22df8f8e
3 files changed
+13 -10

No files matched your search

+7 -4
View File
@@ -53,7 +53,7 @@ struct CallVideoEngine::Impl {
QByteArray cameraId;
bool captureActive = false;
uint64_t captured = 0;
std::atomic<uint64_t> publicationEpoch{0}, pendingSerial{0}, ackSerial{0};
std::atomic<uint64_t> pendingSerial{0}, ackSerial{0};
std::atomic<int64_t> presentedAt{0};
bool presentationDriven = false;
uint64_t publicationSerial = 0;
@@ -136,7 +136,7 @@ CallVideoEngine::CallVideoEngine(QObject* parent) : QObject(parent), m(std::make
}
CallVideoEngine::~CallVideoEngine() { stop(); delete m->guiNotifier; }
void CallVideoEngine::setPresentationDriven(bool enabled) {
std::lock_guard<std::mutex> guard(m->lock); m->presentationDriven = enabled;
m->presentationDriven = enabled;
}
void CallVideoEngine::imagePresented(quint64 serial) {
if (!serial || serial != m->pendingSerial.load(std::memory_order_acquire) || serial == m->ackSerial.load()) return;
@@ -158,7 +158,10 @@ void CallVideoEngine::deliverImage() {
QImage image;
if (m->publicationVideo) {
const auto* slot = m->pictures.readSlot();
if (!slot) { DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video GUI missing published slot serial=%llu", (unsigned long long)serial); return; }
if (!slot) {
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video GUI missing published slot serial=%llu; stopping video", (unsigned long long)serial);
stop(); return;
}
image = slot->image;
}
const int64_t now = nowUs(), wait = now - queued;
@@ -228,7 +231,7 @@ void CallVideoEngine::stop() {
if (m->tx.joinable()) m->tx.join();
if (m->rx.joinable()) m->rx.join();
if (m->id) call_video_port_close(m->id);
++m->publicationEpoch; m->pendingSerial = 0; m->paintWaitMax = 0;
m->pendingSerial = 0; m->paintWaitMax = 0;
while (const auto* event = m->logEvents.readSlot()) { call_video_playout_log_event(event); m->logEvents.release(); }
m->id = 0; m->enabled = false; emit imageChanged({}, 0);
}
+2 -2
View File
@@ -14,8 +14,8 @@ public:
void start(quint64 id);
void stop();
void setVideo(bool enabled, const QByteArray& camera, int width, int height, int codec);
void setPresentationDriven(bool enabled); // Окно подтверждает рисование; без окна достаточно доставки signal.
void imagePresented(quint64 serial);
void setPresentationDriven(bool enabled); // GUI-поток: окно подтверждает рисование, иначе достаточно доставки signal.
void imagePresented(quint64 serial); // GUI-поток; повторный/старый ACK безопасно игнорируется.
signals:
void camerasChanged(const CallCameraDevices& devices);
void imageChanged(const QImage& image, quint64 serial);
+4 -4
View File
@@ -10,18 +10,18 @@
template<class T, unsigned Capacity> class CallVideoQueue {
static_assert(Capacity > 0);
static_assert(std::atomic<uint64_t>::is_always_lock_free);
std::array<T, Capacity> slots{};
std::array<T, Capacity> entries{};
alignas(64) std::atomic<uint64_t> written{0};
alignas(64) std::atomic<uint64_t> consumed{0};
public:
T* writeSlot() {
const uint64_t tail = written.load(std::memory_order_relaxed);
return tail - consumed.load(std::memory_order_acquire) < Capacity ? &slots[tail % Capacity] : nullptr;
return tail - consumed.load(std::memory_order_acquire) < Capacity ? &entries[tail % Capacity] : nullptr;
}
void publish() { written.fetch_add(1, std::memory_order_release); }
const T* readSlot() const {
const uint64_t head = consumed.load(std::memory_order_relaxed);
return head < written.load(std::memory_order_acquire) ? &slots[head % Capacity] : nullptr;
return head < written.load(std::memory_order_acquire) ? &entries[head % Capacity] : nullptr;
}
void release() { consumed.fetch_add(1, std::memory_order_release); }
// Вызывается только producer/consumer: собственный индекс во время снимка не меняется.
@@ -30,7 +30,7 @@ public:
return static_cast<unsigned>(written.load(std::memory_order_acquire) - head);
}
void reset() {
for (auto& slot : slots) slot = {};
for (auto& slot : entries) slot = {};
written.store(0, std::memory_order_relaxed); consumed.store(0, std::memory_order_relaxed);
}
};