/// <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> /// 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> /// AVI 形式のファイルを読み込む処理 /// </summary> /// <remarks> /// RenderStream (NULL, NULL, source, null, splitter)<br/> /// RenderStream (NULL, MEDIATYPE_Video, splitter, videoGrabber, videoRenderner)<br/> /// RenderStream (NULL, MEDIATYPE_Audio, splitter, audioGrabber, audioRenderner)<br/> /// <pre> /// source splitter grabber renderner /// +-------+ +--------+ +---------+ +-------+ /// | 0 --- 0 video 0 --- 0 video 0 --- 0 | /// | | | | +---------+ +-------+ /// | | | | /// | | | | +---------+ +-------+ /// | | | audio 1 --- 0 audio 0 --- 0 | /// +-------+ +--------+ +---------+ +-------+ /// </pre> /// </remarks> public static void Sample21() { string __FUNCTION__ = MethodBase.GetCurrentMethod().Name; Console.WriteLine(__FUNCTION__); IGraphBuilder graph = null; ICaptureGraphBuilder2 builder = null; IBaseFilter videoSource = null; IBaseFilter aviSplitter = 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.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 映像入力用: ソースフィルタを生成します. { 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 音声捕獲用: サンプルグラバーを生成します. { 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; // フィルタの接続: (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, 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 (aviSplitter != null) Marshal.ReleaseComObject(aviSplitter); aviSplitter = 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> /// WMV 形式のファイルを読み込み、AVI 形式のファイルに保存する処理 /// </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 Sample32() { 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; IFileSinkFilter fileSink = null; var videoGrabberCB = new CxSampleGrabberCB(); var audioGrabberCB = new CxSampleGrabberCB(); string src_filename = Path.Combine(TestFiles, "stopwatch_320x240.wmv"); string dst_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 映像入力用: ソースフィルタを生成します. { #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 映像出力用: 保存する動画ファイル名を設定します. unsafe { // 動画ファイルを保存する設定: var filetype = new Guid(GUID.MEDIASUBTYPE_Avi); HRESULT hr = (HRESULT)builder.SetOutputFileName(new IntPtr(&filetype), dst_filename, ref videoRenderer, ref fileSink); 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, 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, videoRenderer); 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 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 (videoGrabber != null) Marshal.ReleaseComObject(videoGrabber); videoGrabber = null; if (audioGrabber != null) Marshal.ReleaseComObject(audioGrabber); audioGrabber = 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 } }