V4L2でカメラからMJPEGのフォーマットで映像を取り出すプログラムをZigで作った
V4L2でカメラからMJPEGのフォーマットで映像を取り出すプログラムをZigで作りました。
これはこの記事で書いたものを発展させたものです。
Githubに置きました。
ビルドとサンプルプログラムの使い方
$ zig version
0.11.0-dev.2696+867441845
$ zig build
$ ./zig-out/bin/v4l2capture
Usage: ./zig-out/bin/v4l2capture /dev/videoX out.mjpg [width height framerate]
default is 640x480@30fps
$ ./zig-out/bin/v4l2capture /dev/video0 out.mjpg 320 240 30
warning: Requested format is 320x240 but set to 320x180.
^Cinfo: 1682150185282:Got SIGINT
info: 1682150185304:duration 24769ms, frame_count 743, 30.00fps
適当なところで^Cを入力して止めます。
320x240を要求したのですが、カメラが対応していなかったので320x180に変更されたというメッセージが出ています。
生成できたmjpgファイルを再生する
$ ffprobe out.mjpg
...
Input #0, jpeg_pipe, from 'out.mjpg':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: mjpeg (Baseline), yuvj422p(pc, bt470bg/unknown/unknown), 320x180, 25 fps, 25 tbr, 25 tbn, 25 tbc
ここには25fpsと出ていますが、これは違います。ffprobeはフレームレートが不明な場合のデフォルト値が25fpsなだけです。
これをffplayで再生するときには明示的にフレームレートを指定する必要があります。
$ ffplay -framerate 30 out.mjpg
MJPEGのデータについて
ChatGPTに質問しました。
mjpegのデータは単純にjpegのデータを連結しただけのものですか。それとも何か情報が追加されていますか
ChatGPT4
Motion JPEG(MJPEG)は、JPEG画像を連続して格納したフォーマットです。基本的には、個々のJPEG画像が単純に連結されており、各フレームは独立してエンコードされています。これは、各フレームが完全な静止画像として符号化されていることを意味します。
ただし、MJPEGはしばしばコンテナフォーマット(例えば、AVIやMOV)内に格納されることがあります。これらのコンテナフォーマットは、タイムスタンプ、フレームレート、同期情報などのメタデータを追加で格納することができます。このような場合、単純にJPEGデータを連結しただけのものではなくなります。
しかし、コンテナフォーマットを使用せず、単純に連続したJPEGデータとしてMJPEGストリームが提供されることもあります。このような場合、MJPEGデータは単純に連続したJPEG画像の並びとなります。
単純に連続したJPEG画像の並びのMJPEGのデータではフレームレートは不明になりますか
ChatGPT4
はい、単純に連続したJPEG画像の並びのMJPEGデータでは、フレームレートは不明になります。このようなMJPEGデータには、フレームレートや他のタイミング情報が含まれていないため、デフォルトのフレームレートを仮定するか、外部の情報に依存しなければなりません。
例えば、ネットワークカメラやビデオキャプチャデバイスからのMJPEGストリームでは、通常、ストリームのフレームレートが文書化されています。この情報を使用して、適切なフレームレートを設定できます。ただし、その情報が利用できない場合、適切なフレームレートを推定することは困難です。
ありがとう。よくわかりました
ChatGPT4
どういたしまして!もしご質問やお手伝いが必要なことがあれば、いつでもお気軽にお問い合わせください。お手伝いできることがあれば幸いです。
各フレームのJPEGデータを取り出したときにタイムスタンプをつけて、下流に渡す必要があるということですね。
関連
Discussion