Describe stream bridge ownership, asynchronous requests and snapshots
This commit is contained in:
1 parent
3960e28638
commit
1f0c7483e0
2 files changed
+42
-12
No files matched your search
@@ -22,7 +22,8 @@ public:
|
||||
~StreamPortalCapture() override;
|
||||
// Начать асинхронный выбор: showCursor=true требует Embedded=2, false — Hidden=1; fallback режима отсутствует.
|
||||
// На служебные этапы отведено 30с, на первый кадр 8с; ожидание пользователя на Start не ограничено.
|
||||
// Успех возвращается через frameReady; отказ/отмена выбора/повторный start — через errorOccurred.
|
||||
// Успех — frameReady; отказ/отмена выбора — errorOccurred. Повтор активного start завершает захват ошибкой;
|
||||
// после Failed start ничего не запускает и повторно не сообщает ошибку.
|
||||
void start(bool showCursor);
|
||||
signals:
|
||||
// Скопированный QVideoFrame; ссылка заимствована на время сигнала, для сохранения скопировать объект.
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
* Один общий publisher и независимые viewers; команды содержат IDs, не borrowed pointers ядра.
|
||||
* Плеер запрашивает ограниченный батч; каждый трек имеет свой бюджет, новые данные будят worker.
|
||||
* Watch до attach запоминает выбранную группу. Каталог идёт через CHAT_EVT_STREAM_SOURCES,
|
||||
* media pull читает ближайшие кадры из общего RS-кольца; копия нужна только для передачи между потоками. */
|
||||
* media pull читает ближайшие кадры из общего RS-кольца; QByteArray владеет копией payload.
|
||||
* notify вызывается под внутренними mutex: только будить worker, не входить повторно в bridge/API ядра. */
|
||||
#pragma once
|
||||
|
||||
#include <QByteArray>
|
||||
@@ -16,35 +17,63 @@
|
||||
struct UTUN_INSTANCE;
|
||||
enum class StreamRecordKind { Video, Audio, Gap, Opened, End, Closed, VideoEnd, AudioEnd };
|
||||
struct StreamRecord {
|
||||
uint64_t id = 0, pts = 0;
|
||||
StreamRecordKind kind = StreamRecordKind::Gap;
|
||||
stream_media_format format{};
|
||||
int flags = 0, reason = 0;
|
||||
QByteArray data;
|
||||
uint64_t id = 0, pts = 0; // ID viewer и PTS этого источника в микросекундах; PTS значим для media.
|
||||
StreamRecordKind kind = StreamRecordKind::Gap; // Media либо событие открытия/разрыва/завершения трека.
|
||||
stream_media_format format{}; // Формат VIDEO/AUDIO; для управляющих событий нули.
|
||||
int flags = 0, reason = 0; // VIDEO: STREAM_MEDIA_FLAG_KEY; CLOSED: stream_close_reason.
|
||||
QByteArray data; // Owned access unit/Opus; у управляющих событий пусто, живёт независимо от viewer/ядра.
|
||||
};
|
||||
|
||||
/* Создать общий publisher/viewers для inst с работающим stream-сервисом; uasync, вне callbacks.
|
||||
* true — managers готовы; false — неверный inst, повторный attach либо отказ создания, с логом нижнего слоя.
|
||||
* Сохранённые watches применяются к новому ядру; отдельный отказ watch логируется и не отменяет attach. */
|
||||
bool gui_stream_attach(UTUN_INSTANCE* inst);
|
||||
/* Только совпавший inst: отменить pending watch, снять watches, уничтожить managers; NULL/старое ядро — no-op.
|
||||
* uasync вне callbacks до destroy inst; mutex ждёт внешних callers. Выбор watches сохраняется для нового attach. */
|
||||
void gui_stream_detach(UTUN_INSTANCE* inst);
|
||||
/* owner=0 — выбранный чат; окно многопросмотра держит свой ненулевой owner. group=0 снимает только его. */
|
||||
/* owner=0 — выбранный чат; окно многопросмотра держит свой ненулевой owner. group=0 снимает только его.
|
||||
* Последнее значение каждого owner сохраняется до attach/через detach; работающий bridge объединяет изменения в post.
|
||||
* true — выбор принят, не подтверждение доступности каталога. false — не выделен post, прежний выбор не меняется. */
|
||||
bool gui_stream_watch(uint64_t group, uint64_t owner = 0);
|
||||
/* notify только будит worker; arg живёт до gui_stream_stop/detach. Callback не вызывает bridge/API ядра. */
|
||||
/* Ненулевые id/group/source/epoch; true — асинхронное открытие VIDEO|AUDIO принято, итог через Opened/Closed.
|
||||
* id уникален до обработки stop actor. notify может вызываться сразу; arg живёт до gui_stream_stop/detach.
|
||||
* Callback только будит worker, не вызывает bridge/API ядра. false — отказ открытия/установки notify. */
|
||||
bool gui_stream_open(uint64_t id, uint64_t group, uint64_t source, uint64_t epoch,
|
||||
void (*notify)(void*) = nullptr, void* arg = nullptr);
|
||||
/* Синхронно разбудить/снять notify и асинхронно закрыть viewer; старый id допустим, полученные records сохраняются. */
|
||||
void gui_stream_stop(uint64_t id);
|
||||
/* true — одна готовая запись записана в record. false — record не меняется; при наличии manager запрошена выдача.
|
||||
* position<0 прогревает звук до KEY; иначе позиция playback в мкс. audioAhead=-1 отключает звук, иначе 0..60000000 мкс.
|
||||
* Это режим выдачи по одной записи: не смешивать с pull_batch на том же id без сброса reader. */
|
||||
bool gui_stream_pull(uint64_t id, StreamRecord& record, int64_t position = -1,
|
||||
bool wantVideo = true, int64_t audioAhead = STREAM_MEDIA_READ_AHEAD_US);
|
||||
/* Добавляет готовый батч в records; при пустом ответе запрашивает до videoBudget кадров и audioAhead звука.
|
||||
* Вызывать после расходования нужного трека: удерживаемые видеокадры не мешают запросить только звук. */
|
||||
/* true — готовый батч добавлен в records, прежние записи не удаляются. false — новых записей пока нет либо viewer недоступен.
|
||||
* При пустом ответе запрашивает до STREAM_VIEWER_BATCH_RECORDS записей: videoBudget=0..16 кадров и audioAhead звука.
|
||||
* position/audioAhead как у pull. Вызывать после расходования нужного трека; удерживаемое видео не мешает запросить только звук.
|
||||
* Запрос исполняется асинхронно, false не отличает ожидание от отказа demand; ошибки scheduling логируются ядром. */
|
||||
bool gui_stream_pull_batch(uint64_t id, std::deque<StreamRecord>& records, int64_t position,
|
||||
unsigned videoBudget, int64_t audioAhead);
|
||||
/* true — последний снимок viewer, сохраняется после End/Closed до stop; до обновления actor/после resync — нули.
|
||||
* false — ID/manager недоступен, выход не меняется. */
|
||||
bool gui_stream_status(uint64_t id, stream_media_status& status);
|
||||
/* true — снимок цепочки; раз в 200мс запрашивает обновление в uasync без ожидания его результата.
|
||||
* До первого снимка нули; false не меняет telemetry. */
|
||||
bool gui_stream_telemetry(uint64_t id, stream_viewer_telemetry& telemetry);
|
||||
/* Очистить готовый ответ и запросить поиск ближайшего KEY только этого viewer; true — принято. */
|
||||
bool gui_stream_resync(uint64_t id);
|
||||
/* Есть прикреплённое ядро/managers; не означает открытие viewer/publisher или готовность сетевых маршрутов. */
|
||||
bool gui_stream_ready();
|
||||
/* Publisher независим от viewer; lifetime ядра ограничивает общий bridge mutex. */
|
||||
/* Единственный publisher независим от viewers. Ненулевые id/group и допустимый format; true — принято OPENING.
|
||||
* После Ended/Failed возможен новый id, результат открытия читается publish_status. */
|
||||
bool gui_stream_publish_open(uint64_t id, uint64_t group, const stream_media_format& format);
|
||||
/* true — mute/unmute принят в OPENING/LIVE без смены эпохи/аудиокодека; включение требует audio codec в format. */
|
||||
bool gui_stream_publish_audio(uint64_t id, bool enabled);
|
||||
/* 1 — data скопирован в очередь, 0 — нужен KEY/перегрузка, -1 — ошибка/старый id; приём не гарантирует доставку.
|
||||
* pts<=INT64_MAX строго растёт отдельно по трекам; video требует полный access unit и format, audio — один Opus.
|
||||
* Новый video revision принимается с KEY; format/key для audio игнорируются. data/format заимствованы только на вызов. */
|
||||
int gui_stream_publish_feed(uint64_t id, bool video, uint64_t pts, bool key, const QByteArray& data,
|
||||
const stream_media_format* format = nullptr);
|
||||
/* Запретить feed, дренировать очередь с TTL и удержать FIN 2с; в OPENING отменить открытие. Повтор/старый id допустимы. */
|
||||
void gui_stream_publish_stop(uint64_t id);
|
||||
/* true — последний снимок, включая ENDED/FAILED; false — id/manager недоступен, status не меняется. */
|
||||
bool gui_stream_publish_status(uint64_t id, stream_publisher_status& status);
|
||||
Reference in new issue
Block a user