以前、mjpg_streamer を使っていた時に、UVC カメラで MJPEG で配信できた気がするのにできなくなりました
症状としては、mjpg_streamer コマンドは MJPEG で起動できるが画像が表示されない
環境としては、 x86 のマシンから raspberry pi に移ってはいるし、3年くらい経過はしている
他のサイトとか調べてみると
MJPEG を使えないなら YUYV にする -y オプションを付けろ
というサイトばかりでした。
カメラ自体も V4L2 でドライブレコーダーデーモン書いた時は MJPEG 使えていたので・・・
この苦労を覚書として書いておきます
環境
使っているカメラは以前と同じで下記の通り
$ sudo v4l2-ctl --info Driver Info (not using libv4l2): Driver name : uvcvideo Card type : UCAM-DLX300B Bus info : usb-3f980000.usb-1.3 Driver version: 4.1.6 Capabilities : 0x84200001 Video Capture Streaming Device Capabilities Device Caps : 0x04200001 Video Capture Streaming
ELECOM のこちらのカメラで、もう売ってません・・・
今回のマシンは raspbian で Raspberry Pi 2 model b です
インストールしたが動かない
まずは、mjpg_streamer のインストール
$ svn co http://svn.code.sf.net/p/mjpg-streamer/code/mjpg-streamer mjpg-streamer $ cd mjpg-streamer
mjpg-streamer には scripts/make_dep.sh という dep パッケージを作成するスクリプトが入ってます
ですが、そのままでは MJPEG が使えません
MJPEG は video4linux2 でないと取得できないのですが、
そのままの make_dep.sh では video4linux2 が使われません
$ vi script/make_dep.sh
このため、改造
#!/bin/sh # update via SVN svn up # find out the current revision SVNVERSION="$(export LANG=C && export LC_ALL=C && echo $(svn info | awk '/^Revision:/ { print $2 }'))" # use checkinstall to create the DEB package sudo checkinstall -D \ --pkgname "mjpg-streamer" \ --pkgversion "r$SVNVERSION" \ --pkgrelease "1" \ --maintainer "tom_stoeveken@users.sourceforge.net" \ --requires "libjpeg62" \ --nodoc \ make USE_LIBV4L2=true DESTDIR=/usr install
改造結果は上記の通り
USE_LIBV4L2=true
を付けるだけ
$ sudo dpkg -r mjpg-streamer $ make clean $ sudo sh scripts/make_dep.sh
そして、上記コマンドでインストール
$ sudo /usr/bin/mjpg_streamer -i "/usr/lib/input_uvc.so -d /dev/video0 -r 320x240 -f 3 -n" -o "/usr/lib/output_http.so -p 8080 -w /usr/www"
と実行しても YUYV でしか取得できません
違うコマンドで MJPEG を取得
MJPEG を取得できる CUI コマンドとして fswebcam があります
$ sudo fswebcam -p MJPEG -v --log hoge.log a.jpg
と実行してみると、MJPEG で取得できてるし、画像も問題なし
つまり、mjpg-streamer がオカシイのがわかりました
まぁ、自分でCで書いたドライブレコーダープログラムでは動いていたし…
パッチを発見
日本語のサイトでは、YUYV オプションを使えというのしか出てきません
諦めかけたところ、こちらの Raspberry Pi のフォーラムで MJPEG で配信できない問題が議論されてました
使っている Raspbian のカーネルのバージョンは 4.1.6-v7+ なので、該当するであろうと考え、パッチを当ててみると
$ cd mjpg-streamer/plugins/input_uvc $ vi input_uvc.patch # クリップボードでパッチの本文をコピー $ patch -p2 input_uvc.patch (Patch is indented 4 spaces.) patching file input_uvc.c (Patch is indented 4 spaces.) patching file v4l2uvc.c (Patch is indented 4 spaces.) patching file v4l2uvc.h
パッチ自体はこちら
--- plugins/input_uvc/input_uvc.c (revision 174) +++ plugins/input_uvc/input_uvc.c (working copy) @@ -405,9 +405,13 @@ if(pcontext->videoIn->formatIn == V4L2_PIX_FMT_YUYV) { DBG("compressing frame from input: %d\n", (int)pcontext->id); pglobal->in[pcontext->id].size = compress_yuyv_to_jpeg(pcontext->videoIn, pglobal->in[pcontext->id].buf, pcontext->videoIn->framesizeIn, gquality); + /* copy this frame's timestamp to user space */ + pglobal->in[pcontext->id].timestamp = pcontext->videoIn->buf.timestamp; } else { DBG("copying frame from input: %d\n", (int)pcontext->id); - pglobal->in[pcontext->id].size = memcpy_picture(pglobal->in[pcontext->id].buf, pcontext->videoIn->tmpbuffer, pcontext->videoIn->buf.bytesused); + pglobal->in[pcontext->id].size = memcpy_picture(pglobal->in[pcontext->id].buf, pcontext->videoIn->tmpbuffer, pcontext->videoIn->tmpbytesused); + /* copy this frame's timestamp to user space */ + pglobal->in[pcontext->id].timestamp = pcontext->videoIn->tmptimestamp; } #if 0 @@ -418,8 +422,6 @@ prev_size = global->size; #endif - /* copy this frame's timestamp to user space */ - pglobal->in[pcontext->id].timestamp = pcontext->videoIn->buf.timestamp; /* signal fresh_frame */ pthread_cond_broadcast(&pglobal->in[pcontext->id].db_update); Index: plugins/input_uvc/v4l2uvc.c =================================================================== --- plugins/input_uvc/v4l2uvc.c (revision 174) +++ plugins/input_uvc/v4l2uvc.c (working copy) @@ -450,6 +450,8 @@ */ memcpy(vd->tmpbuffer, vd->mem[vd->buf.index], vd->buf.bytesused); + vd->tmpbytesused = vd->buf.bytesused; + vd->tmptimestamp = vd->buf.timestamp; if(debug) fprintf(stderr, "bytes in used %d \n", vd->buf.bytesused); Index: plugins/input_uvc/v4l2uvc.h =================================================================== --- plugins/input_uvc/v4l2uvc.h (revision 174) +++ plugins/input_uvc/v4l2uvc.h (working copy) @@ -28,6 +28,7 @@ #include <stdio.h> +#include <stdint.h> #include <string.h> #include <fcntl.h> #include <unistd.h> @@ -105,6 +106,8 @@ int framecount; int recordstart; int recordtime; + uint32_t tmpbytesused; + struct timeval tmptimestamp; }; /* context of each camera thread */
$ cd ../../ $ make clean $ dpkg -r mjpg_streamer $ sudo sh scripts/make_dep.sh
あとは、dep ファイルを作成し、インストール
起動してみたら無事動いた!
リソース消費確認
YUYV だと 640×480 を 3FPS で取得しようとすると、CPU リソースを 20%消費してましたが、
MJPEG にした途端 6FPS でも 5% くらいになりました
スマホで見る
Androidなら CamBuddy と言うアプリが使えます
アプリ設定のURL に
http://example.com:8080/?action=stream
のようにすればストリームで閲覧できます!
正解です!
ありがとうございます。