如何将我的directshow筛选器添加到筛选器图中
How to add my directshow filter into filter graph
我已经编写了一个自定义的directshow过滤器,它派生自directshow CBaseRenderer类。下面的代码是我的过滤器。
class CRenderSamples : public CBaseRenderer
{
// private data members
// constructors and destructors are private, need to use CoCreateInstance(.)
protected:
//BYTE *m_pCopyBuffer;
CMediaType m_MediaType;
CRenderSamples(LPUNKNOWN pUnk,HRESULT *phr);
virtual ~CRenderSamples();
public:
//The CheckMediaType method determines if the
//filter accepts a specific media type.
virtual HRESULT CheckMediaType(const CMediaType *pMediaType);
// The DoRenderSample method renders a sample.
virtual HRESULT DoRenderSample(IMediaSample *pMediaSample);
// Instantiate filter object
static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
};
我已经成功地构建了过滤器并将其注册到COM中。同时,我已经在GraphEdit中测试了我的过滤器和pushsourcedesktop过滤器,它可以正常工作。问题出在编码上。对于实例化过滤器对象应该使用哪种类型的指针,我有点困惑。如果我用IBaseFilter指针实例化过滤器对象,一切都很好,但我不能使用我在自己的过滤器中实现的DoRenderSamBple()方法。但是,如果我使用CBaseRenderer,AddFilter()函数会生成运行时错误,因为它的第一个参数需要IBaseFilter指针。以下代码是我的应用程序。
#include <stdio.h>
#include <windows.h>
#include <ObjBase.h>
#include <DShow.h>
#include <initguid.h>
#include <stdlib.h>
#include <streams.h>
#include "PushGuids.h"
//#pragma once
#pragma comment(lib,"Strmiids.lib")
static const GUID CLSID_RENDER_SAMPLES = {0x9ddd8a2a, 0xa66c, 0x423a, { 0xa7, 0xb1,
0xc3, 0x22, 0xae, 0xbc, 0x1c, 0x1e } };
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
){
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent* pEvent = NULL;
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr)) {
MessageBox(NULL,TEXT("ERROR - Could not initialize COM library."),TEXT("Error!"),MB_OK);
return EXIT_FAILURE;
}
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr)) {
MessageBox(NULL,TEXT("Could not create the Filter Graph Manager."),TEXT("Error!"),MB_OK);
return EXIT_FAILURE;
}
hr = pGraph -> QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph -> QueryInterface(IID_IMediaEvent, (void **)&pEvent);
IBaseFilter* pPushSourceDesktop = 0;
hr = CoCreateInstance(CLSID_PushSourceDesktop, 0, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&pPushSourceDesktop);
if (FAILED(hr)) {
MessageBox(NULL,TEXT("Could not create PushSourceDesktop filter."),TEXT("Error!"),MB_OK);
return EXIT_FAILURE;
}
hr = pGraph -> AddFilter(pPushSourceDesktop, L"PushSourceDesktop");
if (FAILED(hr)) {
MessageBox(NULL,TEXT("Could not add PushSourceDesktop filter."),TEXT("Error!"),MB_OK);
return 0;
}
//IBaseFilter *pRenderSamples;
CBaseRenderer *pRenderSamples;
//IBaseFilter *pRenderer;
hr = CoCreateInstance(CLSID_RENDER_SAMPLES,0,CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&pRenderSamples);
if (FAILED(hr)) {
MessageBox(NULL,TEXT("Could not instantiate RenderSamples."),TEXT("Error!"),MB_OK);
return EXIT_FAILURE;
}else{
MessageBox(NULL,TEXT("Successfully instantiate RenderSamples filter."),TEXT("Success!"),MB_OK);
}
hr = pGraph -> AddFilter(pRenderSamples, L"Render Samples");
if (FAILED(hr)) {
MessageBox(NULL,TEXT("Could not add RenderSamples filter."),TEXT("Error!"),MB_OK);
return EXIT_FAILURE;
}else{
MessageBox(NULL,TEXT("Successfully add RenderSamples filter."),TEXT("Success!"),MB_OK);
}
IPin **ppPushPinDesktop = new (IPin*);
hr = pPushSourceDesktop -> FindPin(L"1", ppPushPinDesktop);
if (FAILED(hr)) {
MessageBox(NULL,TEXT("Could not find pin of filter PushSourceDesktop."),TEXT("Error!"),MB_OK);
return EXIT_FAILURE;
}
IPin **ppRenderSamples = new (IPin*);
hr = pRenderSamples -> FindPin(L"In", ppRenderSamples);
switch(hr)
{
case S_OK:
MessageBox(NULL,TEXT("Successfully find pin."),TEXT("Success!"),MB_OK);
break;
case E_POINTER:
MessageBox(NULL,TEXT("Null pointer argument."),TEXT("Null Pointer!"),MB_OK);
return EXIT_FAILURE;
case VFW_E_NOT_FOUND:
MessageBox(NULL,TEXT("Could not find a pin with this identifier."),TEXT("Error!"),MB_OK);
return EXIT_FAILURE;
}
hr = pGraph -> Connect(*ppPushPinDesktop,*ppRenderSamples);
switch(hr){
case S_OK:
MessageBox(NULL,TEXT("Successfully connect PushSourceDesktop and RenderSamples."),TEXT("Success!"),MB_OK);
break;
case VFW_S_PARTIAL_RENDER:
MessageBox(NULL,TEXT("Partial success; some of the streams from this pin use an unsupported format."),
TEXT("Partial success!"),MB_OK);
break;
case E_ABORT:
MessageBox(NULL,TEXT("Operation aborted."),TEXT("Aborted!"),MB_OK);
break;
case E_POINTER:
MessageBox(NULL,TEXT("NULL pointer argument."),TEXT("NULL Pointer!"),MB_OK);
break;
case VFW_E_CANNOT_CONNECT:
MessageBox(NULL,TEXT("No combination of intermediate filters could be found to make the connection."),TEXT("Aborted!"),MB_OK);
break;
case VFW_E_NOT_IN_GRAPH:
MessageBox(NULL,TEXT("At least one of the filters is not in the filter graph."),TEXT("Filter no in filter graph"),MB_OK);
break;
default:
MessageBox(NULL,TEXT("Unknow error"),TEXT("Error!"),MB_OK);
return EXIT_FAILURE;
}
pControl -> Release();
pEvent -> Release();
(*ppPushPinDesktop) -> Release();
pPushSourceDesktop -> Release();
pRenderSamples-> Release();
(*ppRenderSamples)->Release();
pGraph -> Release();
CoUninitialize();
return EXIT_SUCCESS;
}
有人能想出解决这个问题的办法吗。非常感谢您!!!
由于您将过滤器塑造为COM类/对象,因此应该从那里使用COM接口指针。当你将过滤器添加到图中并开始流式传输时,通常你不需要在控制应用程序和过滤器之间进行任何自定义的直接交互。
然而,如果你想拥有它,你需要在你的过滤器/引脚上实现一个额外的接口(所谓的"私人接口",因为它对公众可用,但对你的应用程序和过滤器来说是已知的,所以没有人在使用它),以及必要的方法。应用程序将通过QueryInterface
获得指针,并能够根据需要调用方法。
作为普通DirectShow流的一部分,渲染器通过标准路径IPin::Receive
接收样本,并且不需要从控制应用程序进行任何外部调用。
相关文章:
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 如何在C++中从两个单独的for循环中添加两个数组
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 如何仅为一个函数添加延迟
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 使用std::transform将一个范围的元素添加到另一个范围中
- 如何将更多文件夹添加到c++include路径
- 如何将元素添加到数组的线程安全函数?
- QT通过C++添加映射QML项目
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 只能向C++添加一定数量的字符
- Qt和C++:将QLineEdit添加到QTabWidget中
- 将QIcon添加到QTableView单元格
- 为什么我必须在C++中添加一个赋值符号来声明一个数组
- 为什么除非添加括号,否则构造函数上的模板替换会失败?
- 如何将我的directshow筛选器添加到筛选器图中
- 将筛选器添加到visual studio模板