C# DirectShow预览摄像头并截图

C# DirectShow预览摄像头并截图,供大家参考,具体内容如下

本事例通过Windows DirectX Filtergraph 一些列管道将电脑所接入视频采集设备的视频流播放到制定区域,通过ISampleGrabberCB接口的BufferCB回调函数截取图片。
用此方法预览图像cpu占用率极低,比其其他事件绑定并逐帧显示图像性能更佳。

UI布局:

代码如下:

using System;
using System.Drawing;
using System.Windows.Forms;

using DirectShowLib;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Drawing.Imaging;

namespace Test
{
    public partial class FormDirect : Form, ISampleGrabberCB
    {

        private int _previewWidth = 640;
        private int _previewHeight = 480;
        private int _previewStride = 0;
        private int _previewFPS = 30;
        private volatile bool isGrab = false;

        IVideoWindow videoWindow = null;
        IMediaControl mediaControl = null;
        IFilterGraph2 graphBuilder = null;
        ICaptureGraphBuilder2 captureGraphBuilder = null;

        DsROTEntry rot = null;

        public FormDirect()
        {
            InitializeComponent();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //截图
            isGrab = true;

        }

        private void button3_Click(object sender, EventArgs e)
        {
            string button_text = button3.Text;
            if (button_text.Equals("Start Webcam"))
            {
                button3.Text = "Stop Webcam";
                StartCamera();
            }
            else
            {
                button3.Text = "Start Webcam";
                StopCamera();
            }
        }

        private void StartCamera()
        {

            DsDevice[] devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
            if (devices.Length == 0)
            {
                MessageBox.Show("No USB webcam connected");
                button3.Text = "Start Webcam";
                return;
            }
            else
            {

                CaptureVideo(devices[0]);
            }
        }

        private void StopCamera()
        {
            button3.Text = "Start Webcam";
            CloseInterfaces();
        }

        public void CaptureVideo(DsDevice device)
        {
            pictureBox1.Image = null;
            int hr = 0;
            IBaseFilter sourceFilter = null;
            ISampleGrabber sampleGrabber = null;

            try
            {
                // Get DirectShow interfaces
                GetInterfaces();

                // Attach the filter graph to the capture graph
                hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder);
                DsError.ThrowExceptionForHR(hr);

                // Use the system device enumerator and class enumerator to find
                // a video capture/preview device, such as a desktop USB video camera.
                sourceFilter = SelectCaptureDevice(device);
                // Add Capture filter to graph.
                hr = this.graphBuilder.AddFilter(sourceFilter, "Video Capture");
                DsError.ThrowExceptionForHR(hr);

                // Initialize SampleGrabber.
                sampleGrabber = new SampleGrabber() as ISampleGrabber;
                // Configure SampleGrabber. Add preview callback.
                ConfigureSampleGrabber(sampleGrabber);
                // Add SampleGrabber to graph.
                hr = this.graphBuilder.AddFilter(sampleGrabber as IBaseFilter, "Frame Callback");
                DsError.ThrowExceptionForHR(hr);

                // Configure preview settings.
                SetConfigParams(this.captureGraphBuilder, sourceFilter, _previewFPS, _previewWidth, _previewHeight);

                // Render the preview
                hr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, (sampleGrabber as IBaseFilter),null);

                DsError.ThrowExceptionForHR(hr);

                SaveSizeInfo(sampleGrabber);

                // Set video window style and position
                SetupVideoWindow();

                // Add our graph to the running object table, which will allow
                // the GraphEdit application to "spy" on our graph
                rot = new DsROTEntry(this.graphBuilder);

                // Start previewing video data
                hr = this.mediaControl.Run();
                DsError.ThrowExceptionForHR(hr);
            }
            catch
            {
                MessageBox.Show("An unrecoverable error has occurred.");
            }
            finally
            {
                if (sourceFilter != null)
                {
                    Marshal.ReleaseComObject(sourceFilter);
                    sourceFilter = null;
                }

                if (sampleGrabber != null)
                {
                    Marshal.ReleaseComObject(sampleGrabber);
                    sampleGrabber = null;
                }
            }
        }

        public void CaptureVideo()
        {
            pictureBox1.Image = null;
            int hr = 0;
            IBaseFilter sourceFilter = null;
            ISampleGrabber sampleGrabber = null;

            try
            {
                // Get DirectShow interfaces
                GetInterfaces();

                // Attach the filter graph to the capture graph
                hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder);
                DsError.ThrowExceptionForHR(hr);

                // Use the system device enumerator and class enumerator to find
                // a video capture/preview device, such as a desktop USB video camera.
                sourceFilter = FindCaptureDevice();
                // Add Capture filter to graph.
                hr = this.graphBuilder.AddFilter(sourceFilter, "Video Capture");
                DsError.ThrowExceptionForHR(hr);

                // Initialize SampleGrabber.
                sampleGrabber = new SampleGrabber() as ISampleGrabber;
                // Configure SampleGrabber. Add preview callback.
                ConfigureSampleGrabber(sampleGrabber);

                // Add SampleGrabber to graph.
                hr = this.graphBuilder.AddFilter(sampleGrabber as IBaseFilter, "Frame Callback");
                DsError.ThrowExceptionForHR(hr);

                // Configure preview settings.
                SetConfigParams(this.captureGraphBuilder, sourceFilter, _previewFPS, _previewWidth, _previewHeight);

                // Render the preview
                hr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, (sampleGrabber as IBaseFilter),null);
                DsError.ThrowExceptionForHR(hr);

                SaveSizeInfo(sampleGrabber);

                // Set video window style and position
                SetupVideoWindow();

                // Add our graph to the running object table, which will allow
                // the GraphEdit application to "spy" on our graph
                rot = new DsROTEntry(this.graphBuilder);

                // Start previewing video data
                hr = this.mediaControl.Run();
                DsError.ThrowExceptionForHR(hr);
            }
            catch
            {
                MessageBox.Show("An unrecoverable error has occurred.");
            }
            finally
            {
                if (sourceFilter != null)
                {
                    Marshal.ReleaseComObject(sourceFilter);
                    sourceFilter = null;
                }

                if (sampleGrabber != null)
                {
                    Marshal.ReleaseComObject(sampleGrabber);
                    sampleGrabber = null;
                }
            }
        }

        public IBaseFilter SelectCaptureDevice(DsDevice device)
        {
            object source = null;
            Guid iid = typeof(IBaseFilter).GUID;
            device.Mon.BindToObject(null, null, ref iid, out source);
            return (IBaseFilter)source;
        }

        public IBaseFilter FindCaptureDevice()
        {
            int hr = 0;
#if USING_NET11
      UCOMIEnumMoniker classEnum = null;
      UCOMIMoniker[] moniker = new UCOMIMoniker[1];
#else
            IEnumMoniker classEnum = null;
            IMoniker[] moniker = new IMoniker[1];
#endif
            object source = null;

            // Create the system device enumerator
            ICreateDevEnum devEnum = (ICreateDevEnum)new CreateDevEnum();

            // Create an enumerator for the video capture devices
            hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, out classEnum, 0);
            DsError.ThrowExceptionForHR(hr);

            // The device enumerator is no more needed
            Marshal.ReleaseComObject(devEnum);

            // If there are no enumerators for the requested type, then
            // CreateClassEnumerator will succeed, but classEnum will be NULL.
            if (classEnum == null)
            {
                throw new ApplicationException("No video capture device was detected.\r\n\r\n" +
                                               "This sample requires a video capture device, such as a USB WebCam,\r\n" +
                                               "to be installed and working properly.  The sample will now close.");
            }

            // Use the first video capture device on the device list.
            // Note that if the Next() call succeeds but there are no monikers,
            // it will return 1 (S_FALSE) (which is not a failure).  Therefore, we
            // check that the return code is 0 (S_OK).
#if USING_NET11
      int i;
      if (classEnum.Next (moniker.Length, moniker, IntPtr.Zero) == 0)
#else
            if (classEnum.Next(moniker.Length, moniker, IntPtr.Zero) == 0)
#endif
            {
                // Bind Moniker to a filter object
                Guid iid = typeof(IBaseFilter).GUID;
                moniker[0].BindToObject(null, null, ref iid, out source);
            }
            else
            {
                throw new ApplicationException("Unable to access video capture device!");
            }

            // Release COM objects
            Marshal.ReleaseComObject(moniker[0]);
            Marshal.ReleaseComObject(classEnum);

            // An exception is thrown if cast fail
            return (IBaseFilter)source;
        }

        public void GetInterfaces()
        {
            int hr = 0;

            // An exception is thrown if cast fail
            this.graphBuilder = (IFilterGraph2)new FilterGraph();
            this.captureGraphBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
            this.mediaControl = (IMediaControl)this.graphBuilder;
            this.videoWindow = (IVideoWindow)this.graphBuilder;

            DsError.ThrowExceptionForHR(hr);
        }

        public void CloseInterfaces()
        {
            if (mediaControl != null)
            {
                int hr = mediaControl.StopWhenReady();
                DsError.ThrowExceptionForHR(hr);
            }

            if (videoWindow != null)
            {
                videoWindow.put_Visible(OABool.False);
                videoWindow.put_Owner(IntPtr.Zero);
            }

            // Remove filter graph from the running object table.
            if (rot != null)
            {
                rot.Dispose();
                rot = null;
            }

            // Release DirectShow interfaces.
            Marshal.ReleaseComObject(this.mediaControl); this.mediaControl = null;
            Marshal.ReleaseComObject(this.videoWindow); this.videoWindow = null;
            Marshal.ReleaseComObject(this.graphBuilder); this.graphBuilder = null;
            Marshal.ReleaseComObject(this.captureGraphBuilder); this.captureGraphBuilder = null;
        }

        public void SetupVideoWindow()
        {
            int hr = 0;

            // Set the video window to be a child of the PictureBox
            hr = this.videoWindow.put_Owner(pictureBox1.Handle);
            DsError.ThrowExceptionForHR(hr);

            hr = this.videoWindow.put_WindowStyle(WindowStyle.Child);
            DsError.ThrowExceptionForHR(hr);

            // Make the video window visible, now that it is properly positioned
            hr = this.videoWindow.put_Visible(OABool.True);
            DsError.ThrowExceptionForHR(hr);

            // Set the video position
            Rectangle rc = pictureBox1.ClientRectangle;
            hr = videoWindow.SetWindowPosition(0, 0, _previewWidth, _previewHeight);
            DsError.ThrowExceptionForHR(hr);
        }

        private void SetConfigParams(ICaptureGraphBuilder2 capGraph, IBaseFilter capFilter, int iFrameRate, int iWidth, int iHeight)
        {
            int hr;
            object config;
            AMMediaType mediaType;
            // Find the stream config interface
            hr = capGraph.FindInterface(
                PinCategory.Capture, MediaType.Video, capFilter, typeof(IAMStreamConfig).GUID, out config);

            IAMStreamConfig videoStreamConfig = config as IAMStreamConfig;
            if (videoStreamConfig == null)
            {
                throw new Exception("Failed to get IAMStreamConfig");
            }

            // Get the existing format block
            hr = videoStreamConfig.GetFormat(out mediaType);
            DsError.ThrowExceptionForHR(hr);

            // copy out the videoinfoheader
            VideoInfoHeader videoInfoHeader = new VideoInfoHeader();
            Marshal.PtrToStructure(mediaType.formatPtr, videoInfoHeader);

            // if overriding the framerate, set the frame rate
            if (iFrameRate > 0)
            {
                videoInfoHeader.AvgTimePerFrame = 10000000 / iFrameRate;
            }

            // if overriding the width, set the width
            if (iWidth > 0)
            {
                videoInfoHeader.BmiHeader.Width = iWidth;
            }

            // if overriding the Height, set the Height
            if (iHeight > 0)
            {
                videoInfoHeader.BmiHeader.Height = iHeight;
            }

            // Copy the media structure back
            Marshal.StructureToPtr(videoInfoHeader, mediaType.formatPtr, false);

            // Set the new format
            hr = videoStreamConfig.SetFormat(mediaType);
            DsError.ThrowExceptionForHR(hr);

            DsUtils.FreeAMMediaType(mediaType);
            mediaType = null;
        }

        private void SaveSizeInfo(ISampleGrabber sampleGrabber)
        {
            int hr;

            // Get the media type from the SampleGrabber
            AMMediaType media = new AMMediaType();
            hr = sampleGrabber.GetConnectedMediaType(media);
            DsError.ThrowExceptionForHR(hr);

            if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero))
            {
                throw new NotSupportedException("Unknown Grabber Media Format");
            }

            // Grab the size info
            VideoInfoHeader videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader));
            _previewStride = _previewWidth * (videoInfoHeader.BmiHeader.BitCount / 8);

            DsUtils.FreeAMMediaType(media);
            media = null;
        }

        private void ConfigureSampleGrabber(ISampleGrabber sampleGrabber)
        {
            AMMediaType media;
            int hr;

            // Set the media type to Video/RBG24
            media = new AMMediaType();
            media.majorType = MediaType.Video;
            media.subType = MediaSubType.RGB24;
            media.formatType = FormatType.VideoInfo;

            hr = sampleGrabber.SetMediaType(media);
            DsError.ThrowExceptionForHR(hr);

            DsUtils.FreeAMMediaType(media);
            media = null;

            hr = sampleGrabber.SetCallback(this, 1);
            DsError.ThrowExceptionForHR(hr);
        }

        public int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
        {

            if (isGrab)
            {
                Bitmap v = new Bitmap(_previewWidth, _previewHeight, _previewStride,PixelFormat.Format24bppRgb, pBuffer);
                //v.RotateFlip(RotateFlipType.Rotate180FlipX);
                v.RotateFlip(RotateFlipType.Rotate90FlipX);

                this.BeginInvoke((MethodInvoker)delegate
                {
                    pictureBox2.BackgroundImage = v;

                    isGrab = false;
                });
            }
            return 0;
        }

        public int SampleCB(double SampleTime, IMediaSample pSample)
        {
            //throw new NotImplementedException();
            return 0;
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C#实现属于自己的QQ截图工具

    下面就具体介绍下实现截图工具的实现思路. 为了让大家更清楚地知道如何去实现自己的截图工具,首先我来描述下截图的一个过程--我们使用QQ的截图工具和Windows 自带的截图工具都可以发现,当我们点击QQ窗体中的截图按钮时,此时我们将看到一个全屏图片,然后我们可以在其上截图,当鼠标左键按下时,即代表开始截图,并我们可以移动鼠标来改变截图的大小,鼠标弹起时即代表结束截图,此时我们可以双击矩形区域完全截图,并且可以通过粘贴操作把截取的图片粘贴到聊天窗口的发送区,鼠标右键点击则是退出截图.这样我们截图的

  • c# 控件截图的简单实例

    首先选择保存图片的路径: 复制代码 代码如下: saveFileDialog1.Title = "保存";            saveFileDialog1.Filter = "*.png|*.png";            saveFileDialog1.RestoreDirectory = true;            if (saveFileDialog1.ShowDialog() == DialogResult.OK)            {  

  • c#实现winform屏幕截图并保存的示例

    复制代码 代码如下: using System.Runtime.InteropServices;using System.Drawing.Imaging;    [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]    private static extern bool BitBlt( IntPtr hdcDest,   //   目标   DC的句柄                       int n

  • 解决C# 截取当前程序窗口指定位置截图的实现方法

    要想完成这个功用,首先要了解一下在C#中如何调用API(利用程序交口)函数.固然在.Net框架中已经降求了很多类库,400电话,这些类库的功效也非常强盛,但关于一些Windows顶层编程来道,仍是要通过调用这些API函数才可以实现.一切API皆在"Kernel"."User "和"GDI"三个库中得以运转:其中"Kernel",他的库名为 "KERNEL32.DLL", 他重要用于发生取操做体系之间的联系关

  • 解决C#全屏幕截图的实现方法

    今天一位同事想写一个全屏幕截图的代码.当然要实现的第一步是能够获取整个屏幕的位图,记得Win32 API的CreateDC, BitBlt等函数可以使用.于是上网查了下,果然屏幕截图用这些函数.但winform已经可以把API都忘记了,所以得寻找一个无Win32 API的实现方式.综合了网上的实现,以及自己的一些设计,实现思路如下:1. 开始截图时,创建一个与屏幕大小一样的位图,然后用Graphics.CopyFromScreen()把屏幕位图拷贝到该位图上.这是很关键的一步,这样所有的操作就都

  • C#实现网页截图功能

    网页截图是很常见的实用功能,今天就为大家共享一个实现浏览器截图的代码,主要程序代码如下所示: private void Form_Load(object sender, EventArgs e) { //接收web url string colle = string.Empty; string url = string.Empty; //获取进程调用传入的命令 string[] args = Environment.GetCommandLineArgs(); string[] args = ne

  • C#实现通过ffmpeg从flv视频文件中截图的方法

    本文实例讲述了C#实现通过ffmpeg从flv视频文件中截图的方法.分享给大家供大家参考.具体分析如下: 需要先下载ffmpeg,这是开源的,代码如下所示: 复制代码 代码如下: using System; using System.Configuration; public class PublicMethod:System.Web.UI.Page {     public PublicMethod()     {     }     //文件路径     public static stri

  • C#中的FileUpload 选择后的预览效果具体实现

    C#中的FileUpload 选择后的预览效果 实现方法: HTML: 复制代码 代码如下: <asp:FileUpload ID="fupTmpPic" runat="server" onchange="onFileChange(this);" /> <asp:Image ID="imgDimensionalPic" runat="server" /> JS: 复制代码 代码如下:

  • C#截图程序类似腾讯QQ截图实现代码

    最近把以前制作的截图程序重新写了一下动了一个大手术 高质量仿照的TX的截图程序 先看几个效果图 拖动过程中显示当前鼠标下一小块的图像信息 尺寸.颜色信息的  注意 这里颜色是用的ARGB 本来截图的话RGB就够了 可是我把那个做成了控件 不仅截图可用 其他地方也可用作图像的选取 具体看代码就知道了 并且我还加了一个可以截图的同时把鼠标也捕获下来 现在看到的是我自己的截图程序 那个工具条啥的 是从TX的截图程序上面拔下来的 上面是几个工具条上的工具的三种粗细型号的展示 看到的蓝色的粗的刷笔 本来想

  • 对指定的网页进行截图的效果 C#版

    碰到一个项目,需要对指定的网页进行截图保存,晕死! 需求永远都是怪异的..... 解决是关键- 遂写了以下代码,快准狠!(因为赶时间!) 可以实现对指定的页面获取,按指定的大小生成缩略图,当然也可以1:1的产生图, 页面上的javascript 运行对截图貌似没任何影响,相当的正常,我个人都觉得很神奇. 首先对项目添加系统引用 System.Drawing; System.Drawing.Design; System.Windows.Forms; 获取指定网页并转换成图片的类: using Sy

随机推荐