我有一个似乎在谷歌很常见的问题,但它并没有帮助我。当我的应用程序试图关闭所有内容时,在释放对象之前调用的最后一个函数是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;
谷歌暗示一些线程等待对方造成死锁(实际上是这样)。 UI线程似乎不是问题,因为我在没有Window的情况下做了一个基于这个应用程序的DLL,问题就是一样。
非常感谢,
蚀
修改:
我只有两个过滤器:source和transform。问题在于转换过滤器,因为没有它,程序运行正常。这是不是在某处释放缓冲区或样本的问题?我不确切知道DirectShow的工作原理,但如果没有信号,可能需要做一些额外的事情吗?
编辑2 :
我在谷歌发现有人通过在停止图表之前停止源过滤器来解决此问题。我做了同样的事情,它也挂了......我用它来获取源过滤器:
hr = pFG2->AddSourceFilterForMoniker(pMoniker, pContext, wszName, &pSource);
*ppF = pSource;
(*ppF)->AddRef();
当我附加VS调试器时,它说它不能显示代码,所以我认为它在MS代码中的某个地方。即使我评论我的功能处理IMediaSamples它仍然挂起。现在我用完了错误的想法。我还尝试以不同的方式停止并从图表中删除过滤器。
答案 0 :(得分:0)
尝试将传入图像从后台线程发送到WPF窗口时遇到了同样的问题。一切都很好,直到我试图停止mediacontrol或释放任何东西。
问题在于调度程序调用该操作以将其移至UI线程。我暂时注释掉了这个电话,它阻止了视频在屏幕上显示,但我可以随时在samplegrabber中断,看它还在运行。
需要在线程之间手动分离图像。泛型函数中的某些东西保持引用,因此com对象
为了解决这个问题,我在窗口中创建了一个dispatchertimer,将其间隔设置为1ms,将其回调到执行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);
}
}