DirectShow(C#)、预览FPS和CPU使用率随着时间的推移而下降

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

我正在构建一个winforms应用程序来学习DirectShow。我让一切都正常工作,除了一个奇怪的问题,CPU使用率和FPS随着时间的推移而下降。 使用中的电脑规格很低。因此,一开始我的CPU使用率为40%,这很好。然后在30分钟左右的时间里,它就降到了4%。当然,FPS也会下降到几FPS

我从互联网上运行并试用了其他示例应用程序,它们的运行方式大致相同。它们也都使用DirectShowLib。因此,基础与我的应用程序相同

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