Gstreamerは、マルチメディアに対し様々な処理を行うことができるライブラリ・ツール・フレームワーク。
コマンドとして実行することもできるし、各種プログラミング言語でライブラリも用意されている。
基本的な使い方
メディアに対して1つの処理を行う「エレメント」と呼ばれる機能を、パイプ(Linuxコマンド等で使われるパイプと同様)で繋ぎ、パイプラインを構築する。
パイプラインにメディアを流し、先頭のエレメントから順に処理を行っていくイメージだ。
例えば、PCに接続されたカメラなどのデバイスから映像を取得するエレメントであるv4l2src
と、
動画をH264形式にエンコードするエレメントであるx264enc
を連結させ、実行するとH264形式でエンコードしたカメラ映像を取得することができる。
パイプラインをコマンドで実行する場合は、gst-launch-1.0
コマンドを使用する。
上記の処理をLinuxコマンドで実行する場合は、下記のようになる。
パイプの記号はLinuxコマンドでは|
だが、Gstreamerではエクスクラメーションマークを使用する。
gst-launch-1.0 v4l2src ! x264enc
ただし、実は上記例では動かない。エラーが出力されるはずだ。
エレメントには一つ前のエレメントからメディアを受け取る口と、処理した後のメディアを送り出す口が存在する。
受け取る口をSink Padと呼び、送り出す口をSource Padと呼ぶ。
それぞれのPadには、こういった形式のメディアを送り出しますよ、こういった形式のメディアを受け取りますよ、という決まりがあり、どういった形式を受け取るかはエレメントによって異なる。
上記例でのv4l2src
のSource Padから送り出したメディアが、x264enc
のSink Padで受け付けているメディアの形式に合っていなければパイプラインはエラーとなってしまう。
各エレメントがどういった形式のメディアを送り出すのか、受付するのかはgst-inspect-1.0
コマンドで調べることができる。
gst-inspect-1.0 v4l2src
上記コマンドを実行すると、v4l2src
エレメントの説明が表示される。
Pad Templates
という項目に、各Padがどういった形式のメディアを扱うかが記載されている。
Pad Templates:
SRC template: 'src'
Availability: Always
Capabilities:
image/jpeg
video/mpeg
mpegversion: 4
systemstream: false
video/mpeg
mpegversion: 2
...(省略)
Capabilities
という項目の中にある通り、メディアの形式のことは「ケイパビリティ」と呼ぶ。
ケイパビリティが複数記述されているのは、デバイスによってケイパビリティが異なるためだ。
デバイスがどういったケイパビリティのメディアを送り出すのかを調べるには、gst-device-monitor-1.0
コマンドを使用する。
gst-device-monitor-1.0
実行すると、下記のようにデバイスの情報のほか、Gstreamerで何のエレメントを使えばメディアを取り出せるかの情報も表示される。
Device found:
name : vi-output, ****** 2-0070
class : Video/Source
caps : video/x-raw, format=(string)UYVY, width=(int)1280, height=(int)720, framerate=(fraction)30/1;
properties:
udev-probed = true
...(省略)
caps
という項目がケイパビリティである。
このデバイスは、formatがUYVYで解像度が1280x720、fpsが30の、生の映像データ(video/x-raw)を出力することがわかる。
ここでx264enc
のSink Padを調べると、下記のように表示される。
SINK template: 'sink'
Availability: Always
Capabilities:
video/x-raw
framerate: [ 0/1, 2147483647/1 ]
width: [ 16, 2147483647 ]
height: [ 16, 2147483647 ]
format: { (string)Y444, (string)Y42B, (string)I420, (string)YV12, (string)NV12, (string)Y444_10LE, (string)I422_10LE, (string)I420_10LE }
fpsは0から2147483647、フレーム幅は16から2147483647、フレーム高さは16から2147483647、formatは上記に表示されているものを受け付ける、と言う意味だが、formatの候補の中にUYVYが存在しない。
そのため、下記パイプラインではエラーになってしまうというわけだ。
gst-launch-1.0 v4l2src ! x264enc
このようにエレメント間でformatがマッチしない場合は、videoconvert
というエレメントを間に挟むことで解決できる。
videoconvert
は受け取ったメディアのformatを、次のエレメントが受け付けられるformatに自動で変換してくれる。
gst-launch-1.0 v4l2src ! videoconvert ! x264enc
上記でパイプライン自体は問題ないはずだが、実際に実行するとまだエラーが表示されるはずだ。
x264enc
のSource Padから送り出されるメディアを最終的にどうするかが指定されていないためだ。
Source Padに対応するSink Padが指定されていないと、エラーとなってしまう。
最終的にメディアをどう出力するかもエレメントで指定する。
例えば、メディアをファイルに出力する場合はfilesink
というエレメントを使用する。
filesink
にはSource Padは存在しないため、パイプラインの最後に置けばエラーにはならない。
この他にも画面に映像を表示するエレメントなど、様々な出力用エレメントがある。
gst-launch-1.0 v4l2src ! videoconvert ! x264enc ! filesink location=/home/test/output.mp4
上記コマンドを実行することで、/home/test/output.mp4
に映像データが蓄積されていく。
v4l2src
はカメラデバイスで撮影された映像を流し続けるため、処理が自動では終わらない。
十分に蓄積できたところでCtrl+Cで中断する必要がある。
ただ、おそらくファイルを再生することはできないはずだ。
x264enc
のSource Padを見ると、下記のようになっている。
SRC template: 'src'
Availability: Always
Capabilities:
video/x-h264
framerate: [ 0/1, 2147483647/1 ]
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
stream-format: { (string)avc, (string)byte-stream }
alignment: au
profile: { (string)high-4:4:4, (string)high-4:2:2, (string)high-10, (string)high, (string)main, (string)baseline, (string)constrained-baseline, (string)high-4:4:4-intra, (string)high-4:2:2-intra, (string)high-10-intra }
stream-formatが、avcかbyte-streamの2択になっている。
avcはサイズが決まっている動画ファイル等に向いている形式であるため、カメラ撮った映像をファイルに流した形式のファイルだとサイズが決まらず、再生できない。
リアルタイムで映像が流れるような形式であれば、byte-streamの方が向いている。
byte-streamでfilesink
にメディアを流したい場合は、x264enc
の後に
video/x-h264,stream-format=byte-stream
というエレメントを挿入する。
gst-launch-1.0 v4l2src ! videoconvert ! x264enc ! video/x-h264,stream-format=byte-stream ! filesink location=/home/nvidia/my_workspace/output_test.mp4
この書き方は、実はエレメント名が省略されている。省略せずに書くと
capsfilter caps=video/x-h264,stream-format=byte-stream
となる。
capsfilterは、一つ前のエレメントから送り出されるメディアに複数のケイパビリティがある場合に、特定のケイパビリティを指定するエレメントである。
上記の例ではstream-formatにbyte-streamを指定しているが、「video/x-h264」の部分(コンテンツタイプと呼ぶ)は選択肢がない場合でも必須となる。
上記のコマンドを実行すればカメラで撮影した映像を再生できるファイルが作成されるはずだ。