在Cubieboard上用USB WebCam 來做 real-time video streaming

在Cubieboard上用USB WebCam 來做 real-time video streaming

想法

手上的CubieTruck 板子是用Allwinner A20的CPU, 其內部有一個A hardware video unit (VE), 可以用來做Video Encoder/Decoder. 看了一些sunxi 社群的資料CedarX, 及一些網站上的討論, 就手癢也來開始玩玩, 目標是將USB WebCam 抓下來的影像, 即時用H.264 硬體壓縮, 再 stream 出去. 在client 端, 我用VLC 來收看這個real-time 的 live video.

Linux Kernel

首先要使用CedarX 的Encoder, 在linux kernel 中要有sunxi_mem 及 cedar driver. 目前sunxi-linux 只有整合cedar driver, 但是並沒有把sunxi_mem driver 整合進去, 所以參考了juanfont的patch, 將其加入到sunxi-linux 的最新kenel source 中.
並且在kernel config 中確認有下列設定:

CONFIG_SUNXI_PHYS_MEM_ALLOCATOR=y
CONFIG_VIDEO_SUNXI_CEDAR=m

然後編譯linux kernel.

我已在這篇文章“從source code 開始打造最基本的Debian linux system” 提到的script 中加入sunxi_mem driver 的支援, 所以有興趣的人, 可以到GitHub這裏 中抓取這些script 來build linux kernel 比較快..

啟用kernel module.

做好kernel image 後, 將其放入你原有的root file system 中, 並且在/etc/modules 加入此行:

sunxi_cedar_mod

然後啟動linux, 請確認在/dev中有下列兩個device

# ls /dev/cedar_dev /dev/sunxi_mem     
/dev/cedar_dev  /dev/sunxi_mem 

若出現這兩個device, 表示你的linux kernel 是ok的了.

若要讓一般user 也能有access 這兩個device 的權限, 請修改/etc/udev 的內容如下:

echo 'KERNEL=="sunxi_mem", MODE="0666"' >> /etc/udev/rules.d/80-cedar.rules
echo 'KERNEL=="cedar_dev", MODE="0666"' >> /etc/udev/rules.d/80-cedar.rules

順便也將USB webcam 的裝置也改成讓一般user 也能access.

echo 'KERNEL=="video?", SUBSYSTEM=="video4linux", MODE="0666"' >> /etc/udev/rules.d/81-v4l2.rules

編譯 libav

libav 是從ffmpeg fork 出來的project, 他也可以說是ffmpeg 的後繼. 它具有跟ffmepg 一樣的功能, 及非常相似的命令參數. 他也可以拿來做 live video stream . 目前許多linux distribution 已經將libav納入其official packages中了. 只是目前libav 及ffmpeg 不提供A20 VE 的支援.

但是網路總有神人出現. alcantor 的實作, 他已經提供libav 的patch file , 可以使用A20 CedarX 的hardware encoder., 所以我也依樣畫葫蘆做了一遍.

要在CubieTruck 板子中Debian 要編譯libav 需要先安裝 libx264-dev libmp3lame-dev libfaac-dev 這些library. 只是libfaac-dev 並不在official package list 中.
目前是由 deb-multimedia來maintain.

所以先將deb-multimedia 納入apt 的source list中, 作法如下:

# echo "deb http://www.deb-multimedia.org wheezy main non-free" >> /etc/apt/sources.list
# echo "deb http://www.deb-multimedia.org wheezy-backports main" >> /etc/apt/sources.list
# apt-get update
# apt-get install deb-multimedia-keyring

然後安裝 libx264-dev libmp3lame-dev libfaac-dev packages

# apt-get update
# apt-get install libx264-dev libmp3lame-dev libfaac-dev 

若是在x86的環境下, 還需要安裝 yasm 這個package, 但由於目前是在ARM的環境中編譯libav, 所以就不用裝這個套件啦.

若是想要順便編譯avplay程式, 還需要安裝SDL library.

# apt-get install libsdl1.2-dev

接下來就是抓取libav 的source code, sunxi-armhf libcedarv binaries 及其header file.
然後加上這個libav 的patch. 詳細步驟請參考alcantor 的實作. 在這裡, 我已經將這些source code 整合到這個GitHub 的repository了, 所以步驟簡化如下:

# git clone https://github.com/haotseng/libav.git -b A20-cedar
# cd libav
# ./configure --enable-nonfree --enable-gpl --enable-vdpau --enable-libx264 --enable-libmp3lame --enable-libfaac
# make -j2

編譯完後, 就可以開始測試avconv 是否能用.

測試 libav 的 avconv

我使用的是Microsoft 的 Microsoft® LifeCam HD-3000. 插入USB WebCam 後, 先確認是否有支援此USB webcam.

# ls /dev/video?
/dev/video0

# v4l2-ctl --all
Driver Info (not using libv4l2):
    Driver name   : uvcvideo
    Card type     : Microsoft® LifeCam HD-3000
    Bus info      : usb-sw-ehci-1
    Driver version: 3.4.103
    Capabilities  : 0x04000001
        Video Capture
        Streaming
Format Video Capture:
    Width/Height  : 640/480
    Pixel Format  : 'YUYV'
    Field         : None
    Bytes per Line: 1280
    Size Image    : 68392364
    Colorspace    : SRGB
Crop Capability Video Capture:
    Bounds      : Left 0, Top 0, Width 640, Height 480
    Default     : Left 0, Top 0, Width 640, Height 480
    Pixel Aspect: 1/1
Video input : 0 (Camera 1: ok)
Streaming Parameters Video Capture:
    Capabilities     : timeperframe
    Frames per second: 0.009 (71/7635)
    Read buffers     : 0

使用avconv 來擷取WebCam 的Video 並且使用硬體壓縮成H2.64格式

# cd libav
# LD_LIBRARY_PATH=sunxicedar/lib/A20-sunxi-rt ./avconv -y -f video4linux2 -s 640x480 -r 30 -i /dev/video0 -filter:v pad="trunc((iw+0)/32)*32:ih:0:0" -c:v cedarh264 -f mp4 test.mp4

這時就開始錄製mp4 檔案了, 若要停止, 請按ctrl-c 結束. 把test.mp4 copy 到你的PC 來看看, 是否有錄製成功.

開始做 live video stream

avconv 支援即時串流協定(RTSP), 要使用之前, 要先產生SDP file, 假設你的client 端PC 的IP address 為 192.168.1.1, 則產生方式如下:

# cd libav
# LD_LIBRARY_PATH=sunxicedar/lib/A20-sunxi-rt ./avconv -y -f video4linux2 -s 640x480 -r 30 -i /dev/video0 -filter:v pad="trunc((iw+0)/32)*32:ih:0:0" -c:v cedarh264 -f rtp rtp://192.168.7.139:1234

avconv version v12_dev0-653-g64019ad, Copyright (c) 2000-2015 the Libav developers
  built on Jan  9 2015 13:49:33 with gcc 4.6 (Debian 4.6.3-14)
[video4linux2 @ 0x237f100] Estimating duration from bitrate, this may be inaccurate
Input #0, video4linux2, from '/dev/video0':
  Duration: N/A, start: 87106.926535, bitrate: 147456 kb/s
    Stream #0:0: Video: rawvideo [YUY2 / 0x32595559]
      yuyv422, 640x480, 147456 kb/s
      30 fps, 1000k tbn
[cedarh264 @ 0x2381340] cedarx_hardware_init
D/cedarv_osal_linux: (177) use sunxi_alloc_open
D/cedarv_osal_linux: (321) init hw ref count:1
D/cedarv_osal_linux: (523) cedar_sys_phymalloc_map
D/cedarv_osal_linux: (528) cedar_sys_phymalloc_map2
D/cedarv_osal_linux: (523) cedar_sys_phymalloc_map
D/cedarv_osal_linux: (528) cedar_sys_phymalloc_map2
D/cedarv_osal_linux: (523) cedar_sys_phymalloc_map
D/cedarv_osal_linux: (528) cedar_sys_phymalloc_map2
D/cedarv_osal_linux: (523) cedar_sys_phymalloc_map
D/cedarv_osal_linux: (528) cedar_sys_phymalloc_map2
D/venc: (232) venc_ctx->base_cfg.codectype = 0
D/cedarv_osal_linux: (523) cedar_sys_phymalloc_map
D/cedarv_osal_linux: (528) cedar_sys_phymalloc_map2
D/cedarv_osal_linux: (523) cedar_sys_phymalloc_map
D/cedarv_osal_linux: (528) cedar_sys_phymalloc_map2
D/cedarv_osal_linux: (523) cedar_sys_phymalloc_map
D/cedarv_osal_linux: (528) cedar_sys_phymalloc_map2
D/cedarv_osal_linux: (523) cedar_sys_phymalloc_map
D/cedarv_osal_linux: (528) cedar_sys_phymalloc_map2
D/cedarv_osal_linux: (523) cedar_sys_phymalloc_map
D/cedarv_osal_linux: (528) cedar_sys_phymalloc_map2
D/cedarv_osal_linux: (523) cedar_sys_phymalloc_map
D/cedarv_osal_linux: (528) cedar_sys_phymalloc_map2
[cedarh264 @ 0x2381340] Input Stream: 640x480@30 fps encode at 200000 bits/s
Output #0, rtp, to 'rtp://192.168.1.1:1234':
  Metadata:
    encoder         : Lavf56.11.0
    Stream #0:0: Video: libx264
      yuv420p, 640x480, q=2-31, 200 kb/s
      30 fps, 90k tbn, 30 tbc
    Metadata:
      encoder         : Lavc56.11.0 cedarh264
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (cedarh264))
SDP:
v=0
o=- 0 0 IN IP4 192.168.1.1
s=No Name
c=IN IP4 192.168.1.1
t=0 0
a=tool:libavformat 56.11.0
m=video 1234 RTP/AVP 96
b=AS:200
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z0IAH+VAUB7I,aM4xEg==; profile-level-id=42001F

Press ctrl-c to stop encoding
frame=   93 fps=  8 q=-1.0 size=      82kB time=3.07 bitrate= 218.4kbits/s    

注意畫面中”SDP:” 以下的文字

v=0
o=- 0 0 IN IP4 192.168.1.1
s=No Name
c=IN IP4 192.168.1.1
t=0 0
a=tool:libavformat 56.11.0
m=video 1234 RTP/AVP 96
b=AS:200
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z0IAH+VAUB7I,aM4xEg==; profile-level-id=42001F

按下ctrl-c , 中斷avconv程式.
將此段文字擷取下來, 存成my_video_stream.sdp, copy 到你的PC 端中.
在你的PC 端, 使用VLC 來開啟my_video_stream.sdp 檔.
然後在CubieTruck 板子上再次執行

# LD_LIBRARY_PATH=sunxicedar/lib/A20-sunxi-rt ./avconv -y -f video4linux2 -s 640x480 -r 30 -i /dev/video0 -filter:v pad="trunc((iw+0)/32)*32:ih:0:0" -c:v cedarh264 -f rtp rtp://192.168.7.139:1234

大約10秒後, PC 端的VLC 就可以看到即時的影像了.


參考資料

  1. avconv H.264 Hardware encoding mit Cubietruck (Mediatomb transcoding)
  2. Streaming Video using RTP on the Beaglebone Black
  3. ffmpeg/avconv使用学习笔记
  4. ffmpeg/avconv 轉檔與影片連接範例
  5. avconv Documentation
  6. ffmpeg H264 encoding with cedrus
  7. VLC 建立 RTSP 串流伺服器
  8. H.264的SPS和PPS串 第一个字节的低5位判断是否为7(sps)或者8(pps)
  9. 在 Linux 以 VLC 搭配 Jtvlc 進行實況
  10. SDP (Session Description Protocol) 閱讀心得
  11. Raspberry Pi camera RTSP 影像串流
  12. 即時串流協定
  13. Advanced streaming using the command line
  14. Streaming webcam audio and video using ffmpeg/avconv
  15. How to stream video from webcam to network with ffmpeg?
This entry was posted in embedded system, MultiMedia and tagged , , , , , . Bookmark the permalink.

3 Responses to 在Cubieboard上用USB WebCam 來做 real-time video streaming

  1. sshchen64 says:

    您好

    請問 只有 client 端PC (192.168.1.1) 能打開my_video_stream.sdp 檔,其他 IP 的client 端PC 不能使用嗎?

    • hao says:

      以這個例子來說, 是的, 他是傳送到指定的IP, 所以只有192.168.1.1 能夠收到.

      若是想要讓其他的人也能收到. 我以前有實做過兩階段轉送影像.
      (1)同上方法, 傳送到192.168.1.1
      (2)在192.168.1.1 利用VLC收到即時影像後, 再轉成RTSP server.

      如此就可以讓任何人連到RTSP server 來觀看即時串流影像了

    • hao says:

      補充說明, 上述的步驟1, 及步驟2, 都是在同一台機器上跑. 不需要2台機器.
      基本上拿VLC 當作RTSP server , 而且串流格式不做修改, 對於CPU 的loading 還算OK, 所以當時就直接用同一台Cubieboard 來完成此功能了

Leave a Reply

Your email address will not be published. Required fields are marked *