• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

[引]C#WinFormDirectShow视频采集及图片抓取实例DxSnap

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

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(9000false) )
                {
                    
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( 00, 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( this1 );
            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 

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#操作摄像头发布时间:2022-07-10
下一篇:
C#调用C++动态库(dll)发布时间:2022-07-10
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap