Skip to content

Захват SDI с карты DekTec

Sapsan принимает сигнал с SDI-порта карты DekTec. Захватывает карту не сам сервер, а отдельный процесс dektec_ingest — по одному на порт; sapsan его запускает, надзирает за ним и читает готовые кадры.

Граница процессов здесь не деталь реализации, а требование: отказ вендорного SDK, слинкованного в медиасервер, уносит не один стрим, а весь сервер. Граница стоит одного процесса на порт, а взамен ни SDK, ни C++-шима в сборке sapsan нет.

Что нужно на машине

  • Карта DekTec и её драйвер. Проверено на DTA-2178 (HD и 12G вплоть до 3840×2160p50) и DTA-2174B (HD).
  • Пакет dektec-bridge — он ставит dektec_ingest и dektec_probe в PATH. Без него вход отказывает с причиной producer_unavailable и называет искомый исполняемый файл, а не молчит до таймаута.
  • Лицензия с поддержкой SDI.

Каталог для сокета (/run/sapsan/sdi) сервер заводит себе сам; юнит systemd отдаёт под это /run/sapsan через RuntimeDirectory. Отдельных параметров развёртывания у входа нет.

Настройка

streams:
  - name: tv1
    inputs:
      - dektec:
          serial: 2174223653
          port: 1
          pixel_format: v210
          audio:
            - channels: [1, 2]
              lang: rus
            - channels: [5, 6]
              lang: eng
Параметр Описание
serial серийный номер карты. Карта адресуется именно им, а не индексом в системе: индекс меняется при перестановке карт и при смене порядка загрузки драйвера
port номер порта карты, с единицы
pixel_format uyvy422 (8 бит, умолчание) или v210 (10 бит)
audio карта звуковых дорожек, см. ниже. Пустой список — умолчание продьюсера: одна стереодорожка PCM из первой пары
ad_marks дорожка сырых меток SCTE-104 из VANC; включена по умолчанию
peer_timeout_ms сколько ждать кадров, прежде чем признать источник мёртвым; он же окно тишины сокета. По умолчанию 30 000; ноль означает умолчание, а не «ждать вечно»

Единица владения — пара «серийный номер и порт»: эксклюзивность драйвера действует на порту. Два стрима на одну такую пару конфигурация отклоняет и называет занявший порт стрим; разные порты одной карты работают независимо и координации не требуют.

Сырое видео играть нечем: HLS, DASH и архив останутся пустыми, пока в стриме нет кодированных дорожек. Чтобы получить их, включите транскодер.

Звуковые дорожки

Позиция дорожки в списке audio — её номер в стриме (a1, a2, …). Каждая дорожка собирается из перечисленных SDI-аудиоканалов, а порядок каналов в списке и есть раскладка каналов дорожки.

Поле Описание
channels номера SDI-аудиоканалов, с единицы, не больше 16 (восемь эмбеддированных пар — предел SDI)
sample_type pcm (умолчание) или smpte337
lang язык дорожки по ISO 639-2

Язык объявляется, а не выводится: SDI языковых дескрипторов не несёт, и знает язык только тот, кто раскладывал программы по парам. Вид звука тоже объявляется и по данным не распознаётся — пара, в которой сегодня AC-3, а завтра тишина, не должна менять состав дорожек стрима.

Радиопрограммы в соседних парах становятся дорожками того же стрима, и слушать их можно селектором дорожек на выдаче. Отдельными стримами они не становятся: своего имени, своей глубины хранения и своей статистики у дорожки нет.

Несжатый звук приходит планарным 32-битным (s32p) и декодируется по объявленному числу каналов. Дорожка шире стерео принимается и декодируется честно, но кодер сводит её в стерео — это существующая граница транскодера. Целиком многоканальный звук доезжает только в обёртке SMPTE 337, где битовый поток никто не трогает.

AC-3 и E-AC-3 через SMPTE 337

Дорожка, объявленная sample_type: smpte337, приезжает готовыми кадрами ac3 или eac3: обёртку снимает продьюсер, sapsan звук не декодирует и не переупаковывает. Поддерживается единственный вариант — SMPTE 337, закодированный в двух каналах: такая дорожка обязана объявлять ровно два канала, иначе конфигурация отклоняется.

audio:
  - channels: [1, 2]
    lang: rus
  - channels: [3, 4]
    sample_type: smpte337
    lang: rus

Паузы сжатой дорожки — тишина между пакетами — законны: вход не синтезирует тишину и не считает паузу ошибкой.

Вспомогательные данные VANC

Вход разбирает мешок VANC каждого кадра и разводит его содержимое:

  • Телетекст и субтитры OP-47 — в общий тракт closed captions, тем же путём, что OP-47 из ST 2110.
  • Строки телетекста VBI — туда же, но с SD-источника: в SD телетекст едет строкой гашения, а не пакетом ANC. Собирается той же функцией, что и OP-47.
  • SCTE-104 — отдельной прикладной дорожкой, сырыми пакетами со штампом несущего кадра. Вход их не разбирает и в SCTE-35 не преобразует.
  • CDP (CEA-608/708) — разбирается и считается счётчиком, но дорожкой не публикуется: носитель closed captions в тракте — SEI кодированного выхода, и вставка туда пока не сделана. Счётчик существует затем, чтобы «closed captions в сигнале нет» и «closed captions некуда отдать» не выглядели снаружи одинаково.
  • Прочие пары DID/SDID — считаются счётчиком, лог ими не засоряется.

Дорожка меток существует с первого кадра пустой. Появись она по приходу первой метки — упаковка переинициализировалась бы ровно в начале рекламного блока; так же устроен MPEG-TS, где PID меток объявлен в таблице задолго до первого сообщения.

Отказы и восстановление

Живость источника, переключение на резерв и бэкофф ретраев у входа общие со всеми остальными протоколами — своей супервизии он не заводит. Собственных наблюдения два: тишина сокета и устойчивое «сигнала нет» на кадрах.

Причина Что случилось Что делать
no_signal на порту нет детектируемого сигнала проверить кабель и источник
device_busy драйвер отказал в порте сперва проверить направление порта, затем свой зависший процесс, и лишь потом искать чужого держателя
producer_unavailable dektec_ingest не найден или не запускается поставить пакет dektec-bridge
device_error продьюсер вышел ненулевым кодом без отдельного значения: неизвестный серийный номер, порт без нужной способности, отказ настройки устройства стадию называет стартовое событие в логе
producer_stuck процесс не завершается ни по закрытию stdin, ни по SIGKILL признак заклинившей карты; разбираться на хосте
producer_killed продьюсера убил кто-то извне sapsan — OOM-killer, systemd, человек выяснить, кто завершил процесс, а не чинить стрим
protocol_error датаграммы идут, но ни одна не разбирается версии dektec-bridge и sapsan разъехались, выкатывать их надо вместе

Неустранимых отказов здесь нет: после любой из них вход пробует подняться снова, с растущим интервалом между попытками. Сервер, стартовавший раньше драйвера карты, поднимется сам, как только драйвер появится; занятый порт освободится, переставленная карта найдётся.

Два случая ошибками не считаются. Смена видеостандарта — штатный рестарт продьюсера: тракт переинициализируется под новое самоописание кадров, счётчик ошибок не растёт. Одиночный плохой кадр — «опоздал» или «дубль» — стрим не рвёт.

Отдельно стоит потеря сигнала на лету. Продьюсер при этом не выходит: он продолжает выдавать кадры по расписанию, повторяя последний кадр и тишину, и для проверки живости источник с оборванным кабелем выглядит идеально здоровым. Поэтому вход, увидев на кадрах устойчивый уровень «сигнала нет», перестаёт отдавать кадры в тракт — иначе стоп-кадр уходил бы в эфир, пока кто-нибудь не вмешается. Дальше работает общая машинерия: источник признаётся мёртвым, резерв подхватывает, ретрай поднимает захват заново.

Счётчики

Главный вопрос статистики этого входа — где именно деградация, и три диагноза различаются арифметикой:

Наблюдение Диагноз
рвутся номера датаграмм транспорт: очередь продьюсера или сокет
номера целы, рвётся pts видео линия
процесс вышел с кодом продьюсер

В снапшоте API v4 у входа едут три величины: sdi_line_state (текущее состояние линии), sdi_producer_restarts_total (рестарты продьюсера) и sdi_boundary_loss_total (датаграммы, не доехавшие между процессами). Рядом — failure_cause: текущая причина отказа из таблицы выше, которая исчезает, как только отказ устранён, в отличие от кумулятивных errors_*.

В метриках Prometheus те же величины идут под префиксом stream_input_sdi_, а с ними — материал для разбора инцидента: обрезанные и неразобранные датаграммы, испорченные ссылки на кадры, неизвестные пары VANC, счётчики CDP и пер-причинная разбивка самого продьюсера. Диагностическая пара, ради которой оба счёта живут рядом: sdi_producer_datagram_dropped_total против sdi_boundary_loss_total — сошлись, значит потеряно в очереди продьюсера; наш счётчик больше, значит на самом сокете.

Расширенная детализация открывается опцией расширенных счётчиков, см. Статистику.

Чего вход не делает

  • Не выдаёт сигнал в карту. Вход только принимает; обратное направление — SDI-выход — в sapsan пока не сделано.
  • Не декодирует AC-3 и Dolby E в PCM.
  • Не преобразует SCTE-104 в SCTE-35 и меток в TS/HLS/DASH не выдаёт.
  • Не публикует дорожку closed captions CEA-608/708.
  • Не работает с картами не-DekTec.
  • Не наблюдает здоровье карты: температуру, обороты и раскладку портов снимает отдельный процесс dektec_probe, а показывает их система управления — в инсталляциях с mcaster это раздел «Карты захвата».

Что дальше