Захотелось забросить свою нокию высоко в небо и посмотреть, как мы выглядим с высоты птичьего полёта.
Как забросить — понятно: самый простой вариант — взять воздушный змей побольше.
Как посмотреть — вопрос немного озадачил.
Что выяснилось:
Отлично.
Фильтр capsfilter задает параметры видеозахвата. Их можно менять в разумных пределах, если видео невозможно захватить с такими параметрами, gstreamer пишет ближайшие допустимые.
Хорошо было бы теперь передать это по сети. Простейший вариант выглядит так (IP машины desktop 192.168.1.254):
Параметр protocol=gdp добавляет к данным передаваемым по сети формат потока: дело в том, что в цепочку могут быть объединены только фильтры, имеющие выход и вход совместимого формата. tcp*src с этим параметром на приемной стороне имеет на выходе тот же формат, что и tcp*sink на передающей стороне на входе.
Простое решение, но через wifi работает тяжко: 7 мегабит, 600 пакетов в секунду — ощутимая нагрузка. 640х480 уже заметно тормозит.
Пусть это будет mpeg4:
Отлично, всё в mpeg-кубиках, но 110 килобит и 30 пакетов в секунду (:
Какие еще существенные минусы этой схемы? TCP/IP: потеря пакетов приводит к повторной передаче уже неактуальной картинки, а значит к задержкам. А разрыв соединения лечится только перезапуском сервера и клиента.
Значит нужно прикрутить RTP:
Что изменилось?
Какой эффект?
Справка по плагинам gstreamer на официальном сайте: gstreamer.freedesktop.org/documentation
Список установленных плагинов и справка по их параметрам — gst-inspect
P.S. Получилась эдакая хвалебная ода gstreamer'у. Откровенно порадовал инструмент (:
Как забросить — понятно: самый простой вариант — взять воздушный змей побольше.
Как посмотреть — вопрос немного озадачил.
Что выяснилось:
- gstreamer предоставляет набор плагинов, которые можно связывать в цепочки, подавая выход одного на вход другого. Среди плагинов есть простые базовые элементы: ввод/вывод из файлов ({file,fd}{src,sink}) и по сети ({tcp{client,server},udp}{src,sink}), захват видео через интерфейс video for linux (v4l2src), вывод видео средствами X (ximagesink). Есть кодировщики и декодировщики множества мультимедийных форматов — я поэкспериментировал с mpeg4video, h263 и theora. Есть средства формирования и разбора потоков RTP. Есть средства автоматического определения формата потока и декодирования (decodebin).
- довольно свежий gstreamer входит в стандартную прошивку OS2008. Для полноты консольной радости нужно установить пакет gstreamer-tools, содержащий утилиты gst-launch и gst-inspect.
Отлично.
Первая попытка
[n810]$ gst-launch -v v4l2src ! \ capsfilter caps="video/x-raw-yuv, format=(fourcc)UYVY, framerate=(fraction)8/1, width=(int)640, height=(int)480" ! \ autovideosink
Фильтр capsfilter задает параметры видеозахвата. Их можно менять в разумных пределах, если видео невозможно захватить с такими параметрами, gstreamer пишет ближайшие допустимые.
Передача по сети
Хорошо было бы теперь передать это по сети. Простейший вариант выглядит так (IP машины desktop 192.168.1.254):
[desktop]$ gst-launch -v tcpserversrc host=0.0.0.0 protocol=gdp ! autovideosink [n810]$ gst-launch -v v4l2src ! \ capsfilter caps="video/x-raw-yuv, format=(fourcc)UYVY, framerate=(fraction)8/1, width=(int)320, height=(int)240" ! \ tcpclientsink host=192.168.1.254 protocol=gdp
Параметр protocol=gdp добавляет к данным передаваемым по сети формат потока: дело в том, что в цепочку могут быть объединены только фильтры, имеющие выход и вход совместимого формата. tcp*src с этим параметром на приемной стороне имеет на выходе тот же формат, что и tcp*sink на передающей стороне на входе.
Простое решение, но через wifi работает тяжко: 7 мегабит, 600 пакетов в секунду — ощутимая нагрузка. 640х480 уже заметно тормозит.
Очевидно, следующий шаг — добавить сжатие.
Пусть это будет mpeg4:
[desktop]$ gst-launch -v tcpserversrc host=0.0.0.0 protocol=gdp ! decodebin ! autovideosink [n810]$ gst-launch -v v4l2src ! \ capsfilter caps="video/x-raw-yuv, format=(fourcc)UYVY, framerate=(fraction)8/1, width=(int)320, height=(int)240" ! \ hantro4200enc ! tcpclientsink host=192.168.1.254 protocol=gdp
Отлично, всё в mpeg-кубиках, но 110 килобит и 30 пакетов в секунду (:
Какие еще существенные минусы этой схемы? TCP/IP: потеря пакетов приводит к повторной передаче уже неактуальной картинки, а значит к задержкам. А разрыв соединения лечится только перезапуском сервера и клиента.
RTP
Значит нужно прикрутить RTP:
[desktop]$ gst-launch -v gstrtpbin name=rtpbin \ udpsrc caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H263" port=5000 ! \ rtpbin.recv_rtp_sink_0 rtpbin. ! \ rtph263depay ! decodebin ! autovideosink [n810]$ gst-launch -v gstrtpbin name=rtpbin \ v4l2src ! \ capsfilter caps="video/x-raw-yuv, format=(fourcc)UYVY, framerate=(fraction)8/1, width=(int)320, height=(int)240" ! \ hantro4200enc stream-type=5 bit-rate=512 ! rtph263pay ! \ rtpbin.send_rtp_sink_0 rtpbin.send_rtp_src_0 ! \ udpsink port=5000 host=192.168.1.254
Что изменилось?
- mpeg4 превратился в h263. Почему-то ffmpeg с десктопной машины не смог расшифровать присылаемые кадры от hantro4200. На передающей стороне это выразилось параметром stream-type=5. Чтобы было меньше кубиков добавился bit-rate=512.
- Добавился rtpbin, используемый через именованные входы и выходы — наше видео идет по нулевому каналу. Конверсию сжатого видеопотока в RTP и обратно выполнили rtph263pay и rtph263depay.
- tcp превратился в udp. На приемной стороне caps="..." вобрал в себя недостающую для восстановления потока информацию; эту строчку напечатал rtph263pay на передающей стороне.
Какой эффект?
- Временная потеря связи не рвет соединения. Соединения-то нет (:
- Просмотр можно останавливать и перезапускать. На сервер видео это никак не влияет.
- Опоздавшие кадры не тормозят показ кадров пришедших вовремя.
Что осталось?
- Непонятные трения между кодировщиками: mpeg4video через RTP не просматривается. Сжатие с помощью theora требует конверсии цветов, но цепочка
v4l2src ! capsfilter ! ffmpegcolorspace ! theoraenc
дает на выходе черный квадрат. При этом просмотр видео закодированного theora проблем не вызывает. - Может быть прикрутить multicasting. В моей конфигурации он конечно пока не нужен. Но было бы забавно посмотреть.
- Сегодня в Питере дождь. Для змея погода нелётная. Ждём солнца и ветра (:
Справка по плагинам gstreamer на официальном сайте: gstreamer.freedesktop.org/documentation
Список установленных плагинов и справка по их параметрам — gst-inspect
P.S. Получилась эдакая хвалебная ода gstreamer'у. Откровенно порадовал инструмент (: