📄 cfiltergraph.cpp
字号:
// CFilterGraph.cpp: implementation of the CFilterGraph class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "streams.h"
#include "CFilterGraph.h"
#include "CDataAdmin.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CFilterGraph::CFilterGraph(CDataAdmin *inBuffer)
{
// Filter graph running status
m_bRun = false;
m_bInit = false;
// Interfaces
m_pGB = NULL;
m_pMC = NULL;
m_pVW = NULL;
m_pME = NULL;
m_pMS = NULL;
m_pBA = NULL;
m_hOwner = NULL;
m_nLeft = 0;
m_nTop = 0;
m_nWidth = 100;
m_nHeight = 100;
m_dwGraphRegister = 0;
// Data buffer pointer
m_pDataList = inBuffer;
}
CFilterGraph::~CFilterGraph()
{
m_bRun = false;
ReleaseGraph();
m_pDataList = NULL;
}
void CFilterGraph::ReleaseGraph(void)
{
// Stop filter graph first
HRESULT hr;
if (m_pMC != NULL)
{
hr = m_pMC->Stop();
}
// Relinquish ownership (IMPORTANT!) after hiding video window
if(m_pVW != NULL)
{
hr = m_pVW->put_Visible(OAFALSE);
hr = m_pVW->put_Owner(NULL);
}
if (m_pGB != NULL)
{
// Unregister....
RemoveGraphFromRot(m_dwGraphRegister);
// remove the filter added before
m_pGB->RemoveFilter(m_pSourceReader);
// media event interface
SAFE_RELEASE(m_pME)
// media seeking interface
SAFE_RELEASE(m_pMS)
// media control interface
SAFE_RELEASE(m_pMC)
// basic audio interface
SAFE_RELEASE(m_pBA)
// video window interface
SAFE_RELEASE(m_pVW)
// graph builder interface
SAFE_RELEASE(m_pGB)
SAFE_DELETE(m_pSourceStream)
SAFE_DELETE(m_pSourceReader)
}
}
bool CFilterGraph::BuildGraph(void)
{
m_bInit = false;
// Create filter graph
HRESULT hr = CoCreateInstance(CLSID_FilterGraph,
NULL,
CLSCTX_INPROC,
IID_IGraphBuilder,
(void**)&m_pGB);
if (SUCCEEDED(hr))
{
m_bInit = true;
// Register...
AddGraphToRot((IUnknown *)m_pGB, &m_dwGraphRegister);
}
if (m_bInit)
{
// Media control interface
hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
if (FAILED(hr))
{
m_bInit = false;
}
}
if (m_bInit)
{
// Media event interface
hr = m_pGB->QueryInterface(IID_IMediaEvent, (void **)&m_pME);
if (FAILED(hr))
{
m_bInit = false;
}
}
if (m_bInit)
{
// Media video window interface
hr = m_pGB->QueryInterface(IID_IVideoWindow, (void **)&m_pVW);
if (FAILED(hr))
{
m_bInit = false;
}
}
if (m_bInit)
{
// Media basic audio interface
hr = m_pGB->QueryInterface(IID_IBasicAudio, (void **)&m_pBA);
if (FAILED(hr))
{
m_bInit = false;
}
}
if (m_bInit)
{
// Media seeking interface
hr = m_pGB->QueryInterface(IID_IMediaSeeking, (void **)&m_pMS);
if (FAILED(hr))
{
m_bInit = false;
}
}
// construct source filter
// Media type
if (m_bInit)
{
CMediaType mt;
mt.majortype = MEDIATYPE_Stream;
mt.subtype = MEDIASUBTYPE_MPEG1System;
m_pSourceStream = new CMemStream(m_pDataList);
m_pSourceReader = new CMemReader(m_pSourceStream, &mt, &hr);
m_pSourceReader->AddRef();
// Add our filter
hr = m_pGB->AddFilter(m_pSourceReader, NULL);
if (FAILED(hr))
{
m_bInit = false;
}
}
if (m_bInit)
{
// Waiting for event to start filter graph
::AfxBeginThread((AFX_THREADPROC)CFilterGraph::WaitingThrd, this);
}
return m_bInit;
}
void CFilterGraph::SetWindowPosition(int nLeft, int nTop, int nWidth, int nHeight)
{
m_nLeft = nLeft;
m_nTop = nTop;
m_nWidth = nWidth;
m_nHeight = nHeight;
}
bool CFilterGraph::StartGraph(void)
{
if (m_bInit)
{
m_bRun = true;
HRESULT hr = m_pGB->Render(m_pSourceReader->GetPin(0));
if (FAILED(hr))
{
m_bRun = false;
return false;
}
hr = m_pVW->put_Visible(OAFALSE);
hr = m_pVW->put_Owner((OAHWND)m_hOwner);
hr = m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
hr = m_pVW->SetWindowPosition(m_nLeft, m_nTop, m_nWidth, m_nHeight);
// Enable the parent window to get the mouse and keyboard event in the video window
hr = m_pVW->put_MessageDrain((OAHWND)m_hOwner);
hr = m_pVW->put_Visible(OATRUE);
// run the filter graph
hr = m_pMC->Run();
return true;
}
return false;
}
void CFilterGraph::SetVideoWndOwner(HWND inWnd)
{
m_hOwner = inWnd;
}
bool CFilterGraph::IsInit(void)
{
return m_bInit;
}
bool CFilterGraph::IsRunning(void)
{
return m_bRun;
}
void CFilterGraph::AdjustLength(LONGLONG inAdd)
{
if (m_pSourceStream)
{
m_pSourceStream->AddAvailableLength(inAdd);
}
}
// When data buffer enough, start the filter graph
UINT CFilterGraph::WaitingThrd(void * pParam)
{
CFilterGraph * pGraph = (CFilterGraph *) pParam;
if (pGraph != NULL && pGraph->m_pDataList != NULL)
{
::WaitForSingleObject(pGraph->m_pDataList->m_hBufEnough, INFINITE);
if (!pGraph->IsRunning())
{
pGraph->StartGraph();
}
}
return 1;
}
bool CFilterGraph::ResetGraph(void)
{
if (m_bRun)
{
// If the filter graph running, release it first
ReleaseGraph();
}
// Reset the datalist
if (m_pDataList != NULL)
{
m_pDataList->ResetList();
ResetEvent(m_pDataList->m_hBufEnough);
}
// Build a new filter graph
BuildGraph();
return true;
}
///////////////////////////////////////////////////////////////////////////
HRESULT CFilterGraph::AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
{
IMoniker * pMoniker;
IRunningObjectTable *pROT;
if (FAILED(GetRunningObjectTable(0, &pROT))) {
return E_FAIL;
}
WCHAR wsz[128];
wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
if (SUCCEEDED(hr)) {
hr = pROT->Register(0, pUnkGraph, pMoniker, pdwRegister);
pMoniker->Release();
}
pROT->Release();
return hr;
}
void CFilterGraph::RemoveGraphFromRot(DWORD pdwRegister)
{
IRunningObjectTable *pROT;
if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
pROT->Revoke(pdwRegister);
pROT->Release();
}
}
//////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -