せしまるです。
仕事で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
バージョン確認などは、以下のコマンドで確認できます
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ビットを優先のチェックを外す
これで準備完了。
こーでぃんぐ
初期化
[STAthread]
static void Main()
{
~~~
Gst.Application.Init();
GtkSharp.GstreamerSharp.ObjectManager.Initialize();
~~~
}
自分はユーザコントロール作って、ユーザコントロール側でパイプラインなどを作成したので、そのコードを記載
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;
}
~~~~
}
}
使う側はデザイナーで作成したユーザコントロールを配置しておく。
public partial class MainForm : Forms
{
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load( object sender, EventArgs e )
{
// Gstreamerのパイプライン生成文字列を入れる.
videoPanel.PipelieSource = "/*再生したい内容*/";
videoPanel.Execute();
}
}
これでMainFormに配置したVideoPanelに映像が再生されるはず。
環境変数
後で書くって行ったやつです。
実は環境変数を通さなくてもGstreamerを動かす方法があります。
アプリケーション実行時だけパスを通すのです。(・∀・)
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すれば、複数の映像を表示することも可能です!
よきストリームライフを!