1

我正在研究从 CTransformFilter 派生的自定义视频转换过滤器。它不会做任何 DirectShow 术语中不寻常的事情,例如媒体样本的额外内部缓冲、输出样本的排队或动态格式更改。

按下播放时,graphedit 中的图表包含我的过滤器的两个实例,首尾相连(第一个输出连接到第二个输入)。该图绝对没有挂在 ::Transform 方法覆盖中。第二个过滤器实例直接连接到视频渲染器。

如果在两个滤镜之间插入颜色转换器,则不会发生此问题。如果我将请求的缓冲区数量(ALLOCATOR_PROPERTIES::cBuffers)从 1 增加到 3,那么问题就会消失。下面是原始的 DecideBufferSize 覆盖,与许多其他示例 DirectShow 过滤器代码类似。

在 DirectShow 过滤器(转换或其他方式)中设置请求缓冲区数量的稳健策略是什么?对于现代需求,请求一个缓冲区的代码是否已过时?我的问题是缓冲区太少还是增加了缓冲区的数量来掩盖不同的问题?

    HRESULT MyFilter::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp)
{
    AM_MEDIA_TYPE mt;
    HRESULT hr = m_pOutput->ConnectionMediaType(&mt);
    if (FAILED(hr)) {
        return hr;
    }

    BITMAPINFOHEADER * const pbmi = GetBitmapInfoHeader(mt);
    pProp->cbBuffer = DIBSIZE(*pbmi);
    if (pProp->cbAlign == 0) {
        pProp->cbAlign = 1;
    } 
    if (pProp->cBuffers == 0) {
        pProp->cBuffers = 3;
    }
    // Release the format block.
    FreeMediaType(mt);

    // Set allocator properties.
    ALLOCATOR_PROPERTIES Actual;
    hr = pAlloc->SetProperties(pProp, &Actual);
    if (FAILED(hr)) {
        return hr;
    }
    // Even when it succeeds, check the actual result.
    if (pProp->cbBuffer > Actual.cbBuffer) {
        return E_FAIL;
    }
    return S_OK;
}
4

1 回答 1

2

缓冲区数量没有具体的政策,但您绝对应该知道固定数量的缓冲区是控制采样率的方法。当所有缓冲区都在使用时,对另一个缓冲区的请求将阻止执行,直到该缓冲区可用。

也就是说,如果您的代码出于某种目的而持有缓冲区引用,您应该分配相应的数量,这样您就不会锁定自己。例如,您在内部保存最后一个媒体样本引用,例如能够重新发送它,并且您仍然希望能够传递其他媒体样本,因此您需要在分配器上至少有两个缓冲区。

输出引脚通常负责选择和设置分配器,如果/当通知要使用哪个分配器时,输入可能需要检查和更新属性。当您共享分配器时,在就地转换过滤器上,您可能需要进行额外检查以确保满足要求。

  • DMO Wrapper Filter仅使用(至少有时)带有一个缓冲区的分配器并且仍然处于良好状态
  • 对于音频,您通常有更多缓冲区,因为您将数据排队等待播放
  • 如果您的代码有参考泄漏并且您没有发布媒体样本指针,那么您的流媒体可能会因此而锁定死
于 2012-06-22T19:07:14.253 回答