|
|
|
|
@ -734,15 +734,15 @@ Restart в той же source_epoch сохраняет consumer cursor: bootstra
|
|
|
|
|
|
|
|
|
|
8. Live media и Android |
|
|
|
|
|
|
|
|
|
Транспортный wire v3 не меняется. stream_publish_block публикует одну непустую FEC-пачку |
|
|
|
|
Транспортный wire v5 не меняется. stream_publish_block публикует одну непустую FEC-пачку |
|
|
|
|
немедленно, с сохранением границ. Первая запись выбирает режим источника: byte write или block write; |
|
|
|
|
смешивание отвергается до изменения данных. stream_publish_finish не освобождает буфер источника. |
|
|
|
|
|
|
|
|
|
Медиаблок uAV1 находится целиком внутри входа RS, поэтому header восстанавливается вместе с данными. |
|
|
|
|
Медиаблок uAV2 находится целиком внутри входа RS, поэтому header восстанавливается вместе с данными. |
|
|
|
|
При штатных 6+2 полный медиаблок <=7345 байт. Раскладка big-endian, без packed-структур: |
|
|
|
|
|
|
|
|
|
fixed header (32 байта): |
|
|
|
|
magic="uAV1":4, video_codec:1, audio_codec:1, video_count:1, audio_count:1, |
|
|
|
|
magic="uAV2":4, video_codec:1, audio_codec:1, video_count:1, audio_count:1, |
|
|
|
|
width:2, height:2, rotation:2, header_size:2, video_size:4, audio_size:4, |
|
|
|
|
first_video_frame_offset:4, config_revision:4 (ненулевой, возрастает при пересоздании видеозахвата). |
|
|
|
|
Далее video_count описаний по 32 байта, audio_count описаний по 16 байт, |
|
|
|
|
@ -758,13 +758,18 @@ first_video_frame_offset относительно начала video bytes: UINT
|
|
|
|
|
иначе это смещение первого фрагмента с fragment_offset=0. Начал может быть несколько, |
|
|
|
|
таблица описывает каждое. Данные конфигурации не являются отдельным кадром. |
|
|
|
|
KEY=bit0 video flags; остальные биты запрещены. frame_id>0, <=16 описаний каждого трека. |
|
|
|
|
Один H.264 кадр <=2MiB. Общий формат допускает медиаблок <=64KiB; реальный максимум дополнительно |
|
|
|
|
ограничен входом RS. Аудиокодек фиксирован на source_epoch. Разрешение, поворот и SPS/PPS видео меняются по config_revision. |
|
|
|
|
Один полный видеокадр с конфигурацией <=2MiB. Общий формат допускает медиаблок <=64KiB; реальный максимум дополнительно |
|
|
|
|
ограничен входом RS. Аудиокодек фиксирован на source_epoch. Кодек, разрешение, поворот и конфигурация видео меняются по config_revision. |
|
|
|
|
Новая revision может пропускать номера; старая игнорируется. Изменение metadata без новой revision запрещено. |
|
|
|
|
При переходе receiver удаляет неполный видеокадр и ждёт полный KEY, сохраняя историю PTS/кадров и аудио. |
|
|
|
|
|
|
|
|
|
video_codec=1: AVC/H.264 Annex B, без B-кадров. Каждый KEY содержит SPS, PPS и IDR в одном |
|
|
|
|
логическом кадре; это позволяет позднему viewer настроить декодер после получения полного KEY. |
|
|
|
|
video_codec: 1=H.264, 2=H.265, 3=VP9, 4=AV1, 5=H.266/VVC. B-кадры при захвате запрещены. |
|
|
|
|
KEY payload: config_length:4BE, decoder configuration (<=64KiB), access unit (непустой). |
|
|
|
|
Обычный payload содержит только access unit. frame_size/offset учитывают всю оболочку KEY. |
|
|
|
|
Конфигурация повторяется с каждым KEY, защищена подписью/RS и разбирается только после полной сборки кадра. |
|
|
|
|
H.264/H.265/H.266 используют Annex B; VP9/AV1 сохраняют собственные access units и opaque codec configuration. |
|
|
|
|
Для H.264 конфигурация содержит SPS/PPS, для H.265 — VPS/SPS/PPS; самодостаточный KEY может иметь пустую конфигурацию. |
|
|
|
|
Ранняя подписка и возобновление после GAP не требуют отдельного CONFIG-запроса. Старый uAV1 отвергается. |
|
|
|
|
audio_codec=0: нет аудио; audio_codec=1: Opus mono, audio_codec=2: Opus stereo. |
|
|
|
|
Оба формата: 48000Hz, 960 кадров на канал (20ms), packet<=1275 bytes; interleaved stereo содержит 1920 отсчётов PCM. |
|
|
|
|
Opus-пакеты между медиаблоками не разрезаются. Размеры треков не включают header/описания. |
|
|
|
|
@ -772,18 +777,23 @@ Opus-пакеты между медиаблоками не разрезаютс
|
|
|
|
|
stream_media проверяет весь блок до изменения view. Receiver собирает один последовательный кадр. |
|
|
|
|
При GAP, потере продолжения или конфликте metadata недособранный кадр удаляется, видео ждёт KEY. |
|
|
|
|
Аудио обрабатывается независимо; неверный формат/длины не передаются платформенным декодерам. |
|
|
|
|
Ретрансляторы не разбирают uAV1 и не пересоздают подписи источника. |
|
|
|
|
Ретрансляторы не разбирают uAV2 и не пересоздают подписи источника. |
|
|
|
|
|
|
|
|
|
Android: |
|
|
|
|
- Один foreground publisher на процесс, один viewer. Каждая операция имеет новый session ID. |
|
|
|
|
- StreamService владеет камерой, микрофоном и PARTIAL_WAKE_LOCK; пересоздание Activity не завершает источник. |
|
|
|
|
Сервис camera|microphone запускается из видимого приложения после runtime-разрешений; без микрофона — camera. |
|
|
|
|
- Camera2 TEMPLATE_RECORD пишет в Surface AVC encoder. Режимы камеры <=1920x1080 пересекаются с возможностями |
|
|
|
|
конкретного AVC baseline Surface encoder. Обычные 30/60fps требуют диапазона AE и подходящей minFrameDuration; |
|
|
|
|
- Camera2 TEMPLATE_RECORD пишет в Surface encoder. Кодеки перечисляются в порядке H.264/H.265/VP9/AV1/H.266; |
|
|
|
|
видны только поддержанные encoder/profile/Surface/size/FPS сочетания, аппаратные encoder имеют приоритет. |
|
|
|
|
Режимы камеры <=1920x1080 пересекаются с возможностями выбранного encoder. Обычные 30/60fps требуют AE и minFrameDuration; |
|
|
|
|
скоростные 120/240fps требуют фиксированного диапазона getHighSpeedVideoFpsRangesFor, скоростной сессии, |
|
|
|
|
createHighSpeedRequestList и setRepeatingBurst. Битрейт зависит от размера/FPS, ограничен 16Mbit/s и codec caps. |
|
|
|
|
I-frame interval=1s. Выход нормализуется в Annex B; |
|
|
|
|
partial output собирается в access unit. Codec config передаётся с каждым IDR. |
|
|
|
|
- Битрейт выбирается отдельно: Авто по разрешению/FPS либо пресет в диапазоне encoder. |
|
|
|
|
На LIVE применяется PARAMETER_KEY_VIDEO_BITRATE; при отказе используется штатная смена конфигурации/rollback. |
|
|
|
|
Смена кодека/камеры/режима создаёт revision и принимается вместе с KEY, без смены source_epoch и перезапуска звука. |
|
|
|
|
Encoder configuration из отдельных NAL callbacks объединяется без дублирования parameter sets. |
|
|
|
|
- Camera MediaCodec Surface timestamps и AudioTimestamp.TIMEBASE_MONOTONIC приводятся к общему |
|
|
|
|
origin System.nanoTime; время callback/получения блока не заменяет capture PTS. |
|
|
|
|
- Микрофон трансляции использует AudioRecord.CAMCORDER, 48kHz stereo. Перед Opus AUDIO/128kbps |
|
|
|
|
@ -838,7 +848,7 @@ Android:
|
|
|
|
|
Скоростной режим подтверждается после 3s фактического encode rate >=80% целевой FPS; до этого lastGood не заменяется. |
|
|
|
|
При ошибке — одна попытка восстановления последнего успешного режима. |
|
|
|
|
Новая конфигурация и первый KEY принимаются native bridge атомарно; старая очередь видео удаляется, аудио сохраняется. |
|
|
|
|
Каждая запись JNI pull имеет header 24 bytes: kind:1, flags:1, width:2, height:2, rotation:2, PTS_us:8, length:4, revision:4. |
|
|
|
|
JNI pull header 28 bytes: kind:1, flags:1, width:2, height:2, rotation:2, PTS_us:8, length:4, revision:4, codec:1, reserved:3. |
|
|
|
|
Kotlin и desktop viewer пересоздают только видеодекодер при смене revision; audio clock не сбрасывается. |
|
|
|
|
- Stop сначала закрывает capture producers и encoder, затем FIN. |
|
|
|
|
Publisher сохраняет конечный буфер ещё 2s для сетевой выдачи, затем снимает своё владение. |
|
|
|
|
@ -876,7 +886,7 @@ Desktop:
|
|
|
|
|
- transport/stream_bridge владеет одним viewer, готовит до двух media records и ограничивает RX 4MiB/16 записей. |
|
|
|
|
Attach/detach выполняются в uasync; команды и копирование медиаданных защищены mutex. |
|
|
|
|
Post отменяется до destroy ядра; GUI/decoder не хранят заимствованные instance/handle pointers. |
|
|
|
|
- stream_media_cursor собирает ближайший H.264 access unit и выдаёт Opus 48kHz mono/stereo/20ms из RS-кольца. |
|
|
|
|
- stream_media_cursor собирает ближайший access unit выбранного кодека и выдаёт Opus 48kHz mono/stereo/20ms из RS-кольца. |
|
|
|
|
Android AudioTrack и desktop output работают в stereo; mono-пакеты upmix выполняет libopus. |
|
|
|
|
FFmpeg/Opus декодируются отдельным worker; Qt-очередь не накапливает кадры. |
|
|
|
|
Worker запрашивает видео при наличии менее двух готовых изображений; защитный предел — четыре. |
|
|
|
|
@ -903,7 +913,7 @@ test_stream_service также проверяет общий каталог дв
|
|
|
|
|
stream_media_store хранит только диапазоны seq, PTS готового видео/аудио и позиции KEY. |
|
|
|
|
Индекс ограничен геометрией кольца и 4MiB метаданных; cursor принадлежит отдельному handle. |
|
|
|
|
Live ingest cursor и оптимизатор выдач продолжают продвигаться, независимо от паузы player. |
|
|
|
|
Рабочая память reader — один H.264 кадр до 2MiB, один Opus-пакет и два scratch медиаблока. |
|
|
|
|
Рабочая память reader — один видеокадр до 2MiB, один Opus-пакет и два scratch медиаблока. |
|
|
|
|
- Подпись пачки проверяется при первом восстановлении. Индексы использованных RS-частей фиксируются; |
|
|
|
|
повторное чтение использует тот же неизменяемый набор, поэтому поздние части не меняют проверенные данные. |
|
|
|
|
Reader не закрепляет старые части против вытеснения. После выхода за окно кольца он начинает с нового KEY. |
|
|
|
|
|