DirectShow(C#)、预览FPS和CPU使用率随着时间的推移而下降
我正在构建一个winforms应用程序来学习DirectShow。我让一切都正常工作,除了一个奇怪的问题,CPU使用率和FPS随着时间的推移而下降。 使用中的电脑规格很低。因此,一开始我的CPU使用率为40%,这很好。然后在30分钟左右的时间里,它就降到了4%。当然,FPS也会下降到几FPS 我从互联网上运行并试用了其他示例应用程序,它们的运行方式大致相同。它们也都使用DirectShowLib。因此,基础与我的应用程序相同DirectShow(C#)、预览FPS和CPU使用率随着时间的推移而下降,c#,webcam,directshow,frame-rate,directshow.net,C#,Webcam,Directshow,Frame Rate,Directshow.net,我正在构建一个winforms应用程序来学习DirectShow。我让一切都正常工作,除了一个奇怪的问题,CPU使用率和FPS随着时间的推移而下降。 使用中的电脑规格很低。因此,一开始我的CPU使用率为40%,这很好。然后在30分钟左右的时间里,它就降到了4%。当然,FPS也会下降到几FPS 我从互联网上运行并试用了其他示例应用程序,它们的运行方式大致相同。它们也都使用DirectShowLib。因此,基础与我的应用程序相同 using System; using System.Diagnost
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Windows.Forms;
using DirectShowLib;
namespace WebCamPerfTestProject
{
public partial class Cftp_Form1 : Form
{
public enum PlayState : int
{
Stopped,
Paused,
Running,
Init
}
private PlayState CurrentState = PlayState.Stopped;
private int WM_GRAPHNOTIFY = Convert.ToInt32("0X8000", 16) + 1;
private IVideoWindow videoWindow = null;
private IMediaControl mediaControl = null;
private IMediaEventEx mediaEventEx = null;
private IGraphBuilder graph = null;
private ICaptureGraphBuilder2 pGraphBuilder = null;
private IBaseFilter pUSB = null;
private IAMStreamConfig streamConfig = null;
private VideoInfoHeader format = null;
private AMMediaType pmt = null;
private decimal ratio = Decimal.Divide(1280, 720); //temp values
private decimal height;
public Cftp_Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Resize += new EventHandler(WebCamControl_Resize);
Console.WriteLine("Building graph...");
GetInterfaces();
Console.WriteLine("Start capture...");
CaptureVideo(graph);
}
private void GetInterfaces()
{
graph = (IGraphBuilder)(new FilterGraph());
pGraphBuilder = (ICaptureGraphBuilder2)(new CaptureGraphBuilder2());
mediaControl = (IMediaControl)graph;
videoWindow = (IVideoWindow)graph;
mediaEventEx = (IMediaEventEx)graph;
// send notification messages to the control window
int hr = mediaEventEx.SetNotifyWindow(Handle, WM_GRAPHNOTIFY, IntPtr.Zero);
DsError.ThrowExceptionForHR(hr);
}
private void CaptureVideo(IGraphBuilder pGraph)
{
int hr = 0;
hr = pGraphBuilder.SetFiltergraph(pGraph);
DsError.ThrowExceptionForHR(hr);
pUSB = FindCaptureDevice();
hr = pGraph.AddFilter(pUSB, "WebCamControl Video");
DsError.ThrowExceptionForHR(hr);
//add smartTee
IBaseFilter pSmartTee = (IBaseFilter)new SmartTee();
hr = pGraph.AddFilter(pSmartTee, "Smart Tee");
DsError.ThrowExceptionForHR(hr);
//connect smart tee to camera
hr = pGraphBuilder.RenderStream(null, MediaType.Video, pUSB, null, pSmartTee);
DsError.ThrowExceptionForHR(hr);
pmt = new AMMediaType();
pmt.majorType = MediaType.Video;
pmt.subType = MediaSubType.MJPG;
pmt.formatType = FormatType.VideoInfo;
pmt.fixedSizeSamples = false; //true for 640x480
pmt.formatSize = 88;
pmt.sampleSize = 2764800; //2764800 614400
pmt.temporalCompression = false;
//////////////////////////////////
format = new VideoInfoHeader();
format.SrcRect = new DsRect();
format.TargetRect = new DsRect();
format.BitRate = 5000000;
format.AvgTimePerFrame = 666666;
//////////////////////////////////
format.BmiHeader = new BitmapInfoHeader();
format.BmiHeader.Size = 40;
format.BmiHeader.Width = 1280;
format.BmiHeader.Height = 720;
format.BmiHeader.Planes = 1;
format.BmiHeader.BitCount = 24;
format.BmiHeader.Compression = 1196444237; //1196444237 //844715353
format.BmiHeader.ImageSize = 2764800; //2764800 614400
pmt.formatPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(format));
Marshal.StructureToPtr(format, pmt.formatPtr, false);
Debug.WriteLine(getCatName(pUSB) + " at line 130");
streamConfig = (IAMStreamConfig)GetPin(pUSB, getCatName(pUSB));
hr = streamConfig.SetFormat(pmt);
DsUtils.FreeAMMediaType(pmt);
if (hr < 0)
{
CapTest.CustomMessage.ShowMessage("Can`t set format");
DsError.ThrowExceptionForHR(hr);
}
//add MJPEG Decompressor
IBaseFilter pMJPEGDecompressor = (IBaseFilter)new MjpegDec();
hr = pGraph.AddFilter(pMJPEGDecompressor, "MJPEG Decompressor");
if (hr < 0)
{
CapTest.CustomMessage.ShowMessage("Can`t add MJPEG Decompressor");
DsError.ThrowExceptionForHR(hr);
}
//add SampleGrabber
IBaseFilter pSampleGrabber = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_SampleGrabber));
hr = pGraph.AddFilter(pSampleGrabber, "SampleGrabber");
checkHR(hr, "Can't add SampleGrabber to graph");
//connect Smart Tee and SampleGrabber
hr = pGraph.ConnectDirect(GetPin(pSmartTee, "Preview"), GetPin(pSampleGrabber, "Input"), null);
checkHR(hr, "Can't connect Smart Tee and SampleGrabber");
//connect smart tee to camera
hr = pGraphBuilder.RenderStream(null, MediaType.Video, pSampleGrabber, null, pMJPEGDecompressor);
//add Color Space Converter
IBaseFilter pColorSpaceConverter = (IBaseFilter)new Colour();
hr = pGraph.AddFilter(pColorSpaceConverter, "Color Space Converter");
if (hr < 0)
{
CapTest.CustomMessage.ShowMessage("Can't add Color Space Converter to graph");
DsError.ThrowExceptionForHR(hr);
}
hr = pGraphBuilder.RenderStream(null, MediaType.Video, pMJPEGDecompressor, null, pColorSpaceConverter);
DsError.ThrowExceptionForHR(hr);
IBaseFilter videoRender = (IBaseFilter)new VideoRenderer();
hr = pGraph.AddFilter(videoRender, "Video Render");
DsError.ThrowExceptionForHR(hr);
hr = pGraphBuilder.RenderStream(null, MediaType.Video, pColorSpaceConverter, null, videoRender);
DsError.ThrowExceptionForHR(hr);
Debug.WriteLine(DsError.GetErrorText(hr) + " is error in rendering");
Marshal.ReleaseComObject(pUSB);
SetupVideoWindow();
}
//Access the camera
private IBaseFilter FindCaptureDevice()
{
IEnumMoniker classEnum = null;
IMoniker[] moniker = new IMoniker[1];
object source = null;
ICreateDevEnum devEnum = (ICreateDevEnum)(new CreateDevEnum());
int hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, out classEnum, CDef.None);
DsError.ThrowExceptionForHR(hr);
Marshal.ReleaseComObject(devEnum);
if (classEnum == null)
{
throw new ApplicationException("No video capture device was detected.\\r\\n\\r\\n" + "This sample requires a video capture device, such as a USB WebCam,\\r\\nto be installed and working properly. The sample will now close.");
}
IntPtr none = IntPtr.Zero;
if (classEnum.Next(moniker.Length, moniker, none) == 0)
{
Guid iid = typeof(IBaseFilter).GUID;
moniker[0].BindToObject(null, null, ref iid, out source);
}
else
{
throw new ApplicationException("Unable to access video capture device!");
}
Marshal.ReleaseComObject(moniker[0]);
Marshal.ReleaseComObject(classEnum);
return (IBaseFilter)source;
}
static IPin GetPin(IBaseFilter filter, string pinname)
{
IEnumPins epins;
int hr = filter.EnumPins(out epins);
if (hr < 0)
{
CapTest.CustomMessage.ShowMessage("Cant enumerate pins");
DsError.ThrowExceptionForHR(hr);
}
IntPtr fetched = Marshal.AllocCoTaskMem(4);
IPin[] pins = new IPin[1];
while (epins.Next(1, pins, fetched) == 0)
{
PinInfo pinfo;
pins[0].QueryPinInfo(out pinfo);
bool found = (pinfo.name == "Capture");
CapTest.CustomMessage.ShowMessage(pinfo.name + " is PIN NAME");
DsUtils.FreePinInfo(pinfo);
if (found)
return pins[0];
}
CapTest.CustomMessage.ShowMessage("Pin not found");
DsError.ThrowExceptionForHR(hr);
return null;
}
string getCatName(IBaseFilter filter)
{
string retval = "";
IEnumPins epins;
int hr = filter.EnumPins(out epins);
if (hr < 0)
{
CapTest.CustomMessage.ShowMessage("Cant enumerate pins");
DsError.ThrowExceptionForHR(hr);
}
IntPtr fetched = Marshal.AllocCoTaskMem(4);
IPin[] pins = new IPin[1];
while (epins.Next(1, pins, fetched) == 0)
{
PinInfo pinfo;
pins[0].QueryPinInfo(out pinfo);
bool found = (pinfo.name == "Capture");
CapTest.CustomMessage.ShowMessage(pinfo.name + " is pinname on getCatName");
DsUtils.FreePinInfo(pinfo);
if (found)
retval = pinfo.name;
}
CapTest.CustomMessage.ShowMessage("Pin found " + retval);
return retval;
}
private void SetupVideoWindow()
{
int hr = 0;
//set the video window to be a child of the main window
//putowner : Sets the owning parent window for the video playback window.
hr = videoWindow.put_Owner(pictureBox1.Handle);
DsError.ThrowExceptionForHR(hr);
hr = videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren);
DsError.ThrowExceptionForHR(hr);
//Use helper function to position video window in client rect of main application window
WebCamControl_Resize(this, null);
//Make the video window visible, now that it is properly positioned
//put_visible : This method changes the visibility of the video window.
hr = videoWindow.put_Visible(OABool.True);
DsError.ThrowExceptionForHR(hr);
hr = mediaControl.Run();
DsError.ThrowExceptionForHR(hr);
HandleGraphEvent();
CurrentState = PlayState.Running;
Cftp_Form1.ActiveForm.WindowState = FormWindowState.Maximized;
}
private void HandleGraphEvent()
{
int hr = 0;
EventCode evCode = 0;
IntPtr evParam1 = IntPtr.Zero;
IntPtr evParam2 = IntPtr.Zero;
while (mediaEventEx != null && mediaEventEx.GetEvent(out evCode, out evParam1, out evParam2, 0) == 0)
{
// Free event parameters to prevent memory leaks associated with
// event parameter data. While this application is not interested
// in the received events, applications should always process them.
hr = mediaEventEx.FreeEventParams(evCode, evParam1, evParam2);
DsError.ThrowExceptionForHR(hr);
Console.WriteLine(evCode + " " + evParam1 + " " + evParam2);
// Insert event processing code here, if desired (see http://msdn2.microsoft.com/en-us/library/ms783649.aspx)
}
}
private void ReleaseInterfaces()
{
if (mediaControl != null)
mediaControl.StopWhenReady();
CurrentState = PlayState.Stopped;
// stop notifications of events
if (mediaEventEx != null)
mediaEventEx.SetNotifyWindow(IntPtr.Zero, WM_GRAPHNOTIFY, IntPtr.Zero);
//// below we relinquish ownership (IMPORTANT!) of the video window.
//// Failing to call put_Owner can lead to assert failures within
//// the video renderer, as it still assumes that it has a valid
//// parent window.
if (videoWindow != null)
{
videoWindow.put_Visible(OABool.False);
videoWindow.put_Owner(IntPtr.Zero);
}
// Release DirectShow interfaces
Marshal.ReleaseComObject(mediaControl);
mediaControl = null;
Marshal.ReleaseComObject(mediaEventEx);
mediaEventEx = null;
Marshal.ReleaseComObject(videoWindow);
videoWindow = null;
Marshal.ReleaseComObject(graph);
graph = null;
Marshal.ReleaseComObject(pGraphBuilder);
pGraphBuilder = null;
}
private void WebCamControl_Resize(object sender, System.EventArgs e)
{
//Resize the video preview window to match owner window size
//Calculate the ratio like 16/9
// 1280/720=1.77777778
if (videoWindow != null)
height = Convert.ToDecimal(pictureBox1.Width) / ratio;
int iheight = (int)height;
videoWindow.SetWindowPosition(0, 0, pictureBox1.Width, iheight);
//Debug.WriteLine(pictureBox1.Width +" "+ iheight + " ratio:" + ratio);
mediaControl.Run();
}
private void Cftp_Form1_FormClosing(object sender, FormClosingEventArgs e)
{
ReleaseInterfaces();
}
}
}
使用系统;
使用系统诊断;
使用System.Runtime.InteropServices;
使用System.Runtime.InteropServices.ComTypes;
使用System.Windows.Forms;
使用DirectShowLib;
命名空间WebCamperTestProject
{
公共部分类Cftp_表格1:表格
{
公共枚举播放状态:int
{
停止,
停顿,
跑步
初始化
}
私有播放状态CurrentState=PlayState.Stopped;
private int WM_GRAPHNOTIFY=转换为32(“0X8000”,16)+1;
私有IVideoWindow videoWindow=null;
专用IMediaControl mediaControl=null;
私有IMediaEventEx mediaEventEx=null;
私有IGraphBuilder图形=空;
私有ICaptureGraphBuilder2 pGraphBuilder=null;
专用IBaseFilter pUSB=null;
私有IAMStreamConfig streamConfig=null;
私有VideoInfoHeader格式=空;
私有AMMediaType pmt=null;
私有十进制比率=十进制。除以(1280720);//临时值
私有十进制高度;
公共Cftp_Form1()
{
初始化组件();
}
私有void Form1\u加载(对象发送方、事件参数e)
{
Resize+=新事件处理程序(WebCamControl_Resize);
Console.WriteLine(“构建图形…”);
GetInterfaces();
Console.WriteLine(“开始捕获…”);
捕获视频(图形);
}
私有void GetInterfaces()
{
图形=(IGraphBuilder)(新FilterGraph());
pGraphBuilder=(ICaptureGraphBuilder2)(新CaptureGraphBuilder2());
mediaControl=(IMediaControl)图形;
视频窗口=(IVideoWindow)图形;
mediaEventEx=(IMediaEventEx)图;
//向控制窗口发送通知消息
int hr=mediaEventEx.SetNotifyWindow(句柄、WM_图形通知、IntPtr.Zero);
DsError.THROWEExceptionForHR(hr);
}
专用void CaptureVideo(IGraphBuilder pGraph)
{
int-hr=0;
hr=pGraphBuilder.SetFiltergraph(pGraph);
DsError.THROWEExceptionForHR(hr);
pUSB=FindCaptureDevice();
hr=pGraph.AddFilter(pUSB,“网络摄像机控制视频”);
DsError.THROWEExceptionForHR(hr);
//添加smartTee
IBaseFilter pSmartTee=(IBaseFilter)新智能TEE();
hr=pGraph.AddFilter(pSmartTee,“智能Tee”);
DsError.THROWEExceptionForHR(hr);
//将智能T恤连接到摄像头
hr=pGraphBuilder.RenderStream(null,MediaType.Video,pUSB,null,pSmartTee);
DsError.THROWEExceptionForHR(hr);
pmt=新的AMMediaType();
pmt.majorType=MediaType.Video;
pmt.subType=MediaSubType.MJPG;
pmt.formatType=formatType.VideoInfo;
pmt.fixedSizeSamples=false;//对于640x480为true
pmt.formatSize=88;
pmt.sampleSize=2764800;//2764800 614400
pmt.temporalCompression=false;
//////////////////////////////////
格式=新的VideoInfoHeader();
format.srrect=新的DsRect();
format.TargetRect=new DsRect();
format.BitRate=5000000;
format.AvgTimePerFrame=666666;
//////////////////////////////////
format.BmiHeader=新的BitMapInfo头();
format.BmiHeader.Size=40;
format.BmiHeader.Width=1280;
format.BmiHeader.Height=720;
format.BmiHeader.Planes=1;
format.BmiHeader.BitCount=24;
format.BmiHeader.Compression=1196444237;//1196444237//844715353
format.BmiHeader.ImageSize=2764800;//2764800 614400
pmt.formatPtr=Marshal.alloctaskmem(Marshal.SizeOf(format));
Marshal.StructureToPtr(格式,pmt.formatPtr,false);
Debug.WriteLine(getCatName(pUSB)+“在第130行”);
streamConfig=(IAMStreamConfig)GetPin(pUSB,getCatName(pUSB));
hr=streamConfig.SetFormat(pmt);
DsUtils.FreeAMMediaType(pmt);
如果(hr<0)
{
CapTest.CustomMessage.ShowMessage(“无法设置格式”);
DsError.THROWEExceptionForHR(hr);
}
//添加MJPEG减压器
IBaseFilter PMJPEG解压缩程序=(IBaseFilter)新的MjpegDec();
hr=pGraph.AddFilter(pmjpeg解压器,“MJPEG解压器”);
如果(hr<0)
{
CapTest.CustomMessage.ShowMessage(“无法添加MJPEG解压器”);
DsError.THROWEExceptionForHR(hr);
}
//添加采样捕获器
IBaseFilter pSampleGrabber=(IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_SampleGrabber));
hr=pGraph.AddFilter(pSampleGrabber,“SampleGrabber”);
checkHR(hr,“无法将SampleGrabber添加到图形中”);
//连接智能T形三通和样本抓取器
hr=pGraph.ConnectDirect(GetPin(pSmartTee,“预览”),GetPin(pSampleGrabber,“输入”),null;
检查hr(hr,“无法连接智能t形三通和采样仪”);
//将智能T恤连接到摄像头
hr=pGraphBuilder.RenderStream(null,MediaType.Video,pSampleGrabber,null,pmjpeg解压器);
//添加颜色空间转换器
IBaseFilter pColorSpaceConverter=(IBaseFilter)新颜色();
hr=pGraph.AddFilter(pColorSpaceConverter,“颜色空间转换器”);
如果(hr<0)
{
CapTest.CustomMessage.ShowMessage(“无法将颜色空间转换器添加到图形”);
DsError.THROWEExceptionForHR(hr);
}
hr=pGraphBuilder.RenderStream(空,MediaType