【问题标题】:IMediaControl::stop hangs when there is no signal无信号时 IMediaControl::stop 挂起
【发布时间】:2012-08-16 09:52:10
【问题描述】:

我有一个在 Google 中似乎很常见的问题,但对我没有帮助。当我的应用程序试图关闭所有内容时,释放对象之前调用的最后一个函数是 IMediaControl::stop。有信号时一切正常。但是当我在没有信号的情况下启动应用程序(或在应用程序工作时终止它)程序永远不会从 stop() 返回。更重要的是,如果我在信号已经挂起时提供信号,一切都会恢复正常,程序会取消挂起并正确退出。

这是我在 main 中的代码的一部分:

hr = connectFilters(pGraph, pCaptureDevice, AUDIO_INPUT_DEVICE_PIN_NAME,
pAnalyzerFilter, SPDIF_ANAL_FILTER_PIN_NAME);
if(SUCCEEDED(hr))
{
    // run the graph
    hr = pControl->Run();
    if(SUCCEEDED(hr))
    {        
        // wait for UI thread to finish
        pFilterObject->WaitForThread();

        // stop the graph and exit
        pControl->Stop();
    }
}

releaseObjects();
return 0;

Google 建议死锁(确实是这样)是由一些线程相互等待引起的。 UI线程似乎不是问题,因为我在没有Window的情况下基于这个应用程序做了一个DLL,问题是一样的。

提前非常感谢,

日食

编辑

我只有两个过滤器:源和转换。问题肯定在变换过滤器中,因为没有它程序运行良好。可能是某处未释放缓冲区或样本的问题吗?我不知道 DirectShow 是如何工作的,但是如果没有信号,可能需要做一些额外的事情?

编辑 2

我在 Google 中发现有人通过在停止图表之前停止源过滤器来解决此问题。我做了同样的事情,它也挂起......我用它来获取源过滤器:

hr = pFG2->AddSourceFilterForMoniker(pMoniker, pContext, wszName, &pSource);
*ppF = pSource;
(*ppF)->AddRef();

当我附加 VS 调试器时,它说它无法显示代码,所以我认为它在 MS 代码中的某个地方。即使我评论我的函数处理 IMediaSamples 它仍然挂起。现在我已经没有什么想法了。我还尝试以不同的方式停止和删除图表中的过滤器。

【问题讨论】:

  • 这是死锁。其中一个过滤器不合格,您需要准确找到哪一个。
  • @Roman R. 你能说我怎么检查它吗?或者有什么问题? DirectShow 不是我的最爱,所以我什至不知道该去哪里找...
  • 从图表中删除过滤器,直到它开始正常工作。因为它是一些过滤器失败,所以重要的是首先有什么过滤器,图的拓扑是什么。
  • 我照你说的做了。主帖中的详细信息。
  • 如果您发现您的过滤器冻结了执行,那么为什么不附加您的调试器并查看它被冻结的确切位置。最终它应该被锁定在你的代码中。

标签: c++ directshow


【解决方案1】:

在尝试将传入图像从后台线程发送到 WPF 窗口时,我遇到了同样的问题。一切都很好,直到我试图停止媒体控制或释放任何东西。

问题在于操作的调度程序调用以将其发送到 UI 线程。我暂时注释掉了这个调用,这使视频根本无法显示在屏幕上,但我可以随时在采样采集器中中断并查看它实际上仍在运行。

需要在线程间手动分离图像。泛型函数中的某些东西保持引用,所以 com 对象

为了修复它,我在窗口中创建了一个调度程序定时器,将其间隔设置为 1 毫秒,将其回调到一个执行 UI 更新的函数,然后在抓取器中,让 buffercb 事件将帧保存到一个独立变量中,然后启用计时器。

以下是我最终得到的简要介绍:

    InteropBitmap newbmp;
    DispatcherTimer refreshTimer;
    refreshTimer = new DispatcherTimer(TimeSpan.FromMilliseconds(1), DispatcherPriority.Render, ontimer, this.Dispatcher);
    videoSampleCB.newframearrived += capGrabber_NewFrameArrived;

    void capGrabber_NewFrameArrived(object sender, EventArgs e)
    {
        newbmp = videoSampleCB.newimage;
        refreshTimer.IsEnabled = true;
    }
    void ontimerobject sender, EventArgs e)
    {
        this.BitmapSource = newbmp;
        refreshTimer.IsEnabled = false;
    }
class VideoSampleGrabberCallBack : ISampleGrabberCB  
{
        event eventhandler newframearrived;

        public InteropImage newimage;
        public int BufferCB(double sampleTime, IntPtr buffer, int bufferLen)
        {
             newimage = ...
             newframearrived(this, eventargs.empty);
        }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多