예제 #1
0
        /// <summary>
        /// Get video formats.
        /// </summary>
        public static VideoFormat[] GetVideoFormat(int camerIndex)
        {
            var filter = DSUtility.CreateFilter(DSConst.FilterCategoryGUID.CLSID_VideoInputDeviceCategory, camerIndex);
            var pin    = DSUtility.FindPin(filter, 0, DSConst.PIN_DIRECTION.PINDIR_OUTPUT);

            return(GetVideoOutputFormat(pin));
        }
예제 #2
0
        /// <summary>
        /// ビデオキャプチャデバイスの出力形式を選択する。
        /// フォーマットの列挙で同サイズがあれば、そのフォーマットを設定する。
        /// 存在しなかった場合は出力形式を変更しない。
        /// </summary>
        /// <param name="pin">ビデオキャプチャデバイスの出力ピン</param>
        /// <param name="size">指定のサイズ</param>
        /// <param name="fps">フレームレートを指定する。0のとき変更しない(デフォルト)。</param>
        private static bool SetVideoOutputFormat(DSInterface.IPin pin, Size size, double fps)
        {
            var vformat = GetVideoOutputFormat(pin);

            // for debug
            // for (int i = 0; i < vformat.Length; i++) Console.WriteLine("{0}:{1}", i, vformat[i]);

            for (int i = 0; i < vformat.Length; i++)
            {
                if (vformat[i].MajorType == DSUtility.GetMediaTypeName(DSConst.MediaTypeGUID.MEDIATYPE_Video))
                {
                    // MajorTypeがVideoの場合、SubTypeは色空間を表す。
                    // BuffaloのWebカメラは[YUY2]と[MPEG]だった。
                    // マイクロビジョンのUSBカメラは[YUY2]と[YUVY]だった。
                    // 固定できないためコメントアウト。最初に見つかったフォーマットを利用する。
                    // if (vformat[i].SubType == DSUtility.GetMediaTypeName(DSConst.MediaTypeGUID.MEDIASUBTYPE_YUY2))

                    // FORMAT_VideoInfoのみ対応する。(FORMAT_VideoInfo2はSampleGrabber未対応のためエラー。)
                    // https://msdn.microsoft.com/ja-jp/library/cc370616.aspx
                    if (DSUtility.CompGUIDString(vformat[i].Caps.Guid.ToString(), DSConst.FormatTypeGUID.FORMAT_VideoInfo))
                    {
                        if (vformat[i].Size.Width == size.Width && vformat[i].Size.Height == size.Height)
                        {
                            SetVideoOutputFormat(pin, i, size, fps);
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
예제 #3
0
        /// <summary>
        /// サンプルグラバを作成する
        /// </summary>
        private DSInterface.IBaseFilter CreateSampleGrabber()
        {
            var filter = DSUtility.CreateFilter(DSConst.FilterGUID.CLSID_SampleGrabber);

            DSInterface.ISampleGrabber i_grabber = (DSInterface.ISampleGrabber)filter;

            // サンプル グラバを最初に作成したときは、優先メディア タイプは設定されていない。
            // これは、グラフ内のほぼすべてのフィルタに接続はできるが、受け取るデータ タイプを制御できないとうことである。
            // したがって、残りのグラフを作成する前に、ISampleGrabber::SetMediaType メソッドを呼び出して、
            // サンプル グラバに対してメディア タイプを設定すること。

            // サンプル グラバは、接続した時に他のフィルタが提供するメディア タイプとこの設定されたメディア タイプとを比較する。
            // 調べるフィールドは、メジャー タイプ、サブタイプ、フォーマット タイプだけである。
            // これらのフィールドでは、値 GUID_NULL は "あらゆる値を受け付ける" という意味である。
            // 通常は、メジャー タイプとサブタイプを設定する。

            // https://msdn.microsoft.com/ja-jp/library/cc370616.aspx
            // https://msdn.microsoft.com/ja-jp/library/cc369546.aspx
            // サンプル グラバ フィルタはトップダウン方向 (負の biHeight) のビデオ タイプ、または
            // FORMAT_VideoInfo2 のフォーマット タイプのビデオ タイプはすべて拒否する。

            var mt = new DSStructure.AM_MEDIA_TYPE();

            mt.majorType = new Guid(DSConst.MediaTypeGUID.MEDIATYPE_Video);
            mt.subType   = new Guid(DSConst.MediaTypeGUID.MEDIASUBTYPE_RGB24);
            i_grabber.SetMediaType(mt);
            return(filter);
        }
예제 #4
0
        /// <summary>
        /// Video Capture Sourceフィルタを作成する
        /// </summary>
        private DSInterface.IBaseFilter CreateVideoCaptureSource(int index, Size size)
        {
            var filter = DSUtility.CreateFilter(DSConst.FilterCategoryGUID.CLSID_VideoInputDeviceCategory, index);
            var pin    = DSUtility.FindPin(filter, 0, DSConst.PIN_DIRECTION.PINDIR_OUTPUT);

            SetVideoOutputFormat(pin, size, 0);
            return(filter);
        }
예제 #5
0
 /// <summary>
 /// Get available USB camera list.
 /// </summary>
 /// <returns>Array of camera name, or if no device found, zero length array/</returns>
 public static string[] FindDevices()
 {
     try
     {
         var list = DSUtility.EnumFilters(DSConst.FilterCategoryGUID.CLSID_VideoInputDeviceCategory);
         return(list.Select(x => x.Name).ToArray());
     }
     catch (Exception)
     {
         return(new string[0]); // not connected.
     }
 }
예제 #6
0
        private void Init(int index, Size size)
        {
            //----------------------------------
            // Create Filter Graph
            //----------------------------------
            // +--------------------+  +----------------+  +---------------+
            // |Video Capture Source|→| Sample Grabber |→| Null Renderer |
            // +--------------------+  +----------------+  +---------------+
            //                                 ↓GetBitmap()

            var graph = DSUtility.CreateNewGraph();

            //----------------------------------
            // VideoCaptureSource
            //----------------------------------
            var vcap_source = CreateVideoCaptureSource(index, size);

            graph.AddFilter(vcap_source, "VideoCapture");

            //------------------------------
            // SampleGrabber
            //------------------------------
            var grabber = CreateSampleGrabber();

            graph.AddFilter(grabber, "SampleGrabber");
            var i_grabber = (DSInterface.ISampleGrabber)grabber;

            i_grabber.SetBufferSamples(true); //サンプルグラバでのサンプリングを開始

            //---------------------------------------------------
            // Null Renderer
            //---------------------------------------------------
            var renderer = CreateNullRenderer();

            graph.AddFilter(renderer, "NullRenderer");

            //---------------------------------------------------
            // Create Filter Graph
            //---------------------------------------------------
            var builder = DSUtility.CoCreateInstance(DSConst.ClassGUID.CLSID_CaptureGraphBuilder2) as DShowLib.DSInterface.ICaptureGraphBuilder2;

            builder.SetFiltergraph(graph);
            var pinCategory = new Guid(DShowLib.DSConst.PinCategoryGUID.PIN_CATEGORY_CAPTURE);
            var mediaType   = new Guid(DShowLib.DSConst.MediaTypeGUID.MEDIATYPE_Video);

            builder.RenderStream(ref pinCategory, ref mediaType, vcap_source, grabber, renderer);

            // SampleGrabber Format.
            {
                var mt = new DSStructure.AM_MEDIA_TYPE();
                i_grabber.GetConnectedMediaType(mt);
                var header = (DSStructure.DSVIDEOINFOHEADER)Marshal.PtrToStructure(mt.formatPtr, typeof(DSStructure.DSVIDEOINFOHEADER));
                var width  = header.BmiHeader.Width;
                var height = header.BmiHeader.Height;
                var stride = width * (header.BmiHeader.BitCount / 8);
                DSUtility.DeleteMediaType(ref mt);

                Size      = new Size(width, height);
                GetBitmap = () => GetBitmapMain(i_grabber, width, height, stride);
            }

            Start   = () => DSUtilityPlay.GraphPlay(graph);
            Stop    = () => DSUtilityPlay.GraphStop(graph);
            Release = () =>
            {
                Stop();
                DSUtility.ReleaseInstance(ref i_grabber);
                DSUtility.ReleaseInstance(ref builder);
                DSUtility.ReleaseInstance(ref graph);
            };
        }
예제 #7
0
        /// <summary>
        /// ビデオキャプチャデバイスの出力形式を選択する。
        /// 事前にGetVideoOutputFormatでメディアタイプ・サイズを得ておき、その中から希望のindexを指定する。
        /// 同時に出力サイズとフレームレートを変更することができる。
        /// </summary>
        /// <param name="index">希望のindexを指定する</param>
        /// <param name="size">Empty以外を指定すると出力サイズを変更する。事前にVIDEO_STREAM_CONFIG_CAPSで取得した可能範囲内を指定すること。</param>
        /// <param name="fps">0以上を指定するとフレームレートを変更する。事前にVIDEO_STREAM_CONFIG_CAPSで取得した可能範囲内を指定すること。</param>
        private static void SetVideoOutputFormat(DSInterface.IPin pin, int index, Size size, double fps)
        {
            // IAMStreamConfigインタフェース取得
            var config = pin as DSInterface.IAMStreamConfig;

            if (config == null)
            {
                throw new DSUtilityException.DSException("ピンはIAMStreamConfigインタフェースを公開しません。");
            }

            // フォーマット個数取得
            int cap_count = 0, cap_size = 0;

            config.GetNumberOfCapabilities(ref cap_count, ref cap_size);
            if (cap_size != Marshal.SizeOf(typeof(VIDEO_STREAM_CONFIG_CAPS)))
            {
                throw new DSUtilityException.DSException("VIDEO_STREAM_CONFIG_CAPSを取得できません。");
            }

            // データ用領域確保
            var cap_data = Marshal.AllocHGlobal(cap_size);

            // idx番目のフォーマット情報取得
            DSStructure.AM_MEDIA_TYPE mt = null;
            config.GetStreamCaps(index, out mt, cap_data);
            var cap = DSUtility.PtrToStructure <VIDEO_STREAM_CONFIG_CAPS>(cap_data);

            // 仕様ではVideoCaptureDeviceはメディア タイプごとに一定範囲の出力フォーマットをサポートできる。例えば以下のように。
            // [0]:YUY2 最小:160x120, 最大:320x240, X軸4STEP, Y軸2STEPごと
            // [1]:RGB8 最小:640x480, 最大:640x480, X軸0STEP, Y軸0STEPごと
            // SetFormatで出力サイズとフレームレートをこの範囲内で設定可能。
            // ただし試した限り、ほとんどのUSBカメラはサイズ固定(最大・最小が同じ)で返してきた。
            // https://msdn.microsoft.com/ja-jp/library/cc353344.aspx
            // https://msdn.microsoft.com/ja-jp/library/cc371290.aspx

            if (DSUtility.CompGUIDString(mt.formatType.ToString(), DSConst.FormatTypeGUID.FORMAT_VideoInfo))
            {
                var vinfo = DSUtility.PtrToStructure <DSStructure.DSVIDEOINFOHEADER>(mt.formatPtr);
                if (!size.IsEmpty)
                {
                    vinfo.BmiHeader.Width = size.Width; vinfo.BmiHeader.Height = size.Height;
                }
                if (fps > 0)
                {
                    vinfo.AvgTimePerFrame = (long)(10000000 / fps);
                }
                Marshal.StructureToPtr(vinfo, mt.formatPtr, true);
            }
            else if (DSUtility.CompGUIDString(mt.formatType.ToString(), DSConst.FormatTypeGUID.FORMAT_VideoInfo2))
            {
                var vinfo = DSUtility.PtrToStructure <DSVIDEOINFOHEADER2>(mt.formatPtr);
                if (!size.IsEmpty)
                {
                    vinfo.BmiHeader.Width = size.Width; vinfo.BmiHeader.Height = size.Height;
                }
                if (fps > 0)
                {
                    vinfo.AvgTimePerFrame = (long)(10000000 / fps);
                }
                Marshal.StructureToPtr(vinfo, mt.formatPtr, true);
            }

            // フォーマットを選択
            config.SetFormat(mt);

            // 解放
            if (cap_data != System.IntPtr.Zero)
            {
                Marshal.FreeHGlobal(cap_data);
            }
            if (mt != null)
            {
                DSUtility.DeleteMediaType(ref mt);
            }
        }
예제 #8
0
        /// <summary>
        /// ビデオキャプチャデバイスがサポートするメディアタイプ・サイズを取得する。
        /// </summary>
        private static VideoFormat[] GetVideoOutputFormat(DSInterface.IPin pin)
        {
            // IAMStreamConfigインタフェース取得
            var config = pin as DSInterface.IAMStreamConfig;

            if (config == null)
            {
                throw new DSUtilityException.DSException("IAMStreamConfigインタフェースを取得できません。");
            }

            // フォーマット個数取得
            int cap_count = 0, cap_size = 0;

            config.GetNumberOfCapabilities(ref cap_count, ref cap_size);
            if (cap_size != Marshal.SizeOf(typeof(VIDEO_STREAM_CONFIG_CAPS)))
            {
                throw new DSUtilityException.DSException("VIDEO_STREAM_CONFIG_CAPSを取得できません。");
            }

            // 返却値の確保
            var result = new VideoFormat[cap_count];

            // データ用領域確保
            var cap_data = Marshal.AllocHGlobal(cap_size);

            // 列挙
            for (int i = 0; i < cap_count; i++)
            {
                var entry = new VideoFormat();

                // x番目のフォーマット情報取得
                DSStructure.AM_MEDIA_TYPE mt = null;
                config.GetStreamCaps(i, out mt, cap_data);
                entry.Caps = DSUtility.PtrToStructure <VIDEO_STREAM_CONFIG_CAPS>(cap_data);

                // フォーマット情報の読み取り
                entry.MajorType = DSUtility.GetMediaTypeName(mt.majorType);
                entry.SubType   = DSUtility.GetMediaTypeName(mt.subType);

                if (DSUtility.CompGUIDString(mt.formatType.ToString(), DSConst.FormatTypeGUID.FORMAT_VideoInfo))
                {
                    var vinfo = DSUtility.PtrToStructure <DSStructure.DSVIDEOINFOHEADER>(mt.formatPtr);
                    entry.Size         = new Size(vinfo.BmiHeader.Width, vinfo.BmiHeader.Height);
                    entry.TimePerFrame = vinfo.AvgTimePerFrame;
                }
                else if (DSUtility.CompGUIDString(mt.formatType.ToString(), DSConst.FormatTypeGUID.FORMAT_VideoInfo2))
                {
                    var vinfo = DSUtility.PtrToStructure <DSVIDEOINFOHEADER2>(mt.formatPtr);
                    entry.Size         = new Size(vinfo.BmiHeader.Width, vinfo.BmiHeader.Height);
                    entry.TimePerFrame = vinfo.AvgTimePerFrame;
                }

                // 解放
                DSUtility.DeleteMediaType(ref mt);

                result[i] = entry;
            }

            // 解放
            Marshal.FreeHGlobal(cap_data);

            return(result);
        }
예제 #9
0
        /// <summary>
        /// Nullレンダラフィルタを作成する。
        /// </summary>
        /// <returns></returns>
        private DSInterface.IBaseFilter CreateNullRenderer()
        {
            var filter = DSUtility.CreateFilter(DSConst.FilterGUID.CLSID_NullRenderer);

            return(filter);
        }