コード例 #1
0
        /// <summary>
        /// サンプルグラバを作成する
        /// </summary>
        private DirectShow.IBaseFilter CreateSampleGrabber()
        {
            var filter = DirectShow.CreateFilter(DirectShow.DsGuid.CLSID_SampleGrabber);
            var ismp   = filter as DirectShow.ISampleGrabber;

            // サンプル グラバを最初に作成したときは、優先メディア タイプは設定されていない。
            // これは、グラフ内のほぼすべてのフィルタに接続はできるが、受け取るデータ タイプを制御できないとうことである。
            // したがって、残りのグラフを作成する前に、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 DirectShow.AM_MEDIA_TYPE();

            mt.MajorType = DirectShow.DsGuid.MEDIATYPE_Video;
            mt.SubType   = DirectShow.DsGuid.MEDIASUBTYPE_RGB24;
            ismp.SetMediaType(mt);
            return(filter);
        }
コード例 #2
0
        /// <summary>
        /// ビデオキャプチャデバイスの出力形式を選択する。
        /// 事前にGetVideoOutputFormatでメディアタイプ・サイズを得ておき、その中から希望のindexを指定する。
        /// 同時に出力サイズとフレームレートを変更することができる。
        /// </summary>
        /// <param name="index">希望のindexを指定する</param>
        /// <param name="size">Empty以外を指定すると出力サイズを変更する。事前にVIDEO_STREAM_CONFIG_CAPSで取得した可能範囲内を指定すること。</param>
        /// <param name="timePerFrame">0以上を指定するとフレームレートを変更する。事前にVIDEO_STREAM_CONFIG_CAPSで取得した可能範囲内を指定すること。</param>
        private static void SetVideoOutputFormat(DirectShow.IPin pin, int index, Size size, long timePerFrame)
        {
            // IAMStreamConfigインタフェース取得
            var config = pin as DirectShow.IAMStreamConfig;

            if (config == null)
            {
                throw new InvalidOperationException("no IAMStreamConfig interface.");
            }

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

            config.GetNumberOfCapabilities(ref cap_count, ref cap_size);
            if (cap_size != Marshal.SizeOf(typeof(DirectShow.VIDEO_STREAM_CONFIG_CAPS)))
            {
                throw new InvalidOperationException("no VIDEO_STREAM_CONFIG_CAPS.");
            }

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

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

            if (mt.FormatType == DirectShow.DsGuid.FORMAT_VideoInfo)
            {
                var vinfo = PtrToStructure <DirectShow.VIDEOINFOHEADER>(mt.pbFormat);
                if (!size.IsDefault)
                {
                    vinfo.bmiHeader.biWidth  = (int)size.Width;
                    vinfo.bmiHeader.biHeight = (int)size.Height;
                }

                if (timePerFrame > 0)
                {
                    vinfo.AvgTimePerFrame = timePerFrame;
                }

                Marshal.StructureToPtr(vinfo, mt.pbFormat, true);
            }
            else if (mt.FormatType == DirectShow.DsGuid.FORMAT_VideoInfo2)
            {
                var vinfo = PtrToStructure <DirectShow.VIDEOINFOHEADER2>(mt.pbFormat);
                if (!size.IsDefault)
                {
                    vinfo.bmiHeader.biWidth  = (int)size.Width;
                    vinfo.bmiHeader.biHeight = (int)size.Height;
                }

                if (timePerFrame > 0)
                {
                    vinfo.AvgTimePerFrame = timePerFrame;
                }

                Marshal.StructureToPtr(vinfo, mt.pbFormat, true);
            }

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

            // 解放
            if (cap_data != System.IntPtr.Zero)
            {
                Marshal.FreeHGlobal(cap_data);
            }
            if (mt != null)
            {
                DirectShow.DeleteMediaType(ref mt);
            }
        }
コード例 #3
0
        /// <summary>
        /// ビデオキャプチャデバイスがサポートするメディアタイプ・サイズを取得する。
        /// </summary>
        private static VideoFormat[] GetVideoOutputFormat(DirectShow.IPin pin)
        {
            // IAMStreamConfigインタフェース取得
            if (!(pin is DirectShow.IAMStreamConfig config))
            {
                throw new InvalidOperationException("no IAMStreamConfig interface.");
            }

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

            config.GetNumberOfCapabilities(ref cap_count, ref cap_size);
            if (cap_size != Marshal.SizeOf(typeof(DirectShow.VIDEO_STREAM_CONFIG_CAPS)))
            {
                throw new InvalidOperationException("no VIDEO_STREAM_CONFIG_CAPS.");
            }

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

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

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

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

                // フォーマット情報の読み取り
                entry.MajorType = DirectShow.DsGuid.GetNickname(mt.MajorType);
                entry.SubType   = DirectShow.DsGuid.GetNickname(mt.SubType);

                if (mt.FormatType == DirectShow.DsGuid.FORMAT_VideoInfo)
                {
                    var vinfo = PtrToStructure <DirectShow.VIDEOINFOHEADER>(mt.pbFormat);
                    entry.Size         = new Size(vinfo.bmiHeader.biWidth, vinfo.bmiHeader.biHeight);
                    entry.TimePerFrame = vinfo.AvgTimePerFrame;
                }
                else if (mt.FormatType == DirectShow.DsGuid.FORMAT_VideoInfo2)
                {
                    var vinfo = PtrToStructure <DirectShow.VIDEOINFOHEADER2>(mt.pbFormat);
                    entry.Size         = new Size(vinfo.bmiHeader.biWidth, vinfo.bmiHeader.biHeight);
                    entry.TimePerFrame = vinfo.AvgTimePerFrame;
                }

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

                result[i] = entry;
            }

            // 解放
            Marshal.FreeHGlobal(cap_data);

            return(result);
        }
コード例 #4
0
        private void Init(int index, VideoFormat format)
        {
            //----------------------------------
            // Create Filter Graph
            //----------------------------------
            // +--------------------+  +----------------+  +---------------+
            // |Video Capture Source|→| Sample Grabber |→| Null Renderer |
            // +--------------------+  +----------------+  +---------------+
            //                                 ↓GetBitmap()

            var graph = DirectShow.CreateGraph();

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

            graph.AddFilter(vcap_source, "VideoCapture");

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

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

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

            //---------------------------------------------------
            // Null Renderer
            //---------------------------------------------------
            var renderer = DirectShow.CoCreateInstance(DirectShow.DsGuid.CLSID_NullRenderer) as DirectShow.IBaseFilter;

            graph.AddFilter(renderer, "NullRenderer");

            //---------------------------------------------------
            // Create Filter Graph
            //---------------------------------------------------
            var builder =
                DirectShow.CoCreateInstance(DirectShow.DsGuid.CLSID_CaptureGraphBuilder2) as
                DirectShow.ICaptureGraphBuilder2;

            builder.SetFiltergraph(graph);
            var pinCategory = DirectShow.DsGuid.PIN_CATEGORY_CAPTURE;
            var mediaType   = DirectShow.DsGuid.MEDIATYPE_Video;

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

            // SampleGrabber Format.
            {
                var mt = new DirectShow.AM_MEDIA_TYPE();
                i_grabber.GetConnectedMediaType(mt);
                var header =
                    (DirectShow.VIDEOINFOHEADER)Marshal.PtrToStructure(mt.pbFormat,
                                                                       typeof(DirectShow.VIDEOINFOHEADER));
                var width  = header.bmiHeader.biWidth;
                var height = header.bmiHeader.biHeight;
                var stride = width * (header.bmiHeader.biBitCount / 8);
                DirectShow.DeleteMediaType(ref mt);

                Size = new Size(width, height);

                // fix screen tearing problem(issue #2)
                // you can use previous method if you swap the comment line below.
                // GetBitmap = () => GetBitmapFromSampleGrabberBuffer(i_grabber, width, height, stride);
                GetBitmap = GetBitmapFromSampleGrabberCallback(i_grabber, width, height, stride);
            }

            // Assign Delegates.
            Start   = () => DirectShow.PlayGraph(graph, DirectShow.FILTER_STATE.Running);
            Stop    = () => DirectShow.PlayGraph(graph, DirectShow.FILTER_STATE.Stopped);
            Release = () =>
            {
                Stop();

                DirectShow.ReleaseInstance(ref i_grabber);
                DirectShow.ReleaseInstance(ref builder);
                DirectShow.ReleaseInstance(ref graph);
            };

            // Properties.
            Properties = new PropertyItems(vcap_source);
        }