LoginSignup
13
14

More than 1 year has passed since last update.

Gstreamer勉強メモ

Last updated at Posted at 2021-09-11

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」の部分(コンテンツタイプと呼ぶ)は選択肢がない場合でも必須となる。

上記のコマンドを実行すればカメラで撮影した映像を再生できるファイルが作成されるはずだ。

13
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
14