/// <summary> /// フォーマット形式の取得 /// </summary> /// <param name="pin">ピン</param> /// <param name="index">フォーマット形式の番号</param> /// <returns> /// フォーマット情報を返します。 /// 取得に成功した場合、取得したデータを DeleteMediaType で解放する必要があります。 /// </returns> public static AM_MEDIA_TYPE GetFormat(IPin pin, int index) { var config = pin as IAMStreamConfig; if (config == null) { throw new DSLab.CxDSException(HRESULT.E_NOINTERFACE); } IntPtr dataptr = IntPtr.Zero; try { // フォーマット個数取得. int count = 0; int size = 0; config.GetNumberOfCapabilities(ref count, ref size); // データ用領域確保. dataptr = Marshal.AllocHGlobal(size); // メディアタイプ取得. AM_MEDIA_TYPE mt = null; config.GetStreamCaps(index, ref mt, dataptr); return(mt); } finally { if (dataptr == IntPtr.Zero) { Marshal.FreeHGlobal(dataptr); } } }
/// <summary> /// サンプルグラバーの生成 /// </summary> /// <returns> /// 生成されたサンプルグラバーを返します。 /// </returns> internal virtual ISampleGrabber CreateSampleGrabber() { ISampleGrabber grabber = (ISampleGrabber)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(GUID.CLSID_SampleGrabber))); if (grabber != null) { // サンプルグラバフィルタの入力形式設定. // 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 AM_MEDIA_TYPE media_type = new AM_MEDIA_TYPE(); media_type.majortype = new Guid(GUID.MEDIATYPE_Video); // Video media_type.subtype = new Guid(GUID.MEDIASUBTYPE_RGB24); // RGB24 media_type.formattype = new Guid(GUID.FORMAT_VideoInfo); // VideoInfo grabber.SetMediaType(media_type); grabber.SetBufferSamples(false); // サンプルコピー 無効. grabber.SetOneShot(false); // One Shot 無効. //grabber.SetCallback(this.SampleGrabberCB, 0); // 0:SampleCB メソッドを呼び出すよう指示する. grabber.SetCallback(this.SampleGrabberCB, 1); // 1:BufferCB メソッドを呼び出すよう指示する. SampleGrabberCB.Notify += SampleGrabberCB_Notify; } return(grabber); }
/// <summary> /// ビデオ情報の取得 /// </summary> /// <param name="grabber">対象のサンプルグラバー</param> /// <returns> /// 取得したビデオ情報(VIDEOINFOHEADER)を返します。 /// </returns> public static VIDEOINFOHEADER GetVideoInfo(ISampleGrabber grabber) { var mt = new AM_MEDIA_TYPE(); grabber.GetConnectedMediaType(mt); var vih = (VIDEOINFOHEADER)Marshal.PtrToStructure(mt.pbFormat, typeof(VIDEOINFOHEADER)); return(vih); }
/// <summary> /// フォーマット形式の設定 /// </summary> /// <param name="pin">ピン</param> /// <param name="format">設定するフォーマット形式</param> public static void SetFormat(IPin pin, AM_MEDIA_TYPE format) { var config = pin as IAMStreamConfig; if (config == null) { throw new DSLab.CxDSException(HRESULT.E_NOINTERFACE); } config.SetFormat(format); }
/// <summary> /// メディアタイプの領域の解放 /// </summary> /// <param name="mt">解放するメディアタイプ</param> public static void FreeMediaType(ref AM_MEDIA_TYPE mt) { if (mt.lSampleSize != 0) { Marshal.FreeCoTaskMem(mt.pbFormat); } if (mt.pUnk != IntPtr.Zero) { Marshal.FreeCoTaskMem(mt.pUnk); } mt = null; }
/// <summary> /// フォーマット形式の取得 /// </summary> /// <param name="pin">ピン</param> /// <returns> /// 現在のフォーマット形式を返します。 /// 取得に成功した場合、取得したデータを DeleteMediaType で解放する必要があります。 /// </returns> public static AM_MEDIA_TYPE GetFormat(IPin pin) { var config = pin as IAMStreamConfig; if (config == null) { throw new DSLab.CxDSException(HRESULT.E_NOINTERFACE); } AM_MEDIA_TYPE mt = null; config.GetFormat(ref mt); return(mt); }
/// <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> /// 画像入力フィルタの生成 /// </summary> /// <param name="param">イメージグラバーパラメータ</param> /// <returns> /// 生成されたインスタンスを返します。 /// </returns> internal virtual IBaseFilter CreateVideoCapture(CxDSCameraParam param) { IBaseFilter capture = DSLab.Axi.CreateFilter(GUID.CLSID_VideoInputDeviceCategory, param.FilterInfo.Name, param.FilterInfo.Index); if (capture != null) { // ビデオ出力フォーマットの設定. // Width,Height に 0,0 が指定されている場合は既定値を使用する. // 指定されている場合は、VIDEOINFOHEADER を書き換えて SetFormat を行う. // // http://msdn.microsoft.com/ja-jp/library/cc353344.aspx // if (0 < param.FormatInfo.VideoSize.Width && 0 < param.FormatInfo.VideoSize.Height) { // 出力ピン. IPin pin = null; if (param.PinInfo.Name != "") pin = DSLab.Axi.FindPin(capture, param.PinInfo.Name); else pin = DSLab.Axi.FindPin(capture, 0, param.PinInfo.Direction); #region 手段1) IAMStreamConfig.GetNumberOfCapabilities で列挙して、該当する AM_MEDIA_TYPE を SetFormat する方法. if (pin is IAMStreamConfig) { IAMStreamConfig config = pin as IAMStreamConfig; int count = 0; int size = 0; config.GetNumberOfCapabilities(ref count, ref size); if (size == Marshal.SizeOf(new VIDEO_STREAM_CONFIG_CAPS())) { for (int i = 0; i < count; i++) { AM_MEDIA_TYPE media_type = new AM_MEDIA_TYPE(); VIDEOINFOHEADER video_info = new VIDEOINFOHEADER(); IntPtr addr = IntPtr.Zero; try { addr = Marshal.AllocCoTaskMem(size); int status = config.GetStreamCaps(i, ref media_type, addr); if (status == (int)HRESULT.S_OK && DS.GUID.Compare(media_type.majortype.ToString(), DS.GUID.MEDIATYPE_Video) && // Function.GuidCompare(media_type.subtype.ToString(), DS.GUID.MEDIASUBTYPE_RGB24) && DS.GUID.Compare(media_type.formattype.ToString(), DS.GUID.FORMAT_VideoInfo) && media_type.cbFormat >= Marshal.SizeOf(video_info) && media_type.pbFormat != IntPtr.Zero ) { video_info = (VIDEOINFOHEADER)Marshal.PtrToStructure(media_type.pbFormat, typeof(VIDEOINFOHEADER)); // --- ビデオ入力サイズの確認. if (video_info.bmiHeader.biWidth == param.FormatInfo.VideoSize.Width && video_info.bmiHeader.biHeight == param.FormatInfo.VideoSize.Height) { config.SetFormat(media_type); return capture; } } } finally { if (addr != IntPtr.Zero) Marshal.FreeCoTaskMem(addr); Axi.DeleteMediaType(ref media_type); } } } } #endregion #region 手段2) VIDEOINFOHEADER の Width,Height を書き換えて SetFormat を行う方法. // // この手段は、多くのカメラで有効だが、LifeCam (x86) では失敗する. // { AM_MEDIA_TYPE media_type = new AM_MEDIA_TYPE(); VIDEOINFOHEADER video_info = new VIDEOINFOHEADER(); media_type = Axi.GetFormat(pin); video_info = (VIDEOINFOHEADER)Marshal.PtrToStructure(media_type.pbFormat, typeof(VIDEOINFOHEADER)); // --- ビデオ入力サイズ. video_info.bmiHeader.biWidth = param.FormatInfo.VideoSize.Width; video_info.bmiHeader.biHeight = param.FormatInfo.VideoSize.Height; // 2013.09.18(Wed): LifeCam (x86) でエラーが発生するので試したが効果は無かった. //video_info.bmiHeader.biBitCount = (short)BppIn; // 2013.09.18(Wed): lSampleSize を変更すると LifeCam (x86) でエラーが発生する. // --- サンプルサイズ. //int horz = System.Math.Abs(param.FilterFormatInfo.VideoSize.Width); //int vert = System.Math.Abs(param.FilterFormatInfo.VideoSize.Height); //int bpp = BppIn; //media_type.lSampleSize = FVIL.Data.CFviImage.CalcHorzByte(horz, bpp) * (uint)vert; Marshal.StructureToPtr(video_info, media_type.pbFormat, true); Axi.SetFormat(pin, media_type); } #endregion } } return capture; }
/// <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> /// 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> /// <returns> /// 生成されたサンプルグラバーを返します。 /// </returns> internal virtual ISampleGrabber CreateSampleGrabber() { ISampleGrabber grabber = (ISampleGrabber)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(GUID.CLSID_SampleGrabber))); if (grabber != null) { // サンプルグラバフィルタの入力形式設定. // 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 AM_MEDIA_TYPE media_type = new AM_MEDIA_TYPE(); media_type.majortype = new Guid(GUID.MEDIATYPE_Video); // Video media_type.subtype = new Guid(GUID.MEDIASUBTYPE_RGB24); // RGB24 media_type.formattype = new Guid(GUID.FORMAT_VideoInfo); // VideoInfo grabber.SetMediaType(media_type); grabber.SetBufferSamples(false); // サンプルコピー 無効. grabber.SetOneShot(false); // One Shot 無効. //grabber.SetCallback(this.SampleGrabberCB, 0); // 0:SampleCB メソッドを呼び出すよう指示する. grabber.SetCallback(this.SampleGrabberCB, 1); // 1:BufferCB メソッドを呼び出すよう指示する. SampleGrabberCB.Notify += SampleGrabberCB_Notify; } return grabber; }
/// <summary> /// 画像入力フィルタの生成 /// </summary> /// <param name="param">イメージグラバーパラメータ</param> /// <returns> /// 生成されたインスタンスを返します。 /// </returns> internal virtual IBaseFilter CreateVideoCapture(CxDSCameraParam param) { IBaseFilter capture = DSLab.Axi.CreateFilter(GUID.CLSID_VideoInputDeviceCategory, param.FilterInfo.Name, param.FilterInfo.Index); if (capture != null) { // ビデオ出力フォーマットの設定. // Width,Height に 0,0 が指定されている場合は既定値を使用する. // 指定されている場合は、VIDEOINFOHEADER を書き換えて SetFormat を行う. // // http://msdn.microsoft.com/ja-jp/library/cc353344.aspx // if (0 < param.FormatInfo.VideoSize.Width && 0 < param.FormatInfo.VideoSize.Height) { // 出力ピン. IPin pin = null; if (param.PinInfo.Name != "") { pin = DSLab.Axi.FindPin(capture, param.PinInfo.Name); } else { pin = DSLab.Axi.FindPin(capture, 0, param.PinInfo.Direction); } #region 手段1) IAMStreamConfig.GetNumberOfCapabilities で列挙して、該当する AM_MEDIA_TYPE を SetFormat する方法. if (pin is IAMStreamConfig) { IAMStreamConfig config = pin as IAMStreamConfig; int count = 0; int size = 0; config.GetNumberOfCapabilities(ref count, ref size); if (size == Marshal.SizeOf(new VIDEO_STREAM_CONFIG_CAPS())) { for (int i = 0; i < count; i++) { AM_MEDIA_TYPE media_type = new AM_MEDIA_TYPE(); VIDEOINFOHEADER video_info = new VIDEOINFOHEADER(); IntPtr addr = IntPtr.Zero; try { addr = Marshal.AllocCoTaskMem(size); int status = config.GetStreamCaps(i, ref media_type, addr); if (status == (int)HRESULT.S_OK && DS.GUID.Compare(media_type.majortype.ToString(), DS.GUID.MEDIATYPE_Video) && // Function.GuidCompare(media_type.subtype.ToString(), DS.GUID.MEDIASUBTYPE_RGB24) && DS.GUID.Compare(media_type.formattype.ToString(), DS.GUID.FORMAT_VideoInfo) && media_type.cbFormat >= Marshal.SizeOf(video_info) && media_type.pbFormat != IntPtr.Zero ) { video_info = (VIDEOINFOHEADER)Marshal.PtrToStructure(media_type.pbFormat, typeof(VIDEOINFOHEADER)); // --- ビデオ入力サイズの確認. if (video_info.bmiHeader.biWidth == param.FormatInfo.VideoSize.Width && video_info.bmiHeader.biHeight == param.FormatInfo.VideoSize.Height) { config.SetFormat(media_type); return(capture); } } } finally { if (addr != IntPtr.Zero) { Marshal.FreeCoTaskMem(addr); } Axi.DeleteMediaType(ref media_type); } } } } #endregion #region 手段2) VIDEOINFOHEADER の Width,Height を書き換えて SetFormat を行う方法. // // この手段は、多くのカメラで有効だが、LifeCam (x86) では失敗する. // { AM_MEDIA_TYPE media_type = new AM_MEDIA_TYPE(); VIDEOINFOHEADER video_info = new VIDEOINFOHEADER(); media_type = Axi.GetFormat(pin); video_info = (VIDEOINFOHEADER)Marshal.PtrToStructure(media_type.pbFormat, typeof(VIDEOINFOHEADER)); // --- ビデオ入力サイズ. video_info.bmiHeader.biWidth = param.FormatInfo.VideoSize.Width; video_info.bmiHeader.biHeight = param.FormatInfo.VideoSize.Height; // 2013.09.18(Wed): LifeCam (x86) でエラーが発生するので試したが効果は無かった. //video_info.bmiHeader.biBitCount = (short)BppIn; // 2013.09.18(Wed): lSampleSize を変更すると LifeCam (x86) でエラーが発生する. // --- サンプルサイズ. //int horz = System.Math.Abs(param.FilterFormatInfo.VideoSize.Width); //int vert = System.Math.Abs(param.FilterFormatInfo.VideoSize.Height); //int bpp = BppIn; //media_type.lSampleSize = FVIL.Data.CFviImage.CalcHorzByte(horz, bpp) * (uint)vert; Marshal.StructureToPtr(video_info, media_type.pbFormat, true); Axi.SetFormat(pin, media_type); } #endregion } } return(capture); }
/// <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 } }
/// <summary> /// フォーマットサイズの設定 /// </summary> /// <param name="pin">ピン</param> /// <param name="width">幅 [0,1~]</param> /// <param name="height">高さ [0,1~]</param> /// <remarks> /// width,height に 0,0 が指定されている場合は既定値を使用する. /// それ以外は、VIDEOINFOHEADER を書き換えて SetFormat を行う. /// http://msdn.microsoft.com/ja-jp/library/cc353344.aspx /// </remarks> public static void SetFormatSize(IPin pin, int width, int height) { if (width <= 0 || height <= 0) { return; } #region 手段1) IAMStreamConfig.GetNumberOfCapabilities で列挙して、該当する AM_MEDIA_TYPE を SetFormat する方法. if (pin is IAMStreamConfig) { var config = (IAMStreamConfig)pin; int count = 0; int size = 0; config.GetNumberOfCapabilities(ref count, ref size); if (size == Marshal.SizeOf(new VIDEO_STREAM_CONFIG_CAPS())) { for (int i = 0; i < count; i++) { var mt = new AM_MEDIA_TYPE(); var vih = new VIDEOINFOHEADER(); IntPtr addr = IntPtr.Zero; try { addr = Marshal.AllocCoTaskMem(size); int status = config.GetStreamCaps(i, ref mt, addr); if (status == (int)HRESULT.S_OK && GUID.Compare(mt.majortype.ToString(), GUID.MEDIATYPE_Video) && GUID.Compare(mt.formattype.ToString(), GUID.FORMAT_VideoInfo) && mt.cbFormat >= Marshal.SizeOf(vih) && mt.pbFormat != IntPtr.Zero ) { vih = (VIDEOINFOHEADER)Marshal.PtrToStructure(mt.pbFormat, typeof(VIDEOINFOHEADER)); // --- ビデオ入力サイズの確認. if (vih.bmiHeader.biWidth == width && vih.bmiHeader.biHeight == height) { config.SetFormat(mt); return; } } } finally { if (addr != IntPtr.Zero) { Marshal.FreeCoTaskMem(addr); } Axi.FreeMediaType(ref mt); } } } } #endregion #region 手段2) VIDEOINFOHEADER の Width,Height を書き換えて SetFormat を行う方法. // // この手段は、多くのカメラで有効だが、LifeCam (x86) では失敗する. // { AM_MEDIA_TYPE mt = new AM_MEDIA_TYPE(); VIDEOINFOHEADER video_info = new VIDEOINFOHEADER(); mt = Axi.GetFormat(pin); video_info = (VIDEOINFOHEADER)Marshal.PtrToStructure(mt.pbFormat, typeof(VIDEOINFOHEADER)); // --- ビデオ入力サイズ. video_info.bmiHeader.biWidth = width; video_info.bmiHeader.biHeight = height; // 2013.09.18(Wed): LifeCam (x86) でエラーが発生するので試したが効果は無かった. //video_info.bmiHeader.biBitCount = (short)BppIn; // 2013.09.18(Wed): lSampleSize を変更すると LifeCam (x86) でエラーが発生する. // --- サンプルサイズ. //int horz = System.Math.Abs(param.FilterFormatInfo.VideoSize.Width); //int vert = System.Math.Abs(param.FilterFormatInfo.VideoSize.Height); //int bpp = BppIn; //mt.lSampleSize = FVIL.Data.CFviImage.CalcHorzByte(horz, bpp) * (uint)vert; Marshal.StructureToPtr(video_info, mt.pbFormat, true); Axi.SetFormat(pin, mt); } #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> /// デバッグ /// </summary> /// <param name="graph"></param> private void DebugPrint(IGraphBuilder graph) { IEnumFilters filters = null; IBaseFilter filter = null; int fetched = 0; int hr = graph.EnumFilters(ref filters); while (filters.Next(1, ref filter, ref fetched) == (int)DSLab.HRESULT.S_OK) { if (fetched == 0) { break; } FILTER_INFO info = new FILTER_INFO(); hr = filter.QueryFilterInfo(info); Console.WriteLine("{0}", info.achName); // フィルタ解放. Marshal.ReleaseComObject(filter); filter = null; } // 解放. Marshal.ReleaseComObject(filters); // サンプルグラバフィルタの入力形式設定. // majortype: http://msdn.microsoft.com/ja-jp/library/cc370108.aspx // subtype : http://msdn.microsoft.com/ja-jp/library/cc371040.aspx AM_MEDIA_TYPE media_type = new AM_MEDIA_TYPE(); SampleGrabber.GetConnectedMediaType(media_type); Debug.WriteLine("{0}:{1}", "majortype", media_type.majortype); Debug.WriteLine("{0}:{1}", "subtype", media_type.subtype); Debug.WriteLine("{0}:{1}", "formattype", media_type.formattype); Debug.WriteLine("{0}:{1}", "bFixedSizeSamples", media_type.bFixedSizeSamples); Debug.WriteLine("{0}:{1}", "bTemporalCompression", media_type.bTemporalCompression); Debug.WriteLine("{0}:{1}", "cbFormat", media_type.cbFormat); Debug.WriteLine("{0}:{1}", "lSampleSize", media_type.lSampleSize); Debug.WriteLine("{0}:{1}", "pbFormat", media_type.pbFormat); Debug.WriteLine("{0}:{1}", "pUnk", media_type.pUnk); // 映像形式の場合、サイズを取得する. if (GUID.Compare(media_type.formattype.ToString(), GUID.FORMAT_VideoInfo)) { VIDEOINFOHEADER vinfo = new VIDEOINFOHEADER(); vinfo = (VIDEOINFOHEADER)Marshal.PtrToStructure(media_type.pbFormat, typeof(VIDEOINFOHEADER)); Debug.WriteLine("{0}:{1}", "Width", vinfo.bmiHeader.biWidth); Debug.WriteLine("{0}:{1}", "Height", vinfo.bmiHeader.biHeight); Debug.WriteLine("{0}:{1}", "BitCount", vinfo.bmiHeader.biBitCount); Debug.WriteLine("{0}:{1}", "Size", vinfo.bmiHeader.biSize); Debug.WriteLine("{0}:{1}", "ImageSize", vinfo.bmiHeader.biSizeImage); Debug.WriteLine("{0}:{1}", "ClrImportant", vinfo.bmiHeader.biClrImportant); Debug.WriteLine("{0}:{1}", "ClrUsed", vinfo.bmiHeader.biClrUsed); Debug.WriteLine("{0}:{1}", "Compression", vinfo.bmiHeader.biCompression); Debug.WriteLine("{0}:{1}", "Planes", vinfo.bmiHeader.biPlanes); Debug.WriteLine("{0}:{1}", "XPelsPerMeter", vinfo.bmiHeader.biXPelsPerMeter); Debug.WriteLine("{0}:{1}", "YPelsPerMeter", vinfo.bmiHeader.biYPelsPerMeter); } }
/// <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> /// デバッグ /// </summary> /// <param name="graph"></param> private void DebugPrint(IGraphBuilder graph) { IEnumFilters filters = null; IBaseFilter filter = null; int fetched = 0; int hr = graph.EnumFilters(ref filters); while (filters.Next(1, ref filter, ref fetched) == (int)DSLab.HRESULT.S_OK) { if (fetched == 0) break; FILTER_INFO info = new FILTER_INFO(); hr = filter.QueryFilterInfo(info); Console.WriteLine("{0}", info.achName); // フィルタ解放. Marshal.ReleaseComObject(filter); filter = null; } // 解放. Marshal.ReleaseComObject(filters); // サンプルグラバフィルタの入力形式設定. // majortype: http://msdn.microsoft.com/ja-jp/library/cc370108.aspx // subtype : http://msdn.microsoft.com/ja-jp/library/cc371040.aspx AM_MEDIA_TYPE media_type = new AM_MEDIA_TYPE(); SampleGrabber.GetConnectedMediaType(media_type); Debug.WriteLine("{0}:{1}", "majortype", media_type.majortype); Debug.WriteLine("{0}:{1}", "subtype", media_type.subtype); Debug.WriteLine("{0}:{1}", "formattype", media_type.formattype); Debug.WriteLine("{0}:{1}", "bFixedSizeSamples", media_type.bFixedSizeSamples); Debug.WriteLine("{0}:{1}", "bTemporalCompression", media_type.bTemporalCompression); Debug.WriteLine("{0}:{1}", "cbFormat", media_type.cbFormat); Debug.WriteLine("{0}:{1}", "lSampleSize", media_type.lSampleSize); Debug.WriteLine("{0}:{1}", "pbFormat", media_type.pbFormat); Debug.WriteLine("{0}:{1}", "pUnk", media_type.pUnk); // 映像形式の場合、サイズを取得する. if (GUID.Compare(media_type.formattype.ToString(), GUID.FORMAT_VideoInfo)) { VIDEOINFOHEADER vinfo = new VIDEOINFOHEADER(); vinfo = (VIDEOINFOHEADER)Marshal.PtrToStructure(media_type.pbFormat, typeof(VIDEOINFOHEADER)); Debug.WriteLine("{0}:{1}", "Width", vinfo.bmiHeader.biWidth); Debug.WriteLine("{0}:{1}", "Height", vinfo.bmiHeader.biHeight); Debug.WriteLine("{0}:{1}", "BitCount", vinfo.bmiHeader.biBitCount); Debug.WriteLine("{0}:{1}", "Size", vinfo.bmiHeader.biSize); Debug.WriteLine("{0}:{1}", "ImageSize", vinfo.bmiHeader.biSizeImage); Debug.WriteLine("{0}:{1}", "ClrImportant", vinfo.bmiHeader.biClrImportant); Debug.WriteLine("{0}:{1}", "ClrUsed", vinfo.bmiHeader.biClrUsed); Debug.WriteLine("{0}:{1}", "Compression", vinfo.bmiHeader.biCompression); Debug.WriteLine("{0}:{1}", "Planes", vinfo.bmiHeader.biPlanes); Debug.WriteLine("{0}:{1}", "XPelsPerMeter", vinfo.bmiHeader.biXPelsPerMeter); Debug.WriteLine("{0}:{1}", "YPelsPerMeter", vinfo.bmiHeader.biYPelsPerMeter); } }
/// <summary> /// フォーマット一覧の取得 /// </summary> /// <param name="pin">対象のピン</param> /// <returns> /// 取得したフォーマット情報のコレクションを返します。 /// </returns> public static List <CxFormatInfo> GetFormatList(IPin pin) { var result = new List <CxFormatInfo>(); if (pin == null) { return(result); } var config = pin as IAMStreamConfig; if (config == null) { return(result); } IntPtr dataptr = IntPtr.Zero; try { int count = 0; int size = 0; config.GetNumberOfCapabilities(ref count, ref size); dataptr = Marshal.AllocHGlobal(size); for (int i = 0; i < count; i++) { AM_MEDIA_TYPE mt = null; try { config.GetStreamCaps(i, ref mt, dataptr); // 基本情報の取得. var info = new CxFormatInfo(); info.MediaType = GUID.Normalize(mt.majortype.ToString()); info.MediaSubType = GUID.Normalize(mt.subtype.ToString()); info.FormatType = GUID.Normalize(mt.formattype.ToString()); // 映像形式か否か. if (GUID.Compare(info.FormatType, GUID.FORMAT_VideoInfo)) { var vih = new VIDEOINFOHEADER(); vih = (VIDEOINFOHEADER)Marshal.PtrToStructure(mt.pbFormat, typeof(VIDEOINFOHEADER)); info.VideoSize = new Size(vih.bmiHeader.biWidth, vih.bmiHeader.biHeight); } // コレクションに追加. result.Add(info); } finally { if (mt != null) { Axi.FreeMediaType(ref mt); } } } } finally { if (dataptr != IntPtr.Zero) { Marshal.FreeHGlobal(dataptr); } } return(result); }