KernelコンフィグでUVCカメラを有効にする。
make menuconfig
Kernel
Device Drivers
Multimedia support
media USB Adapters
USB Video Class(UVC)
UVC input events device support
/dev/videoX
ZYBOの場合、Linux起動時にUSBデバイスがいない場合はUSBを認識しないので起動前にデバイスを接続しておく。
ZYBOにログインしてからlsusbを実行して下記のように表示された場合、USBを認識していない。
この場合は、ZYBOのリセットボタンを押しての再起動で認識するようだ。
おそらく、USB PHY(SMSC)のリセット系(OTG_RESETN)を適切に処理していないせいなんだろう。
この辺りはドライバに手を加えなければいけないかもしれないので今は深追いしない。
% lsusb
unable to initialize libusb: -99
または、dmesgすると下記のように表示されている場合はNGの可能性高い。
% dmesg | grep USB
[ 1.121599] ehci_hcd: USB 2.0 ''Enhanced'' Host Controller (EHCI) Driver
[ 1.129572] zynq-dr e0002000.ps7-usb: Unable to init USB phy, missing?
[ 1.161156] USB Video Class driver (1.1.1)
[ 1.258772] usbhid: USB HID core driver
% lsusb
Bus 001 Device 002: ID 0603:8122 Novatek Microelectronics Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
% dmesg |grep USB
[ 1.121486] ehci_hcd: USB 2.0 ''Enhanced'' Host Controller (EHCI) Driver
[ 1.131160] Found SMSC USB3320 ULPI transceiver.
[ 1.137335] zynq-ehci zynq-ehci.0: Xilinx Zynq USB EHCI Host Controller
[ 1.142609] zynq-ehci zynq-ehci.0: new USB bus registered, assigned bus number 1
[ 1.192619] zynq-ehci zynq-ehci.0: USB 2.0 started, EHCI 1.00
[ 1.197826] hub 1-0:1.0: USB hub found
[ 1.229694] USB Video Class driver (1.1.1)
[ 1.328594] usbhid: USB HID core driver
[ 1.522664] usb 1-1: new high-speed USB device number 2 using zynq-ehci
% ls /dev/video*
/dev/video0
今回はBUFFALOのBSWHD01を接続しているので認識しているデバイス名を見ると、次のように表示される。
% cat /sys/class/video4linux/video0/name
BUFFALO BSWHD01 Webcam
V4L2のインフォを見てみると次のように表示される。
% v4l2-ctl --info
Driver Info (not using libv4l2):
Driver name : uvcvideo
Card type : BUFFALO BSWHD01 Webcam
Bus info : usb-zynq-ehci.0-1
Driver version: 3.17.0
Capabilities : 0x84000001
Video Capture
Streaming
Device Capabilities
Device Caps : 0x04000001
Video Capture
Streaming
V4L2ドキュメント
http://linuxtv.org/downloads/v4l-dvb-apis/
「Appendix D. Video Capture Example」にサンプルプログラムがあるのでそのまま利用して動作確認をする。
% gcc -o smaple sample.c
% ./sample -d /dev/video0
VIDIOC_REQBUFS error 12, Cannot allocate memory
バッファの取得でエラーが発生する。
これはおかしいのでdmesgで見てみると・・・
約3.7GBの領域をアロケーションしようとしている。
これ、おかしいでしょ?
% dmesg
[ 1118.914251] vmalloc: allocation failure: 3680411648 bytes
[ 1118.918260] sample: page allocation failure: order:0, mode:0x80d2
[ 1118.923073] CPU: 1 PID: 1049 Comm: sample Not tainted 3.17.0-xilinx-dirty #1
[ 1118.928793] [<40013a18>] (unwind_backtrace) from [<40010a84>] (show_stack+0x10/0x14)
[ 1118.935233] [<40010a84>] (show_stack) from [<40431a3c>] (dump_stack+0x80/0xcc)
[ 1118.941109] [<40431a3c>] (dump_stack) from [<40084cec>] (warn_alloc_failed+0xf4/0x120)
[ 1118.947739] [<40084cec>] (warn_alloc_failed) from [<400a90f4>] (__vmalloc_node_range+0x1b8/0x1dc)
[ 1118.955267] [<400a90f4>] (vmalloc_node_range) from [<400a914c>] (vmalloc_node+0x34/0x40)
[ 1118.962363] [<400a914c>] (__vmalloc_node) from [<400a9298>] (vmalloc_user+0x24/0x48)
[ 1118.968819] [<400a9298>] (vmalloc_user) from [<40308acc>] (vb2_vmalloc_alloc+0x48/0xa4)
[ 1118.975505] [<40308acc>] (vb2_vmalloc_alloc) from [<403055d0>] (__vb2_queue_alloc+0xb8/0x2b8)
[ 1118.982701] [<403055d0>] (vb2_queue_alloc) from [<40306f20>] (reqbufs+0x130/0x24c)
[ 1118.989279] [<40306f20>] (__reqbufs) from [<4031434c>] (uvc_alloc_buffers+0x24/0x40)
[ 1118.995719] [<4031434c>] (uvc_alloc_buffers) from [<40315c64>] (uvc_v4l2_do_ioctl+0xbf8/0x101c)
[ 1119.003087] [<40315c64>] (uvc_v4l2_do_ioctl) from [<402fa0f8>] (video_usercopy+0x2d4/0x44c)
[ 1119.010108] [<402fa0f8>] (video_usercopy) from [<402f5660>] (v4l2_ioctl+0x78/0x120)
[ 1119.016472] [<402f5660>] (v4l2_ioctl) from [<400c39e4>] (do_vfs_ioctl+0x534/0x5a0)
[ 1119.022705] [<400c39e4>] (do_vfs_ioctl) from [<400c3a84>] (SyS_ioctl+0x34/0x58)
[ 1119.028679] [<400c3a84>] (SyS_ioctl) from [<4000dfa0>] (ret_fast_syscall+0x0/0x30)
[ 1119.035010] Mem-info:
[ 1119.035889] Normal per-cpu:
[ 1119.037366] CPU 0: hi: 186, btch: 31 usd: 148
[ 1119.040837] CPU 1: hi: 186, btch: 31 usd: 109
[ 1119.044359] active_anon:1003 inactive_anon:78 isolated_anon:0
active_file:5491 inactive_file:4016 isolated_file:0
unevictable:0 dirty:0 writeback:0 unstable:0
free:114645 slab_reclaimable:336 slab_unreclaimable:910
mapped:2700 shmem:134 pagetables:111 bounce:0
free_cma:3257
[ 1119.068138] Normal free:458580kB min:2864kB low:3580kB high:4296kB active_anon:4012kB inactive_anon:312kB active_file:21964kB inactive_file:16064kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:524288kB managed:513160kB mlocked:0kB dirty:0kB writeback:0kB mapped:10800kB shmem:536kB slab_reclaimable:1344kB slab_unreclaimable:3640kB kernel_stack:552kB pagetables:444kB unstable:0kB bounce:0kB free_cma:13028kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[ 1119.108994] lowmem_reserve[]: 0 0 0
[ 1119.111143] Normal: 994kB (UC) 558kB (UM) 2716kB (UEM) 1532kB (UEMC) 864kB (UMC) 11128kB (UMC) 1256kB (M) 2512kB (EC) 11024kB (U) 32048kB (UEM) 109*4096kB (MRC) = 458580kB
[ 1119.125986] 9640 total pagecache pages
[ 1119.128419] 0 pages in swap cache
[ 1119.130414] Swap cache stats: add 0, delete 0, find 0/0
[ 1119.134339] Free swap = 0kB
[ 1119.135881] Total swap = 0kB
[ 1119.150006] 131072 pages of RAM
[ 1119.151758] 115051 free pages
[ 1119.153456] 2782 reserved pages
[ 1119.155228] 1190 slab pages
[ 1119.156703] 277922 pages shared
[ 1119.158526] 0 pages swap cached
サンプルプログラムに与えるパラメータが存在するのだろう。
サンプルプログラムのHelpを見てみる。
% ./sample --help
Usage: ./sample [options]
Version 1.3
Options:
-d | --device name Video device name [/dev/video0]
-h | --help Print this message
-m | --mmap Use memory mapped buffers [default]
-r | --read Use read() calls
-u | --userp Use application allocated buffers
-o | --output Outputs stream to stdout
-f | --format Force format to 640x480 YUYV
-c | --count Number of frames to grab [70]
% ./sample -f
...........................select timeout
-fを付けると動作したようだが・・・
timeoutしてしまうと次のようにbusyで開けなくなる。
稀に正常終了する。
ここはアプリの作り方しだいだから、特に深追いしない。
% ./sample -f
Cannot open ''/dev/video0'': 16, Device or resource busy
下記のパラメータを与えるとエラー無しが比較的多いのでこれでデータを取得。
画像は1枚取れれば十分なので・・・
% ./sample -f -u -o -c 1
そうすると、614400Byteの画像データが取得できた。
640×480×2のYUV4:2:2といったサイズだ。
ImageMagicのconvertでRGB変換できるかと思ったけど、できなかったのでYUV→RGB変換アプリを作成してRGB化してGIMPで確認した。
画像データさえ出来ていれば、表示方法はDirectFBのAPI使えば、ZYBOで表示出きるのでそれで良し。
void main()
{
int fd, fdo;
fd = open("test.data", O_RDWR),
fdo = open("test_rgb.data", O_RDWR | O_CREAT),
unsigned char data[4];
int x,y,z;
float fr, fg, fb;
unsigned char r, g, b;
for(y=0;y<480;y++){
for(x=0;x<640/2;x++){
read(fd, &data, 4),
for(z=0;z<2;z++){
fr = (1.000 data[z2]) + (1.402 * (data[3] -128.0)),
fg = (1.000 data[z2]) - (0.344 (data[1] -128.0)) - (0.714 (data[3] -128.0)),
fb = (1.000 data[z2]) + (1.772 * (data[1] -128.0)),
if(fr < 0) r = 0;
else if(fr > 255) r = 255;
else r = (unsigned char)fr;
if(fg < 0) g = 0;
else if(fg > 255) g = 255;
else g = (unsigned char)fg;
if(fb < 0) b = 0;
else if(fb > 255) b = 255;
else b = (unsigned char)fb;
write(fdo, &r, 1),
write(fdo, &g, 1),
write(fdo, &b, 1),
}
}
close(fdo),
close(fd),
}