/// <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> /// フォーマット一覧の取得 /// </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); }