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.\r\n\r\n" +
  21.  
    "This sample requires a video capture device, such as a USB WebCam,\r\n" +
  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

C# 基于Directshow.Net lib库 USB摄像头使用DirectShow.NET获取摄像头视频流的更多相关文章

  1. 基于opencv在摄像头ubuntu根据视频获取

     基于opencv在摄像头ubuntu根据视频获取 1  工具 原料 平台 :UBUNTU12.04 安装库  Opencv-2.3 2  安装编译执行步骤 安装编译opencv-2.3  參考h ...

  2. ubuntu下安装opencv库+Python2.7环境安装及开发摄像头拍照应用

    好久没有更新了,今天更一篇最近遇到的问题,及解决办法,后面博客得继续写起来 安装 #使用Python下的lib库直接进行安装 apt-get install python-opencv 测试 #使用如 ...

  3. Keil中LIB库的作用、生成与调用

    LIB库有什么用,一个简单的例子就是Silicon Labs为C8051F单片机USB提供的USBXpress LIB库了,如USB发送数据.接收数据等,都是通用性很强的函数,但因为保密的原因,这个函 ...

  4. 由动态库文件dll生成lib库文件(手动生成.def文件,然后使用lib命令编译,非常牛),同理可使用dll生成.a库文件

    本文基于OpenBlas的编译和安装,来说明如何从一个dll文件生成lib库文件. 参考OpenBlas的说明“Howto generate import library for MingW”,和Mi ...

  5. 利用cocoapods创建基于git的私有库

    上一篇文章记录了我利用cocoapods创建基于SVN的私有库的全部过程,今天我再记录一下基于git创建的过程. 整体先说明一下创建一个私有的podspec包括如下那么几个步骤: 创建并设置一个私有的 ...

  6. 利用cocoapods创建基于git的私有库Spec Repo

    上一篇文章记录了我利用cocoapods创建基于SVN的私有库的全部过程,今天我再记录一下基于git创建的过程. 整体先说明一下创建一个私有的podspec包括如下那么几个步骤: 创建并设置一个私有的 ...

  7. QT 编译遇到重定义;不同的基类型&在QT中使用C++ lib库

    最近在使用osg和qt开发,在集成osg时候因为我使用的qt版本为非opengl的版本,导致qt自己封了一遍opengl的一些基类变量如double 这时候就会跟osg中声明的opengl的类型冲突, ...

  8. 由动态库文件dll生成lib库文件

    本文基于OpenBlas的编译和安装.来说明怎样从一个dll文件生成lib库文件. 參考OpenBlas的说明"Howto generate import library for MingW ...

  9. Element没更新了?Element没更新,基于El的扩展库更新

    think-vuele 基于Vue和ElementUI框架进行整合二次开发的一个框架.提供一些elementUI没有的或当时没有的控件.优化了或简化了便于2B软件开发的一些控件 demo:http:/ ...

随机推荐

  1. Linux中三种SCSI target的介绍之各个target的优劣

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/scaleqiao/article/deta ...

  2. 洛谷 P1083 借教室 题解

    P1083 借教室 题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借 ...

  3. 微信小程序微信登录

    开发接口 登录 wx.login wx.checkSession 签名加密 小程序登录 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系. 登录流程时序 ...

  4. 发现Mathematica中求逆出错

    发现Mathematica中应用Inverse求逆时出错.

  5. 【golang】使用rpcx不指定tags报错 undefined: serverplugin.ConsulRegisterPlugin

    为了避免引入不必要的库, rpcx采用了 Go 条件编译 的特性, 你可以只引入必要的特性. 比如你只使用 etcd 作为注册中心的时候, 你不希望引入 consul.zookeeper相关的库,你需 ...

  6. SSH如何使用

    如何查看SSH服务是否已经安装? 在终端命令行执行 rpm -qa | grep "ssh" 执行结果请看下图,说明已经安装:其实在安装linux操作系统的时候默认就会安装上的. ...

  7. Ubuntu16.04 RYU pip命令安装

    pip命令安装方法 sudo apt install gcc python-dev libffi-dev libssl-dev libxml2-dev libxslt1-dev zlib1g-dev ...

  8. 15.linux iptables防火墙规则vsftp服务

    一.服务所开启的端口号.          dhcp 67       samba 139 445       http 80  https 443       mysql 3306         ...

  9. FIS3

    #npm install -g cnpm --registry=https://registry.npm.taobao.org#cnpm install -g fis3 npm install fis ...

  10. C++提示没有与这些操作数匹配的<<运算符

    应该是忘了#include.#include<string>