/// <summary> /// カメラ制御とビデオ品質制御 /// </summary> public static void Sample14() { string __FUNCTION__ = MethodBase.GetCurrentMethod().Name; Console.WriteLine(__FUNCTION__); IGraphBuilder graph = null; ICaptureGraphBuilder2 builder = null; IBaseFilter videoSource = null; IBaseFilter videoGrabber = null; IBaseFilter videoRenderer = null; var videoGrabberCB = new CxSampleGrabberCB(); try { #region グラフビルダーの生成: { // 必須: graph = (IGraphBuilder)Axi.CoCreateInstance(GUID.CLSID_FilterGraph); if (graph == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } // 任意: 当例に於いては必須ではありませんが、後述のフィルタ接続を簡潔に記述できます. builder = (ICaptureGraphBuilder2)Axi.CoCreateInstance(GUID.CLSID_CaptureGraphBuilder2); if (builder == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } builder.SetFiltergraph(graph); } #endregion #region 像入力用: ソースフィルタを生成します. { videoSource = Axi.CreateFilter(GUID.CLSID_VideoInputDeviceCategory, null, 0); if (videoSource == null) { throw new System.IO.IOException("Failed to create a videoSource."); } graph.AddFilter(videoSource, "VideoSource"); // フレームサイズを設定します. // ※注) この操作は、ピンを接続する前に行う必要があります. IPin pin = Axi.FindPin(videoSource, 0, PIN_DIRECTION.PINDIR_OUTPUT); Axi.SetFormatSize(pin, 640, 480); } #endregion #region 像捕獲用: サンプルグラバーを生成します. { videoGrabber = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_SampleGrabber); if (videoGrabber == null) { throw new System.IO.IOException("Failed to create a videoGrabber."); } graph.AddFilter(videoGrabber, "videoGrabber"); // サンプルグラバフィルタの入力形式設定. // SetMediaType で必要なメディア タイプを指定します。 // http://msdn.microsoft.com/ja-jp/library/cc369546.aspx // ※AM_MEDIA_TYPE 構造体のメンバをすべて設定する必要はない。 // ※デフォルトでは、サンプル グラバに優先メディア タイプはない。 // ※サンプル グラバを正しいフィルタに確実に接続するには、フィルタ グラフを作成する前にこのメソッドを呼び出す。 // majortype: http://msdn.microsoft.com/ja-jp/library/cc370108.aspx // subtype : http://msdn.microsoft.com/ja-jp/library/cc371040.aspx { var grabber = (ISampleGrabber)videoGrabber; var mt = new AM_MEDIA_TYPE(); mt.majortype = new Guid(GUID.MEDIATYPE_Video); mt.subtype = new Guid(GUID.MEDIASUBTYPE_RGB24); mt.formattype = new Guid(GUID.FORMAT_VideoInfo); grabber.SetMediaType(mt); grabber.SetBufferSamples(false); // サンプルコピー 無効. grabber.SetOneShot(false); // One Shot 無効. //grabber.SetCallback(videoGrabberCB, 0); // 0:SampleCB メソッドを呼び出すよう指示する. grabber.SetCallback(videoGrabberCB, 1); // 1:BufferCB メソッドを呼び出すよう指示する. } } #endregion #region 像出力用: レンダラーを生成します. { videoRenderer = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_NullRenderer); if (videoRenderer == null) { throw new System.IO.IOException("Failed to create a videoRenderer."); } graph.AddFilter(videoRenderer, "videoRenderer"); } #endregion #region フィルタの接続: if (builder != null) { unsafe { var mediatype = new Guid(GUID.MEDIATYPE_Video); var hr = (HRESULT)builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype), videoSource, videoGrabber, videoRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } } else { // ピンの取得. IPin videoSourceOutput = Axi.FindPin(videoSource, 0, PIN_DIRECTION.PINDIR_OUTPUT); IPin videoGrabberInput = Axi.FindPin(videoGrabber, 0, PIN_DIRECTION.PINDIR_INPUT); IPin videoGrabberOutput = Axi.FindPin(videoGrabber, 0, PIN_DIRECTION.PINDIR_OUTPUT); IPin videoRendererInput = Axi.FindPin(videoRenderer, 0, PIN_DIRECTION.PINDIR_INPUT); // ピンの接続. graph.Connect(videoSourceOutput, videoGrabberInput); graph.Connect(videoGrabberOutput, videoRendererInput); } #endregion // ------------------------------ #region カメラ制御: Console.WriteLine(""); Console.WriteLine("CameraControlProperty"); { #region 取得: var watch = new Stopwatch(); watch.Start(); var ranges = new Dictionary <CameraControlProperty, TxPropertyRange>(); var control = Axi.GetInterface <IAMCameraControl>(graph); foreach (CameraControlProperty prop in Enum.GetValues(typeof(CameraControlProperty))) { HRESULT hr; var range = TxPropertyRange.Reset(); try { // レンジの取得. hr = (HRESULT)control.GetRange( prop, ref range.Min, ref range.Max, ref range.SteppingDelta, ref range.DefaultValue, ref range.CapsFlag ); if (hr < HRESULT.S_OK) { continue; } // 現在値の取得. hr = (HRESULT)control.Get( prop, ref range.Value, ref range.Flag ); if (hr < HRESULT.S_OK) { continue; } range.IsSupported = true; } catch (System.Exception) { } finally { ranges[prop] = range; } } Console.WriteLine("Completed. {0:F3} msec", watch.Elapsed.TotalMilliseconds); #endregion #region 視覚的な確認の為の出力: Console.WriteLine("--- {0,-22}: {1,5}, {2,5}, {3,6}, {4,4}, {5,5} ~ {6,5}", "Name", "Value", "Def", "Flag", "Step", "Lower", "Upper"); foreach (var item in ranges) { var name = item.Key.ToString(); var range = item.Value; if (range.IsSupported) { Console.WriteLine("[O] {0,-22}: {1,5}, {2,5}, 0x{3:X4}, {4,4}, {5,5} ~ {6,5}", name, range.Value, range.DefaultValue, range.CapsFlag, range.SteppingDelta, range.Min, range.Max ); } else { Console.WriteLine("[-] {0,-22}:", name); } } #endregion } #endregion #region ビデオ品質制御: Console.WriteLine(""); Console.WriteLine("VideoProcAmpProperty"); { #region 取得: var watch = new Stopwatch(); watch.Start(); var ranges = new Dictionary <VideoProcAmpProperty, TxPropertyRange>(); var control = Axi.GetInterface <IAMVideoProcAmp>(graph); foreach (VideoProcAmpProperty prop in Enum.GetValues(typeof(VideoProcAmpProperty))) { HRESULT hr; var range = TxPropertyRange.Reset(); try { // レンジ. hr = (HRESULT)control.GetRange( prop, ref range.Min, ref range.Max, ref range.SteppingDelta, ref range.DefaultValue, ref range.CapsFlag ); if (hr >= HRESULT.S_OK) { // 現在値. hr = (HRESULT)control.Get( prop, ref range.Value, ref range.Flag ); if (hr >= HRESULT.S_OK) { range.IsSupported = true; } } } catch (System.Exception) { } ranges[prop] = range; } Console.WriteLine("Completed. {0:F3} msec", watch.Elapsed.TotalMilliseconds); #endregion #region 視覚的な確認の為の出力: Console.WriteLine("--- {0,-22}: {1,5}, {2,5}, {3,6}, {4,4}, {5,5} ~ {6,5}", "Name", "Value", "Def", "Flag", "Step", "Lower", "Upper"); foreach (var item in ranges) { var name = item.Key.ToString(); var range = item.Value; if (range.IsSupported) { Console.WriteLine("[O] {0,-22}: {1,5}, {2,5}, 0x{3:X4}, {4,4}, {5,5} ~ {6,5}", name, range.Value, range.DefaultValue, range.CapsFlag, range.SteppingDelta, range.Min, range.Max ); } else { Console.WriteLine("[-] {0,-22}:", name); } } #endregion } #endregion } catch (System.Exception ex) { Console.WriteLine("{0}", ex.StackTrace); } finally { #region 解放: if (videoSource != null) { Marshal.ReleaseComObject(videoSource); } videoSource = null; if (videoGrabber != null) { Marshal.ReleaseComObject(videoGrabber); } videoGrabber = null; if (videoRenderer != null) { Marshal.ReleaseComObject(videoRenderer); } videoRenderer = null; if (builder != null) { Marshal.ReleaseComObject(builder); } builder = null; if (graph != null) { Marshal.ReleaseComObject(graph); } graph = null; #endregion } }
/// <summary> /// WMV 形式のファイルを読み込む処理 /// </summary> /// <remarks> /// RenderStream (NULL, MEDIATYPE_Video, source, videoGrabber, renderner)<br/> /// RenderStream (NULL, MEDIATYPE_Audio, source, audioGrabber, renderner)<br/> /// <pre> /// source grabber mux renderner /// +--------+ +---------+ +-------+ +-------+ /// | audio 0 ----0 audio 0 --- 1 0 --- 0 | /// | | +---------+ | | +-------+ /// | | | | /// | | +---------+ | | /// | video 1 --- 0 video 0 --- 0 | /// +--------+ +---------+ | | /// 2 | /// +-------+ /// </pre> /// </remarks> public static void Sample31() { string __FUNCTION__ = MethodBase.GetCurrentMethod().Name; Console.WriteLine(__FUNCTION__); IGraphBuilder graph = null; ICaptureGraphBuilder2 builder = null; IBaseFilter videoSource = null; IBaseFilter videoGrabber = null; IBaseFilter audioGrabber = null; IBaseFilter videoRenderer = null; IBaseFilter audioRenderer = null; var videoGrabberCB = new CxSampleGrabberCB(); var audioGrabberCB = new CxSampleGrabberCB(); string src_filename = Path.Combine(TestFiles, "stopwatch_320x240.wmv"); try { #region グラフビルダーの生成: { graph = (IGraphBuilder)Axi.CoCreateInstance(GUID.CLSID_FilterGraph); if (graph == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } builder = (ICaptureGraphBuilder2)Axi.CoCreateInstance(GUID.CLSID_CaptureGraphBuilder2); if (builder == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } builder.SetFiltergraph(graph); } #endregion #region 像入力用: ソースフィルタを生成します. { #if true graph.AddSourceFilter(src_filename, "VideoSource", ref videoSource); if (videoSource == null) { throw new System.IO.IOException("Failed to create a videoSource."); } #else videoSource = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_WMAsfReader); if (videoSource == null) { throw new System.IO.IOException("Failed to create a videoSource."); } graph.AddFilter(videoSource, "VideoSource"); // Configure the file source filter. var pConfig = (IFileSourceFilter)videoSource; { HRESULT hr = (HRESULT)pConfig.Load(src_filename, IntPtr.Zero); if (hr < HRESULT.S_OK) { throw new System.IO.IOException("Failed to set the src_filename."); } } #endif } #endregion #region 像捕獲用: サンプルグラバーを生成します. { videoGrabber = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_SampleGrabber); if (videoGrabber == null) { throw new System.IO.IOException("Failed to create a videoGrabber."); } graph.AddFilter(videoGrabber, "videoGrabber"); // サンプルグラバフィルタの入力形式設定. // SetMediaType で必要なメディア タイプを指定します。 // http://msdn.microsoft.com/ja-jp/library/cc369546.aspx // ※AM_MEDIA_TYPE 構造体のメンバをすべて設定する必要はない。 // ※デフォルトでは、サンプル グラバに優先メディア タイプはない。 // ※サンプル グラバを正しいフィルタに確実に接続するには、フィルタ グラフを作成する前にこのメソッドを呼び出す。 // majortype: http://msdn.microsoft.com/ja-jp/library/cc370108.aspx // subtype : http://msdn.microsoft.com/ja-jp/library/cc371040.aspx { var grabber = (ISampleGrabber)videoGrabber; var mt = new AM_MEDIA_TYPE(); mt.majortype = new Guid(GUID.MEDIATYPE_Video); mt.subtype = new Guid(GUID.MEDIASUBTYPE_RGB24); mt.formattype = new Guid(GUID.FORMAT_VideoInfo); grabber.SetMediaType(mt); grabber.SetBufferSamples(false); // サンプルコピー 無効. grabber.SetOneShot(false); // One Shot 無効. //grabber.SetCallback(videoGrabberCB, 0); // 0:SampleCB メソッドを呼び出すよう指示する. grabber.SetCallback(videoGrabberCB, 1); // 1:BufferCB メソッドを呼び出すよう指示する. } } #endregion #region 音声捕獲用: サンプルグラバーを生成します. { audioGrabber = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_SampleGrabber); if (audioGrabber == null) { throw new System.IO.IOException("Failed to create a audioGrabber."); } graph.AddFilter(audioGrabber, "audioGrabber"); // サンプルグラバフィルタの入力形式設定. // SetMediaType で必要なメディア タイプを指定します。 // http://msdn.microsoft.com/ja-jp/library/cc369546.aspx // ※AM_MEDIA_TYPE 構造体のメンバをすべて設定する必要はない。 // ※デフォルトでは、サンプル グラバに優先メディア タイプはない。 // ※サンプル グラバを正しいフィルタに確実に接続するには、フィルタ グラフを作成する前にこのメソッドを呼び出す。 // majortype: http://msdn.microsoft.com/ja-jp/library/cc370108.aspx // subtype : http://msdn.microsoft.com/ja-jp/library/cc371040.aspx { var grabber = (ISampleGrabber)audioGrabber; var mt = new AM_MEDIA_TYPE(); mt.majortype = new Guid(GUID.MEDIATYPE_Audio); mt.subtype = new Guid(GUID.MEDIASUBTYPE_PCM); mt.formattype = new Guid(GUID.FORMAT_WaveFormatEx); grabber.SetMediaType(mt); grabber.SetBufferSamples(false); // サンプルコピー 無効. grabber.SetOneShot(false); // One Shot 無効. //grabber.SetCallback(audioGrabberCB, 0); // 0:SampleCB メソッドを呼び出すよう指示する. grabber.SetCallback(audioGrabberCB, 1); // 1:BufferCB メソッドを呼び出すよう指示する. } } #endregion #region 像出力用: レンダラーを生成します. { videoRenderer = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_NullRenderer); if (videoRenderer == null) { throw new System.IO.IOException("Failed to create a videoRenderer."); } graph.AddFilter(videoRenderer, "videoRenderer"); } #endregion #region 音声出力用: レンダラーを生成します. { audioRenderer = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_NullRenderer); if (audioRenderer == null) { throw new System.IO.IOException("Failed to create a audioRenderer."); } graph.AddFilter(audioRenderer, "audioRenderer"); } #endregion #region フィルタの接続: unsafe { HRESULT hr; // フィルタの接続: (映像入力) var mediatype_video = new Guid(GUID.MEDIATYPE_Video); hr = (HRESULT)builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype_video), videoSource, videoGrabber, videoRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // フィルタの接続: (音声入力) var mediatype_audio = new Guid(GUID.MEDIATYPE_Audio); hr = (HRESULT)builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype_audio), videoSource, audioGrabber, audioRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } #endregion #region DEBUG: GraphEdit ファイルを保存します. /* * 現在のフィルタ構成を指定されたファイル(GRF 拡張子)に保存します。 * 保存されたファイルは graphedt.exe (Windws SDK 同梱) で確認できます。 */ try { Axi.SaveGraphFile(graph, Path.GetFullPath(__FUNCTION__ + ".GRF")); } catch (System.Exception ex) { Console.WriteLine(ex.StackTrace); } #endregion // ------------------------------ #region 取り込み処理: { var mediaControl = (IMediaControl)graph; var mediaEvent = (IMediaEvent)graph; var mediaSeeking = (IMediaSeeking)graph; // 映像サイズの取得. var vih = Axi.GetVideoInfo((ISampleGrabber)videoGrabber); var images = new List <Bitmap>(); var watch = new Stopwatch(); watch.Start(); // 取り込み処理. videoGrabberCB.Notify += delegate(object _sender, CxSampleGrabberEventArgs _e) { Console.WriteLine("{0}: SampleTime={1:F6}", images.Count, _e.SampleTime); images.Add(_e.ToImage(vih)); }; // 再生. Console.WriteLine("Run ..."); { HRESULT hr; int state; hr = (HRESULT)mediaControl.Run(); hr = (HRESULT)mediaControl.GetState(1000, out state); } Console.WriteLine("Running ... {0:F3} msec", watch.Elapsed.TotalMilliseconds); // 再生が完了するまで待機する. { HRESULT hr; int code; hr = (HRESULT)mediaEvent.WaitForCompletion(-1, out code); hr = (HRESULT)mediaControl.Stop(); } // 確認用: Console.WriteLine("Save ... {0:F3} msec", watch.Elapsed.TotalMilliseconds); { string subdir = Path.Combine(Results, __FUNCTION__); if (Directory.Exists(subdir) == false) { Directory.CreateDirectory(subdir); } for (int i = 0; i < images.Count; i++) { var filename = string.Format("image{0}.png", i); images[i].Save(Path.Combine(subdir, filename)); } } Console.WriteLine("Completed. {0:F3} msec", watch.Elapsed.TotalMilliseconds); } #endregion } catch (System.Exception ex) { Console.WriteLine("{0}", ex.StackTrace); } finally { #region 解放: if (videoSource != null) { Marshal.ReleaseComObject(videoSource); } videoSource = null; if (videoGrabber != null) { Marshal.ReleaseComObject(videoGrabber); } videoGrabber = null; if (audioGrabber != null) { Marshal.ReleaseComObject(audioGrabber); } audioGrabber = null; if (videoRenderer != null) { Marshal.ReleaseComObject(videoRenderer); } videoRenderer = null; if (audioRenderer != null) { Marshal.ReleaseComObject(audioRenderer); } audioRenderer = null; if (builder != null) { Marshal.ReleaseComObject(builder); } builder = null; if (graph != null) { Marshal.ReleaseComObject(graph); } graph = null; #endregion } }
/// <summary> /// プレイヤーの接続 /// </summary> /// <param name="filename"></param> private void Player_Connect(string filename) { #region グラフビルダーの生成: { Graph = (IGraphBuilder)Axi.CoCreateInstance(GUID.CLSID_FilterGraph); if (Graph == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } Builder = (ICaptureGraphBuilder2)Axi.CoCreateInstance(GUID.CLSID_CaptureGraphBuilder2); if (Builder == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } Builder.SetFiltergraph(Graph); } #endregion #region 像入力用: ソースフィルタを生成します. { Graph.AddSourceFilter(filename, "VideoSource", ref VideoSource); if (VideoSource == null) { throw new System.IO.IOException("Failed to create a VideoSource."); } } #endregion #region 像捕獲用: サンプルグラバーを生成します. { VideoGrabber = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_SampleGrabber); if (VideoGrabber == null) { throw new System.IO.IOException("Failed to create a VideoGrabber."); } Graph.AddFilter(VideoGrabber, "VideoGrabber"); // サンプルグラバフィルタの入力形式設定. // SetMediaType で必要なメディア タイプを指定します。 // http://msdn.microsoft.com/ja-jp/library/cc369546.aspx // ※AM_MEDIA_TYPE 構造体のメンバをすべて設定する必要はない。 // ※デフォルトでは、サンプル グラバに優先メディア タイプはない。 // ※サンプル グラバを正しいフィルタに確実に接続するには、フィルタ グラフを作成する前にこのメソッドを呼び出す。 // majortype: http://msdn.microsoft.com/ja-jp/library/cc370108.aspx // subtype : http://msdn.microsoft.com/ja-jp/library/cc371040.aspx { var grabber = (ISampleGrabber)VideoGrabber; var mt = new AM_MEDIA_TYPE(); mt.majortype = new Guid(GUID.MEDIATYPE_Video); mt.subtype = new Guid(GUID.MEDIASUBTYPE_RGB24); mt.formattype = new Guid(GUID.FORMAT_VideoInfo); grabber.SetMediaType(mt); grabber.SetBufferSamples(false); // サンプルコピー 無効. grabber.SetOneShot(false); // One Shot 無効. //grabber.SetCallback(VideoGrabberCB, 0); // 0:SampleCB メソッドを呼び出すよう指示する. grabber.SetCallback(VideoGrabberCB, 1); // 1:BufferCB メソッドを呼び出すよう指示する. } } #endregion #region 音声捕獲用: サンプルグラバーを生成します. { AudioGrabber = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_SampleGrabber); if (AudioGrabber == null) { throw new System.IO.IOException("Failed to create a AudioGrabber."); } Graph.AddFilter(AudioGrabber, "AudioGrabber"); // サンプルグラバフィルタの入力形式設定. // SetMediaType で必要なメディア タイプを指定します。 // http://msdn.microsoft.com/ja-jp/library/cc369546.aspx // ※AM_MEDIA_TYPE 構造体のメンバをすべて設定する必要はない。 // ※デフォルトでは、サンプル グラバに優先メディア タイプはない。 // ※サンプル グラバを正しいフィルタに確実に接続するには、フィルタ グラフを作成する前にこのメソッドを呼び出す。 // majortype: http://msdn.microsoft.com/ja-jp/library/cc370108.aspx // subtype : http://msdn.microsoft.com/ja-jp/library/cc371040.aspx { var grabber = (ISampleGrabber)AudioGrabber; var mt = new AM_MEDIA_TYPE(); mt.majortype = new Guid(GUID.MEDIATYPE_Audio); mt.subtype = new Guid(GUID.MEDIASUBTYPE_PCM); mt.formattype = new Guid(GUID.FORMAT_WaveFormatEx); grabber.SetMediaType(mt); grabber.SetBufferSamples(false); // サンプルコピー 無効. grabber.SetOneShot(false); // One Shot 無効. //grabber.SetCallback(AudioGrabberCB, 0); // 0:SampleCB メソッドを呼び出すよう指示する. grabber.SetCallback(AudioGrabberCB, 1); // 1:BufferCB メソッドを呼び出すよう指示する. } } #endregion #region 像出力用: レンダラーを生成します. { VideoRenderer = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_NullRenderer); if (VideoRenderer == null) { throw new System.IO.IOException("Failed to create a VideoRenderer."); } Graph.AddFilter(VideoRenderer, "VideoRenderer"); } #endregion #region 音声出力用: レンダラーを生成します. { AudioRenderer = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_NullRenderer); if (AudioRenderer == null) { throw new System.IO.IOException("Failed to create a AudioRenderer."); } Graph.AddFilter(AudioRenderer, "AudioRenderer"); } #endregion #region フィルタの接続: if (filename.EndsWith(".avi", StringComparison.InvariantCultureIgnoreCase)) { #region AVI 形式ファイル用の初期化: unsafe { HRESULT hr; // AVI 分離器の追加: Splitter = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_AviSplitter); if (Splitter == null) { throw new System.IO.IOException("Failed to create a Splitter."); } Graph.AddFilter(Splitter, "Splitter"); // フィルタの接続: (AVI 分離器) hr = (HRESULT)Builder.RenderStream(IntPtr.Zero, IntPtr.Zero, VideoSource, null, Splitter); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // フィルタの接続: (映像入力) var mediatype_video = new Guid(GUID.MEDIATYPE_Video); hr = (HRESULT)Builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype_video), Splitter, VideoGrabber, VideoRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // フィルタの接続: (音声入力) ※ Audioless も有る. try { var mediatype_audio = new Guid(GUID.MEDIATYPE_Audio); hr = (HRESULT)Builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype_audio), Splitter, AudioGrabber, AudioRenderer); } catch (System.Exception ex) { Debug.WriteLine(ex.StackTrace); } } #endregion } else if ( filename.EndsWith(".asf", StringComparison.InvariantCultureIgnoreCase) || filename.EndsWith(".wmv", StringComparison.InvariantCultureIgnoreCase)) { #region WMV 形式ファイル用の初期化: unsafe { HRESULT hr; // フィルタの接続: (映像入力) var mediatype_video = new Guid(GUID.MEDIATYPE_Video); hr = (HRESULT)Builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype_video), VideoSource, VideoGrabber, VideoRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // フィルタの接続: (音声入力) var mediatype_audio = new Guid(GUID.MEDIATYPE_Audio); hr = (HRESULT)Builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype_audio), VideoSource, AudioGrabber, AudioRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } #endregion } #endregion // 同期用: サンプルグラバーのイベント登録: VideoGrabberCB.Enable = true; VideoGrabberCB.Notify += VideoGrabberCB_Notify; VideoInfoHeader = Axi.GetVideoInfo((ISampleGrabber)VideoGrabber); }
/// <summary> /// AVI 形式のファイルを読み込み、WMV 形式のファイルに保存する処理 /// </summary> /// <remarks> /// RenderStream (NULL, NULL, source, null, splitter)<br/> /// RenderStream (NULL, MEDIATYPE_Video, splitter, grabber, renderner)<br/> /// RenderStream (NULL, MEDIATYPE_Audio, splitter, null, renderner)<br/> /// <pre> /// source splitter grabber renderner /// +-------+ +--------+ +---------+ +-------+ /// | 0 --- 0 video 0 --- 0 video 0 --- 1 | /// | | | | +---------+ | | /// | | | | | | /// | | | | +---------+ | | /// | | | audio 1 --- 0 audio 0 --- 0 | /// +-------+ +--------+ +---------+ +-------+ /// </pre> /// ※ 本例では grabber は省略しています。<br/> /// </remarks> public static void Sample22() { string __FUNCTION__ = MethodBase.GetCurrentMethod().Name; Console.WriteLine(__FUNCTION__); IGraphBuilder graph = null; ICaptureGraphBuilder2 builder = null; IBaseFilter videoSource = null; IBaseFilter aviSplitter = null; IBaseFilter videoGrabber = null; IBaseFilter videoRenderer = null; IFileSinkFilter fileSink = null; var videoGrabberCB = new CxSampleGrabberCB(); string src_filename = Path.Combine(TestFiles, "stopwatch_320x240.avi"); string dst_filename = Path.Combine(Results, __FUNCTION__ + ".wmv"); try { #region グラフビルダーの生成: { graph = (IGraphBuilder)Axi.CoCreateInstance(GUID.CLSID_FilterGraph); if (graph == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } builder = (ICaptureGraphBuilder2)Axi.CoCreateInstance(GUID.CLSID_CaptureGraphBuilder2); if (builder == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } builder.SetFiltergraph(graph); } #endregion #region 像入力用: ソースフィルタを生成します. { graph.AddSourceFilter(src_filename, "VideoSource", ref videoSource); if (videoSource == null) { throw new System.IO.IOException("Failed to create a videoSource."); } aviSplitter = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_AviSplitter); if (aviSplitter == null) { throw new System.IO.IOException("Failed to create a aviSplitter."); } graph.AddFilter(aviSplitter, "aviSplitter"); } #endregion #region 像捕獲用: サンプルグラバーを生成します. { videoGrabber = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_SampleGrabber); if (videoGrabber == null) { throw new System.IO.IOException("Failed to create a videoGrabber."); } graph.AddFilter(videoGrabber, "videoGrabber"); // サンプルグラバフィルタの入力形式設定. // SetMediaType で必要なメディア タイプを指定します。 // http://msdn.microsoft.com/ja-jp/library/cc369546.aspx // ※AM_MEDIA_TYPE 構造体のメンバをすべて設定する必要はない。 // ※デフォルトでは、サンプル グラバに優先メディア タイプはない。 // ※サンプル グラバを正しいフィルタに確実に接続するには、フィルタ グラフを作成する前にこのメソッドを呼び出す。 // majortype: http://msdn.microsoft.com/ja-jp/library/cc370108.aspx // subtype : http://msdn.microsoft.com/ja-jp/library/cc371040.aspx { var grabber = (ISampleGrabber)videoGrabber; var mt = new AM_MEDIA_TYPE(); mt.majortype = new Guid(GUID.MEDIATYPE_Video); mt.subtype = new Guid(GUID.MEDIASUBTYPE_RGB24); mt.formattype = new Guid(GUID.FORMAT_VideoInfo); grabber.SetMediaType(mt); grabber.SetBufferSamples(false); // サンプルコピー 無効. grabber.SetOneShot(false); // One Shot 無効. //grabber.SetCallback(videoGrabberCB, 0); // 0:SampleCB メソッドを呼び出すよう指示する. grabber.SetCallback(videoGrabberCB, 1); // 1:BufferCB メソッドを呼び出すよう指示する. } } #endregion #region 像出力用: 保存する動画ファイル名を設定します. unsafe { HRESULT hr; // 動画ファイルを保存する設定: var filetype = new Guid(GUID.MEDIASUBTYPE_Asf); hr = (HRESULT)builder.SetOutputFileName(new IntPtr(&filetype), dst_filename, ref videoRenderer, ref fileSink); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } /* * Capturing Video to a Windows Media File * https://msdn.microsoft.com/en-us/library/windows/desktop/dd318630(v=vs.85).aspx */ var config = (IConfigAsfWriter)videoRenderer; // WMProfile { // WMProfile_V80_256Video が取得されます. Guid currentProfileGuid; hr = (HRESULT)config.GetCurrentProfileGuid(out currentProfileGuid); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // WMProfile_V80_BESTVBRVideo に書き替えます. Guid newProfileGuid = new Guid(GUID.WMProfile_V80_BESTVBRVideo); hr = (HRESULT)config.ConfigureFilterUsingProfileGuid(newProfileGuid); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } } #endregion #region フィルタの接続: unsafe { HRESULT hr; // フィルタの接続: (AVI 分離器) hr = (HRESULT)builder.RenderStream(IntPtr.Zero, IntPtr.Zero, videoSource, null, aviSplitter); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // フィルタの接続: (映像入力) var mediatype_video = new Guid(GUID.MEDIATYPE_Video); hr = (HRESULT)builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype_video), aviSplitter, videoGrabber, videoRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // フィルタの接続: (音声入力) var mediatype_audio = new Guid(GUID.MEDIATYPE_Audio); hr = (HRESULT)builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype_audio), aviSplitter, null, videoRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } #endregion #region 像出力用: 保存する動画ファイルのフレームサイズを設定します. unsafe { /* * Capturing Video to a Windows Media File * https://msdn.microsoft.com/en-us/library/windows/desktop/dd318630(v=vs.85).aspx */ var config = (IConfigAsfWriter)videoRenderer; // フレームサイズの取得: var vih = Axi.GetVideoInfo((ISampleGrabber)videoGrabber); var frameSize = new Size(vih.bmiHeader.biWidth, vih.bmiHeader.biHeight); // フレームサイズの変更: Axi.SetVideoFrameSize(config, frameSize); } #endregion #region DEBUG: GraphEdit ファイルを保存します. /* * 現在のフィルタ構成を指定されたファイル(GRF 拡張子)に保存します。 * 保存されたファイルは graphedt.exe (Windws SDK 同梱) で確認できます。 */ try { Axi.SaveGraphFile(graph, Path.GetFullPath(__FUNCTION__ + ".GRF")); } catch (System.Exception ex) { Console.WriteLine(ex.StackTrace); } #endregion // ------------------------------ #region 取り込み処理: { var mediaControl = (IMediaControl)graph; var mediaEvent = (IMediaEvent)graph; var mediaSeeking = (IMediaSeeking)graph; var watch = new Stopwatch(); watch.Start(); // 再生. Console.WriteLine("Run ..."); { HRESULT hr; int state; hr = (HRESULT)mediaControl.Run(); hr = (HRESULT)mediaControl.GetState(1000, out state); } Console.WriteLine("Running ... {0:F3} msec", watch.Elapsed.TotalMilliseconds); // 再生が完了するまで待機する. { HRESULT hr; int code; hr = (HRESULT)mediaEvent.WaitForCompletion(-1, out code); hr = (HRESULT)mediaControl.Stop(); } Console.WriteLine("Completed. {0:F3} msec", watch.Elapsed.TotalMilliseconds); } #endregion } catch (System.Exception ex) { Console.WriteLine("{0}", ex.StackTrace); } finally { #region 解放: if (videoSource != null) { Marshal.ReleaseComObject(videoSource); } videoSource = null; if (aviSplitter != null) { Marshal.ReleaseComObject(aviSplitter); } aviSplitter = null; if (videoRenderer != null) { Marshal.ReleaseComObject(videoRenderer); } videoRenderer = null; if (fileSink != null) { Marshal.ReleaseComObject(fileSink); } fileSink = null; if (builder != null) { Marshal.ReleaseComObject(builder); } builder = null; if (graph != null) { Marshal.ReleaseComObject(graph); } graph = null; #endregion } }
/// <summary> /// カメラから画像を取り込み、動画ファイル(wmv)へ保存する処理 /// </summary> /// <remarks> /// WMV 形式で保存する場合は映像と音声の両方が必要です。<br/> /// <br/> /// RenderStream (NULL, MEDIATYPE_Audio, audio, null, renderner)<br/> /// RenderStream (NULL, MEDIATYPE_Video, video, grabber, renderner)<br/> /// <pre> /// audio renderer /// +-------+ +-------+ /// | 0 ----------------- 0 | /// +-------+ | | /// video grabber | | /// +-------+ +-------+ | | /// | 0 --- 0 0 --- 1 | /// | 1 | | +-------+ /// +-------+ +-------+ /// </pre> /// ※ 本例では grabber は省略しています。<br/> /// </remarks> public static void Sample13() { string __FUNCTION__ = MethodBase.GetCurrentMethod().Name; Console.WriteLine(__FUNCTION__); IGraphBuilder graph = null; ICaptureGraphBuilder2 builder = null; IBaseFilter videoSource = null; IBaseFilter audioSource = null; IBaseFilter videoRenderer = null; IFileSinkFilter fileSink = null; string filename = Path.Combine(Results, __FUNCTION__ + ".wmv"); var frameSize = new Size(640, 480); try { #region グラフビルダーの生成: { graph = (IGraphBuilder)Axi.CoCreateInstance(GUID.CLSID_FilterGraph); if (graph == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } builder = (ICaptureGraphBuilder2)Axi.CoCreateInstance(GUID.CLSID_CaptureGraphBuilder2); if (builder == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } builder.SetFiltergraph(graph); } #endregion #region 像入力用: ソースフィルタを生成します. { videoSource = Axi.CreateFilter(GUID.CLSID_VideoInputDeviceCategory, null, 0); if (videoSource == null) { throw new System.IO.IOException("Failed to create a videoSource."); } graph.AddFilter(videoSource, "VideoSource"); // フレームサイズを設定します. // ※注) この操作は、ピンを接続する前に行う必要があります. IPin pin = Axi.FindPin(videoSource, 0, PIN_DIRECTION.PINDIR_OUTPUT); Axi.SetFormatSize(pin, frameSize.Width, frameSize.Height); } #endregion #region 音声入力用: ソースフィルタを生成します. { audioSource = Axi.CreateFilter(GUID.CLSID_AudioInputDeviceCategory, null, 0); if (audioSource == null) { throw new System.IO.IOException("Failed to create a audioSource."); } graph.AddFilter(audioSource, "audioSource"); } #endregion #region 像出力用: 保存する動画ファイル名を設定します. unsafe { // 動画ファイルを保存する設定: var filetype = new Guid(GUID.MEDIASUBTYPE_Asf); HRESULT hr = (HRESULT)builder.SetOutputFileName(new IntPtr(&filetype), filename, ref videoRenderer, ref fileSink); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } /* * Capturing Video to a Windows Media File * https://msdn.microsoft.com/en-us/library/windows/desktop/dd318630(v=vs.85).aspx */ var config = (IConfigAsfWriter)videoRenderer; // WMProfile { // WMProfile_V80_256Video が取得されます. Guid currentProfileGuid; hr = (HRESULT)config.GetCurrentProfileGuid(out currentProfileGuid); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // WMProfile_V80_BESTVBRVideo に書き替えます. Guid newProfileGuid = new Guid(GUID.WMProfile_V80_BESTVBRVideo); hr = (HRESULT)config.ConfigureFilterUsingProfileGuid(newProfileGuid); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } } #endregion #region フィルタの接続: unsafe { HRESULT hr; // フィルタの接続: (映像入力) var mediatype_video = new Guid(GUID.MEDIATYPE_Video); hr = (HRESULT)builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype_video), videoSource, null, videoRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // フィルタの接続: (音声入力) var mediatype_audio = new Guid(GUID.MEDIATYPE_Audio); hr = (HRESULT)builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype_audio), audioSource, null, videoRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } #endregion #region 像出力用: 保存する動画ファイルのフレームサイズを設定します. unsafe { /* * Capturing Video to a Windows Media File * https://msdn.microsoft.com/en-us/library/windows/desktop/dd318630(v=vs.85).aspx */ var config = (IConfigAsfWriter)videoRenderer; // フレームサイズの変更: Axi.SetVideoFrameSize(config, frameSize); } #endregion // ------------------------------ #region 取り込み処理: { var mediaControl = (IMediaControl)graph; var mediaEvent = (IMediaEvent)graph; var watch = new Stopwatch(); watch.Start(); // 露光開始. Console.WriteLine("Run ..."); { HRESULT hr; int state; hr = (HRESULT)mediaControl.Run(); hr = (HRESULT)mediaControl.GetState(1000, out state); } Console.WriteLine("Running ... {0:F3} msec", watch.Elapsed.TotalMilliseconds); // 取り込み待機. while (watch.ElapsedMilliseconds < 5000) { System.Threading.Thread.Sleep(1); } // 露光停止. Console.WriteLine("Stop ... {0:F3} msec", watch.Elapsed.TotalMilliseconds); { HRESULT hr; int state; hr = (HRESULT)mediaControl.Stop(); hr = (HRESULT)mediaControl.GetState(1000, out state); } Console.WriteLine("Completed. {0:F3} msec", watch.Elapsed.TotalMilliseconds); } #endregion } catch (System.Exception ex) { Console.WriteLine("{0}", ex.StackTrace); } finally { #region 解放: if (videoSource != null) { Marshal.ReleaseComObject(videoSource); } videoSource = null; if (videoRenderer != null) { Marshal.ReleaseComObject(videoRenderer); } videoRenderer = null; if (fileSink != null) { Marshal.ReleaseComObject(fileSink); } fileSink = null; if (builder != null) { Marshal.ReleaseComObject(builder); } builder = null; if (graph != null) { Marshal.ReleaseComObject(graph); } graph = null; #endregion } }
/// <summary> /// カメラの接続 /// </summary> /// <param name="filterInfo"></param> /// <param name="pinno"></param> /// <param name="frameSize"></param> private void Camera_Connect(CxFilterInfo filterInfo, int pinno, Size frameSize) { #region グラフビルダーの生成: { Graph = (IGraphBuilder)Axi.CoCreateInstance(GUID.CLSID_FilterGraph); if (Graph == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } Builder = (ICaptureGraphBuilder2)Axi.CoCreateInstance(GUID.CLSID_CaptureGraphBuilder2); if (Builder == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } Builder.SetFiltergraph(Graph); } #endregion #region 像入力用: ソースフィルタを生成します. { VideoSource = Axi.CreateFilter(GUID.CLSID_VideoInputDeviceCategory, filterInfo.CLSID, filterInfo.Index); if (VideoSource == null) { throw new System.IO.IOException("Failed to create a VideoSource."); } Graph.AddFilter(VideoSource, "VideoSource"); // フレームサイズを設定します. // ※注) この操作は、ピンを接続する前に行う必要があります. IPin pin = Axi.FindPin(VideoSource, pinno, PIN_DIRECTION.PINDIR_OUTPUT); Axi.SetFormatSize(pin, frameSize.Width, frameSize.Height); } #endregion #region 像捕獲用: サンプルグラバーを生成します. { VideoGrabber = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_SampleGrabber); if (VideoGrabber == null) { throw new System.IO.IOException("Failed to create a VideoGrabber."); } Graph.AddFilter(VideoGrabber, "VideoGrabber"); // サンプルグラバフィルタの入力形式設定. // SetMediaType で必要なメディア タイプを指定します。 // http://msdn.microsoft.com/ja-jp/library/cc369546.aspx // ※AM_MEDIA_TYPE 構造体のメンバをすべて設定する必要はない。 // ※デフォルトでは、サンプル グラバに優先メディア タイプはない。 // ※サンプル グラバを正しいフィルタに確実に接続するには、フィルタ グラフを作成する前にこのメソッドを呼び出す。 // majortype: http://msdn.microsoft.com/ja-jp/library/cc370108.aspx // subtype : http://msdn.microsoft.com/ja-jp/library/cc371040.aspx { var grabber = (ISampleGrabber)VideoGrabber; var mt = new AM_MEDIA_TYPE(); mt.majortype = new Guid(GUID.MEDIATYPE_Video); mt.subtype = new Guid(GUID.MEDIASUBTYPE_RGB24); mt.formattype = new Guid(GUID.FORMAT_VideoInfo); grabber.SetMediaType(mt); grabber.SetBufferSamples(false); // サンプルコピー 無効. grabber.SetOneShot(false); // One Shot 無効. //grabber.SetCallback(VideoGrabberCB, 0); // 0:SampleCB メソッドを呼び出すよう指示する. grabber.SetCallback(VideoGrabberCB, 1); // 1:BufferCB メソッドを呼び出すよう指示する. } } #endregion #region 像出力用: レンダラーを生成します. { VideoRenderer = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_NullRenderer); if (VideoRenderer == null) { throw new System.IO.IOException("Failed to create a VideoRenderer."); } Graph.AddFilter(VideoRenderer, "VideoRenderer"); } #endregion #region フィルタの接続: unsafe { var mediatype = new Guid(GUID.MEDIATYPE_Video); var hr = (HRESULT)Builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype), VideoSource, VideoGrabber, VideoRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } #endregion // 同期用: サンプルグラバーのイベント登録: VideoGrabberCB.Enable = true; VideoGrabberCB.Notify += VideoGrabberCB_Notify; VideoInfoHeader = Axi.GetVideoInfo((ISampleGrabber)VideoGrabber); // カメラ制御インターフェースの抽出. CameraControl = Axi.GetInterface <IAMCameraControl>(this.Graph); }
/// <summary> /// カメラから画像を取り込み、動画ファイル(avi)へ保存する処理 /// </summary> /// <remarks> /// AVI 形式で保存する場合は音声入力は省略可能です。<br/> /// <br/> /// RenderStream (NULL, MEDIATYPE_Video, source, grabber, renderner)<br/> /// <pre> /// source grabber renderer /// +-------+ +-------+ +-------+ /// | 0 --- 0 0 --- 0 | /// | 1 | | | | /// +-------+ +-------+ +-------+ /// </pre> /// ※ 本例では grabber は省略しています。<br/> /// </remarks> public static void Sample12() { string __FUNCTION__ = MethodBase.GetCurrentMethod().Name; Console.WriteLine(__FUNCTION__); IGraphBuilder graph = null; ICaptureGraphBuilder2 builder = null; IBaseFilter videoSource = null; IBaseFilter videoRenderer = null; IFileSinkFilter fileSink = null; string filename = Path.Combine(Results, __FUNCTION__ + ".avi"); try { #region グラフビルダーの生成: { graph = (IGraphBuilder)Axi.CoCreateInstance(GUID.CLSID_FilterGraph); if (graph == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } builder = (ICaptureGraphBuilder2)Axi.CoCreateInstance(GUID.CLSID_CaptureGraphBuilder2); if (builder == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } builder.SetFiltergraph(graph); } #endregion #region 像入力用: ソースフィルタを生成します. { videoSource = Axi.CreateFilter(GUID.CLSID_VideoInputDeviceCategory, null, 0); if (videoSource == null) { throw new System.IO.IOException("Failed to create a videoSource."); } graph.AddFilter(videoSource, "VideoSource"); // フレームサイズを設定します. // ※注) この操作は、ピンを接続する前に行う必要があります. IPin pin = Axi.FindPin(videoSource, 0, PIN_DIRECTION.PINDIR_OUTPUT); Axi.SetFormatSize(pin, 640, 480); } #endregion #region 像出力用: 保存する動画ファイル名を設定します. unsafe { // 動画ファイルを保存する設定: var filetype = new Guid(GUID.MEDIASUBTYPE_Avi); HRESULT hr = (HRESULT)builder.SetOutputFileName(new IntPtr(&filetype), filename, ref videoRenderer, ref fileSink); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } #endregion #region フィルタの接続: unsafe { // フィルタの接続: var mediatype = new Guid(GUID.MEDIATYPE_Video); HRESULT hr = (HRESULT)builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype), videoSource, null, videoRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } #endregion // ------------------------------ #region 取り込み処理: { var mediaControl = (IMediaControl)graph; var mediaEvent = (IMediaEvent)graph; var watch = new Stopwatch(); watch.Start(); // 露光開始. Console.WriteLine("Run ..."); { HRESULT hr; int state; hr = (HRESULT)mediaControl.Run(); hr = (HRESULT)mediaControl.GetState(1000, out state); } Console.WriteLine("Running ... {0:F3} msec", watch.Elapsed.TotalMilliseconds); // 取り込み待機. while (watch.ElapsedMilliseconds < 3000) { System.Threading.Thread.Sleep(1); } // 露光停止. Console.WriteLine("Stop ... {0:F3} msec", watch.Elapsed.TotalMilliseconds); { HRESULT hr; int state; hr = (HRESULT)mediaControl.Stop(); hr = (HRESULT)mediaControl.GetState(1000, out state); } Console.WriteLine("Completed. {0:F3} msec", watch.Elapsed.TotalMilliseconds); } #endregion } catch (System.Exception ex) { Console.WriteLine("{0}", ex.StackTrace); } finally { #region 解放: if (videoSource != null) { Marshal.ReleaseComObject(videoSource); } videoSource = null; if (videoRenderer != null) { Marshal.ReleaseComObject(videoRenderer); } videoRenderer = null; if (fileSink != null) { Marshal.ReleaseComObject(fileSink); } fileSink = null; if (builder != null) { Marshal.ReleaseComObject(builder); } builder = null; if (graph != null) { Marshal.ReleaseComObject(graph); } graph = null; #endregion } }
/// <summary> /// カメラから画像を取り込む処理 /// </summary> /// <remarks> /// この方法が最も単純です。<br/> /// <br/> /// RenderStream (NULL, MEDIATYPE_Video, source, grabber, renderner)<br/> /// <pre> /// source grabber renderer /// +-------+ +-------+ +-------+ /// | 0 --- 0 0 --- 0 | /// | 1 | | | | /// +-------+ +-------+ +-------+ /// </pre> /// </remarks> public static void Sample11() { string __FUNCTION__ = MethodBase.GetCurrentMethod().Name; Console.WriteLine(__FUNCTION__); IGraphBuilder graph = null; ICaptureGraphBuilder2 builder = null; IBaseFilter videoSource = null; IBaseFilter videoGrabber = null; IBaseFilter videoRenderer = null; var videoGrabberCB = new CxSampleGrabberCB(); try { #region グラフビルダーの生成: { // 必須: graph = (IGraphBuilder)Axi.CoCreateInstance(GUID.CLSID_FilterGraph); if (graph == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } // 任意: 当例に於いては必須ではありませんが、後述のフィルタ接続を簡潔に記述できます. builder = (ICaptureGraphBuilder2)Axi.CoCreateInstance(GUID.CLSID_CaptureGraphBuilder2); if (builder == null) { throw new System.IO.IOException("Failed to create a GraphBuilder."); } builder.SetFiltergraph(graph); } #endregion #region 像入力用: ソースフィルタを生成します. { videoSource = Axi.CreateFilter(GUID.CLSID_VideoInputDeviceCategory, null, 0); if (videoSource == null) { throw new System.IO.IOException("Failed to create a videoSource."); } graph.AddFilter(videoSource, "VideoSource"); // フレームサイズを設定します. // ※注) この操作は、ピンを接続する前に行う必要があります. IPin pin = Axi.FindPin(videoSource, 0, PIN_DIRECTION.PINDIR_OUTPUT); Axi.SetFormatSize(pin, 640, 480); } #endregion #region 像捕獲用: サンプルグラバーを生成します. { videoGrabber = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_SampleGrabber); if (videoGrabber == null) { throw new System.IO.IOException("Failed to create a videoGrabber."); } graph.AddFilter(videoGrabber, "videoGrabber"); // サンプルグラバフィルタの入力形式設定. // SetMediaType で必要なメディア タイプを指定します。 // http://msdn.microsoft.com/ja-jp/library/cc369546.aspx // ※AM_MEDIA_TYPE 構造体のメンバをすべて設定する必要はない。 // ※デフォルトでは、サンプル グラバに優先メディア タイプはない。 // ※サンプル グラバを正しいフィルタに確実に接続するには、フィルタ グラフを作成する前にこのメソッドを呼び出す。 // majortype: http://msdn.microsoft.com/ja-jp/library/cc370108.aspx // subtype : http://msdn.microsoft.com/ja-jp/library/cc371040.aspx { var grabber = (ISampleGrabber)videoGrabber; var mt = new AM_MEDIA_TYPE(); mt.majortype = new Guid(GUID.MEDIATYPE_Video); mt.subtype = new Guid(GUID.MEDIASUBTYPE_RGB24); mt.formattype = new Guid(GUID.FORMAT_VideoInfo); grabber.SetMediaType(mt); grabber.SetBufferSamples(false); // サンプルコピー 無効. grabber.SetOneShot(false); // One Shot 無効. //grabber.SetCallback(videoGrabberCB, 0); // 0:SampleCB メソッドを呼び出すよう指示する. grabber.SetCallback(videoGrabberCB, 1); // 1:BufferCB メソッドを呼び出すよう指示する. } } #endregion #region 像出力用: レンダラーを生成します. { videoRenderer = (IBaseFilter)Axi.CoCreateInstance(GUID.CLSID_NullRenderer); if (videoRenderer == null) { throw new System.IO.IOException("Failed to create a videoRenderer."); } graph.AddFilter(videoRenderer, "videoRenderer"); } #endregion #region フィルタの接続: if (builder != null) { unsafe { var mediatype = new Guid(GUID.MEDIATYPE_Video); var hr = (HRESULT)builder.RenderStream(IntPtr.Zero, new IntPtr(&mediatype), videoSource, videoGrabber, videoRenderer); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } } else { // ピンの取得. IPin videoSourceOutput = Axi.FindPin(videoSource, 0, PIN_DIRECTION.PINDIR_OUTPUT); IPin videoGrabberInput = Axi.FindPin(videoGrabber, 0, PIN_DIRECTION.PINDIR_INPUT); IPin videoGrabberOutput = Axi.FindPin(videoGrabber, 0, PIN_DIRECTION.PINDIR_OUTPUT); IPin videoRendererInput = Axi.FindPin(videoRenderer, 0, PIN_DIRECTION.PINDIR_INPUT); // ピンの接続. graph.Connect(videoSourceOutput, videoGrabberInput); graph.Connect(videoGrabberOutput, videoRendererInput); } #endregion // ------------------------------ #region 取り込み処理: { var mediaControl = (IMediaControl)graph; // 映像サイズの取得. var vih = Axi.GetVideoInfo((ISampleGrabber)videoGrabber); var images = new List <Bitmap>(); var watch = new Stopwatch(); watch.Start(); // 取り込み処理. videoGrabberCB.Notify += delegate(object _sender, CxSampleGrabberEventArgs _e) { Console.WriteLine("{0}: SampleTime={1:F6}", images.Count, _e.SampleTime); images.Add(_e.ToImage(vih)); }; // 露光開始. Console.WriteLine("Run ..."); { HRESULT hr; int state; hr = (HRESULT)mediaControl.Run(); hr = (HRESULT)mediaControl.GetState(1000, out state); } Console.WriteLine("Running ... {0:F3} msec", watch.Elapsed.TotalMilliseconds); // 取り込み待機. while (watch.ElapsedMilliseconds < 3000) { System.Threading.Thread.Sleep(1); } // 露光停止. Console.WriteLine("Stop ... {0:F3} msec", watch.Elapsed.TotalMilliseconds); { HRESULT hr; int state; hr = (HRESULT)mediaControl.Stop(); hr = (HRESULT)mediaControl.GetState(1000, out state); } // 確認用: Console.WriteLine("Save ... {0:F3} msec", watch.Elapsed.TotalMilliseconds); { string subdir = Path.Combine(Results, __FUNCTION__); if (Directory.Exists(subdir) == false) { Directory.CreateDirectory(subdir); } for (int i = 0; i < images.Count; i++) { var filename = string.Format("image{0}.png", i); images[i].Save(Path.Combine(subdir, filename)); } } Console.WriteLine("Completed. {0:F3} msec", watch.Elapsed.TotalMilliseconds); } #endregion } catch (System.Exception ex) { Console.WriteLine("{0}", ex.StackTrace); } finally { #region 解放: if (videoSource != null) { Marshal.ReleaseComObject(videoSource); } videoSource = null; if (videoGrabber != null) { Marshal.ReleaseComObject(videoGrabber); } videoGrabber = null; if (videoRenderer != null) { Marshal.ReleaseComObject(videoRenderer); } videoRenderer = null; if (builder != null) { Marshal.ReleaseComObject(builder); } builder = null; if (graph != null) { Marshal.ReleaseComObject(graph); } graph = null; #endregion } }