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.\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

原文地址:https://www.cnblogs.com/Leo_wl/p/11435277.html

时间: 2024-08-04 15:18:22

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

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

 基于opencv在摄像头ubuntu根据视频获取 1  工具 原料 平台 :UBUNTU12.04 安装库  Opencv-2.3 2  安装编译执行步骤 安装编译opencv-2.3  參考http://blog.csdn.net/xiabodan/article/details/23547847 提前下载OPENCV源代码包 官方:http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/ 我的:http://dow

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

本文基于OpenBlas的编译和安装.来说明怎样从一个dll文件生成lib库文件. 參考OpenBlas的说明"Howto generate import library for MingW",和MinGW的说明HOWTO Create an ImportLibrary for a DLL using MinGW,学习怎样生成lib库.当中OpenBlas的说明讲的是怎样使用Visual studio的lib.exe工具从dll生成lib文件,而MinGW讲的是怎样把一个windows

基于Qt的动态库*.dll文件创建

有时候在做项目的时候我们需要将自己编写的类封装起来,Qt提供了一个很好的封装途径.下面将详细讲述一个简单的库的制作过程,最后再创建另外一个工程,在这个工程里面对封装的库进行调用,从而完成一个dll库从创建到调用的过程.谢谢大家指正! 第一步:先制作一个库文件. 1.首先新建一个工程,工程选项如下,我们要创建一个基于qmake的C++共享库. 2.选择库的类型和存放路径. 3.在"hellolib.cpp"中添加如下的代码,让库函数输出一行文字. 4.点击左下角的编译,如果没有错误就生成

【VC++6.0】成功制作并使用lib库,转载

微软有许多头文件,这些头文件里面定义了许多函数,但是在头文件中你却找不到函数内容的身影,因为函数主体被保存在了lib库中.保存在库中有一个好处,那就是源代码不容易被发现,也就是说其中的一些技术别人不容易学到.废话少说,我们现在就开始制作lib库. 首先,第一步,打开VC++6.0,按Ctrl+N,选择工程选项卡,选中“Win32 Static Library”选项,输入工程名称,我们这里用“Lib库”,大家可以自己选择,至于路径,随便选一个吧,反正这次只是lib的实验. 然后点击“确定”,我们两

lib库dll库的使用方法与关系

一.lib库 lib库有两种:一种是静态lib(static Lib),也就是最常见的lib库,在编译时直接将代码加入程序当中.静态lib中,一个lib文件实际上是任意个obj文件的集合,obj文件是cpp文件编译生成的. 另一种lib包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供.也就是平时编写dll时附带产生的lib,其中Lib只是Dll的附带品,是DLL导出的函数列表文件而已. 共同点:两者都是二进制文件,都是在链接时调用,使用stati

vc下DLL项目设置dll和lib库输出路径以及使用lib/dll库时的包含路径

include 头文件包含路径设置: project->setting->C/C++->常规: Additional include directories(附加包含目录): ../../include等等 链接文件输出目录:    project->setting->配置属性->常规:输出目录 例如:输出目录:$(SolutionDir)Temp\Link\$(ProjectName)\$(ConfigurationName) 解释:项目目录-Temp-Link-工程

(C/C++)基于SharpUI控件库的插件式框架开发--第一篇简介

看到题目,很明显这里要说的是插件式框架的开发,当然是用c/c++来实现的.开发对于我来说,是一种爱好,但并非科班出身,所以这里要说的一点分享就是,开发并不是会写代码就行了,最主要的是要有思路想法,比如要实现一个功能,就要知道,这个功能到底是要来实现啥的,要实现它需要什么样的算法等等,做到胸中有丘壑,再去用最简单代码去实现它,就会发现写代码是一件很享受的事情. 参加工作快两年了,一开始的是用C#开发,写了半年多的功能和小控件,上手之后,参考ICSharpCode.Core.Presentation

基于Qt的第三方库和控件

====================== 基于Qt的第三方库和控件 ======================     libQxt --------   http://dev.libqxt.org/libqxt/wiki/Home   按照文档中所流露的意思,libQxt实现了一些“Qt本来就应该有但实际上没有”的功能. 对应Qt相应的Module,Qxt有 QxtCore.QxtGui.QxtNetwork.QxtSql等模块作为Qt功能的 补充,此外,还提供了QxtWeb(Web S

使用ffmepg的lib库调试,debug版本下调试无问题,但release版本会出现跑飞的现象

如题(“使用ffmepg的lib库调试,debug版本下调试无问题,但release版本会出现跑飞的现象”). 今天使用ffmpeg进行宿放和颜色格式转换,很简单的代码,却折腾了我一天,这里说来就气啊,全是一顿的蛋疼,这里记下来,防止以后再蛋疼.呵呵 开始的时候,我以为是我的代码问题,然后我把我的代码很多地方都注释了,发现debug没问题,release还是不断跑飞,啥原因? 于是我从新建了一个测试工程,很简单,就调用一句话. 整个工程的代码如下: 1 // ffmpegtest.cpp : 定