今回作ったもの
さて、前回はパイプラインにコマンド文字列を渡す parse_launch()
だったためGStreamerを呼び出すメリットはあまりなさそうでした。
今回はエレメントをプログラムで作成してリンクする方法にて映像と音声のテスト信号を再生するところをやってみます。
これで基本エレメントを接続したりプロパティを設定したりできるようになります。ただし queue
などを使う場合は Pad
を動的に繋ぐ必要があり、まだまだGStreamerらしさは発揮できません。
チュートリアルと違うところ
チュートリアルでは映像か音声か片方だけだったので、両方合わせたパイプラインにしました。
また、サイズやフレームレートを指定する方法もチュートリアル一覧にはなかったような気がするので追加してみました。
ソースコード
パイプライン
gst-launch-1.0
で書くとすると以下のようになります。
映像と音声は特に同期する必要もなく別々です。
$ gst-launch-1.0 videotestsrc pattern=smpte ! video/x-raw,width=720,height=480,framerate=30/1 ! audiovideosink \
audiotestsrc ! audioconvert ! autoaudiosink
プログラムの中身
前回のプログラムに少し追加されるくらいです。
エレメントを作成する
gst::ElementFactory::make()
にてエレメントを作成します。ここは完全に動的リンクになりますのでパスが通っていないとエラーになります。
fn tutorial_main() {
gst::init().unwrap();
let pipeline = gst::Pipeline::new(Some("test-pipeline"));
let v_source = gst::ElementFactory::make("videotestsrc", Some("v_source")).expect("error videotestsrc");
let v_sink = gst::ElementFactory::make("autovideosink", Some("v_sink")).expect("error autovideosink");
let a_source = gst::ElementFactory::make("audiotestsrc", Some("a_source")).expect("error audiotestsrc");
let a_convert = gst::ElementFactory::make("audioconvert", Some("a_convert")).expect("error audioconvert");
let a_sink = gst::ElementFactory::make("autoaudiosink", Some("a_sink")).expect("error autoaudiosink");
let capsfilter = gst::ElementFactory::make("capsfilter", None).expect("error capsfilter");
...
}
エレメントをリンクする
エレメントを作成したらパイプラインに追加し、それから処理の繋がりごとにリンクします。
ただしここでリンクできるのは静的な Pad
を持っているものだけで、queue
や demuxer
などの動的に生成されるエレメントについては処理をフックしてリンクする必要があります。
...上の続き
pipeline.add_many(&[&v_source, &capsfilter, &v_sink]);
gst::Element::link_many(&[&v_source, &capsfilter, &v_sink]);
pipeline.add_many(&[&a_source, &a_convert, &a_sink]);
gst::Element::link_many(&[&a_source, &a_convert, &a_sink]);
// プロパティなどを設定する
v_source.set_property_from_str("pattern", "ball");
... capsfilterの設定 (次を参照)
// 以降は前回と同じ。
pipeline.set_state(gst::State::Playing).expect("set state");
let bus = pipeline.bus().unwrap();
for msg in bus.iter_timed(gst::ClockTime::NONE) {
...
}
pipeline.set_state(gst::State::Null).expect("set to null");
}
cpasfilterにて設定する
エレメントのリンクやプロパティの設定は上記の通りで特筆する点はなさそうですが、
パイプラインにてサイズやフレームレートを設定するには cpasfilter
というエレメントにて設定するようです。
# パイプラインによく出てくる
# こういうのとか
... ! video/x-raw,width=720,height=480 ...
# こういうやつ
... ! video/x-h264 ! h264parse ! ...
# 正確に書くとcapsfilterのプロパティということらしい
... ! capsfilter caps="video/x-raw,width=720,height=480" ...
そのためプログラム上では capsfilter
エレメントを作成し、ビルダーを用いてプロパティを合成しています。
capsfilter.set_property(
"caps",
gst::Caps::builder("video/x-raw")
.field("format", "I420")
.field("width", 720)
.field("height", 480)
.field("framerate", gst::Fraction::new(30, 1))
.build(),
);
次回
さて、これでエレメントの作成とプロパティの設定はできるようになりましたが、まだまだ queue
や demuxer
などが使えません。
次回は Pad
を動的に繋ぐ方法を書きたいと思います。