Шрифт:
Еще раз о видеонаблюдении, камерах, RTSP, onvif. И «велосипед»!
Play

Еще раз о видеонаблюдении, камерах, RTSP, onvif. И «велосипед»!

Interleaved Mode. Разница с Non-Interleaved Mode в том что все пакеты будут сыпаться в этот же порт. Пример:

Запоминаем Transport: RTP/AVP/TCP;unicast;interleaved=0-1

Теперь смотрим что и как. Камеры шлют видео и аудио в разные RTP потоки. 2n поток — данные, 2n+1 поток — RTCP. На видео нам идет 0 и 1 канал, на аудио 2 и 3 канал. Теперь смотрим Transport: RTP/AVP;unicast;destination=10.112.28.33;source=10.112.28.231;client_port=49501-49502;server_port=6970-6971 Transport: RTP/AVP/TCP;unicast;interleaved=0-1 В первом случае указаны порты, во втором каналы.

С с Non-Interleaved Mode всё понятно. Просто RTP пакеты сыпятся в порты и их можно читать как то так: DatagramPacket packet = new DatagramPacket(buffer, buffer.length); s.receive(packet);

Проблемы начинаются с Interleaved mode. По факту ни каких проблем быть не должно. По RFC мы ищем magic char "$", следующий байт — канал (он указывается в подключении 0-4 у нас) и 2 байта Length. Всего 4 байта. Но есть не нормальные камеры. Например D-ling DCS-2103 «Досыпает» какие то данные после rtp пакета. frame дает размер 1448, шлет 1448 фрейма, и после 827 байт какого то мусора. (Так делает Dlink DCS-2103 прошивка 1.00 и 1.20)

И такое у «них» происходит постоянно. Этим частенько страдают китайские камеры. Qihan (356) этим не страдали. Кроме как пропускать этот мусор идей больше нет. В RTP сыпятся полезные данные. При DESCRIBE RTSP возвращается SDP пакет Примеры SDP (h264, mjpeg, mpeg4):

Прочитать про SDP Так как мода была mjpeg и текущая на h264, то рассмотрим их. С MJpeg всё предельно ясно. А вот с H264 начинаются различия в камерах. Формат h264 состоит из блоков с NAL заголовками (7.4.1 NAL unit semantics). Чтобы можно было декодировать h264 необходимо помимо данных самого h264 иметь данные SPS (Sequence parameter set) и PPS(Picture parameter set). Первый описывает последовательность, второй параметры картинки. Так как сам кодек h264 знаю очень плохо, то большего описания не будет. SPS имеет тип 7, PPS 8. Без них невозможно декодировать h264. Самое интересное — Qihan шлет SPS и PPS прям в RTP пакетах, Dlink не шлет их в RTP пакетах. Но SPS и PPS шлется в SDP пакете в параметре sprop-parameter-sets в кодировке base64. sprop-parameter-sets=Z2QAKK2EBUViuKxUdCAqKxXFYqOhAVFYrisVHQgKisVxWKjoQFRWK4rFR0ICorFcVio6ECSFITk8nyfk/k/J8nm5s00IEkKQnJ5Pk/J/J+T5PNzZprQCgDLSpAAAAwHgAAAu4YEAAPQkAABEqjve+F4RCNQ=,aO48sA== Шлются они через запятую Вариант декодирования.

Так как камеры 720p или 1080p, то в 1 RTP пакет ни jpeg фрейм, ни h264 фрейм не поместится, то они режутся на пакеты. RTP Payload Format for JPEG-compressed Video RTP Payload Format for H.264 Video

JPEG RTP пакет содержит main JPEG header

а дальше может варьироваться от Type и Q

Для декодирования jpeg нужно знать или вычислить quantization tables. В моих камерах quantization tables шли в стартовом пакете Jpeg, по этому они просто брались оттуда. Все вычисления есть в RFC. Последний пакет фрейма вычисляется по RTP header Marker bit. Если он 1, то это последний пакет фрейма.

H264 NAL Header

Single NAL Unit Packet Это как раз SPS и PPS. Type=7 или Type=8

Если фрейм h264 не влезает в RTP пакет (1448 байт), то фрейм режется на фрагменты. (5.8. Fragmentation Units (FUs)) Type = 28

Эти заголовки следуют сразу после RTP заголовка

Для декодера h264 NAL — нужная информация. Если идет фрагментация фрейма, то NAL нужно восстанавливать. (FU) нужно взять первые 3 бита из FU indicator и слить их с 5 последними FU header.

Теперь самое главное — сохраняем поток. Jpeg

NON_IDR_PICTURE — необходим для декодирования, «разделяем» фреймы. (h264) Тут нужно меня поправить, так как это просто «костыль» и обоснований пока нет. Просто работает. Получается такой поток: 00000001 + SPS + 00000001 + PPS + 00000001 + NAL… erlyvideo: 0,0,0,1 — это префикс AnnexB записи H264. Это не часть H264 NAL-юнита, а разделитель между юнитами.

ну и обработка «всего» этого

в 2х словах. Получаем RTSP Interleaved Frame (например Channel: 0x00, 1448 bytes), читаем 1448 байт, делаем writeRawToStream, полиморфизм делает свое дело.

Дальше это нужно обкатать. Казалось бы что для поддержания потока RTSP нужно делать RTCP отчеты, но нет, всё оказалось проще Dlink, Qihan, VLC просто «едят» GET_PARAMETER:

шлем его раз в 55 секунд и всё.

  1. Добавить
  2. Удалить
  3. Запустить
  4. Остановить
  5. Архив
  6. Настройка
  7. Выход
  1. Посмотреть — запускает Vlc
  2. Склеить и посмотреть — клеит файлы и запускает Vlc
  3. Выход

При простом просмотре генерируется m3u файл и кормится в VLC 4

При склеивании ffmpeg клеит, после запускается VLC 5

Программа нарезает поток на файлы, интервал задается в настройках

Что делает ffmpeg: Клеит

«Нормализует» (просчитывает заголовки и т.д.)

На выходе куча файлов 6

По хорошему можно писать в любой OutputStream Git hub Дальнейшей жизни программы может и не быть. Возможно допишу когда нибудь RTP классы для звука. (так как увлекаюсь до сих пор SIP)

Ну и самое вкусное. Есть стандарт видео наблюдения ONVIF Есть профессиональные железки, которые с камерами работают только по нему. Есть камеры, которые работают по нему (Qihan, он же Proline), а ссылки rtsp приходится гуглить. Есть опенсорсный продукт Onvif device manager для управления подобными железяками. Я же в программу добавил поддержку onvif без авторизации и с авторизацией. 7 Git hub

В 2х словах об Onvif: Это soap. Работа простая. 1. Шлем POST-XML, 2. Получаем XML Код на гитхабе. Ключ -s сохраняет все запросы и ответы XML. пример запроса:

Если пройтись по ссылкам выше, то можно получить всю документацию по Onvif. Ответ:

Дальнейшее общение по onvif без авторизации идет в этом же ключе.

А вот пример общения но уже с авторизацией

Т.е. нужно слать заголовок. (тестилось на D-link DCS-2103, остальные камеры без авторизации работали, китай).

и пароль (Password_Digest = Base64 ( SHA-1 ( nonce + created + password ) ))

Всё было сделано в образовательных целях. Если есть вопросы и вдруг понадобиться более подробное описание чего либо — пишите. Надеюсь кому нибудь пригодится.

PS Не надо писать в комментариях про организацию на большую букву «I». Их Server использует SQLite, SSL, avcodec (ffmpeg), а в папке \Resources есть божественный файлик с названием camera_list.json, но моя наглость не позволила его прикрутить к своей программе :) Но я не видел у них поддержку Onvif, видимо потому что они выпускают «свои» камеры. UPDATED: см комментарии от ivideon

Если прикрутить к программе OpenVPN и OpenCV, то будет забавное решение и «велосипед» Ну и вот вам полезная ссылка на базу ссылок потоков камер

📎📎📎📎📎📎📎📎📎📎