ひでみのアイデア帳

くだらないことなんだけど、忘れないために・・・

ZYBOでUSBカメラを使う

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で表示出きるのでそれで良し。


include

include

include

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),

}