みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

recipetoolの使い方(yoctoでmjpg-streamer)

raspberrypiにUVCカメラをつけて、HTTPでストリーミングを行いたいと考えた。 mjpg-streamerを使用することにしたが、 mjpg-streamerはレシピ化されていないため、レシピを自作する必要があった。^1

recipetoolの使用

レシピを作成する場合、ゼロから作成することもできるが、recipetoolを使用して雛形を作成することができる。

recipetoolを実行するにはbitbakeと同様にoe-init-build-envをsourceコマンド等で読み込んでおく必要がある。 作業ディレクトリは%HOME/work/yocto/rpiとする。

$ cd %HOME/work/yocto/rpi
$ source poky/oe-init-build-env build_webcam

mjpg-streamerのレシピを作成するには以下のコマンドを実行する。

$ recipetool create -o mjpg-streamer_git.bb --src-subdir=mjpg-streamer-experimental https://github.com/jacksonliam/mjpg-streamer.git

recipatoolはプロジェクトの中身を解析して、そのプロジェクトで使用しているautomakeやcmakeなどのビルドシステムに対応したレシピの雛形を生成する。 デフォルトではビルドシステムのソースディレクトリ=プロジェクトのルートディレクトリとして解析を行うが、mjpg-streamerではmjpg-streamer-experimentalがソースディレクトリとなっている。 その場合は--src-subdir=mjpg-streamer-experimentalオプションでソースディレクトリを指定することができる。

生成されたレシピは コード 1 のようになる。

コード 1: recipetoolで生成されたレシピ
# Recipe created by recipetool
# This is the basis of a recipe and may need further editing in order to be fully functional.
# (Feel free to remove these comments when editing.)
#
# WARNING: the following LICENSE and LIC_FILES_CHKSUM values are best guesses - it is
# your responsibility to verify that the values are complete and correct.
#
# NOTE: multiple licenses have been detected; if that is correct you should separate
# these in the LICENSE value using & if the multiple licenses all apply, or | if there
# is a choice between the multiple licenses. If in doubt, check the accompanying
# documentation to determine which situation is applicable.
LICENSE = "GPLv2 Unknown"
LIC_FILES_CHKSUM = "file://LICENSE;md5=751419260aa954499f7abaabaa882bbe \
                    file://www/LICENSE.txt;md5=713496289346a6c1c265f0e1f615ecd0"

SRC_URI = "git://github.com/jacksonliam/mjpg-streamer.git;protocol=https"

# Modify these as desired
PV = "1.0+git${SRCPV}"
SRCREV = "${AUTOREV}"

S = "${WORKDIR}/git/${BPN}-experimental"

# NOTE: unable to map the following CMake package dependencies: OpenCV Numpy Gphoto2
# NOTE: the following library dependencies are unknown, ignoring: v4l2
#       (this is based on recipes that have previously been built and packaged)
DEPENDS = "libjpeg-turbo libsdl"

inherit cmake python-dir

# Specify any options you want to pass to cmake using EXTRA_OECMAKE:
EXTRA_OECMAKE = ""

mjpg-streamerはcmakeでビルドしているためinherit cmakeとなっている。 その他、依存関係なども自動的に解決されている。

レシピのビルド

生成されたレシピがビルドできるかどうかbitbakeを実行してみる。

meta-webcamの作成

recipetoolで生成したmjpg-streamer_git.bbはビルドディレクトリである%HOME/work/yocto/rpi/build_webcamに格納されている。 これはどのレイヤにも属していない状態であるため、bitbakeの対象にならない。 そこで、作業用のレイヤmeta-webcamを作成し、mjpg-streamer_git.bbを含めるようにする。

下記の手順で作成する。

$ cd $HOME/work/yocto/rpi/build_webcam
$ mkdir -p $HOME/work/yocto/rpi/poky/meta-webcam/conf
$ mkdir -p $HOME/work/yocto/rpi/poky/meta-webcam/recipes-multimedia/mjpg-streamer
$ mv ./mjpg-streamer_git.bb $HOME/work/yocto/rpi/poky/meta-webcam/recipes-multimedia/mjpg-streamer
$ cat << 'EOF' > $HOME/work/yocto/rpi/poky/meta-webcam/conf/layer.conf
# We have a conf and classes directory, append to BBPATH
BBPATH .= ":${LAYERDIR}"

# We have a recipes directory containing .bb and .bbappend files, add to BBFILES
BBFILES += "${LAYERDIR}/recipes*/*/*.bb \
            ${LAYERDIR}/recipes*/*/*.bbappend"

BBFILE_COLLECTIONS += "webcam"
BBFILE_PATTERN_webcam := "^${LAYERDIR}/"
BBFILE_PRIORITY_webcam = "10"

LAYERDEPENDS_webcam = "core"
EOF

レイヤの構成は下記のツリーの様になる。

meta-webcam
├── conf
│   └── layer.conf
└── recipes-multimedia
    └── mjpg-streamer
        └── mjpg-streamer_git.bb

bblayers.conf

bblayers.confはbitbakeがビルド対象とするレイヤを定義する。

以下の手順で、bblayers.confの内容を置き換える。

$ cd $HOME/work/yocto/rpi/build_webcam
$ mv ./conf/bblayers.conf ./conf/bblayers.conf.bak
$ cat << 'EOF' > ./conf/bblayers.conf
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

LAYERSTOP = "${TOPDIR}/.."

BBLAYERS ?= " \
  ${LAYERSTOP}/poky/meta \
  ${LAYERSTOP}/poky/meta-poky \
  ${LAYERSTOP}/poky/meta-yocto-bsp \
  ${LAYERSTOP}/poky/meta-raspberrypi \
  ${LAYERSTOP}/poky/meta-webcam \
  "
EOF

local.conf

local.confは生成されたそのままの状態では、qemux86向けのイメージを作成するようになっているため、 raspberrypi向けのイメージが作成されるようにする。

コード 2 の内容をlocal.confの先頭の方に追加する。

コード 2: local.conf(抜粋)
MACHINE ?= "raspberrypi"
BB_NUMBER_THREADS ?= "${@oe.utils.cpu_count()}"
PARALLEL_MAKE ?= "-j ${@oe.utils.cpu_count()}"
GPU_MEM = "128"
DL_DIR ?= "${HOME}/work/yocto/downloads"

IMAGE_INSTALL_append = " mjpg-streamer"

bitbake実行

$ cd $HOME/work/yocto/rpi/build_webcam
$ bitbake mjpg-streamer

この時点でエラーが発生しなければ、ビルドまでは成功している。

以下の手順で結果を確認する。

$ cd tmp/work/arm1176jzfshf-vfp-poky-linux-gnueabi/mjpg-streamer/1.0+gitAUTOINC+2bd6f2c28d-r0/
$ tree ./image

treeの結果を以下に示す。

./image
└── usr
    ├── bin
    │   └── mjpg_streamer
    ├── lib
    │   └── mjpg-streamer
    │       ├── input_file.so
    │       ├── input_http.so
    │       ├── input_uvc.so
    │       ├── output_file.so
    │       ├── output_http.so
    │       ├── output_rtsp.so
    │       ├── output_udp.so
    │       └── output_viewer.so
    └── share
        └── mjpg-streamer
            └── www
                ├── JQuerySpinBtn.css
                ├── JQuerySpinBtn.js
                ├── LICENSE.txt
                ├── bodybg.gif
                ├── cambozola.jar
                ├── control.htm
                ├── example.jpg
                ├── favicon.ico
                ├── favicon.png
                ├── fix.css
                ├── functions.js
                ├── index.html
                ├── java.html
                ├── java_control.html
                ├── java_simple.html
                ├── javascript.html
                ├── javascript_motiondetection.html
                ├── javascript_simple.html
                ├── jquery.js
                ├── jquery.rotate.js
                ├── jquery.ui.core.min.js
                ├── jquery.ui.custom.css
                ├── jquery.ui.tabs.min.js
                ├── jquery.ui.widget.min.js
                ├── rotateicons.png
                ├── sidebarbg.gif
                ├── spinbtn_updn.gif
                ├── static.html
                ├── static_simple.html
                ├── stream.html
                ├── stream_simple.html
                ├── style.css
                └── videolan.html

無事にビルドおよび、ローカルへのインストールは成功している。 しかし、このままではOSイメージのRootFSへ反映されない。

インストールされたファイルをRootFSへ反映されるようにするためには、 レシピでFILES_${PN}を定義する。

また、bitbakeした時にLicense関連でエラーが発生しているので、GPLv2 UnknownからGPLv2に変更する。

それらの修正を行った、一応の完成版のmjpg-streamer_git.bbを lst:mjpg_streamer_git_bb に示す。

コード 3: mjpg-streamer\_git.bb(完成版)
# Recipe created by recipetool
# This is the basis of a recipe and may need further editing in order to be fully functional.
# (Feel free to remove these comments when editing.)
#
# WARNING: the following LICENSE and LIC_FILES_CHKSUM values are best guesses - it is
# your responsibility to verify that the values are complete and correct.
#
# NOTE: multiple licenses have been detected; if that is correct you should separate
# these in the LICENSE value using & if the multiple licenses all apply, or | if there
# is a choice between the multiple licenses. If in doubt, check the accompanying
# documentation to determine which situation is applicable.
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://LICENSE;md5=751419260aa954499f7abaabaa882bbe \
                    file://www/LICENSE.txt;md5=713496289346a6c1c265f0e1f615ecd0"

SRC_URI = "git://github.com/jacksonliam/mjpg-streamer.git;protocol=https"

# Modify these as desired
PV = "1.0+git${SRCPV}"
SRCREV = "${AUTOREV}"

S = "${WORKDIR}/git/${BPN}-experimental"

# NOTE: unable to map the following CMake package dependencies: OpenCV Numpy Gphoto2
# NOTE: the following library dependencies are unknown, ignoring: v4l2
#       (this is based on recipes that have previously been built and packaged)
DEPENDS = "libjpeg-turbo libsdl"

inherit cmake python-dir

# Specify any options you want to pass to cmake using EXTRA_OECMAKE:
EXTRA_OECMAKE = ""

FILES_${PN} = "${bindir}/* \
           ${libdir}/* \
           ${datadir}/* \
           ${sysconfdir}* \
        "

イメージの作成

以下のコマンドを実行してOSイメージを作成する。

$ bitbake rpi-basic-image

イメージの書き込み

ddコマンドでrpi-basic-image-raspberrypi.rpi-sdimgをSDカードに書き込む。

sudo dd if=tmp/deploy/images/raspberrypi/rpi-basic-image-raspberrypi.rpi-sdimg of=/dev/sdb bs=40M

実行

UVCカメラを接続したraspberrypiをSDカードのイメージで起動する。

ログインしたあと、以下のコマンドでmjpg-streamerを実行する。

mjpg_streamer -i "input_uvc.so -y" -o "output_http.so -w /usr/share/mjpg-streamer/www"

ブラウザでhttp://XXX.XXX.XXX.XXX:8080/?action=streamにアクセスして、カメラの映像が表示されれば成功。

XXX.XXX.XXX.XXXはraspberrypiのIPアドレス