在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
DirectShowSamples-2007-July\Samples\Capture\DxSnap Capture.cs
*************************************************************************** While the underlying libraries are covered by LGPL, this sample is released as public domain. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *****************************************************************************/ using System; using System.Drawing; using System.Drawing.Imaging; using System.Collections; using System.Runtime.InteropServices; using System.Threading; using System.Diagnostics; using System.Windows.Forms; using DirectShowLib; namespace SnapShot { /// <summary> Summary description for MainForm. </summary> internal class Capture : ISampleGrabberCB, IDisposable { #region Member variables /// <summary> graph builder interface. </summary> private IFilterGraph2 m_FilterGraph = null; // Used to snap picture on Still pin private IAMVideoControl m_VidControl = null; private IPin m_pinStill = null; /// <summary> so we can wait for the async job to finish </summary> private ManualResetEvent m_PictureReady = null; private bool m_WantOne = false; /// <summary> Dimensions of the image, calculated once in constructor for perf. </summary> private int m_videoWidth; private int m_videoHeight; private int m_stride; /// <summary> buffer for bitmap data. Always release by caller</summary> private IntPtr m_ipBuffer = IntPtr.Zero; #if DEBUG // Allow you to "Connect to remote graph" from GraphEdit DsROTEntry m_rot = null; #endif #endregion #region APIs [DllImport("Kernel32.dll", EntryPoint="RtlMoveMemory")] private static extern void CopyMemory(IntPtr Destination, IntPtr Source, [MarshalAs(UnmanagedType.U4)] int Length); #endregion // Zero based device index and device params and output window public Capture(int iDeviceNum, int iWidth, int iHeight, short iBPP, Control hControl) { DsDevice [] capDevices; // Get the collection of video devices capDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice); if (iDeviceNum + 1 > capDevices.Length) { throw new Exception("No video capture devices found at that index!"); } try { // Set up the capture graph SetupGraph( capDevices[iDeviceNum], iWidth, iHeight, iBPP, hControl); // tell the callback to ignore new images m_PictureReady = new ManualResetEvent(false); } catch { Dispose(); throw; } } /// <summary> release everything. </summary> public void Dispose() { #if DEBUG if (m_rot != null) { m_rot.Dispose(); } #endif CloseInterfaces(); if (m_PictureReady != null) { m_PictureReady.Close(); } } // Destructor ~Capture() { Dispose(); } /// <summary> /// Get the image from the Still pin. The returned image can turned into a bitmap with /// Bitmap b = new Bitmap(cam.Width, cam.Height, cam.Stride, PixelFormat.Format24bppRgb, m_ip); /// If the image is upside down, you can fix it with /// b.RotateFlip(RotateFlipType.RotateNoneFlipY); /// </summary> /// <returns>Returned pointer to be freed by caller with Marshal.FreeCoTaskMem</returns> public IntPtr Click() { int hr; // get ready to wait for new image m_PictureReady.Reset(); m_ipBuffer = Marshal.AllocCoTaskMem(Math.Abs(m_stride) * m_videoHeight); try { m_WantOne = true; // If we are using a still pin, ask for a picture if (m_VidControl != null) { // Tell the camera to send an image hr = m_VidControl.SetMode(m_pinStill, VideoControlFlags.Trigger); DsError.ThrowExceptionForHR( hr ); } // Start waiting if ( ! m_PictureReady.WaitOne(9000, false) ) { throw new Exception("Timeout waiting to get picture"); } } catch { Marshal.FreeCoTaskMem(m_ipBuffer); m_ipBuffer = IntPtr.Zero; throw; } // Got one return m_ipBuffer; } public int Width { get { return m_videoWidth; } } public int Height { get { return m_videoHeight; } } public int Stride { get { return m_stride; } } /// <summary> build the capture graph for grabber. </summary> private void SetupGraph(DsDevice dev, int iWidth, int iHeight, short iBPP, Control hControl) { int hr; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; IPin pCaptureOut = null; IPin pSampleIn = null; IPin pRenderIn = null; // Get the graphbuilder object m_FilterGraph = new FilterGraph() as IFilterGraph2; try { #if DEBUG m_rot = new DsROTEntry(m_FilterGraph); #endif // add the video input device hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter); DsError.ThrowExceptionForHR( hr ); // Find the still pin m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Still, 0); // Didn't find one. Is there a preview pin? if (m_pinStill == null) { m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Preview, 0); } // Still haven't found one. Need to put a splitter in so we have // one stream to capture the bitmap from, and one to display. Ok, we // don't *have* to do it that way, but we are going to anyway. if (m_pinStill == null) { IPin pRaw = null; IPin pSmart = null; // There is no still pin m_VidControl = null; // Add a splitter IBaseFilter iSmartTee = (IBaseFilter)new SmartTee(); try { hr = m_FilterGraph.AddFilter(iSmartTee, "SmartTee"); DsError.ThrowExceptionForHR( hr ); // Find the find the capture pin from the video device and the // input pin for the splitter, and connnect them pRaw = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); pSmart = DsFindPin.ByDirection(iSmartTee, PinDirection.Input, 0); hr = m_FilterGraph.Connect(pRaw, pSmart); DsError.ThrowExceptionForHR( hr ); // Now set the capture and still pins (from the splitter) m_pinStill = DsFindPin.ByName(iSmartTee, "Preview"); pCaptureOut = DsFindPin.ByName(iSmartTee, "Capture"); // If any of the default config items are set, perform the config // on the actual video device (rather than the splitter) if (iHeight + iWidth + iBPP > 0) { SetConfigParms(pRaw, iWidth, iHeight, iBPP); } } finally { if (pRaw != null) { Marshal.ReleaseComObject(pRaw); } if (pRaw != pSmart) { Marshal.ReleaseComObject(pSmart); } if (pRaw != iSmartTee) { Marshal.ReleaseComObject(iSmartTee); } } } else { // Get a control pointer (used in Click()) m_VidControl = capFilter as IAMVideoControl; pCaptureOut = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); // If any of the default config items are set if (iHeight + iWidth + iBPP > 0) { SetConfigParms(m_pinStill, iWidth, iHeight, iBPP); } } // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; // Configure the sample grabber IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); pSampleIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); // Get the default video renderer IBaseFilter pRenderer = new VideoRendererDefault() as IBaseFilter; hr = m_FilterGraph.AddFilter(pRenderer, "Renderer"); DsError.ThrowExceptionForHR( hr ); pRenderIn = DsFindPin.ByDirection(pRenderer, PinDirection.Input, 0); // Add the sample grabber to the graph hr = m_FilterGraph.AddFilter( baseGrabFlt, "Ds.NET Grabber" ); DsError.ThrowExceptionForHR( hr ); if (m_VidControl == null) { // Connect the Still pin to the sample grabber hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR( hr ); // Connect the capture pin to the renderer hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn); DsError.ThrowExceptionForHR( hr ); } else { // Connect the capture pin to the renderer hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn); DsError.ThrowExceptionForHR( hr ); // Connect the Still pin to the sample grabber hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR( hr ); } // Learn the video properties SaveSizeInfo(sampGrabber); ConfigVideoWindow(hControl); // Start the graph IMediaControl mediaCtrl = m_FilterGraph as IMediaControl; hr = mediaCtrl.Run(); DsError.ThrowExceptionForHR( hr ); } finally { if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (pCaptureOut != null) { Marshal.ReleaseComObject(pCaptureOut); pCaptureOut = null; } if (pRenderIn != null) { Marshal.ReleaseComObject(pRenderIn); pRenderIn = null; } if (pSampleIn != null) { Marshal.ReleaseComObject(pSampleIn); pSampleIn = null; } } } private void SaveSizeInfo(ISampleGrabber sampGrabber) { int hr; // Get the media type from the SampleGrabber AMMediaType media = new AMMediaType(); hr = sampGrabber.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) ); m_videoWidth = videoInfoHeader.BmiHeader.Width; m_videoHeight = videoInfoHeader.BmiHeader.Height; m_stride = m_videoWidth * (videoInfoHeader.BmiHeader.BitCount / 8); DsUtils.FreeAMMediaType(media); media = null; } // Set the video window within the control specified by hControl private void ConfigVideoWindow(Control hControl) { int hr; IVideoWindow ivw = m_FilterGraph as IVideoWindow; // Set the parent hr = ivw.put_Owner(hControl.Handle); DsError.ThrowExceptionForHR( hr ); // Turn off captions, etc hr = ivw.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings); DsError.ThrowExceptionForHR( hr ); // Yes, make it visible hr = ivw.put_Visible( OABool.True ); DsError.ThrowExceptionForHR( hr ); // Move to upper left corner Rectangle rc = hControl.ClientRectangle; hr = ivw.SetWindowPosition( 0, 0, rc.Right, rc.Bottom ); DsError.ThrowExceptionForHR( hr ); } private void ConfigureSampleGrabber(ISampleGrabber sampGrabber) { int hr; AMMediaType media = new AMMediaType(); // Set the media type to Video/RBG24 media.majorType = MediaType.Video; media.subType = MediaSubType.RGB24; media.formatType = FormatType.VideoInfo; hr = sampGrabber.SetMediaType( media ); DsError.ThrowExceptionForHR( hr ); DsUtils.FreeAMMediaType(media); media = null; // Configure the samplegrabber hr = sampGrabber.SetCallback( this, 1 ); DsError.ThrowExceptionForHR( hr ); } // Set the Framerate, and video size private void SetConfigParms(IPin pStill, int iWidth, int iHeight, short iBPP) { int hr; AMMediaType media; VideoInfoHeader v; IAMStreamConfig videoStreamConfig = pStill as IAMStreamConfig; // Get the existing format block hr = videoStreamConfig.GetFormat(out media); DsError.ThrowExceptionForHR(hr); try { // copy out the videoinfoheader v = new VideoInfoHeader(); Marshal.PtrToStructure( media.formatPtr, v ); // if overriding the width, set the width if (iWidth |
请发表评论