zoukankan      html  css  js  c++  java
  • C# 基于Directshow.Net lib库 USB摄像头使用DirectShow.NET获取摄像头视频流

    https://blog.csdn.net/u010118312/article/details/91766787

    https://download.csdn.net/download/u010118312/11238555

    https://github.com/wanglong/DirectShow.NET-Webcam-Barcode-Reader

    开源社区提供了DirectShow的.NET版本,为C#开发者提供了便利。这里分享下如何用DirectShow.NET API来启动摄像头,以及获取视频流数据。

    参考原文:Read Barcode from Webcam Viewer with DirectShow.NET

    作者:Xiao Ling

    翻译:yushulx

    学习资源

    示例:获取视频流数据识别barcode

    获取连接设备:

    DsDevice[] devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);

    获取DirectShow接口:

    1.  
      int hr = 0;
    2.  
       
    3.  
      this.graphBuilder = (IFilterGraph2)new FilterGraph();
    4.  
      this.captureGraphBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
    5.  
      this.mediaControl = (IMediaControl)this.graphBuilder;
    6.  
      this.videoWindow = (IVideoWindow)this.graphBuilder;
    7.  
      DsError.ThrowExceptionForHR(hr);

    把filter graph添加到capture graph中:

    1.  
      hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder);
    2.  
      DsError.ThrowExceptionForHR(hr);

    绑定Moniker:

    1.  
      int hr = 0;
    2.  
      IEnumMoniker classEnum = null;
    3.  
      IMoniker[] moniker = new IMoniker[1];
    4.  
      object source = null;
    5.  
       
    6.  
      // Create the system device enumerator
    7.  
      ICreateDevEnum devEnum = (ICreateDevEnum)new CreateDevEnum();
    8.  
       
    9.  
      // Create an enumerator for the video capture devices
    10.  
      hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, out classEnum, 0);
    11.  
      DsError.ThrowExceptionForHR(hr);
    12.  
       
    13.  
      // The device enumerator is no more needed
    14.  
      Marshal.ReleaseComObject(devEnum);
    15.  
       
    16.  
      // If there are no enumerators for the requested type, then
    17.  
      // CreateClassEnumerator will succeed, but classEnum will be NULL.
    18.  
      if (classEnum == null)
    19.  
      {
    20.  
      throw new ApplicationException("No video capture device was detected. " +
    21.  
      "This sample requires a video capture device, such as a USB WebCam, " +
    22.  
      "to be installed and working properly. The sample will now close.");
    23.  
      }
    24.  
       
    25.  
      // Use the first video capture device on the device list.
    26.  
      // Note that if the Next() call succeeds but there are no monikers,
    27.  
      // it will return 1 (S_FALSE) (which is not a failure). Therefore, we
    28.  
      // check that the return code is 0 (S_OK).
    29.  
       
    30.  
      if (classEnum.Next(moniker.Length, moniker, IntPtr.Zero) == 0)
    31.  
      {
    32.  
      // Bind Moniker to a filter object
    33.  
      Guid iid = typeof(IBaseFilter).GUID;
    34.  
      moniker[0].BindToObject(null, null, ref iid, out source);
    35.  
      }
    36.  
      else
    37.  
      {
    38.  
      throw new ApplicationException("Unable to access video capture device!");
    39.  
      }
    40.  
       
    41.  
      // Release COM objects
    42.  
      Marshal.ReleaseComObject(moniker[0]);
    43.  
      Marshal.ReleaseComObject(classEnum);
    44.  
       
    45.  
      // An exception is thrown if cast fail
    46.  
      return (IBaseFilter)source;

    把选择的设备添加到graph中:

    1.  
      hr = this.graphBuilder.AddFilter(sourceFilter, "Video Capture");
    2.  
      DsError.ThrowExceptionForHR(hr);

    创建sampleGrabber来设置取视频流回调函数:

    1.  
      sampleGrabber = new SampleGrabber() as ISampleGrabber;
    2.  
       
    3.  
      {
    4.  
      AMMediaType media;
    5.  
      int hr;
    6.  
      // Set the media type to Video/RBG24
    7.  
      media = new AMMediaType();
    8.  
      media.majorType = MediaType.Video;
    9.  
      media.subType = MediaSubType.RGB24;
    10.  
      media.formatType = FormatType.VideoInfo;
    11.  
      hr = sampleGrabber.SetMediaType(media);
    12.  
      DsError.ThrowExceptionForHR(hr);
    13.  
      DsUtils.FreeAMMediaType(media);
    14.  
      media = null;
    15.  
      hr = sampleGrabber.SetCallback(this, 1);
    16.  
      DsError.ThrowExceptionForHR(hr);
    17.  
      }

    把SampleGrabber添加到graph中:

    1.  
      hr = this.graphBuilder.AddFilter(sampleGrabber as IBaseFilter, "Frame Callback");
    2.  
      DsError.ThrowExceptionForHR(hr);

    初始化视频属性:

    1.  
      private void SetConfigParams(ICaptureGraphBuilder2 capGraph, IBaseFilter capFilter, int iFrameRate, int iWidth, int iHeight)
    2.  
      {
    3.  
      int hr;
    4.  
      object config;
    5.  
      AMMediaType mediaType;
    6.  
      // Find the stream config interface
    7.  
      hr = capGraph.FindInterface(
    8.  
      PinCategory.Capture, MediaType.Video, capFilter, typeof(IAMStreamConfig).GUID, out config);
    9.  
       
    10.  
      IAMStreamConfig videoStreamConfig = config as IAMStreamConfig;
    11.  
      if (videoStreamConfig == null)
    12.  
      {
    13.  
      throw new Exception("Failed to get IAMStreamConfig");
    14.  
      }
    15.  
       
    16.  
      // Get the existing format block
    17.  
      hr = videoStreamConfig.GetFormat(out mediaType);
    18.  
      DsError.ThrowExceptionForHR(hr);
    19.  
       
    20.  
      // copy out the videoinfoheader
    21.  
      VideoInfoHeader videoInfoHeader = new VideoInfoHeader();
    22.  
      Marshal.PtrToStructure(mediaType.formatPtr, videoInfoHeader);
    23.  
       
    24.  
      // if overriding the framerate, set the frame rate
    25.  
      if (iFrameRate > 0)
    26.  
      {
    27.  
      videoInfoHeader.AvgTimePerFrame = 10000000 / iFrameRate;
    28.  
      }
    29.  
       
    30.  
      // if overriding the width, set the width
    31.  
      if (iWidth > 0)
    32.  
      {
    33.  
      videoInfoHeader.BmiHeader.Width = iWidth;
    34.  
      }
    35.  
       
    36.  
      // if overriding the Height, set the Height
    37.  
      if (iHeight > 0)
    38.  
      {
    39.  
      videoInfoHeader.BmiHeader.Height = iHeight;
    40.  
      }
    41.  
       
    42.  
      // Copy the media structure back
    43.  
      Marshal.StructureToPtr(videoInfoHeader, mediaType.formatPtr, false);
    44.  
       
    45.  
      // Set the new format
    46.  
      hr = videoStreamConfig.SetFormat(mediaType);
    47.  
      DsError.ThrowExceptionForHR(hr);
    48.  
       
    49.  
      DsUtils.FreeAMMediaType(mediaType);
    50.  
      mediaType = null;
    51.  
      }

    绘制画面:

    1.  
      hr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, (sampleGrabber as IBaseFilter), null);
    2.  
      DsError.ThrowExceptionForHR(hr);

    设置视频输出窗口,调整视频位置:

    1.  
      int hr = 0;
    2.  
      // Set the video window to be a child of the PictureBox
    3.  
      hr = this.videoWindow.put_Owner(pictureBox1.Handle);
    4.  
      DsError.ThrowExceptionForHR(hr);
    5.  
       
    6.  
      hr = this.videoWindow.put_WindowStyle(WindowStyle.Child);
    7.  
      DsError.ThrowExceptionForHR(hr);
    8.  
       
    9.  
      // Make the video window visible, now that it is properly positioned
    10.  
      hr = this.videoWindow.put_Visible(OABool.True);
    11.  
      DsError.ThrowExceptionForHR(hr);
    12.  
       
    13.  
      // Set the video position
    14.  
      Rectangle rc = pictureBox1.ClientRectangle;
    15.  
      hr = videoWindow.SetWindowPosition(0, 0, _previewWidth, _previewHeight);
    16.  
      DsError.ThrowExceptionForHR(hr);

    启动摄像头预览画面:

    1.  
      rot = new DsROTEntry(this.graphBuilder);
    2.  
      hr = this.mediaControl.Run();
    3.  
      DsError.ThrowExceptionForHR(hr);

    获取视频流数据,异步读取barcode:

    1.  
      public int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
    2.  
      {
    3.  
       
    4.  
      Bitmap v = new Bitmap(_previewWidth, _previewHeight, _previewStride,
    5.  
      PixelFormat.Format24bppRgb, pBuffer);
    6.  
      v.RotateFlip(RotateFlipType.Rotate180FlipX);
    7.  
       
    8.  
      if (isFinished)
    9.  
      {
    10.  
      this.BeginInvoke((MethodInvoker)delegate
    11.  
      {
    12.  
      isFinished = false;
    13.  
      ReadBarcode(v);
    14.  
      isFinished = true;
    15.  
      });
    16.  
      }
    17.  
      return 0;
    18.  
      }

    源码

    https://github.com/yushulx/DirectShow.NET-Webcam-Barcode-Reader

    C# 基于Directshow.Net lib库 USB摄像头硬件按钮捕获程序采用无窗模式显示

    经过半个月的学习,虽然对Directshow还知之甚少,但总算完成了自己的需求,故mark,希望可以帮助有需要的;

           先说点闲篇,本人不是专业程序员出身,属于半路出家,学了C#,搞了点应用开发;之前是做电路设计的,所以我的程序说好听点叫移植,说白了就是东拼西凑出来,能实现功能是我的最大追求,至于效率等更高层次的,还不是我现在能搞定的,代码肯定有很多需要修改的,大家自己看着用;

           首先,我的项目需求原先是客户的USB摄像头,上面带了个硬件按钮,客户按下按钮,需要捕获一张图片,然后再做其他的分析;程序需求2个显示串口,可以在不同的tab下显示,所以我需要2个可以获取视屏的显示窗口,同时这两个窗口还需要显示视屏流,同时中间可以停止,并显示图片,处理图片,处理完再接通视屏流;一开始我是用的是OPENCV,C#版,但是OPENCV好像没有找到可以捕获USB摄像头的硬件按钮的函数接口,实在没办法,网上搜索,发现用Directshow 的Still功能可以实现,所以才有了半个月的Directshow学习;同样为了实现目的,我用了4个panel控件,2个用于显示视屏流,2个用于显示按键捕获的图片;

           先说一下无窗模式,因为之前用的是有窗模式显示,但是用4个显示时,有2个不显示在Panel上,而单独弹出显示窗口,后来才发现可以使用无窗模式;

    我的程序主要采用的是C# Directshow.net lib实现,程序是基于该库的Sample实例,整合拼凑而来;库和实例地址如下:

    库:https://sourceforge.net/projects/directshownet/

    示例:https://sourceforge.net/projects/directshownet/files/DirectShowSamples/2010-February/

    当然这些都是好几年前的,很久没有跟新了,不过对我来说还能用,还是很不错的,我才基于Sample示例里面的Capwmv和VMR9Snapper 2个示例合成并加以改编完成的;先来看一下显示界面:

    上面2个Panel显示的是视屏流,一个为Capture一个为Preview;

    下面2个为捕获显示图片,用于后续图像处理;

    Filter设置如下:

    USB camera一般有2个Output pin,一个捕获(capture),一个静态(still),捕获用有试试显示视频流,still用于按钮抓取图像,Smart tee用于将2个1个输入视频流转成2个,中间的MJPEG 和Color Space 不需要;但EditGrhap会自动添加;

    不多说了,程序代碼如下:

    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;

    using DirectShowLib;

    using Microsoft.Win32;
    using System.Diagnostics;
    using System.IO;

    namespace DirectShowLib.Sample
    {
    public class MainForm : System.Windows.Forms.Form, ISampleGrabberCB, IDisposable
    {
    private System.Windows.Forms.MainMenu mainMenu;
    private System.Windows.Forms.OpenFileDialog openFileDialog;
    private System.Windows.Forms.MenuItem menuFile;
    private System.Windows.Forms.MenuItem menuItem1;
    private System.Windows.Forms.MenuItem menuFileExit;
    private IContainer components;

    // Used to snap picture on Still pin
    private IAMVideoControl m_VidControl = null;
    private IPin pPreviewOut = null;
    private IPin pPreviewOutStill = null;
    private int m_videoWidth;
    private int m_videoHeight;
    private int m_stride;

    #if DEBUG
    // Allow you to "Connect to remote graph" from GraphEdit
    DsROTEntry m_rot = null;
    #endif
    // DirectShow stuff
    private IFilterGraph2 graphBuilder = null;
    private IMediaControl mediaControl = null;
    private IBaseFilter vmr9 = null;
    private IBaseFilter vmr9_2 = null;
    private IBaseFilter vmr9_3 = null;
    private IBaseFilter vmr9_4 = null;

    private IVMRWindowlessControl9 windowlessCtrl = null;
    private IVMRWindowlessControl9 windowlessCtrl_2 = null;
    private IVMRWindowlessControl9 windowlessCtrl_3 = null;
    private IVMRWindowlessControl9 windowlessCtrl_4 = null;

    private SaveFileDialog saveFileDialog;
    private Panel panel1; // Needed to remove delegates
    private Panel panel2;
    private Panel panel3;
    private Panel panel4;

    private IntPtr m_ipBuffer = IntPtr.Zero;
    public delegate void Changepicturebox(int num, bool visible, Bitmap bitmap1); //picbox
    public delegate void Changeimagebox(int num, bool visible); //imagebox
    public Changepicturebox changepicbox1;
    public Changeimagebox changeimgbox1;

    string file_name_image = null;
    int count_pic = 0;

    // Menus stuff
    private MenuItem menuSnap;

    public MainForm()
    {
    InitializeComponent();
    changepicbox1 = FunChangepicture;
    }

    /// <summary>
    /// Nettoyage des ressources utilis閑s.
    /// </summary>
    protected override void Dispose( bool disposing )
    {
    if( disposing )
    {
    if (components != null)
    {
    components.Dispose();
    }
    }
    // Clean-up DirectShow interfaces
    CloseInterfaces();
    base.Dispose( disposing );
    }

    #region Code g閚閞?par le Concepteur Windows Form
    /// <summary>
    /// M閠hode requise pour la prise en charge du concepteur - ne modifiez pas
    /// le contenu de cette m閠hode avec l'閐iteur de code.
    /// </summary>
    private void InitializeComponent()
    {
    this.components = new System.ComponentModel.Container();
    System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
    this.mainMenu = new System.Windows.Forms.MainMenu(this.components);
    this.menuFile = new System.Windows.Forms.MenuItem();
    this.menuSnap = new System.Windows.Forms.MenuItem();
    this.menuItem1 = new System.Windows.Forms.MenuItem();
    this.menuFileExit = new System.Windows.Forms.MenuItem();
    this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
    this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
    this.panel1 = new System.Windows.Forms.Panel();
    this.panel2 = new System.Windows.Forms.Panel();
    this.panel3 = new System.Windows.Forms.Panel();
    this.panel4 = new System.Windows.Forms.Panel();
    this.SuspendLayout();
    //
    // mainMenu
    //
    this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
    this.menuFile});
    //
    // menuFile
    //
    this.menuFile.Index = 0;
    this.menuFile.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
    this.menuSnap,
    this.menuItem1,
    this.menuFileExit});
    this.menuFile.Text = "File";
    //
    // menuSnap
    //
    this.menuSnap.Index = 0;
    this.menuSnap.Text = "Save image...";
    this.menuSnap.Click += new System.EventHandler(this.menuSnap_Click);
    //
    // menuItem1
    //
    this.menuItem1.Index = 1;
    this.menuItem1.Text = "-";
    //
    // menuFileExit
    //
    this.menuFileExit.Index = 2;
    this.menuFileExit.Text = "Exit";
    this.menuFileExit.Click += new System.EventHandler(this.menuFileExit_Click);
    //
    // openFileDialog
    //
    this.openFileDialog.Filter = resources.GetString("openFileDialog.Filter");
    //
    // panel1
    //
    this.panel1.BackColor = System.Drawing.SystemColors.ControlDarkDark;
    this.panel1.Location = new System.Drawing.Point(3, 3);
    this.panel1.Name = "panel1";
    this.panel1.Size = new System.Drawing.Size(639, 475);
    this.panel1.TabIndex = 1;
    //
    // panel2
    //
    this.panel2.BackColor = System.Drawing.SystemColors.ControlDarkDark;
    this.panel2.Location = new System.Drawing.Point(654, 3);
    this.panel2.Name = "panel2";
    this.panel2.Size = new System.Drawing.Size(639, 475);
    this.panel2.TabIndex = 1;
    //
    // panel3
    //
    this.panel3.BackColor = System.Drawing.SystemColors.ControlDarkDark;
    this.panel3.Location = new System.Drawing.Point(3, 493);
    this.panel3.Name = "panel3";
    this.panel3.Size = new System.Drawing.Size(639, 475);
    this.panel3.TabIndex = 2;
    //
    // panel4
    //
    this.panel4.BackColor = System.Drawing.SystemColors.ControlDarkDark;
    this.panel4.Location = new System.Drawing.Point(654, 493);
    this.panel4.Name = "panel4";
    this.panel4.Size = new System.Drawing.Size(639, 475);
    this.panel4.TabIndex = 3;
    //
    // MainForm
    //
    this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
    this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
    this.ClientSize = new System.Drawing.Size(1305, 980);
    this.Controls.Add(this.panel2);
    this.Controls.Add(this.panel1);
    this.Controls.Add(this.panel4);
    this.Controls.Add(this.panel3);
    this.Menu = this.mainMenu;
    this.Name = "MainForm";
    this.Text = "VMR Snapper";
    this.Load += new System.EventHandler(this.MainForm_Load);
    this.ResumeLayout(false);

    }
    #endregion
    private void CloseInterfaces()
    {
    if (mediaControl != null)
    mediaControl.Stop();

    if (vmr9 != null)
    {
    Marshal.ReleaseComObject(vmr9);
    vmr9 = null;
    windowlessCtrl = null;
    }
    if (vmr9_2 != null)
    {
    Marshal.ReleaseComObject(vmr9_2);
    vmr9_2 = null;
    windowlessCtrl_2 = null;
    }

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

    }

    private void ConfigureVMR9InWindowlessMode()
    {
    int hr = 0;

    IVMRFilterConfig9 filterConfig = (IVMRFilterConfig9) vmr9;

    // Not really needed for VMR9 but don't forget calling it with VMR7
    hr = filterConfig.SetNumberOfStreams(1);
    DsError.ThrowExceptionForHR(hr);

    // Change VMR9 mode to Windowless
    hr = filterConfig.SetRenderingMode(VMR9Mode.Windowless);
    DsError.ThrowExceptionForHR(hr);

    windowlessCtrl = (IVMRWindowlessControl9) vmr9;

    // Set "Parent" window
    hr = windowlessCtrl.SetVideoClippingWindow(this.panel1.Handle);
    DsError.ThrowExceptionForHR(hr);

    // Set Aspect-Ratio
    hr = windowlessCtrl.SetAspectRatioMode(VMR9AspectRatioMode.LetterBox);
    DsError.ThrowExceptionForHR(hr);

    if (windowlessCtrl != null)
    {
    hr = windowlessCtrl.SetVideoPosition(null, DsRect.FromRectangle(this.panel1.ClientRectangle));
    }
    }

    private void ConfigureVMR9InWindowlessMode_2()
    {
    int hr = 0;

    IVMRFilterConfig9 filterConfig = (IVMRFilterConfig9)vmr9_2;

    // Not really needed for VMR9 but don't forget calling it with VMR7
    hr = filterConfig.SetNumberOfStreams(1);
    DsError.ThrowExceptionForHR(hr);

    // Change VMR9 mode to Windowless
    hr = filterConfig.SetRenderingMode(VMR9Mode.Windowless);
    DsError.ThrowExceptionForHR(hr);

    windowlessCtrl_2 = (IVMRWindowlessControl9)vmr9_2;

    // Set "Parent" window
    hr = windowlessCtrl_2.SetVideoClippingWindow(this.panel2.Handle);
    DsError.ThrowExceptionForHR(hr);

    // Set Aspect-Ratio
    hr = windowlessCtrl_2.SetAspectRatioMode(VMR9AspectRatioMode.LetterBox);
    DsError.ThrowExceptionForHR(hr);

    if (windowlessCtrl_2 != null)
    {
    hr = windowlessCtrl_2.SetVideoPosition(null, DsRect.FromRectangle(this.panel2.ClientRectangle));
    }
    }

    private void ConfigureVMR9InWindowlessMode_3()
    {
    int hr = 0;

    IVMRFilterConfig9 filterConfig = (IVMRFilterConfig9)vmr9_3;

    // Not really needed for VMR9 but don't forget calling it with VMR7
    hr = filterConfig.SetNumberOfStreams(1);
    DsError.ThrowExceptionForHR(hr);

    // Change VMR9 mode to Windowless
    hr = filterConfig.SetRenderingMode(VMR9Mode.Windowless);
    DsError.ThrowExceptionForHR(hr);

    windowlessCtrl_3 = (IVMRWindowlessControl9)vmr9_3;

    // Set "Parent" window
    hr = windowlessCtrl_3.SetVideoClippingWindow(this.panel3.Handle);
    DsError.ThrowExceptionForHR(hr);

    // Set Aspect-Ratio
    hr = windowlessCtrl_3.SetAspectRatioMode(VMR9AspectRatioMode.LetterBox);
    DsError.ThrowExceptionForHR(hr);

    if (windowlessCtrl_3 != null)
    {
    hr = windowlessCtrl_3.SetVideoPosition(null, DsRect.FromRectangle(this.panel3.ClientRectangle));
    }
    }

    private void ConfigureVMR9InWindowlessMode_4()
    {
    int hr = 0;

    IVMRFilterConfig9 filterConfig = (IVMRFilterConfig9)vmr9_4;

    // Not really needed for VMR9 but don't forget calling it with VMR7
    hr = filterConfig.SetNumberOfStreams(1);
    DsError.ThrowExceptionForHR(hr);

    // Change VMR9 mode to Windowless
    hr = filterConfig.SetRenderingMode(VMR9Mode.Windowless);
    DsError.ThrowExceptionForHR(hr);

    windowlessCtrl_4 = (IVMRWindowlessControl9)vmr9_4;

    // Set "Parent" window
    hr = windowlessCtrl_4.SetVideoClippingWindow(this.panel4.Handle);
    DsError.ThrowExceptionForHR(hr);

    // Set Aspect-Ratio
    hr = windowlessCtrl_4.SetAspectRatioMode(VMR9AspectRatioMode.LetterBox);
    DsError.ThrowExceptionForHR(hr);

    if (windowlessCtrl_4 != null)
    {
    hr = windowlessCtrl_4.SetVideoPosition(null, DsRect.FromRectangle(this.panel4.ClientRectangle));
    }
    }

    private void menuFileExit_Click(object sender, System.EventArgs e)
    {
    CloseInterfaces();
    this.Dispose();
    }

    [STAThread]
    static void Main()
    {
    using (MainForm form = new MainForm())
    {
    Application.Run(form);
    }
    }

    private void menuSnap_Click(object sender, EventArgs e)
    {
    count_pic++;
    snapImage();
    panel3.BackgroundImage = Image.FromFile(file_name_image);
    panel4.BackgroundImage = Image.FromFile(file_name_image);
    }

    // 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)
    {
    v.BmiHeader.Width = iWidth;
    }
    // if overriding the Height, set the Height
    if (iHeight > 0)
    {
    v.BmiHeader.Height = iHeight;
    }
    // if overriding the bits per pixel
    if (iBPP > 0)
    {
    v.BmiHeader.BitCount = iBPP;
    }
    // Copy the media structure back
    Marshal.StructureToPtr(v, media.formatPtr, false);
    // Set the new format
    hr = videoStreamConfig.SetFormat( media );
    DsError.ThrowExceptionForHR(hr);
    }
    finally
    {
    DsUtils.FreeAMMediaType(media);
    media = null;
    }
    }

    private void SetConfigParmsStill(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)
    {
    v.BmiHeader.Width = iWidth;
    }
    // if overriding the Height, set the Height
    if (iHeight > 0)
    {
    v.BmiHeader.Height = iHeight;
    }
    // if overriding the bits per pixel
    if (iBPP > 0)
    {
    v.BmiHeader.BitCount = iBPP;
    }
    // Copy the media structure back
    Marshal.StructureToPtr(v, media.formatPtr, false);
    // Set the new format
    hr = videoStreamConfig.SetFormat(media);
    DsError.ThrowExceptionForHR(hr);
    }
    finally
    {
    DsUtils.FreeAMMediaType(media);
    media = null;
    }
    }
    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);
    }
    private void ConfigureSampleGrabberStill(ISampleGrabber sampGrabberStill)
    {
    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 = sampGrabberStill.SetMediaType(media);
    DsError.ThrowExceptionForHR(hr);

    DsUtils.FreeAMMediaType(media);
    media = null;

    // Configure the samplegrabber
    hr = sampGrabberStill.SetCallback(this, 1);
    DsError.ThrowExceptionForHR(hr);
    }
    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;
    }
    private void SetupGraph(DsDevice dev, int iWidth, int iHeight, short iBPP)
    {
    int hr;
    ISampleGrabber sampGrabber = null;
    ISampleGrabber sampGrabberStill = null; //add by tim

    IBaseFilter capFilter = null;
    IPin pCaptureOut = null;
    IPin pCaptureOutStill = null; //add by tim
    IPin pStill = null; //add by tim
    IPin pSampleIn = null;
    IPin pSampleOut = null;

    IPin pSampleInStill = null; //add by tim
    IPin pSampleOutStill = null; //add by tim

    IPin pRenderIn = null;
    IPin pRenderIn_2 = null;

    IPin pRenderIn_3 = null; //add by tim
    IPin pRenderIn_4 = null; //add by tim

    // Get the graphbuilder object
    graphBuilder = new FilterGraph() as IFilterGraph2;
    try
    {
    #if DEBUG
    m_rot = new DsROTEntry(graphBuilder);
    #endif
    // add the video input device
    hr = graphBuilder.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter);
    DsError.ThrowExceptionForHR(hr);

    IPin pRaw = null;
    IPin pSmart = null;

    IPin pRawStill = null; //add by tim
    IPin pSmartStill = null; //add by tim

    // There is no still pin
    m_VidControl = null;
    // Add a splitter
    IBaseFilter iSmartTee = (IBaseFilter)new SmartTee();
    IBaseFilter iSmartTeeStill = (IBaseFilter)new SmartTee(); //add by tim
    try
    {
    hr = graphBuilder.AddFilter(iSmartTee, "SmartTee");
    DsError.ThrowExceptionForHR(hr);

    hr = graphBuilder.AddFilter(iSmartTeeStill, "SmartTeeStill"); //add by tim
    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 = graphBuilder.Connect(pRaw, pSmart);
    DsError.ThrowExceptionForHR(hr);

    pStill = DsFindPin.ByCategory(capFilter, PinCategory.Still, 0); // by tim
    pSmartStill = DsFindPin.ByDirection(iSmartTeeStill, PinDirection.Input, 0); // by tim

    hr = graphBuilder.Connect(pStill, pSmartStill); // by tim
    DsError.ThrowExceptionForHR(hr); // by tim

    // Now set the capture and still pins (from the splitter)
    pPreviewOut = DsFindPin.ByName(iSmartTee, "Preview");
    pCaptureOut = DsFindPin.ByName(iSmartTee, "Capture");

    pPreviewOutStill = DsFindPin.ByName(iSmartTeeStill, "Preview");
    pCaptureOutStill = DsFindPin.ByName(iSmartTeeStill, "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);
    SetConfigParms(pStill, iWidth, iHeight, iBPP);
    }
    }
    finally
    {
    if (pRaw != null)
    {
    Marshal.ReleaseComObject(pRaw);
    }
    if (pRaw != pSmart)
    {
    Marshal.ReleaseComObject(pSmart);
    }
    if (pRaw != iSmartTee)
    {
    Marshal.ReleaseComObject(iSmartTee);
    }

    if (pStill != null) // by tim
    {
    Marshal.ReleaseComObject(pStill);
    }
    if (pStill != pSmartStill) // by tim
    {
    Marshal.ReleaseComObject(pSmartStill);
    }
    if (pStill != iSmartTeeStill) // by tim
    {
    Marshal.ReleaseComObject(iSmartTeeStill);
    }
    }

    // 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);
    pSampleOut = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0);

    // Get the SampleGrabber interface
    sampGrabberStill = new SampleGrabber() as ISampleGrabber; // by tim
    // Configure the sample grabber Still
    IBaseFilter baseGrabFlt_Still = sampGrabberStill as IBaseFilter; // by tim
    ConfigureSampleGrabberStill(sampGrabberStill);
    pSampleInStill = DsFindPin.ByDirection(baseGrabFlt_Still, PinDirection.Input, 0); // by tim
    pSampleOutStill = DsFindPin.ByDirection(baseGrabFlt_Still, PinDirection.Output, 0); // by tim


    // Get the default video renderer
    vmr9 = (IBaseFilter)new VideoMixingRenderer9();
    ConfigureVMR9InWindowlessMode();
    hr = graphBuilder.AddFilter(vmr9, "Video Mixing Renderer 9");
    DsError.ThrowExceptionForHR(hr);
    pRenderIn = DsFindPin.ByDirection(vmr9, PinDirection.Input, 0);

    // Get the default video renderer
    vmr9_2 = (IBaseFilter)new VideoMixingRenderer9();
    ConfigureVMR9InWindowlessMode_2();
    hr = graphBuilder.AddFilter(vmr9_2, "Video Mixing Renderer 9_2");
    DsError.ThrowExceptionForHR(hr);
    pRenderIn_2 = DsFindPin.ByDirection(vmr9_2, PinDirection.Input, 0);


    // Get the default video renderer
    vmr9_3 = (IBaseFilter)new VideoMixingRenderer9(); // by tim
    ConfigureVMR9InWindowlessMode_3();
    hr = graphBuilder.AddFilter(vmr9_3, "Video Mixing Renderer 9_3");
    DsError.ThrowExceptionForHR(hr);
    pRenderIn_3 = DsFindPin.ByDirection(vmr9_3, PinDirection.Input, 0);

    // Get the default video renderer
    vmr9_4 = (IBaseFilter)new VideoMixingRenderer9(); // by tim
    ConfigureVMR9InWindowlessMode_4();
    hr = graphBuilder.AddFilter(vmr9_4, "Video Mixing Renderer 9_4");
    DsError.ThrowExceptionForHR(hr);
    pRenderIn_4 = DsFindPin.ByDirection(vmr9_4, PinDirection.Input, 0);


    hr = graphBuilder.AddFilter(baseGrabFlt, "Ds.NET Grabber");
    DsError.ThrowExceptionForHR(hr);

    hr = graphBuilder.AddFilter(baseGrabFlt_Still, "Still"); //Still
    DsError.ThrowExceptionForHR(hr);

    // Connect the Still pin to the sample grabber
    hr = graphBuilder.Connect(pPreviewOut, pSampleIn);
    DsError.ThrowExceptionForHR(hr);

    // Connect the Still pin to the sample grabber
    hr = graphBuilder.Connect(pPreviewOutStill, pSampleInStill); // by tim
    DsError.ThrowExceptionForHR(hr);

    // Connect the capture pin to the renderer
    hr = graphBuilder.Connect(pCaptureOut, pRenderIn_2);
    DsError.ThrowExceptionForHR(hr);

    // Connect the capture pin to the renderer
    hr = graphBuilder.Connect(pSampleOut, pRenderIn);
    DsError.ThrowExceptionForHR(hr);

    // Connect the capture pin to the renderer
    hr = graphBuilder.Connect(pCaptureOutStill, pRenderIn_4); // by tim
    DsError.ThrowExceptionForHR(hr);

    // Connect the capture pin to the renderer
    hr = graphBuilder.Connect(pSampleOutStill, pRenderIn_3); // by tim
    DsError.ThrowExceptionForHR(hr);

    SaveSizeInfo(sampGrabber);
    SaveSizeInfo(sampGrabberStill); // by tim
    mediaControl = (IMediaControl)graphBuilder;
    hr = mediaControl.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;
    }
    if (sampGrabberStill != null)
    {
    Marshal.ReleaseComObject(sampGrabberStill);
    sampGrabberStill = null;
    }
    if (pCaptureOutStill != null)
    {
    Marshal.ReleaseComObject(pCaptureOutStill);
    pCaptureOutStill = null;
    }
    if (pRenderIn_3 != null)
    {
    Marshal.ReleaseComObject(pRenderIn_3);
    pRenderIn_3 = null;
    }
    if (pRenderIn_4 != null)
    {
    Marshal.ReleaseComObject(pRenderIn_4);
    pRenderIn_4 = null;
    }
    if (pSampleInStill != null)
    {
    Marshal.ReleaseComObject(pSampleInStill);
    pSampleInStill = null;
    }
    }
    }

    int ISampleGrabberCB.SampleCB(double SampleTime, IMediaSample pSample)
    {
    Marshal.ReleaseComObject(pSample);
    return 0;
    }

    /// <summary> buffer callback, COULD BE FROM FOREIGN THREAD. </summary>
    int ISampleGrabberCB.BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
    {
    //按钮捕获的图片及后续处理可以在此执行
    //{.....}

    return 0;
    }


    public void FunChangepicture(int num, bool visible, Bitmap bitmap1)
    {
    if (num == 1)
    {
    panel3.BackgroundImage = bitmap1;
    }
    else if (num == 2)
    {
    panel4.BackgroundImage = bitmap1;
    }
    }
    private void snapImage()
    {
    if (windowlessCtrl != null)
    {
    IntPtr currentImage = IntPtr.Zero;
    Bitmap bmp = null;

    try
    {
    int hr = windowlessCtrl.GetCurrentImage(out currentImage);
    DsError.ThrowExceptionForHR(hr);

    if (currentImage != IntPtr.Zero)
    {
    BitmapInfoHeader structure = new BitmapInfoHeader();
    Marshal.PtrToStructure(currentImage, structure);

    bmp = new Bitmap(structure.Width, structure.Height, (structure.BitCount / 8) * structure.Width, System.Drawing.Imaging.PixelFormat.Format32bppArgb, new IntPtr(currentImage.ToInt64() + 40));
    bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
    file_name_image = Application.StartupPath + "\Image\pic" + DateTime.Now.ToString("yyyyMMdd") + count_pic.ToString("D4") + ".jpg";
    bmp.Save(file_name_image, System.Drawing.Imaging.ImageFormat.Jpeg);
    }
    }
    catch (Exception anyException)
    {
    MessageBox.Show("Failed getting image: " + anyException.Message);
    }
    finally
    {
    if (bmp != null)
    {
    bmp.Dispose();
    }
    Marshal.FreeCoTaskMem(currentImage);
    }
    }
    }

    private void MainForm_Load(object sender, EventArgs e)
    {
    Capture(0,640, 480, 24);
    }
    public void Capture(int iDeviceNum, int iWidth, int iHeight, short iBPP)
    {
    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);
    }
    catch
    {
    Dispose();
    throw;
    }
    }
    }
    }
    源码下载:https://download.csdn.net/download/u010118312/11238555

    如果运行有错误,请重新添加引用Directshow-2005.lib,因为路径不同;
    ————————————————
    版权声明:本文为CSDN博主「秦风古韵」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/u010118312/article/details/91766787

  • 相关阅读:
    2018.12.29-dtoj-3626
    2018.12.28-bzoj-3784-树上的路径
    2018.12.28-bzoj-2006-[NOI2010]超级钢琴
    2018.12.28-dtoj-3648-寝室管理
    2018.12.27-dtoj-4089-line
    2018.12.27-dtoj-3151-相遇
    2018.12.25-dtoj-4086-针老师(truth) || dtoj-3657: 排列(permutation)
    不要62 hdu2089
    Kia's Calculation hdu4726
    The Moving Points hdu4717
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/11435277.html
Copyright © 2011-2022 走看看