0

我使用来自 msdn 示例的大部分代码在我的媒体会话中使用 Sample Grabber Sink。

在 OnProcessSample 方法中,我将数据 memcpy 到媒体缓冲区,将其附加到 MFSample 并将其放入主进程指针。问题是我在 ntdll.dll 中出现内存泄漏或崩溃

ntdll.dll!@RtlpLowFragHeapFree@8() 未知

SampleGrabberSink:

OnProcessSample(...)
{
    MFCreateMemoryBuffer(dwSampleSize,&tmpBuff);
    tmpBuff->Lock(&data,NULL,NULL);
    memcpy(data,pSampleBuffer,dwSampleSize); tmpBuff->Unlock();
    MFCreateSample(&tmpSample);
    tmpSample->AddBuffer(tmpBuff);

    while(!(*Free) && (*pSample)!=NULL)
    {
        Sleep(1);
    }

    (*Free)=false;
    (*pSample)=tmpSample;
    (*Free)=true;
    SafeRelease(&tmpBuff);
}

在主线程中

ReadSample()
{
    if(pSample==NULL)
        return;
    while(!Free)
        Sleep(1);
    Free=false;
    //process sample into dx surface//
    SafeRelease(&pSample);
    Free=true;
}

//hr 检查省略// 使用这段代码,我在播放几个视频后得到了 ntdll.dll 错误。我还尝试在队列中推送样本,这样 OnProcess 就不必等待,但是在视频结束后一些内存还没有释放。(即使现在它实际上也不等待,会话速率为 1,主进程可以读取超过 60fps)

编辑:这是线程同步问题。多亏了 Roman R ,通过使用临界区来解决。

4

1 回答 1

1

从代码片段中不容易看出,但我想您正在流式线程上刻录周期(您已调用回调),直到全局/共享变量NULL出现,然后您在那里复制媒体样本。

您需要查看同步 API 并序列化对共享变量的访问。你不这样做,最终要么访问释放的内存,要么破坏 COM 对象的引用计数。

当您准备好从回调中接受新缓冲区时,您需要在外部设置一个事件,然后回调看到该事件,进入临界区(或读/写器锁),在*pSample那里施展魔法,从临界区退出并设置另一个事件指示缓冲区的可用性。

于 2013-03-11T16:28:56.610 回答