2024.12.24
ビジネスが急速に変化する現代は「OODAサイクル」と親和性が高い 流通卸売業界を取り巻く5つの課題と打開策
カメラの映像をリアルタイムで送信するための部品をZig言語で書く(Part2)(全1記事)
リンクをコピー
記事をブックマーク
小林哲之氏:tetsu_kobaと申します。今日は、「カメラの映像をリアルタイムで送信するための部品をZig言語で書く(Part2)」というタイトルで、発表したいと思います。
概要です。Zig言語はOSのシステムコールの呼び出しや、C言語で書かれたライブラリを利用するのがとても容易です。Video for Linux 2でカメラの映像をキャプチャし、それをエンコード、デコードして、画面に表示するまでの一連のプログラムをパーツとしてZig言語で書きました。これは5月22日に別の勉強会で話した内容の続きなのでPart2です。
なぜこのようなことをしたかというと、映像の配信に必要な各プロセスをきちんと自分で理解するためです。実験のために再利用しやすいパーツを自分で作ります。将来的には新しいコーデックや通信方式を試したいので、そのための土台を作っておくということになります。要するに車輪の再発明ですが、とにかくZig言語でなにかを作ってみたかったということになります。
「とにかくシンプルに」ということで、今回はいろいろな制約を付けています。まず、映像と音声の同期を今回は行いません。さらに今回は映像だけを扱っています。プロセス間のデータの受け渡しにはパイプを使いました。非常にシンプルなプロセス間通信です。パイプの中には画像のデータのみが流れます。映像のサイズは決め打ちで、コマンドラインから指定するようにしました。
ネットワーク間のデータ送信には、TCP socketを使用しました。LAN環境のみなので、ネットワークがひどく混雑している状況は想定していません。今回はとにかく正常系を優先して実装しています。異常が起きたら基本的にはそこで終了するということにしています。必要に応じてエラーリカバリを追加しています。
前回発表時までに作ったものは(スライドを示して)以下のものです。主に送信側を中心に作りました。
今回は以下のようなものを追加しています。jpegのデコーダをエンハンスして、Motion JPEGに対応しました。受信側に使うものはVP8のデコーダ、それからTCPのソケットをlistenして (待ち受けて)、受けた内容をstdoutに出力する。今回はこれをGo言語で書きました。それからI420のローデータのビューアを、libsdl2を使って作りました。
V4L2 captureは、前回作ったものと同じです。
jpegのデコーダです。USBカメラでは、高解像度・高フレームレートの画像はmjpegのフォーマットになるので、今回このjpegのデコーダでmjpegを扱えるようにしました。これによって1,280×720の画像サイズを扱えるようになっています。
mjpegからjpegを切り出すために、jpegの先頭と最後に付いているマーカーを検出しているわけですが、このコードを書く時にいくつかTipsを見つけたので、(スライドを示して)このブログに書いています。jpegのデコードそのものには、libturbojpegのライブラリを使っています。
Convert to I420。これはさまざまな基本的な映像フォーマットをI420に変換するものです。
VP8用のエンコーダとデコーダを作りました。libvpxを使用しています。なぜVP8を利用したかというと、このエンコード済みのフォーマットがIVFになるからです。IVFはH.264やH.265で使われているNALフォーマットよりもずっとシンプルで扱いやすいです。
AV1もraw video formatとしてIVFを採用しているので、それの足掛かりとして、まずはIVFを使っているVP8でやってみました。エンコーダはVP8専用に作りましたが、デコーダはVP8とVP9の両対応にしています。
次にI420 Viewerです。これはlibsdl2を利用しています。フレームレートの制御はしていないので、データが来たタイミングで映像の更新をしています。画面に表示するためにはRGBへ変換する必要がありますが、変換はlibsdl2の内部に任せてあります。
作ったこれらのパーツを組み合わせて使用します。送信側はLinuxで動かすわけですが、V4L2 captureからmjpegのデータを取り込んでそれをデコードして、その結果をさらにI420の形式に変換します。それをVP8でエンコードしてTCP送信。それぞれのパーツをパイプでつなげています。
同様に受信側はLinux、あるいはmacで動かすようになっています。TCPで受信したものをVP8でデコードして画面に表示する。この3つがつながっています。
具体的に使用したシェルスクリプトです。(スライドを示して)このようにパラメーターをシェル変数に入れて呼んでいて、それぞれの入力・出力はファイルで指定するようになっていますが、/dev/stdin、/dev/stdoutを指定することによって、標準入力から得て標準出力に出すということにして、パイプでつなげていくことができるようになっています。
(スライドを示して)同様に、これは受信側です。前回は受信側を作っていなかったので「ffplay」にやらせていましたが、今回は受信側も自分で作りました。
パイプの効率化ですが、パイプのバッファサイズはLinuxの場合、デフォルトで64KBです。これはビデオデータを送るにはけっこう小さいので、何回もシステムコールを呼ばなければいけません。なのでパイプのバッファサイズの変更をしたり、パイプへの書き込みに対してwriteをシステムコールじゃなくvmspliceを使うことによってコピーの回数を1回減らしています。そういった工夫に関してはブログに書いたので、そちらをご覧ください。
Future workです。まだこれは土台なので、これからいろいろなことをやっていきたいと思っています。まずは各ライブラリをZigのパッケージにしたいと思います。それによってパイプでつなげるのではなく、もっとメモリで受け渡すとか、もっと効率の良いやり方で実用化に近いものに変更していけばいいと思います。最終的にはハードウェアアクセラレータによる動画のエンコードやデコードまでやってみたいと思っています。
まとめです。このように単純ではありますが、最低限の映像の送信と受信を行うことはできました。このレイヤーのソフトウェアを実装するのにZig言語はとても有用だと思います。特にC言語で書かれているCのABIのライブラリを使う上では、非常にスマートに使えるので、いいなと思いました。今日紹介したプログラムのソースコードはGitHubに公開しているので、ご覧ください。ブログにもいろいろなことを書いています。
このあと簡単にですが、デモをしたいと思います。2つの画面がありますが、上のほうが送信側。これはArmの評価ボードのJetson AGX OrinにSSHしているところです。下のほうは、M1 Macのターミナルです。動かすシェルスクリプトは(スライドを示して)このとおりです。
まず、下のレシーブ側から動かします。続いて送信側。こんな感じです。音に比べてそれほど遅延がないことがわかります。
以上です。終わります。ありがとうございました。
2025.01.09
マッキンゼーのマネージャーが「資料を作る前」に準備する すべてのアウトプットを支える論理的なフレームワーク
2025.01.16
社内プレゼンは時間のムダ パワポ資料のプロが重視する、「ペライチ資料」で意見を通すこと
2025.01.15
若手がごろごろ辞める会社で「給料を5万円アップ」するも効果なし… 従業員のモチベーションを上げるために必要なことは何か
2025.01.14
コンサルが「理由は3つあります」と前置きする理由 マッキンゼー流、プレゼンの質を向上させる具体的Tips
2025.01.07
資料は3日前に完成 「伝え方」で差がつく、マッキンゼー流プレゼン準備術
2025.01.07
1月から始めたい「日記」を書く習慣 ビジネスパーソンにおすすめな3つの理由
2025.01.10
プレゼンで突っ込まれそうなポイントの事前準備術 マッキンゼー流、顧客や上司の「意思決定」を加速させる工夫
2025.01.08
職場にいる「嫌われた上司」がたどる末路 よくあるダメな嫌われ方・良い嫌われ方の違いとは
2024.06.03
「Willハラスメント」にならず、部下のやりたいことを聞き出すコツ 個人の成長と組織のパフォーマンス向上を両立するには
2025.01.14
目標がなく悩む若手、育成を放棄する管理職… 社員をやる気にさせる「等級制度」を作るための第一歩
安野たかひろ氏・AIプロジェクト「デジタル民主主義2030」立ち上げ会見
2025.01.16 - 2025.01.16
国際コーチング連盟認定のプロフェッショナルコーチ”あべき光司”先生新刊『リーダーのためのコーチングがイチからわかる本』発売記念【オンラインイベント】
2024.12.09 - 2024.12.09
NEXT Innovation Summit 2024 in Autumn特別提供コンテンツ
2024.12.24 - 2024.12.24
プレゼンが上手くなる!5つのポイント|話し方のプロ・資料のプロが解説【カエカ 千葉様】
2024.08.31 - 2024.08.31
育て方改革第2弾!若手をつぶす等級制度、若手を育てる等級制度~等級設定のポイントから育成計画策定まで~
2024.12.18 - 2024.12.18