C#|C# DirectShow预览摄像头并截图

C# DirectShow预览摄像头并截图,供大家参考,具体内容如下
本事例通过Windows DirectX Filtergraph 一些列管道将电脑所接入视频采集设备的视频流播放到制定区域,通过ISampleGrabberCB接口的BufferCB回调函数截取图片。
用此方法预览图像cpu占用率极低,比其其他事件绑定并逐帧显示图像性能更佳。
UI布局:
C#|C# DirectShow预览摄像头并截图
文章图片

代码如下:

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 interfacesGetInterfaces(); // Attach the filter graph to the capture graphhr = 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 previewhr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, (sampleGrabber as IBaseFilter),null); DsError.ThrowExceptionForHR(hr); SaveSizeInfo(sampleGrabber); // Set video window style and positionSetupVideoWindow(); // Add our graph to the running object table, which will allow// the GraphEdit application to "spy" on our graphrot = new DsROTEntry(this.graphBuilder); // Start previewing video datahr = 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 interfacesGetInterfaces(); // Attach the filter graph to the capture graphhr = 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 previewhr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, (sampleGrabber as IBaseFilter),null); DsError.ThrowExceptionForHR(hr); SaveSizeInfo(sampleGrabber); // Set video window style and positionSetupVideoWindow(); // Add our graph to the running object table, which will allow// the GraphEdit application to "spy" on our graphrot = new DsROTEntry(this.graphBuilder); // Start previewing video datahr = 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_NET11UCOMIEnumMoniker classEnum = null; UCOMIMoniker[] moniker = new UCOMIMoniker[1]; #elseIEnumMoniker classEnum = null; IMoniker[] moniker = new IMoniker[1]; #endifobject source = null; // Create the system device enumeratorICreateDevEnum devEnum = (ICreateDevEnum)new CreateDevEnum(); // Create an enumerator for the video capture deviceshr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, out classEnum, 0); DsError.ThrowExceptionForHR(hr); // The device enumerator is no more neededMarshal.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_NET11int i; if (classEnum.Next (moniker.Length, moniker, IntPtr.Zero) == 0)#elseif (classEnum.Next(moniker.Length, moniker, IntPtr.Zero) == 0)#endif{// Bind Moniker to a filter objectGuid 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 objectsMarshal.ReleaseComObject(moniker[0]); Marshal.ReleaseComObject(classEnum); // An exception is thrown if cast failreturn (IBaseFilter)source; }public void GetInterfaces(){int hr = 0; // An exception is thrown if cast failthis.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 PictureBoxhr = 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 positionedhr = this.videoWindow.put_Visible(OABool.True); DsError.ThrowExceptionForHR(hr); // Set the video positionRectangle 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 interfacehr = 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 blockhr = videoStreamConfig.GetFormat(out mediaType); DsError.ThrowExceptionForHR(hr); // copy out the videoinfoheaderVideoInfoHeader videoInfoHeader = new VideoInfoHeader(); Marshal.PtrToStructure(mediaType.formatPtr, videoInfoHeader); // if overriding the framerate, set the frame rateif (iFrameRate > 0){videoInfoHeader.AvgTimePerFrame = 10000000 / iFrameRate; }// if overriding the width, set the widthif (iWidth > 0){videoInfoHeader.BmiHeader.Width = iWidth; }// if overriding the Height, set the Heightif (iHeight > 0){videoInfoHeader.BmiHeader.Height = iHeight; }// Copy the media structure backMarshal.StructureToPtr(videoInfoHeader, mediaType.formatPtr, false); // Set the new formathr = videoStreamConfig.SetFormat(mediaType); DsError.ThrowExceptionForHR(hr); DsUtils.FreeAMMediaType(mediaType); mediaType = null; }private void SaveSizeInfo(ISampleGrabber sampleGrabber){int hr; // Get the media type from the SampleGrabberAMMediaType 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 infoVideoInfoHeader 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/RBG24media = 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; }}}

【C#|C# DirectShow预览摄像头并截图】以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    推荐阅读