Directshow 过滤器之间协商分配器失败

发布于 2024-12-12 13:40:38 字数 3147 浏览 1 评论 0原文

我正在开发一个自定义 Directshow 源过滤器,以向渲染过滤器提供解压缩的视频数据。我使用 Directshow SDK 提供的 PushSource 示例作为我的过滤器的基础。我正在尝试将其连接到 VideoMishingRenderer9 过滤器。

创建图形时,我调用 ConnectDirect():

HRESULT hr = mp_graph_builder->ConnectDirect(OutPin, InPin, &mediaType);

但在此调用期间,在下游过滤器分配器(在 DecideBufferSize() 中)上调用 SetProperties,失败并显示 D3DERR_INVALIDCALL (0x8876086c):

ALLOCATOR_PROPERTIES actual;
memset(&actual,0,sizeof(actual));
hr = pAlloc->SetProperties(pRequest, &actual);

如果我让它尝试使用我的分配器(即由 CBaseOutputPin 提供)在下游过滤器上设置分配器时,会失败并显示 E_FAIL(在CBaseOutputPin::DecideAllocator)

hr = pPin->NotifyAllocator(*ppAlloc, FALSE);

任何帮助将不胜感激! 谢谢。

编辑: 这是由 GetMediaType 和 DecideBufferSize 提供的媒体类型

VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER*)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
if (pvi == 0) 
    return(E_OUTOFMEMORY);

ZeroMemory(pvi, pMediaType->cbFormat);   
pvi->AvgTimePerFrame = m_rtFrameLength;

pMediaType->formattype = FORMAT_VideoInfo; 
pMediaType->majortype = MEDIATYPE_Video;
pMediaType->subtype = MEDIASUBTYPE_RGB24; 
pMediaType->bTemporalCompression = FALSE;
pMediaType->bFixedSizeSamples = TRUE;
pMediaType->formattype = FORMAT_VideoInfo;
pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biWidth = (640 / 128 + 1) * 128;
pvi->bmiHeader.biHeight = -480; // negative so top down..
pvi->bmiHeader.biPlanes = 1;
pvi->bmiHeader.biBitCount = 24;
pvi->bmiHeader.biCompression = NULL; // ok if rgb else use MAKEFOURCC(...)
pvi->bmiHeader.biSizeImage  = GetBitmapSize(&pvi->bmiHeader);
pvi->bmiHeader.biClrImportant = 0;
pvi->bmiHeader.biClrUsed    = 0;        //Use max colour depth
pvi->bmiHeader.biXPelsPerMeter = 0; 
pvi->bmiHeader.biYPelsPerMeter = 0;
SetRectEmpty(&(pvi->rcSource));
SetRectEmpty(&(pvi->rcTarget));
pvi->rcSource.bottom = 480;
pvi->rcSource.right = 640;
pvi->rcTarget.bottom = 480;
pvi->rcTarget.right = 640;

pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetTemporalCompression(FALSE);
const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
pMediaType->SetSubtype(&SubTypeGUID);
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);

,其中调用 pAlloc->SetProperties

HRESULT CPushPinBitmap::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest) {
    HRESULT hr;
    CAutoLock cAutoLock(CBasePin::m_pLock);

    CheckPointer(pAlloc, E_POINTER);
    CheckPointer(pRequest, E_POINTER);

    if (pRequest->cBuffers == 0) {
        pRequest->cBuffers = 2;
    }
    pRequest->cbBuffer =  480 * ( (640 / 128 + 1) * 128 ) * 3;

    ALLOCATOR_PROPERTIES actual;
    memset(&actual,0,sizeof(actual));
    hr = pAlloc->SetProperties(pRequest, &actual);
    if (FAILED(hr)) {
        return hr;
    }
    if (actual.cbBuffer < pRequest->cbBuffer) {
        return E_FAIL;
    }

    return S_OK;
}

常量只是临时的!

I'm developing a custom Directshow source filter to provide decompressed video data to a rendering filter. I've used the PushSource sample provided by the Directshow SDK as a basis for my filter. I'm attempting to connect this to a VideoMixingRenderer9 filter.

When creating the graph I'm calling ConnectDirect():

HRESULT hr = mp_graph_builder->ConnectDirect(OutPin, InPin, &mediaType);

but during this call, calling SetProperties on the downstream filters allocator (in DecideBufferSize()), fails with D3DERR_INVALIDCALL (0x8876086c):

ALLOCATOR_PROPERTIES actual;
memset(&actual,0,sizeof(actual));
hr = pAlloc->SetProperties(pRequest, &actual);

If I let it try to use my allocator (the one provided by CBaseOutputPin) when setting the allocator on the downstream filter, this fails with E_FAIL (in CBaseOutputPin::DecideAllocator)

hr = pPin->NotifyAllocator(*ppAlloc, FALSE);

Any help would be much appreciated!
Thanks.

EDIT:
This is the media type provided by GetMediaType

VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER*)pMediaType->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
if (pvi == 0) 
    return(E_OUTOFMEMORY);

ZeroMemory(pvi, pMediaType->cbFormat);   
pvi->AvgTimePerFrame = m_rtFrameLength;

pMediaType->formattype = FORMAT_VideoInfo; 
pMediaType->majortype = MEDIATYPE_Video;
pMediaType->subtype = MEDIASUBTYPE_RGB24; 
pMediaType->bTemporalCompression = FALSE;
pMediaType->bFixedSizeSamples = TRUE;
pMediaType->formattype = FORMAT_VideoInfo;
pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biWidth = (640 / 128 + 1) * 128;
pvi->bmiHeader.biHeight = -480; // negative so top down..
pvi->bmiHeader.biPlanes = 1;
pvi->bmiHeader.biBitCount = 24;
pvi->bmiHeader.biCompression = NULL; // ok if rgb else use MAKEFOURCC(...)
pvi->bmiHeader.biSizeImage  = GetBitmapSize(&pvi->bmiHeader);
pvi->bmiHeader.biClrImportant = 0;
pvi->bmiHeader.biClrUsed    = 0;        //Use max colour depth
pvi->bmiHeader.biXPelsPerMeter = 0; 
pvi->bmiHeader.biYPelsPerMeter = 0;
SetRectEmpty(&(pvi->rcSource));
SetRectEmpty(&(pvi->rcTarget));
pvi->rcSource.bottom = 480;
pvi->rcSource.right = 640;
pvi->rcTarget.bottom = 480;
pvi->rcTarget.right = 640;

pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetTemporalCompression(FALSE);
const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
pMediaType->SetSubtype(&SubTypeGUID);
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);

and DecideBufferSize where pAlloc->SetProperties is called

HRESULT CPushPinBitmap::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pRequest) {
    HRESULT hr;
    CAutoLock cAutoLock(CBasePin::m_pLock);

    CheckPointer(pAlloc, E_POINTER);
    CheckPointer(pRequest, E_POINTER);

    if (pRequest->cBuffers == 0) {
        pRequest->cBuffers = 2;
    }
    pRequest->cbBuffer =  480 * ( (640 / 128 + 1) * 128 ) * 3;

    ALLOCATOR_PROPERTIES actual;
    memset(&actual,0,sizeof(actual));
    hr = pAlloc->SetProperties(pRequest, &actual);
    if (FAILED(hr)) {
        return hr;
    }
    if (actual.cbBuffer < pRequest->cbBuffer) {
        return E_FAIL;
    }

    return S_OK;
}

The constants are only temporary!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

时光礼记 2024-12-19 13:40:38

您无法将自己的分配器与 VMR/EVR 过滤器一起使用。他们只是坚持自己的观点,而这又以 DirectDraw/Direct3D 表面为基础。

要直接连接到 VMR/EVR 过滤器,您需要不同的策略。分配器始终是他们的。您需要支持大步前进。请参阅处理视频格式更改渲染器

There is no way you can use your own allocator with VMR/EVR filters. They just insist on their own, which in turn is backed on DirectDraw/Direct3D surfaces.

To connect directly to VMR/EVR filters you need a different strategy. The allocator is always theirs. You need to support extended strides. See Handling Format Changes from the Video Renderer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文