Clarify desktop demand reader ownership and preparation bounds
This commit is contained in:
1 parent
ef0fc85eb9
commit
c0c4310f08
3 files changed
+32
-32
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
/* Просмотр одной live-трансляции: FFmpeg/Opus в worker, ограниченные очереди PCM/кадров.
|
/* Просмотр одной live-трансляции: запас остаётся в RS-кольце, worker готовит ближайшие FFmpeg/Opus кадры.
|
||||||
* GUI владеет output device и окном; audio callback публикует часы физического воспроизведения.
|
* GUI владеет output device и окном; audio callback публикует часы физического воспроизведения.
|
||||||
* Закрытие останавливает worker и снимает reader. Публикация и общий транспорт не закрываются. */
|
* Закрытие останавливает worker и снимает reader. Публикация и общий транспорт не закрываются. */
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -103,36 +103,36 @@ void process(void*) {
|
|||||||
bridge.stopping = false;
|
bridge.stopping = false;
|
||||||
}
|
}
|
||||||
if (bridge.opening) {
|
if (bridge.opening) {
|
||||||
bridge.opening = false; bridge.viewer = bridge.requested; bridge.requested = {};
|
bridge.opening = false; bridge.viewer = bridge.requested; bridge.requested = {};
|
||||||
bridge.status = {}; bridge.statusId = bridge.viewer.id; bridge.position = -1; bridge.waiting = false;
|
bridge.status = {}; bridge.statusId = bridge.viewer.id; bridge.position = -1; bridge.waiting = false;
|
||||||
stream_member_state member{};
|
stream_member_state member{};
|
||||||
int reason = STREAM_CLOSE_FAILED;
|
int reason = STREAM_CLOSE_FAILED;
|
||||||
int result = stream_member_load(bridge.inst, bridge.viewer.group, bridge.viewer.source, &member, nullptr);
|
int result = stream_member_load(bridge.inst, bridge.viewer.group, bridge.viewer.source, &member, nullptr);
|
||||||
if (result == STREAM_OK && (!member.published || member.source.source_epoch != bridge.viewer.epoch)) {
|
if (result == STREAM_OK && (!member.published || member.source.source_epoch != bridge.viewer.epoch)) {
|
||||||
DEBUG_WARN(DEBUG_CATEGORY_STREAM, "desktop selected source changed source=%llx expected=%llx actual=%llx",
|
DEBUG_WARN(DEBUG_CATEGORY_STREAM, "desktop selected source changed source=%llx expected=%llx actual=%llx",
|
||||||
(unsigned long long)bridge.viewer.source, (unsigned long long)bridge.viewer.epoch,
|
(unsigned long long)bridge.viewer.source, (unsigned long long)bridge.viewer.epoch,
|
||||||
(unsigned long long)(member.published ? member.source.source_epoch : 0));
|
(unsigned long long)(member.published ? member.source.source_epoch : 0));
|
||||||
result = STREAM_ERR_CONFLICT; reason = STREAM_CLOSE_SOURCE_CHANGED;
|
result = STREAM_ERR_CONFLICT; reason = STREAM_CLOSE_SOURCE_CHANGED;
|
||||||
}
|
}
|
||||||
if (result == STREAM_OK) result = stream_subscribe_open(bridge.inst, bridge.viewer.group, bridge.viewer.source, &bridge.handle);
|
if (result == STREAM_OK) result = stream_subscribe_open(bridge.inst, bridge.viewer.group, bridge.viewer.source, &bridge.handle);
|
||||||
stream_info info{};
|
stream_info info{};
|
||||||
if (result == STREAM_OK) result = stream_get_info(bridge.handle, &info);
|
if (result == STREAM_OK) result = stream_get_info(bridge.handle, &info);
|
||||||
if (result == STREAM_OK && info.descriptor.source_epoch != bridge.viewer.epoch) {
|
if (result == STREAM_OK && info.descriptor.source_epoch != bridge.viewer.epoch) {
|
||||||
DEBUG_WARN(DEBUG_CATEGORY_STREAM, "desktop reader encountered stale local epoch");
|
DEBUG_WARN(DEBUG_CATEGORY_STREAM, "desktop reader encountered stale local epoch");
|
||||||
result = STREAM_ERR_CONFLICT; reason = STREAM_CLOSE_SOURCE_CHANGED;
|
result = STREAM_ERR_CONFLICT; reason = STREAM_CLOSE_SOURCE_CHANGED;
|
||||||
}
|
}
|
||||||
if (result == STREAM_OK) result = stream_media_enable(bridge.handle, STREAM_MEDIA_TRACK_VIDEO | STREAM_MEDIA_TRACK_AUDIO);
|
if (result == STREAM_OK) result = stream_media_enable(bridge.handle, STREAM_MEDIA_TRACK_VIDEO | STREAM_MEDIA_TRACK_AUDIO);
|
||||||
if (result != STREAM_OK) {
|
if (result != STREAM_OK) {
|
||||||
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop viewer open failed id=%llu group=%llx source=%llx result=%d",
|
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop viewer open failed id=%llu group=%llx source=%llx result=%d",
|
||||||
|
(unsigned long long)bridge.viewer.id, (unsigned long long)bridge.viewer.group,
|
||||||
|
(unsigned long long)bridge.viewer.source, result);
|
||||||
|
closeViewer(StreamRecordKind::Closed, reason); return;
|
||||||
|
}
|
||||||
|
output({bridge.viewer.id, 0, StreamRecordKind::Opened});
|
||||||
|
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop viewer opened id=%llu group=%llx source=%llx epoch=%llx",
|
||||||
(unsigned long long)bridge.viewer.id, (unsigned long long)bridge.viewer.group,
|
(unsigned long long)bridge.viewer.id, (unsigned long long)bridge.viewer.group,
|
||||||
(unsigned long long)bridge.viewer.source, result);
|
(unsigned long long)bridge.viewer.source, (unsigned long long)bridge.viewer.epoch);
|
||||||
closeViewer(StreamRecordKind::Closed, reason); return;
|
bridge.wantRead = true;
|
||||||
}
|
|
||||||
output({bridge.viewer.id, 0, StreamRecordKind::Opened});
|
|
||||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop viewer opened id=%llu group=%llx source=%llx epoch=%llx",
|
|
||||||
(unsigned long long)bridge.viewer.id, (unsigned long long)bridge.viewer.group,
|
|
||||||
(unsigned long long)bridge.viewer.source, (unsigned long long)bridge.viewer.epoch);
|
|
||||||
bridge.wantRead = true;
|
|
||||||
}
|
}
|
||||||
if (!bridge.handle) return;
|
if (!bridge.handle) return;
|
||||||
if (bridge.resync) {
|
if (bridge.resync) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* Desktop live viewer: attach/detach в uasync до destroy ядра; остальные вызовы потокобезопасны.
|
/* Desktop live viewer: attach/detach в uasync до destroy ядра; остальные вызовы потокобезопасны.
|
||||||
* Один viewer, команды содержат IDs; RX ограничен 4MB/256 записей, borrowed данные копируются.
|
* Один viewer, команды содержат IDs; подготовлено не более двух media records, общий предел RX 4MiB/16 записей.
|
||||||
* Watch до attach запоминает выбранную группу. Каталог идёт через CHAT_EVT_STREAM_SOURCES,
|
* Watch до attach запоминает выбранную группу. Каталог идёт через CHAT_EVT_STREAM_SOURCES,
|
||||||
* медиаданные — через отдельную очередь pull. */
|
* media pull читает ближайшие кадры из общего RS-кольца; копия нужна только для передачи между потоками. */
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|||||||
Reference in new issue
Block a user