Pull to refresh

Трансляция h264 видео без перекодирования с камеры Logitech C920

Reading time 12 min
Views 23K


Задержка составила не более 0.3 секунды, с учетом того что камера подключена к слабому BeagleBone Blue с загрузкой процессора не более 30% и передачей потока видео через wifi роутер на ноутбук.

Изначально стояла задача транслировать видео с робота на большой компьютер без загрузки процессора на роботе и без задержек. В процессе гугления камер и программ для этой задачи было найдено что есть камеры с аппаратным кодирование видео на самой камере, после этого была приобретена камера Logitech C920. И начались тесты и эксперименты, в ходе которых найдены два варианта трансляции без перекодирования.

Все дальнейшие действия проверены на Ubuntu 16.04, второй вариант возможно работает в Windows

Трансляция аппаратно кодированного видео с камеры Logitech C920 через cvlc и v4l2


clvc — сервер трансляции видео через vlc из командной строки.

Аппаратное кодирование видеопотока


Установить pixelformat камеры в H264

v4l2-ctl --device=/dev/video1 --set-fmt-video=width=800,height=600,pixelformat=1

Протестировать H264 с помощью vlc, таким образом он не сбросит настройки:

cvlc v4l2:///dev/video1 --demux h264

Если вы попробуете это, vlc сбросит настройки перед воспроизведением:

cvlc v4l2:///dev/video1:chroma=h264

Воспроизведение работает. Мы получаем поток H264 с камеры. Теперь давайте передадим по сети через HTTP:

cvlc v4l2:///dev/video1:chroma=h264:width=800:height=600 --sout '#standard{access=http,mux=ts,dst=localhost:8080,name=stream,mime=video/ts}' -vvv

(в сети вам необходимо использовать IP-адрес вашего локального устройства вместо localhost)

Запуск приемника:

mplayer http://localhost:8080/

Получается, MPEG-TS позволяет mplayer подключаться к потоку в любое время с небольшой задержкой (вероятно, ждет ключевой кадр или sth).

Если вы используете mux = avi, mime = video / avi, вам нужно запустить mplayer в тот момент, когда вы запускаете vlc, иначе mplayer не начнет играть.

Ошибка ffmpeg


  • Если вы попробуете ffmpeg вместо vlc для воспроизведения, вы, вероятно, столкнетесь с этой проблемой: ffmpeg.org/trac/ffmpeg/ticket/1387
  • Как только вы запустите ffmpeg, он переключится на «Видео: rawvideo (YUY2 / 0x32595559)»
  • В то время когда он принимает MJPEG, он не будет работать с H.264
  • То же самое происходит при использовании qv4l2: начало захвата в режиме H264 фактически дает вам видеоокно YUY2

Воспроизведение аппаратного декодированного видео


Mplayer способен воспроизводить фреймбуфер, убедитесь, что X не работает и введите:

mplayer http://192.168.1.100:8080/ -fs -framedrop -vo fbdev

Вы также можете воспроизводить в X window, если хотите: запустить X из командной строки:

Xorg -retro &> /dev/zero

Есть масса сообщений об ошибках fbdev, которые мы молча отбрасываем в /dev/zero

Воспроизведение видеопотока из источника LAN vlc (см. раздел выше):

DISPLAY=":0" mplayer http://192.168.1.100:8080/ -fs -framedrop

  • Если мы это сделаем, мы заметим, что мы пока не используем Xvideo или любое аппаратное ускорение
  • linux-sunxi.org/CedarX, похоже, предоставляет нам библиотеку VPU, которая, к сожалению, является незащищенной вещью Allwinner
  • Но существует взломанный VLC, который может его использовать: linux-sunxi.org/VLC
  • Скомпилировано успешно

Raspberry Pi


В случае, если вы испытываете артефакты на картинке, а потоки из Raspberry Pi используют:

cvlc v4l2:///dev/video0:chroma=h264 ...

Вам может потребоваться обновить прошивку:

apt-get install rpi-update raspi-config
rpi-update
reboot

Резюме по трансляции через cvlc и v4l2


Тесты показали что загрузка процессора на Beaglebone Blue составляет не более 30%, что очень хорошо для слабого процессора, но не понятно как это видео потом затолкнуть в ROS.

Если пропускного канала wifi не хватает то, задержка видео сильно возрастает, по идее это можно решить переходом с tcp на udp, в документации по cvlc упоминается о возможности трансляции по udp.

Трансляция аппаратно кодированного видео с камеры Logitech C920 через Gstreamer


Оригинальная статья разработчика поддержки этого метода в Gstreamer.
Установка gstreamer на Ubuntu 16.04

sudo apt-get install libgstreamer1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools
sudo apt-get install libgstreamer-plugins-base1.0-dev

Источник uvch264src позволяет:


  • Одновременно захватывать аппаратно кодированный поток видео h264 и поток видео искателя.
  • Настраивать аппаратное кодирование видео(битрэйт, ключевые кадры и другое)

Вторичный источник видоискателя — интересная концепция. В дополнение к основному потоку H.264 вы получаете вторичный поток с низким разрешением в формате MJPG или YUV. Я не уверен, является ли это особенностью камеры, драйвера или блока источника gstreamer, но я надеюсь, что это будет полезно для наших камер Beaglebone при условии, что функция не использует слишком большой процессор для преобразования между raw и jpg.

Ниже приведен пример конвейера, который отображает поток H.264 с высоким разрешением и поток видоискателя:

gst-launch-1.0 -v -e uvch264src device=/dev/video0 name=src auto-start=true src.vfsrc ! queue ! video/x-raw,format=YUY2,width=320,height=240,framerate=10/1 ! xvimagesink sync=false src.vidsrc ! queue ! video/x-h264,width=1280,height=720,framerate=30/1 ! h264parse ! avdec_h264 ! xvimagesink sync=false

Первичный поток H.264 декодируется с использованием блока avdec_h264, доступного через пакет gst-libav, см. заметки в вики oz9aec. Панель видоискателя может быть подключена к фейклинку, если она не нужна, но я не думаю, что ее можно отключить(отключить все таки можно). По крайней мере, это впечатление, что я читаю оригинальный пост в блоге KaKaRoTo.

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

gst-inspect-1.0 uvch264src

Список параметров uvch264src
Factory Details:
Rank none (0)
Long-name UVC H264 Source
Klass Source/Video
Description UVC H264 Encoding camera source
Author Youness Alaoui <youness.alaoui@collabora.co.uk>

Plugin Details:
Name uvch264
Description UVC compliant H264 encoding cameras plugin
Filename /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstuvch264.so
Version 1.8.3
License LGPL
Source module gst-plugins-bad
Source release date 2016-08-19
Binary package GStreamer Bad Plugins (Ubuntu)
Origin URL launchpad.net/distros/ubuntu/+source/gst-plugins-bad1.0

GObject
+----GInitiallyUnowned
+----GstObject
+----GstElement
+----GstBin
+----GstBaseCameraSrc
+----GstUvcH264Src

Реализованные интерфейсы:
GstChildProxy

Pad Templates:
SRC template: 'vidsrc'
Availability: Always
Capabilities:
video/x-raw
format: { I420, YV12, YUY2, UYVY, AYUV, RGBx, BGRx, xRGB, xBGR, RGBA, BGRA, ARGB, ABGR, RGB, BGR, Y41B, Y42B, YVYU, Y444, v210, v216, NV12, NV21, NV16, NV61, NV24, GRAY8, GRAY16_BE, GRAY16_LE, v308, RGB16, BGR16, RGB15, BGR15, UYVP, A420, RGB8P, YUV9, YVU9, IYU1, ARGB64, AYUV64, r210, I420_10LE, I420_10BE, I422_10LE, I422_10BE, Y444_10LE, Y444_10BE, GBR, GBR_10LE, GBR_10BE, NV12_64Z32, A420_10LE, A420_10BE, A422_10LE, A422_10BE, A444_10LE, A444_10BE }
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]
image/jpeg
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]
video/x-h264
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]
stream-format: { byte-stream, avc }
alignment: au
profile: { high, main, baseline, constrained-baseline }

SRC template: 'imgsrc'
Availability: Always
Capabilities:
EMPTY

SRC template: 'vfsrc'
Availability: Always
Capabilities:
video/x-raw
format: { I420, YV12, YUY2, UYVY, AYUV, RGBx, BGRx, xRGB, xBGR, RGBA, BGRA, ARGB, ABGR, RGB, BGR, Y41B, Y42B, YVYU, Y444, v210, v216, NV12, NV21, NV16, NV61, NV24, GRAY8, GRAY16_BE, GRAY16_LE, v308, RGB16, BGR16, RGB15, BGR15, UYVP, A420, RGB8P, YUV9, YVU9, IYU1, ARGB64, AYUV64, r210, I420_10LE, I420_10BE, I422_10LE, I422_10BE, Y444_10LE, Y444_10BE, GBR, GBR_10LE, GBR_10BE, NV12_64Z32, A420_10LE, A420_10BE, A422_10LE, A422_10BE, A444_10LE, A444_10BE }
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]
image/jpeg
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]

Element Flags:
no flags set

Bin Flags:
no flags set

Element Implementation:
Has change_state() function: 0x7ff438f22ba0

Element has no clocking capabilities.
Element has no URI handling capabilities.

Pads:
SRC: 'vfsrc'
SRC: 'imgsrc'
SRC: 'vidsrc'

Element Properties:
name: The name of the object
flags: считываемый, записываемый
String. Default: «uvch264src0»
parent: The parent of the object
flags: считываемый, записываемый
Object of type «GstObject»
async-handling: The bin will handle Asynchronous state changes
flags: считываемый, записываемый
Boolean. Default: false
message-forward: Forwards all children messages
flags: считываемый, записываемый
Boolean. Default: false
mode: The capture mode (still image capture or video recording)
flags: считываемый, записываемый
Enum «GstCameraBin2Mode» Default: 2, «mode-video»
(1): mode-image — Still image capture (default)
(2): mode-video — Video recording
zoom: Digital zoom factor (e.g. 1.5 means 1.5x)
flags: считываемый, записываемый
Float. Range: 1 — 3,402823e+38 Default: 1
max-zoom: Digital zoom factor (e.g. 1.5 means 1.5x)
flags: считываемый
Float. Range: 1 — 3,402823e+38 Default: 10
ready-for-capture: Informs this element is ready for starting another capture
flags: считываемый
Boolean. Default: true
post-previews: If capture preview images should be posted to the bus
flags: считываемый, записываемый
Boolean. Default: true
preview-caps: The caps of the preview image to be posted (NULL means ANY)
flags: считываемый, записываемый
ANY

preview-filter: A custom preview filter to process preview image data
flags: считываемый, записываемый
Object of type «GstElement»
auto-start: Automatically starts capture when going to the PAUSED state
flags: считываемый, записываемый
Boolean. Default: false
colorspace-name: The name of the colorspace element
flags: считываемый, записываемый, может быть равно только состоянию NULL или READY
String. Default: «videoconvert»
jpeg-decoder-name: The name of the jpeg decoder element
flags: считываемый, записываемый, может быть равно только состоянию NULL или READY
String. Default: «jpegdec»
num-clock-samples: Number of clock samples to gather for the PTS synchronization (-1 = unlimited)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Integer. Range: 0 — 2147483647 Default: 0
num-buffers: Number of buffers to output before sending EOS (-1 = unlimited)
flags: считываемый, записываемый
Integer. Range: -1 — 2147483647 Default: -1
device: Device location
flags: считываемый, записываемый
String. Default: "/dev/video0"
device-name: Name of the device
flags: считываемый
String. Default: ""
initial-bitrate: Initial bitrate in bits/second (static control)
flags: считываемый, записываемый, может быть равно только состоянию NULL или READY
Unsigned Integer. Range: 0 — 4294967295 Default: 3000000
slice-units: Slice units (static control)
flags: считываемый, записываемый, может быть равно только состоянию NULL или READY
Unsigned Integer. Range: 0 — 65535 Default: 4
slice-mode: Defines the unit of the slice-units property (static control)
flags: считываемый, записываемый, может быть равно только состоянию NULL или READY
Enum «UvcH264SliceMode» Default: 3, «slice/frame»
(0): ignored — Ignored
(1): bits/slice — Bits per slice
(2): MBs/slice — MBs per Slice
(3): slice/frame — Slice Per Frame
iframe-period: Time between IDR frames in milliseconds (static control)
flags: считываемый, записываемый, может быть равно только состоянию NULL или READY
Unsigned Integer. Range: 0 — 65535 Default: 10000
usage-type: The usage type (static control)
flags: считываемый, записываемый, может быть равно только состоянию NULL или READY
Enum «UvcH264UsageType» Default: 1, «realtime»
(1): realtime — Realtime (video conferencing)
(2): broadcast — Broadcast
(3): storage — Storage
(4): ucconfig0 — UCConfig 0
(5): ucconfig1 — UCConfig 1
(6): ucconfig2q — UCConfig 2Q
(7): ucconfig2s — UCConfig 2S
(8): ucconfig3 — UCConfig 3
entropy: Entropy (static control)
flags: считываемый, записываемый, может быть равно только состоянию NULL или READY
Enum «UvcH264Entropy» Default: 0, «cavlc»
(0): cavlc — CAVLC
(1): cabac — CABAC
enable-sei: Enable SEI picture timing (static control)
flags: считываемый, записываемый, может быть равно только состоянию NULL или READY
Boolean. Default: false
num-reorder-frames: Number of B frames between the references frames (static control)
flags: считываемый, записываемый, может быть равно только состоянию NULL или READY
Unsigned Integer. Range: 0 — 255 Default: 0
preview-flipped: Horizontal flipped image for non H.264 streams (static control)
flags: считываемый, записываемый, может быть равно только состоянию NULL или READY
Boolean. Default: false
leaky-bucket-size: Size of the leaky bucket size in milliseconds (static control)
flags: считываемый, записываемый, может быть равно только состоянию NULL или READY
Unsigned Integer. Range: 0 — 65535 Default: 1000
rate-control: Rate control mode (static & dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Enum «UvcH264RateControl» Default: 1, «cbr»
(1): cbr — Constant bit rate
(2): vbr — Variable bit rate
(3): qp — Constant QP
fixed-framerate: Fixed framerate (static & dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Boolean. Default: false
max-mbps: The number of macroblocks per second for the maximum processing rate
flags: считываемый
Unsigned Integer. Range: 0 — 4294967295 Default: 0
level-idc: Level IDC (dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Unsigned Integer. Range: 0 — 255 Default: 40
peak-bitrate: The peak bitrate in bits/second (dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Unsigned Integer. Range: 0 — 4294967295 Default: 3000000
average-bitrate: The average bitrate in bits/second (dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Unsigned Integer. Range: 0 — 4294967295 Default: 3000000
min-iframe-qp: The minimum Quantization step size for I frames (dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Integer. Range: -127 — 127 Default: 10
max-iframe-qp: The minimum Quantization step size for I frames (dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Integer. Range: -127 — 127 Default: 46
min-pframe-qp: The minimum Quantization step size for P frames (dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Integer. Range: -127 — 127 Default: 10
max-pframe-qp: The minimum Quantization step size for P frames (dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Integer. Range: -127 — 127 Default: 46
min-bframe-qp: The minimum Quantization step size for B frames (dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Integer. Range: -127 — 127 Default: 10
max-bframe-qp: The minimum Quantization step size for B frames (dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Integer. Range: -127 — 127 Default: 46
ltr-buffer-size: Total number of Long-Term Reference frames (dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Integer. Range: 0 — 255 Default: 0
ltr-encoder-control: Number of LTR frames the device can control (dynamic control)
flags: считываемый, записываемый, может быть равно состоянию NULL, READY, PAUSED или PLAYING
Integer. Range: 0 — 255 Default: 0

Element Actions:
«get-enum-setting»: gboolean user_function (GstElement* object,
gchararray arg0,
gpointer arg1,
gpointer arg2);
«get-boolean-setting»: gboolean user_function (GstElement* object,
gchararray arg0,
gpointer arg1,
gpointer arg2);
«get-int-setting»: gboolean user_function (GstElement* object,
gchararray arg0,
gpointer arg1,
gpointer arg2,
gpointer arg3);
«start-capture»: void user_function (GstElement* object);
«stop-capture»: void user_function (GstElement* object);

Многие из этих параметров могут использоваться для настройки параметров в сжатии H.264. Я нахожу это довольно удивительным, учитывая, что сжатие выполняется чипом внутри камеры. Следующий пример увеличивает скорость передачи данных по умолчанию от 3 до 5 Мбит/с и уменьшает интервал ключевого кадра по умолчанию от 10 до 3 секунд:

gst-launch-1.0 -v -e uvch264src initial-bitrate=5000000 average-bitrate=5000000 iframe-period=3000 device=/dev/video0 name=src auto-start=true src.vfsrc ! queue ! video/x-raw,format=YUY2,width=320,height=240,framerate=10/1 ! xvimagesink sync=false src.vidsrc ! queue ! video/x-h264,width=1280,height=720,framerate=30/1 ! h264parse ! avdec_h264 ! xvimagesink sync=false

С другой стороны, нет параметров для настройки обычных параметров веб-камеры, таких как контрастность, яркость, фокус и т. Д. Таким образом, для их настройки нам все еще нужны внешние инструменты, такие как v4l2.ctl, или вариант, упомянутый в следующем разделе.

v4l2src


Похоже, мы также можем использовать старый добрый v4l2src для захвата потоков, закодированных H.264, из Logitech C920:

gst-launch-1.0 -v -e v4l2src device=/dev/video1 ! queue ! video/x-h264,width=1280,height=720,framerate=30/1 ! h264parse ! avdec_h264 ! xvimagesink sync=false

Вероятно, это связано с эволюцией как gstreamer, так и V4L2. Эта опция выглядит проще, если вам не нужно изменять параметры сжатия H.264, и это дает нам доступ к настройкам камеры, таким как яркость и контрастность. Это также имеет преимущество в том, что он находится в хорошем пакете плагинов, который может быть лучше сохранен в будущем.

Трансляция по сети через Gstreamer


На принимающем компьютере запускаем приемник:

gst-launch-1.0 -v udpsrc port=6666 ! application/x-rtp, encoding-name=H264 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! autovideosink

На устройстве с камерой запускаем передачу аппаратно кодированного видео:

gst-launch-1.0 uvch264src name=src auto-start=true src.vidsrc ! video/x-h264,width=160,height=120,framerate=30/1 ! h264parse ! rtph264pay ! udpsink host=192.168.1.196 port=6666

За помощь в написании этого кода отдельная благодарность Amomum

Резюме по задержке трансляции видео через Gstreamer


Даже при разрешении 1920*1080 загрузка процессора на Beaglebone Blue не превышала 30%, а задержка видео была не более 0.3 секунды. Да так как видео в этом варианте транслировалось по udp, то при потере пакетов картинка разваливается до следующего ключевого кадра, но мы можем настроить чтобы ключевые кадры отправлялись чаще.

Задачи по ROS


Осталось теперь только запихнуть полученное видео в ROS, если кто может с этим помочь пишите в личку.
Tags:
Hubs:
+19
Comments 20
Comments Comments 20

Articles