春雨日記 about me tags

クロスコンパイルはツールチェインの用意やライブラリを揃えたりと面倒くさいイメージがありますが,chrootを使えばその必要はありません!😎

G-Clusterでウェブカメラの配信をやってみたいなと思い,mjpeg-streanerを試してみたのですが,しっくりこないのでffmpegで挑戦してみようという魂胆です.

はじめに

クロスコンパイルの何が面倒かというと,カーネルモジュールやカーネルの機能を使う際には適合するヘッダを用意する必要があったり,異なるアーキテクチャ向けのライブラリをいちいちビルドして最後に本命を…みたいな手順を踏む必要がある所です.

実機環境でのビルドであればそういった手間は一切不要で,一般的に必要なライブラリをパッケージマネージャで落としてmakeでOKです. が,今回のG-Clusterは超の付くロースペック環境であり,実際に試してみたところほぼ最小ffmpegで4時間かかりました.

そこでAlpineのインストールでも使用したbinfmtを使ってarmhfのrootfsにchrootし,実機同様のパッケージを揃えた上で普通にmakeすれば上記と同じ効果が得られるという訳です.

プロセッサやメモリはホスト同様の数使用できるので並列ビルドもできますし,大きな依存関係の入り組んだプロジェクト(それこそffmpegみたいな)でも大丈夫です.

れっつビルド

手順としては https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu の公式ガイド通りです.

これをchroot上で実行するだけです.

*今回のホストはUbuntuです.

1. chroot環境の用意

パッケージのインストール

1
apt install qemu-user-static binfmt-support 

chroot

1
2
3
4
5
wget https://dl-cdn.alpinelinux.org/alpine/v3.16/releases/armhf/alpine-minirootfs-3.16.2-armhf.tar.gz
mkdir alpine
cd alpine
tar xvf alpine-minirootfs-3.16.2-armhf.tar.gz
chroot . ash # alpineのashに入る

ここでuname -aを実行するとアーキテクチャがarmv7lに化けている事がわかります.

1
2
uname -a
Linux user-VirtualBox 5.15.0-43-generic #46~20.04.1-Ubuntu SMP Thu Jul 14 15:20:17 UTC 2022 armv7l Linux

2. ffmpegの用意

1
2
3
4
cd /root
wget https://ffmpeg.org/releases/ffmpeg-5.1.1.tar.xz
tar xvf ffmpeg-5.1.1.tar.xz
cd ffmpeg-5.1.1

次に,必要なパッケージを入れます.

全部メモれてないので怒られたら探して追加してください.

1
apk add build-base yasm automake autoconf git pkgconfig libtool texinfo alsa-lib-dev libjpeg-turbo-dev v4l-utils-dev linux-headers

*横着してlinux-headersを入れてます.場合によっては実機と同じものが必要となります.

3. ビルド

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
PKG_CONFIG_PATH="/usr/lib/pkgconfig" ./configure --prefix="/opt/ffmpeg" --pkg-config-flags="--static \
--keep-system-cflags --keep-system-libs" --extra-libs="-lpthread -lm -lv4l2" --enable-gpl --disable-ffplay \
--arch="armv6" --cpu="armv6z" --enable-libv4l2 --enable-indev=v4l2 \
--disable-encoders --enable-encoder=aac --enable-encoder=mjpeg --enable-encoder=pcm_s16le --enable-encoder=jpeg2000 \
--enable-encoder=rawvideo \
--disable-decoders --enable-decoder=mjpeg --enable-decoder=rawvideo --disable-filters \
--disable-demuxers --enable-demuxer=image2pipe --enable-demuxer=image_jpeg_pipe --enable-demuxer=rawvideo \
--enable-demuxer=mjpeg --enable-demuxer=mjpeg_2000 --enable-demuxer=pcm_s16le --enable-demuxer=wav \
--disable-muxers --enable-muxer=avi --enable-muxer=bit --enable-muxer=hls --enable-muxer=mjpeg \
--enable-muxer=image2pipe --enable-muxer=mpegts --enable-muxer=pcm_s16le --enable-muxer=wav \
--enable-muxer=yuv4mpegpipe --enable-muxer=smjpeg --enable-muxer=rawvideo \
--disable-bsfs --enable-bsf=mjpeg2jpeg --enable-bsf=mjpega_dump_header --enable-bsf=pcm_rechunk

make -j4

試行錯誤の末ぐちゃぐちゃになってますが,とりあえずWebカメラを動かせる最小を攻めてます.h264サポートすらないです.

終わったらカレントディレクトリにffmpegが生成されるので,scpとかで実機に飛ばしましょう.

staticビルドなので1バイナリだけで大丈夫なはず.

同様のパッケージをインストールしていれば怒られる事なく実行できると思います.

おわりに

実はこれまで横着がってずっと実機でクソ遅コンパイルをやってたのですが,こんな簡単にクロスコンパイルできるならやっとけば良かった…と後悔

無事カメラを認識し,録画できました.

おまけ

archやcpuはgccのパラメータです(多分).

https://github.com/gcc-mirror/gcc/blob/master/gcc/config/arm/arm-cpus.in

を参考に設定してください.

G-clusterのCPUはARM1176JZF(-Sではない)らしいですが,どれを選ぶのが正解なんですかね…

とりあえずarm6zで動いてはいます.

configureの引数は

https://github.com/FFmpeg/FFmpeg/blob/release/5.1/configure

に詳細が載っています.

v4lのパッケージが入ってるにも関わらずERROR: libv4l2 not found using pkg-configが出たときはlibjpegが入ってるか見てください.

ffbuild/config.logに書いてありますがシリアル経由だと見たくないねんな(言い訳)