5
7

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 5 years have passed since last update.

WindowsFormsでGstSharpを使った

Posted at

せしまるです。

仕事でGStreamerのC#版を使ったので備忘録として。

開発環境

・VisualStudio 2017
・.NET Framework 4.7.2
・Gstreamer 1.16.0

環境構築

まずは、Gstreamerの公式ページに書かれているとおりにGstreamerのダウンロード&インストールを行います。

Windows項目にある「1.16.0 runtime installer」をダウンロードしてインストール。
自分はインストールするときのオプションでcompleteを選択しました。

後でまた書きますが、Gstreamerのbinフォルダへのパスを環境変数に追加しておきます。
自分はCドライブ直下に配置したので以下のようにパスを追加しました

C:\gstreamer\1.0\x86_64\bin

バージョン確認などは、以下のコマンドで確認できます

console
C:\Users\seshimaru> gst-inspect-1.0.exe --version
gst-inspect-1.0 version 1.16.0
GStreamer 1.16.0
Unknown package origin

次にVisualStudioを起動してWindowsFormsアプリケーションプロジェクトを作成します。
その後NuGetパッケージマネージャーで「GstSharp」をインストールします。

Gstreamerは64bitのため、プロジェクトのプロパティから、ビルドの設定を変更します。
・プラットフォーム ターゲット:Any CPU
・32ビットを優先のチェックを外す

これで準備完了。

こーでぃんぐ

初期化

Programs.cs
[STAthread]
static void Main()
{
    ~~~
    Gst.Application.Init();
    GtkSharp.GstreamerSharp.ObjectManager.Initialize();
    ~~~
}

自分はユーザコントロール作って、ユーザコントロール側でパイプラインなどを作成したので、そのコードを記載

UserControl.cs
using System;
using Gst;
using Gst.Video;

namespace MyApp.Controlls.UserControlls
{
    public partial class VideoPanel : USerControll
    {
        // パイプライン作成のための文字列.
        public string PipelineSource;
        // 文字列から生成したパイプライン格納変数.
        private Element _pipeline { get; set; }
        // コントロールのハンドル.
        private IntPtr _handle;

        public VideoPanel()
        {
            InitializeComponent();
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            // 開放処理を追加しておく.
            this.Dispose += ( sender, args ) =>
            {
                if( _pipeline == null )
                    return;

                _pipeline.Bus.SyncMessage -= Bus_SyncMessage;
                _pipeline.Bus.Message -= Bus_Message;
                _pipeline.SetState( State.Null );
                _pipeline.Dispose();
                _pipeline = null;
            };
        }

        // 実行.
        public void Execute()
        {
            if( string.IsNullOrEmpty( PipelineSource ) )
                return;
            if( InitGstreamerPipeline() )
                HandleRealized();
        }

        // パイプライン作成.
        private bool InitGstreamerPipeline()
        {
            if( _pipeline != null )
                _pipeline.SetState( State.Null );
            // パイプライン生成
            _pipeline = Parse.Launch( PipelineSource );

            if( _pipeline == null )
                return false;

            _pipeline.Bus.EnableSyncMessageEmission();
            _pipeline.Bus.AddSignalWatch();
            _pipeline.Bus.SyncMessage += Bus_SyncMessage;
            _pipeline.Bus.Message += Bus_Message;
            _pipeline.SetState( State.Playing );
            return true;
        }

        private void Bus_SyncMessage( object o, SyncMessageArgs args )
        {
            string msg;
            switch( args.Message.Type )
            {
                case MessageType.Error:
                    GLib.GException err;
                    args.Message.ParseError( out err, out msg );
                    // エラー処理.
                    break;
                case MessageType.Eos:
                    // ストリーム終了.
                    break;
                case MessageType.NewClock:
                    // 再生開始.
                    break;
                default:
                    break;
            }
        }

        private void Bus_Message( object o, MessageArgs args )
        {
            Console.WriteLine( args );
        }

        // コントロールに映像を埋め込むためハンドルを渡す.
        private void HandleRealized()
        {
            _handle = this.Handle();
            Element overlay = ( ( Gst.Bin ) _pipeline ).GetByInterface( VideoOerlayAdapter.GType );
            var adapter = new VideoOverlayAdapter( overlay.Handle );
            adapter.WindowHandle = _handle;
            adapter.HandleEvent( true );
        }

        // 停止.
        public void Stop()
        {
            if( _pipeline == null )
                return;

            _pipeline.Bus.SyncMessage -= Bus_SyncMessage;
            _pipeline.Bus.Message -= Bus_Message;
            _pipeline.SetState( State.Null );
            _pipeline.Dispose();
            _pipeline = null;
        }
        ~~~~
    }
}

使う側はデザイナーで作成したユーザコントロールを配置しておく。

MainForm.cs
public partial class MainForm : Forms
{
    public MainForm()
    {
        InitializeComponent();
    }

    private void MainForm_Load( object sender, EventArgs e )
    {
        // Gstreamerのパイプライン生成文字列を入れる.
        videoPanel.PipelieSource = "/*再生したい内容*/";
        videoPanel.Execute();
    }
}

これでMainFormに配置したVideoPanelに映像が再生されるはず。

環境変数

後で書くって行ったやつです。
実は環境変数を通さなくてもGstreamerを動かす方法があります。
アプリケーション実行時だけパスを通すのです。(・∀・)

Programs.cs
static void Main()
{
    ~~~
    var gstreamerPath= "C:\gstreamer\1.0\x86_64";
    var path = Environment.GetEnvironmentVariable( "PATH" ).Split( ';', path) );
    path.Add( Path.Combine( gstreamerPath, "bin" ) );
    Environment.SetEnvironmentVariable( "PATH", string.Join( ";", path ) );
    ~~~
}

上記を書くことで一時的にパスを追加できます。
ベタ書きはどうかと思いますが…(^^;)

感想

書籍やサイトがあんまり無くて困りました。
最終的に行き着いたサンプルをみつつできたのでよかったなぁ…

あと、ユーザーコントロールを複数置いて、それぞれでLaunchすれば、複数の映像を表示することも可能です!
よきストリームライフを!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?