КДПВ
Предыстория
В наше время повсеместного засилья очень компактных, экономных и многомегапиксельных цифровых видеосенсоров старые добрые аналоговые видеокамеры CCD потихоньку уходят в забытье, оставаясь востребованными лишь там где требуется наличие преимуществ CCD матриц над CMOS. Это и автомобильная промышленность (камеры заднего вида), и видеонаблюдение, и различное профессиональное оборудование (например, тепловизоры). В общем, там где требуется высокая чувствительность при плохом освещении и приличный динамический диапазон. Но и в этих сферах камеры с CMOS сенсорами потихоньку вытесняют «цэцэдешки».
Но остаётся большое количество старых аналоговых камер и хочется их как-то задействовать на новый лад. А если вспомнить, что аналоговый (композитный, с разъёмами «RCA», он же — «тюльпан») выход есть и у многих интересных устройств, очень хотелось захватывать с них видеопоток для последующей передачи по цифровым каналам связи. Само собой, для этих целей можно использовать USB TV-тюнер или более-менее специализированные USB-устройства с композитным входом, но такой вариант получается довольно громоздким, да и не все ARM контролеры могут использовать преимущества аппаратного кодирования видео для USB источников.
Наша железка
В общем, для решения некоторых задач потребовалось к нашей Виртурилке подключить устройство, выдающее именно аналоговый видеосигнал. Мы (а точнее — наш аппаратчик Саша) порыскали по интернету и нашли подходящий чип — Texas Instruments TVP5150AM1. Он имеет два входа для композитного видеосигнала, но работать они могут поочерёдно, не одновременно. Чип формирует 720x576@50fps по параллельной шине, по которой мы обычно подключаем наш цифровой сенсор камеры к Виртурилке.
Аналоговый видеопоток после захвата получается чресстрочный (interlaced), в отличие от привычного прогрессивного (progressive), так что сформированный чипом видеопоток требуется подвергнуть процедуре деинтерлейсинга. Этим занимается DSP Виртурилки. Причём вариантов деинтерлейса несколько, задаются на уровне драйвера ядра. Пока опробовали только один вариант, он всех устраивает так что дальше не ковыряли. Так же пока не опробовали режим NTSC, при котором разрешение видео составляет 640x480 точек. Такой режим чип поддерживает без проблем, но вот в драйвере переключение ещё не реализовано, сейчас работает только в PAL.
Вообще, ковыряние драйвера составило наибольшую проблему при разработке платы аналогового входа. Изначально PAL видео работало только 640х480, края обрезались от исходного кадра. Проблему решил один из ранних тестировщиков платы, который нашёл ошибку и пристал устраняющий проблему патч. Оказалось что в видеоподсистеме было захардкожено разрешение 640x480. :-)
В общем, встречайте — плата для захвата аналогового видеосигнала:
http://wiki.virt2real.ru/wiki/Аналоговый_модуль_TVP5150
Размер 37x29 мм (без учёта выступающих разъёмов).
С чем это едят
Подключение платы аналогично подключению модуля камеры — просто воткнуть шлейф и защёлкнуть защёлку. :-) В надетом состоянии выглядит примерно вот так:
Для работы с этим модулем необходимо использовать специальное ядро, исходники которого находятся у нас на Гитхабе в бранче TVP5150.
Само собой, мало кто будет ядро сам собирать, так что для большинства подойдёт готовая свежая прошивка для Виртурилки, где уже есть ядра под нашу обычную цифровую камеру и есть ядро под аналоговый модуль. Правда, там есть ещё и ядро для HDMI входа, но эти платы у нас самих на вес золота, так что в магазин пока не пускаем. :-)
Ссылка на прошивку http://files.virt2real.ru/firmware/virt2real-board/1.1/virt2real-1.02.002.zip
По умолчанию в прошивке активно ядро HD, для цифровой камеры, так что для использования с аналоговым модулем надо переключить ядро. Делается это простым копированием файла uImage.tvp5150 в файл uImage в разделе boot, но намного удобнее сделать это в админке. Раздел «Настройка -> Ядра». Выбираем «uImage.tvp5150», жмём кнопку «Сохранить», ребутим железку и получаем активное ядро для TVP5150.
К слову, там же, в админке, можно сразу и проверить трансляцию видео с аналогового входа. Для этого в разделе «Видео» есть много вариантов передачи видео (можно вещать в RTP, RTSP, RTMP и на Ivideon).
Как я уже говорил, видеовход двойной, т.е. можно подключить два независимых источника композитного видеосигнала и переключать их по мере надобности. Переключение состоит в изменении состояния одного регистра i2c устройства и сводится к командам
Выбрать первый вход:
i2cset -f -y 1 0x5d 0x00 0x00
Выбрать второй вход:
i2cset -f -y 1 0x5d 0x00 0x02
То же самое можно сделать мышкой в админке, в разделе «Камеры -> TVP5150» есть две кнопочки, «Вход 1» и «Вход 2», при нажатии на которые выполняются вышеупомянутые команды.
Так как у большинства устройств с аналоговым выходом есть и линейный аудиовыход (обычно белый тюльпанчик рядом с жёлтым, или белый+красный для стерео), то можно и звук завести на Виртурилку. У неё есть микрофонный вход, который, по совместительству, является ещё и линейным аудиовходом.
При использовании gstreamer для трансляции необходимо указать правильные параметры формата видео, т.к. есть один маленький нюанс — обязательно требуется указание параметра pitch, без него картинка будет искажена.
Вот пример передачи видео с аналогового входа по RTP:
gst-launch v4l2src always-copy=false chain-ipipe=true !
capsfilter caps=video/x-raw-yuv,format='(fourcc)'NV12,width=720,height=576,framerate='(fraction)'25,pitch=736 !
dmaiaccel ! dmaienc_h264 copyOutput=false ddrbuf=false encodingpreset=2 ratecontrol=2 intraframeinterval=30 idrinterval=120 t8x8intra=true t8x8inter=true targetbitrate=$BITRATE bytestream=true headers=false !
rtph264pay mtu=1500 !
multiudpsink clients="192.168.1.10:3000" sync=false enable-last-buffer=false
Для всех скриптов трансляции видео, используемых в штатной прошивке, все основные параметры видео сохраняются в файле настроек при смене текущего ядра. Сделано это было для того чтоб каждый раз руками не править цепочки. Мелочь, а очень удобно.
Где это можно использовать в деле
Самая интересная часть моего повествования, ИМХО. Абстрактно железка нафиг никому не нужна, нужно её применение для конкретных целей.
Управляемая тележка
Первое что я сделал, когда заполучил тестовый экземпляр аналогового модуля — приделал его на шестиколёсную тележку. На тележке была установлена DSLR камера Canon 60D и обычная аналоговая видеокамера с CCD сенсором от SONY. Сонька выступала курсовой камерой, т.е. по картинке с неё я дистанционно управлял тележкой. А зеркалка выступала в роли фотографа — в управляющем приложении Virt2real Player при нажатии специальной кнопочки происходило переключение видеовхода, а вторая кнопочка отвечала за спуск затвора на зеркалке. Таким образом, можно было кататься с видом через одну камеру, а перед фотографированием переключаться на зеркалку, наводиться и фокусироваться на нужный объект и делать снимок. К большому сожалению, Canon 60D не умеет одновременно отдавать видео на аналоговый видеовыход (да и на hdmi тоже, уже проверял) и позволять управлять собой по PTP. Очень жаль, так как управление зеркалкой по PTP давно уже освоено, даже в нашей админке есть соответствующий модуль, можно любые настройки съёмки менять на лету.
В общем, эту тележку опробовали на выставке «Открытые инновации 2014». На тележку была смонтирована белка из «Ледникового периода» для большей мимимишности и, соответственно, для привлечения внимания женского пола. Зеркалка была задрана вверх, а тележка получила кодовое имя «Подъюбочник». Угадайте, почему.
Езда выглядела примерно вот так
Коротких юбок было мало, так что улов вышел негустой. Отличных лишь два кадра получилось, но их публиковать не буду, дабы соблюсти приличия. Покажу лишь один невинный кадр с «Подъюбочника»:
Видеоглазок
Этот вариант применения у меня всё никак руки не дойдут установить на постоянное место дислокации, так и валяется для использования в качестве отладки. Суть простая: в двери на лестничную площадку стоит видеоглазок (CCD, само собой), просто Виртурилку с цифровой камерой там установить не получается, нужен именно глазок в форме обычного дверного стеклянного глазка. От видеоглазка идёт стандартный кабель, две жилы и экран. По одной жиле идёт 12В питание, по другому идёт видеосигнал с глазка, экран, соответственно, общая земля. Видео с глазка одновременно пишется на флешку Виртурилки, плюс выводится на монитор у входной двери моей квартиры. Памятка самому себе: запись надо бы циклическую сделать, а то некошерно получается.
Ну и, само собой, видео дублируется по сети на любой подключившийся девайс (обычный комп, девайс под iOS или девайс под Android).
Сейчас это у меня валяется разобранное, так что иллюстрация не шибко наглядная. На мониторчике видна картинка с гопрохи:
CAPS=video/x-raw-yuv,format=(fourcc)NV12,width=720,height=576,pitch=736,framerate=(fraction)25/1
ENCODER="dmaienc_h264 encodingpreset=2 ratecontrol=2 targetbitrate=2000000 maxbitrate=2000000 intraframeinterval=25 idrinterval=500 bytestream=false headers=false aud=false level=51 t8x8intra=true t8x8inter=true airrate=30"
VIDEOOUT="TIDmaiVideoSink videoStd=D1_PAL videoOutput=composite accelFrameCopy=false noCopy=true sync=false max-lateness=300000000 render-delay=300000000"
REC="matroskamux streamable=true min-index-interval=1000000000 ! filesink location=video.mkv enable-last-buffer=false sync=true"
#REC="flvmux ! filesink location=video.flv enable-last-buffer=false sync=false"
#REC="mp4mux streamable=false dts-method=1 presentation-time=true ! filesink location=video.mp4 enable-last-buffer=false sync=false"
# clear overlay window
fbset -yres 0 -fb /dev/fb0
# show
type0 () {
gst-launch v4l2src always-copy=false chain-ipipe=true !
$CAPS !
dmaiaccel !
$VIDEOOUT
}
# show and send
type1 () {
gst-launch v4l2src always-copy=false chain-ipipe=true !
$CAPS !
dmaiaccel !
tee name=sendvideo !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 !
$VIDEOOUT
sendvideo. !
$ENCODER !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 !
rtph264pay !
multiudpsink clients=192.168.1.10:3000 enable-last-buffer=false sync=false
}
# show, send and record
type2 () {
gst-launch v4l2src always-copy=false chain-ipipe=true !
$CAPS !
dmaiaccel !
tee name=sendvideo !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 !
$VIDEOOUT
sendvideo. !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 !
$ENCODER !
tee name=recvideo !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 !
rtph264pay !
multiudpsink clients=192.168.1.10:3000 enable-last-buffer=false sync=false
recvideo. !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 !
legacyh264parse config-interval=2 split-packetized=false output-format=2 access-unit=true !
$REC
}
# send and record
type3 () {
gst-launch v4l2src always-copy=false chain-ipipe=true !
$CAPS !
dmaiaccel !
dmaiperf print-arm-load=true !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 !
$ENCODER !
tee name=recvideo !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 !
rtph264pay !
multiudpsink clients=192.168.1.10:3000 enable-last-buffer=false sync=false
recvideo. !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 !
legacyh264parse config-interval=2 split-packetized=false output-format=2 access-unit=true !
$REC
}
# show and record
type4 () {
gst-launch v4l2src always-copy=false chain-ipipe=true !
$CAPS !
dmaiaccel !
tee name=recvideo !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 !
$VIDEOOUT
recvideo. !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 !
$ENCODER !
queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 !
legacyh264parse config-interval=2 split-packetized=false output-format=2 access-unit=true !
$REC
}
type0
В общем, ещё предстоит всё это дело облагородить и таки установить всё это, наконец-то, на постоянное место у двери.
Тепловизор
Дали мне как-то настоящий тепловизор напрокат, фирмы Flir (точную модель определить не удалось). Сначала планировал его на тележку установить в качестве второй камеры (вместо зеркалки), но увлёкся обследованием своих пластиковых окон на предмет промерзания и про тележку забыл напрочь.
С тепловизором всё просто — его аналоговый выход подключаем к нашему входу, включаем трансляцию и ходим по квартире, смотрим где окна плохо теплоизолированы. Ну и себя сфотать в ИК диапазоне не забываем.
Конечно, с тепловизора видео можно передавать обычным RC-шным видеопередатчиком, но это получается более громоздкий вариант. С Виртурилки сразу в сетку удобнее стримить поток, чтоб смотреть на смартфоне или планшете.
Live стриминг с зеркалки
Собственно, это частный случай того, как зеркалка использовалась на тележке. Рилтайм передача видео с видоискателя. Видео, ужатое в H264 с нужным битрейтом, для передачи через сравнительно узкие каналы (3G/4G). Если модель фотоагрегата поддерживает одновременный вывод видео и управление через PTP — тогда просто красота, ещё и любые параметры менять можно (выдержка, диафрагма, точки фокусировки и прочее-прочее). Мой Canon 60D это не поддерживает, к сожалению. Либо управление, либо видео. Правда, при PTP есть возможность получать видео с видоискателя, но оно низкого разрешения и в формате MJPEG, а это обычно малопригодно для передачи куда-либо.
Видеонаблюдение с помощью VideoNet
Когда я служил в армии (взвод связи), много пришлось возиться с довольно клёвой системой видеонаблюдения под названием VideoNet. Так что, само собой, попробовал и с ней Виртурилку подружить. Подружились они легко — достаточно на Виртурилке запустить RTSP сервер (можно из админки), а в Видеонете добавить камеру типа «Universal RTSP». Само собой, тут необязательно аналоговый вход использовать, но с ним лично мне интереснее.
Источником видео является GoPro, подключенная к нашему аналоговому видеовходу.
Видеонаблюдение через Ivideon
Наверное, все читатели Хабра знают про клёвую компанию под названием Ivideon. Они часто ковыряются с камерами на базе процессора DM368 (да и DM365, думаю), так что пошли нам навстречу — дали нам свой клиент для подключения к их облаку. В итоге в админке появился модуль для привязки Виртурилки к сервису Ivideon и возможность транслировать видео на него. Модуль админки писал наспех, каюсь, корявенько вышло, но таки работает.
Видеоисточником выступает всё та же гопроха:
Надо бы ещё ребят из Ivideon попросить API на детектор движения и на первоначальную привязку камеры через распознавание QR кода через камеру. :-)
Стриминг с олдскульных приставок
Многие слышали про сервис Twitch? Я вот совсем не геймер, так что услышал про него совсем недавно. Как раз на руках был тестовый сэмпл аналогового входа, так что подумалось — а почему бы не постримить со старой приставки? В современных (PS, XBOX) трансляция на Твитч уже в штатной прошивке идёт (вроде как), а вот для старых приставок такой возможности нет.
Правда, настоящей Dendy (NES) или Sega у меня давно уже нет, но есть Playstation2, для которой я давным-давно делал диск с эмулятором NES и иногда с дочей рубимся в Чип-н-дейл. А как бы это на твитч запустить?
Фигня вопрос. Берём… Да, всё ту же нашу Виртурилку, свеженький аналоговый модуль. Подключаем, открываем в админке раздел с RTMP трансляциями, вводим адрес потока (берётся из настроек канала в личном кабинете на Twitch), что-то вроде такого
rtmp://live-lhr.twitch.tv/app/live_73242159_p0OUfxtnBGoSwgdcaQVXZ7uRJO3hsM Запускаем трансляцию и, вуаля, видим на твитче свою игру!
Скриншот из моего бложика
Видеодемонстрация трансляции игры Chip'n'Dale 2 на сервис Twitch.tv:
gst-launch v4l2src always-copy=false chain-ipipe=true !
capsfilter caps=video/x-raw-yuv,format='(fourcc)'NV12,width=720,height=576,framerate='(fraction)'25,pitch=736 !
dmaiaccel !
dmaienc_h264 copyOutput=false ddrbuf=false encodingpreset=2 ratecontrol=2 single-nalu=true targetbitrate=2000000 maxbitrate=4000000 level=51 intraframeinterval=150 idrinterval=250 t8x8intra=true t8x8inter=true bytestream=false headers=false !
flvmux name=mux streamable=true !
queue !
rtmpsink location="rtmp://live-lhr.twitch.tv/app/live_73242159_p0OUfxtnBGoSwgdcaQVXZ7uRJO3hsM" sync=false enable-last-buffer=false
А если аудиовыход подключить к микрофонному входу Виртурилки то можно и так:
gst-launch v4l2src always-copy=false chain-ipipe=true !
capsfilter caps=video/x-raw-yuv,format='(fourcc)'NV12,width=$WIDTH,height=$HEIGHT,framerate='(fraction)'$FPS$PITCH !
dmaiaccel !
dmaienc_h264 copyOutput=false ddrbuf=false encodingpreset=2 ratecontrol=2 single-nalu=true targetbitrate=$BITRATE maxbitrate=4000000 level=51 intraframeinterval=150 idrinterval=250 t8x8intra=true t8x8inter=true bytestream=false headers=false !
queue !
flvmux streamable=true name=mux
alsasrc latency-time=200000 buffer-time=4000000 slave-method=3 do-timestamp=false provide-clock=false !
capsfilter caps=audio/x-raw-int,channels=1,rate=16000,endianness=1234,signed=true,width=16,depth=16 !
queue !
dmaienc_aac bitrate=48000 maxbitrate=48000 tns=false copyOutput=false outputBufferSize=500000 fullbandwidth=true fixTimestamp=true !
mux.
mux. !
queue !
rtmpsink location="rtmp://live-lhr.twitch.tv/app/live_73242159_p0OUfxtnBGoSwgdcaQVXZ7uRJO3hsM" sync=false enable-last-buffer=false
Другие варианты применения
Само собой, я успел опробовать лишь малую часть из того что можно сотворить с аналоговым видеовыходом. Лично мне он нравится даже больше чем HDMI вход и чем обычные цифровые камеры, ибо совместим с кучей всякого оборудования.
Когда мы впервые твитнули про аналоговый вход, сразу несколько ответных твитов было про то что надо бы подключить штатную автомобильную камеру заднего вида, чтоб видеть картинку на андроидном девайсе. У меня в машине парковочной камеры нет, так что проверить не могу. А обычную прикручивать к бамперу как-то не хочется :-)
Ещё один человек собирался прикрутить видеовыход телескопа к виртурилке, чтоб стримить в инет. Посмотрим что у него получится в итоге.
Можете кидать свои варианты использования (если они не секретные, конечно) в комменты. Что смогу — оперативно опробую и отпишусь о результатах. Ну или вы можете сами проверить интересные варианты, аналоговый модуль уже поступил в продажу. Если же увидим в комментах очень интересный вариант применения — гарантируем автору призовой аналоговый вход. Само собой, только если у него уже есть Виртурилка, иначе модуль цеплять не к чему. Ну а уж если применение очень-очень-очень интересное — подарим и Виртурилку в полном боекомплекте.
Сами мы продавать девайсы конечным потребителям давно уже завязали, так что теперь все наши железки продаются в интернет-магазине Chipster. И да, сами знаете что сейчас с курсом рубля творится, так что цены периодически придётся повышать, уж извиняйте.
Оффтопик
Не совсем про аналоговый модуль, но для него тоже полезно. Буквально позавчера в результате крышесносящего эксперимента оказалось что Виртурилка, которая вообще-то на базе процессора DM365, прекрасно работает на частотах старшего процессора, DM368. Копипастить не буду, дам ссылку, если кому вдруг интересно — http://www.g0l.ru/blog/n4018
Вкратце — наш DM365 прекрасно себя чувствует на частотах DM368 (CPU 432 Mhz, DDR 340 MHz). Сеть работает, вайфай работает, видео с камер, с аналогового входа, с HDMI входа — всё работает как надо. Только вот не получилось проверить Full HD видео, за неимением подходящего источника. Как перенастроим HDMI вход на 1080p или раздобудем сенсор с Full HD — проверю, может на целый топик потянет.
Разогнанная таким образом Виртурилка работает уже непрерывно более 14 часов, полёт стабильный. Повышенная частота очень пригодилась при HD RTMP трансляциях, там где раньше обычной частоты 300 MHz впритык хватало при скромном битрейте.
Если кому интересно попробовать — ссылка на прошивку
Только сразу предупреждаю — пока это в стадии тестирования, ничего гарантировать не могу. Если разогнанная Виртурилка взорвётся, вспухнет, схлопнется, аннигилирует — компания Virt2real ответственность за это не несёт. Так что, «You have been warned!», как говорится.
Приложения
Для просмотра RTP видеопотоков на мобильных устройствах у нас вышли первые версии приложений:
А для просмотра на десктопе:
Под Windows
Где купить?
Автор: Gol