Introduction
掲題の通り。
開発メモ その315 FFMPEG で libopenh264 を Windows で使う、開発メモ その316 FFMPEG で libopenh264 を Windows で使う その2、開発メモ その475 カスタムビルドした FFMPEG を OpenCV にリンクできない にて libopenh264 を使ってライセンス的に問題なく FFmpeg 及び OpenCV から H264 を扱うことを記事にしてきたが…
「再生方法」について一切記載していなかった。
エンコード方法は正しいが、肝心のデコード方法がない。
そして、普通にデコードするだけではライセンス違反だと思われる。
Why?
結論からいうと、 FFmpeg にはデフォルトで h264 をデコードする libavcodec が存在するからである。
何も指定しないと、libopenh264 は使われない。
当然、バックエンドに FFmpeg を使うようにビルドした OpenCV でも同様。
なので
- OpenH264+FFmpeg+OpenCV4をソースビルドしてH.264を使う
- ライセンス問題を解消してH.264動画をデコード【OpenCV/FFmpeg】
- YOLOv3の利用(2):UBUNTU20.04 環境での転移学習
等々、見たところすべてが libavcodec で再生しており、せっかく用意した libopenh264 を使っていない状態になる。
草生える。
Cisco の libopenh264 を同梱しているので悪意はないとは思うが…それを判断するのは裁判所なので (無慈悲)
根拠
ちゃんと証拠がある。
ffmpeg をビルドすると生成される ffmpeg という実行ファイルがあるのだが、これを使って libopenh264 を指定した時とそうでないときの出力が違うからである。
言うまでもなく OpenCV も同様。
FFmpeg
INTER-STREAM®サポートページ にある bun33s.mp4 という H264 動画で試験してみる。ffmpeg のオプションで入力する動画を意味する -i より前に -c:v <codec name> を指定することでデコーダを指定できる。-i より後ろだとエンコーダになる。
デコーダ指定無し
1 | $ ./ffmpeg -i bun33s.mp4 -map 0:v:0 -f null - |
デコーダ指定あり
1 | $ ./ffmpeg -c:v libopenh264 -i bun33s.mp4 -map 0:v:0 -f null - |
違いは下記。
1 | Stream mapping: |
デコーダの指定の有無で明確に違うことがわかる。
OpenCV
こっちがややこしい。
まず cv::VideoCapture にはバックエンドを指定するオプションはあるが、デコーダを指定するオプションがない。
では、どうするかというと下記の環境変数を使う。
- OPENCV_FFMPEG_CAPTURE_OPTIONS
- OPENCV_FFMPEG_DEBUG
- OPENCV_LOG_LEVEL
きちんとドキュメントがある。
OpenCV environment variables reference#videoio
上記を使うと、FFmpeg に対して使用するデコーダを指定し、かつデコード中の処理内容を標準出力に吐き出せる。
重要なのは OPENCV_FFMPEG_CAPTURE_OPTIONS。こいつでデコーダを指定する。
指定方法は上記のドキュメントにある通り
Note: extra FFmpeg options should be pased in form key;value|key;value|key;value, for example hwaccel;cuvid|video_codec;h264_cuvid|vsync;0 or vcodec;x264|vprofile;high|vlevel;4.0
とあるので video_codec;libopenh264 と指定すればよい。
cv::VideoCapture を使ったサンプルコードは下記。
1 |
|
環境変数指定無し
1 | $ OPENCV_LOG_LEVEL=INFO OPENCV_FFMPEG_DEBUG=1 ./Demo ./bun33s.mp4 |
環境変数指定あり
1 | $ OPENCV_FFMPEG_CAPTURE_OPTIONS="video_codec;libopenh264" OPENCV_LOG_LEVEL=INFO OPENCV_FFMPEG_DEBUG=1 ./Demo ./bun33s.mp4 |
比較するまでもないが、デコーダを指定すると、openh264 を使っていることがよくわかる。openh264 codec version = d12e51a. なんて https://github.com/cisco/openh264/blob/v2.6.0/codec/decoder/plus/src/welsDecoderExt.cpp#L350 そのままである。
画質
念のため比較した。ffmpeg でデコードし静止画に分割したファイルを liopenh264 指定あり/なしについて WinMerge で比較したが差はなかったで一安心。
まとめ
今すぐソースコードを確認しよう (戒め)
