下面贴出来我的DirectShow初始化及销毁的主要代码程序运行后,调用DirectShowInit能初始化成功,并能正常播放视频,但是调用DirectShowFree后,经常出现虽然最后一帧视频输出不再显示了,但是有两个奇怪的现象:
1. 窗口没有恢复原来的背景色,还是ActiveMovieWindow的黑色背景
2. 重新调用DirectShowInit并播放视频时,有时出现窗口内视频播放正常,但桌面左上角还出现了一个ActiveMovie窗口感觉是原来调用DirectShowFree时原ActiveMovieWindow并没有销毁.是我的DirectShowFree的代码有问题吗?盼高手指教!!!
CDlg::Dlg(CWnd* pParent /*=NULL*/)
: CDialog(CDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_pFilter=NULL;
m_pGraph=NULL;
m_pBaseFilter=NULL;
m_pMediaControl=NULL;
m_pVideoWindow=NULL; CoInitialize(NULL); // 创建 GRAPH
if(CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void**)&m_pGraph)!=S_OK) m_pGraph=NULL;
}CDlg::~CDlg()
{
// 如果DirectShow已初始化但未释放
DirectShowFree(); // 释放 GRAPH
if(m_pGraph) {
m_pGraph->Release();
m_pGraph=NULL;
} CoUninitialize();
}HRESULT CDlg::DirectShowInit()
{
HRESULT hr=S_FALSE; if(m_pGraph) {
// 取得 IID_IVideoWindow 接口
hr=m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&m_pVideoWindow);
if(SUCCEEDED(hr)) {
m_pVideoWindow->put_AutoShow(OAFALSE); // 添加自定义的FILTER,因为是专用FILTER,无需注册,直接创建FILTER对象加入GRAPH即可
m_pFilter=new CNvsFilter(m_nSrcWidth, m_nSrcHeight, NULL, &hr);
if(m_pFilter) {
m_pFilter->AddRef(); m_pBaseFilter=NULL;
hr = m_pFilter->QueryInterface(IID_IBaseFilter,(void**)&m_pBaseFilter);
if(SUCCEEDED(hr)) {
hr=m_pGraph->AddFilter(m_pBaseFilter,L"NVS Filter");
if(SUCCEEDED(hr)) {
IPin* pOutPin=0;
// 取未连接的PIN,自定义FILTER有一个YUY2格式的输出PIN
hr=GetUnConnectedPin(m_pBaseFilter,PINDIR_OUTPUT,&pOutPin);
if(SUCCEEDED(hr)) {
// 自动连接显示FILTER以播放YUY2媒体流
hr=m_pGraph->Render(pOutPin);
pOutPin->Release();
if(SUCCEEDED(hr)) {
// 初始化ActiveMovieWindow
m_pVideoWindow->put_Owner((OAHWND)m_hWnd);
m_pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
m_pVideoWindow->SetWindowPosition(m_nDispX, m_nDispY, m_nDispWidth, m_nDispHeight);
m_pVideoWindow->put_Visible(OATRUE);
m_pVideoWindow->SetWindowForeground(OATRUE);
m_pVideoWindow->put_MessageDrain((OAHWND)m_hWnd); hr=m_pGraph->QueryInterface(IID_IMediaControl,(void**)&m_pMediaControl);
if(SUCCEEDED(hr)) {
// 运行GRAPH
hr=m_pMediaControl->Run();
if(SUCCEEDED(hr)) TRACE("DirectShow Graph Running ...\n");
else TRACE("DirectShow Graph run fail\n");
} else TRACE("QueryInterface IID_IMediaControl fail\n");
} else TRACE("Graph render fail\n");
} else TRACE("Get output pin fail\n");
} else TRACE("AddFilter into graph fail\n");
} else TRACE("QueryInterface IID_IBaseFilter fail\n");
} else {
hr = E_OUTOFMEMORY;
TRACE("New NVS-Filter object fail\n");
}
} else TRACE("QueryInterface IID_IVideoWindow fail\n"); if(FAILED(hr)) {
if(m_pVideoWindow) {
if(m_pFilter) {
if(m_pBaseFilter) {
if(m_pMediaControl) {
m_pMediaControl->Stop();
m_pMediaControl->Release();
m_pMediaControl=NULL;
}
m_pGraph->RemoveFilter(m_pBaseFilter);
m_pBaseFilter->Release();
m_pBaseFilter=NULL;
}
delete m_pFilter;
m_pFilter=NULL;
}
m_pVideoWindow->put_MessageDrain((OAHWND)NULL);
m_pVideoWindow->put_Visible(OAFALSE);
m_pVideoWindow->Release();
m_pVideoWindow=NULL;
}
}
} return hr;
}void CDlg::DirectShowFree()
{
if(m_pGraph) {
if(m_pVideoWindow) {
// 销毁ActiveMovieWindow
m_pVideoWindow->put_MessageDrain((OAHWND)NULL);
m_pVideoWindow->put_Visible(OAFALSE);
m_pVideoWindow->Release();
m_pVideoWindow=NULL; // 销毁Filter
if(m_pFilter) {
if(m_pBaseFilter) {
if(m_pMediaControl) {
hr=m_pMediaControl->Stop();
m_pMediaControl->Release();
m_pMediaControl=NULL;
}
hr=m_pGraph->RemoveFilter(m_pBaseFilter);
m_pBaseFilter->Release();
m_pBaseFilter=NULL;
}
delete m_pFilter;
m_pFilter=NULL;
}
}
}
}
1. 窗口没有恢复原来的背景色,还是ActiveMovieWindow的黑色背景
2. 重新调用DirectShowInit并播放视频时,有时出现窗口内视频播放正常,但桌面左上角还出现了一个ActiveMovie窗口感觉是原来调用DirectShowFree时原ActiveMovieWindow并没有销毁.是我的DirectShowFree的代码有问题吗?盼高手指教!!!
CDlg::Dlg(CWnd* pParent /*=NULL*/)
: CDialog(CDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_pFilter=NULL;
m_pGraph=NULL;
m_pBaseFilter=NULL;
m_pMediaControl=NULL;
m_pVideoWindow=NULL; CoInitialize(NULL); // 创建 GRAPH
if(CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void**)&m_pGraph)!=S_OK) m_pGraph=NULL;
}CDlg::~CDlg()
{
// 如果DirectShow已初始化但未释放
DirectShowFree(); // 释放 GRAPH
if(m_pGraph) {
m_pGraph->Release();
m_pGraph=NULL;
} CoUninitialize();
}HRESULT CDlg::DirectShowInit()
{
HRESULT hr=S_FALSE; if(m_pGraph) {
// 取得 IID_IVideoWindow 接口
hr=m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&m_pVideoWindow);
if(SUCCEEDED(hr)) {
m_pVideoWindow->put_AutoShow(OAFALSE); // 添加自定义的FILTER,因为是专用FILTER,无需注册,直接创建FILTER对象加入GRAPH即可
m_pFilter=new CNvsFilter(m_nSrcWidth, m_nSrcHeight, NULL, &hr);
if(m_pFilter) {
m_pFilter->AddRef(); m_pBaseFilter=NULL;
hr = m_pFilter->QueryInterface(IID_IBaseFilter,(void**)&m_pBaseFilter);
if(SUCCEEDED(hr)) {
hr=m_pGraph->AddFilter(m_pBaseFilter,L"NVS Filter");
if(SUCCEEDED(hr)) {
IPin* pOutPin=0;
// 取未连接的PIN,自定义FILTER有一个YUY2格式的输出PIN
hr=GetUnConnectedPin(m_pBaseFilter,PINDIR_OUTPUT,&pOutPin);
if(SUCCEEDED(hr)) {
// 自动连接显示FILTER以播放YUY2媒体流
hr=m_pGraph->Render(pOutPin);
pOutPin->Release();
if(SUCCEEDED(hr)) {
// 初始化ActiveMovieWindow
m_pVideoWindow->put_Owner((OAHWND)m_hWnd);
m_pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
m_pVideoWindow->SetWindowPosition(m_nDispX, m_nDispY, m_nDispWidth, m_nDispHeight);
m_pVideoWindow->put_Visible(OATRUE);
m_pVideoWindow->SetWindowForeground(OATRUE);
m_pVideoWindow->put_MessageDrain((OAHWND)m_hWnd); hr=m_pGraph->QueryInterface(IID_IMediaControl,(void**)&m_pMediaControl);
if(SUCCEEDED(hr)) {
// 运行GRAPH
hr=m_pMediaControl->Run();
if(SUCCEEDED(hr)) TRACE("DirectShow Graph Running ...\n");
else TRACE("DirectShow Graph run fail\n");
} else TRACE("QueryInterface IID_IMediaControl fail\n");
} else TRACE("Graph render fail\n");
} else TRACE("Get output pin fail\n");
} else TRACE("AddFilter into graph fail\n");
} else TRACE("QueryInterface IID_IBaseFilter fail\n");
} else {
hr = E_OUTOFMEMORY;
TRACE("New NVS-Filter object fail\n");
}
} else TRACE("QueryInterface IID_IVideoWindow fail\n"); if(FAILED(hr)) {
if(m_pVideoWindow) {
if(m_pFilter) {
if(m_pBaseFilter) {
if(m_pMediaControl) {
m_pMediaControl->Stop();
m_pMediaControl->Release();
m_pMediaControl=NULL;
}
m_pGraph->RemoveFilter(m_pBaseFilter);
m_pBaseFilter->Release();
m_pBaseFilter=NULL;
}
delete m_pFilter;
m_pFilter=NULL;
}
m_pVideoWindow->put_MessageDrain((OAHWND)NULL);
m_pVideoWindow->put_Visible(OAFALSE);
m_pVideoWindow->Release();
m_pVideoWindow=NULL;
}
}
} return hr;
}void CDlg::DirectShowFree()
{
if(m_pGraph) {
if(m_pVideoWindow) {
// 销毁ActiveMovieWindow
m_pVideoWindow->put_MessageDrain((OAHWND)NULL);
m_pVideoWindow->put_Visible(OAFALSE);
m_pVideoWindow->Release();
m_pVideoWindow=NULL; // 销毁Filter
if(m_pFilter) {
if(m_pBaseFilter) {
if(m_pMediaControl) {
hr=m_pMediaControl->Stop();
m_pMediaControl->Release();
m_pMediaControl=NULL;
}
hr=m_pGraph->RemoveFilter(m_pBaseFilter);
m_pBaseFilter->Release();
m_pBaseFilter=NULL;
}
delete m_pFilter;
m_pFilter=NULL;
}
}
}
}
[email protected]
{
if (mSeeking)
{
mSeeking->Release();
mSeeking = NULL;
}
if (mMediaControl)
{
mMediaControl->Release();
mMediaControl = NULL;
}
if (mEvent)
{
mEvent->Release();
mEvent = NULL;
}
if (mBasicVideo)
{
mBasicVideo->Release();
mBasicVideo = NULL;
}
if (mBasicAudio)
{
mBasicAudio->Release();
mBasicAudio = NULL;
}
if (mVideoWindow)
{
mVideoWindow->put_Visible(OAFALSE);
mVideoWindow->put_MessageDrain((OAHWND)NULL);
mVideoWindow->put_Owner(OAHWND(0));
mVideoWindow->Release();
mVideoWindow = NULL;
}
RemoveFromObjectTable();
if (mGraph)
{
mGraph->Release();
mGraph = NULL;
}
}
源代码已发送,请查收邮件,谢谢!to::changpei(饱汉不知饿汉饥,饿了一日,方知饿乃天下第一大事!)
我在DirectShowFree中没有释放mGraph,是因为释放后经常出现在DirectShowInit中创建mGraph失败,我也不知道原因,是不是因为没有调用RemoveFromObjectTable()的原故?你这里的RemoveFromObjectTable() 是干什么用的?如何实现?
能否留下你的email,我把源代码发一份给你,帮我看看?谢谢 !