/// <summary> /// プロパティボタンが押下されたとき /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void toolProperty_Click(object sender, EventArgs e) { if (this.Filter == null) { return; } Axi.OpenPropertyDialog(this.Handle, this.Filter, "Property"); }
/// <summary> /// フォームロード時の初期化処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void CxDeviceSelectionForm_Load(object sender, EventArgs e) { // デバイスの列挙. this.FilterInfos = Axi.GetFilterList(this.Category); foreach (var item in this.FilterInfos) { comboName.Items.Add(item.Name); } timerUpdateUI.Start(); }
/// <summary> /// ピンリストの指標が変化したとき /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void comboPin_SelectedIndexChanged(object sender, EventArgs e) { try { FormatInfos = null; comboFormat.Items.Clear(); IPin pin = null; try { var index = comboPin.SelectedIndex; pin = Axi.FindPin(this.Filter, index, PIN_DIRECTION.PINDIR_OUTPUT); // フォーマットの列挙. var formatInfos = Axi.GetFormatList(pin); // 映像の情報のみ抽出します. this.FormatInfos = formatInfos.FindAll( delegate(CxFormatInfo item) { return(GUID.Compare(item.FormatType, GUID.FORMAT_VideoInfo)); }); foreach (var item in this.FormatInfos) { var caption = string.Format("{0} x {1}", item.VideoSize.Width, item.VideoSize.Height); comboFormat.Items.Add(caption); } if (comboFormat.Items.Count > 0) { comboFormat.SelectedIndex = 0; } } finally { if (pin != null) { Marshal.ReleaseComObject(pin); } pin = null; } } catch (System.Exception ex) { MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <summary> /// デバイス名称リストの指標が変化したとき /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void comboName_SelectedIndexChanged(object sender, EventArgs e) { try { PinInfos = null; FormatInfos = null; comboPin.Items.Clear(); comboFormat.Items.Clear(); Filter_Dispose(); // フィルタ生成. var index = comboName.SelectedIndex; var filterInfo = this.FilterInfos[index]; this.Filter = Axi.CreateFilter(this.Category, filterInfo.CLSID, filterInfo.Index); // ピンの列挙. var pinInfos = Axi.GetPinList(this.Filter); // 出力ピンの情報のみ抽出します. this.PinInfos = pinInfos.FindAll( delegate(CxPinInfo item) { return(item.Direction == PIN_DIRECTION.PINDIR_OUTPUT); }); foreach (var item in this.PinInfos) { comboPin.Items.Add(item.Name); } if (comboPin.Items.Count > 0) { comboPin.SelectedIndex = 0; } } catch (System.Exception ex) { MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <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> void InitializeFilterPairs() { // [1] フィルタとピンのペア. List <FilterPair> filter_pairs = FilterPairs; // カテゴリ: GUID.CLSID_VideoInputDeviceCategory string category = GUID.CLSID_VideoInputDeviceCategory; // フィルタの一覧を取得する. List <CxDSFilterInfo> filters = Axi.GetFilterList(category); foreach (var filter in filters) { IBaseFilter capture = null; try { #region フィルタを生成する. capture = Axi.CreateFilter(category, filter.Name, filter.Index); #endregion #region ピンの一覧を取得する. List <CxDSPinInfo> pins = new List <CxDSPinInfo>(); { List <CxDSPinInfo> items = Axi.GetPinList(capture); // 出力ピンのみ抽出する. foreach (var item in items) { if (item.Direction == PIN_DIRECTION.PINDIR_OUTPUT) { pins.Add(item); } } } #endregion #region フォーマットの一覧を取得する. try { // [2] ピンとフォーマットのペア. List <PinPair> pin_pairs = new List <PinPair>(); for (int i = 0; i < pins.Count; i++) { CxDSPinInfo pin = pins[i]; // 出力ピンを探す. IPin outpin = Axi.FindPin(capture, i, PIN_DIRECTION.PINDIR_OUTPUT); // フォーマットの色空間グループ分け. Dictionary <string, List <CxDSFormatInfo> > groups = new Dictionary <string, List <CxDSFormatInfo> >(); // フォーマットの一覧を取得する. List <CxDSFormatInfo> formats = Axi.GetFormatList(outpin); foreach (var format in formats) { if (GUID.Compare(format.FormatType, GUID.FORMAT_VideoInfo) == false) { continue; } List <CxDSFormatInfo> groups_value = null; if (groups.TryGetValue(format.MediaSubType, out groups_value) == false) { groups_value = new List <CxDSFormatInfo>(); groups[format.MediaSubType] = (groups_value); } groups_value.Add(format); } // [3] 色空間とフォーマットのペア. List <FormatPair> format_pairs = new List <FormatPair>(); // フォーマットを色空間グループ毎に列挙する. foreach (var group in groups) { // 色空間のニックネーム. string nickname = GUID.GetNickname(group.Key); // Key=MediaSubType if (string.IsNullOrEmpty(nickname)) { nickname = "(unknown)"; } // [3] 色空間とフォーマットのペア. format_pairs.Add(new FormatPair(nickname, group.Value)); } // [2] ピンとフォーマットのペア. pin_pairs.Add(new PinPair(pin, format_pairs)); } // [1] フィルタとピンのペア. filter_pairs.Add(new FilterPair(filter, pin_pairs)); } catch (System.Exception ex) { Debug.WriteLine(ex.StackTrace); } finally { Axi.ReleaseInstance(capture); } #endregion } catch (System.Exception ex) { Debug.WriteLine(ex.StackTrace); } finally { #region フィルタを解放する. Axi.ReleaseInstance(capture); #endregion } } int index = -1; // コンボボックスへの追加. comboFilter.Items.Clear(); for (int i = 0; i < filter_pairs.Count; i++) { var filter_pair = filter_pairs[i]; comboFilter.Items.Add(filter_pair.Key.Name); if (filter_pair.Key.ContentEquals(this.Backup.FilterInfo)) { index = i; } } if (0 <= index && index < comboFilter.Items.Count) { comboFilter.SelectedIndex = index; } }
/// <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); }