2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

RustでもGStreamer理解がしたい! その2 〜 映像・音声テスト信号を流す 〜

Posted at

今回作ったもの

さて、前回はパイプラインにコマンド文字列を渡す 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() にてエレメントを作成します。ここは完全に動的リンクになりますのでパスが通っていないとエラーになります。

src/main.rs
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 を持っているものだけで、queuedemuxer などの動的に生成されるエレメントについては処理をフックしてリンクする必要があります。

src/main.rs

    ...上の続き

    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 というエレメントにて設定するようです。

pipeline
# パイプラインによく出てくる
# こういうのとか
 ... ! video/x-raw,width=720,height=480 ...
# こういうやつ
 ... ! video/x-h264 ! h264parse ! ...

# 正確に書くとcapsfilterのプロパティということらしい
... ! capsfilter caps="video/x-raw,width=720,height=480" ...

そのためプログラム上では capsfilter エレメントを作成し、ビルダーを用いてプロパティを合成しています。

src/main.rs
    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(),
        );

次回

さて、これでエレメントの作成とプロパティの設定はできるようになりましたが、まだまだ queuedemuxer などが使えません。
次回は Pad を動的に繋ぐ方法を書きたいと思います。

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?