📄 cdxgraph.cpp
字号:
//
// CDXGraph.cpp
//
#include "stdafx.h"
#include <streams.h>
#include "CDXGraph.h"
#include "CDataAdmin.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////////////////////////////////////////////////////////////
CDXGraph::CDXGraph(CDataAdmin *inBuffer)
{
// Interfaces
mGraph = NULL;
mMediaControl = NULL;
mEvent = NULL;
mBasicAudio = NULL;
mSeeking = NULL;
// Filter graph running status
m_bInit = false;
// Data buffer pointer
m_pDataList = inBuffer;
}
CDXGraph::~CDXGraph()
{
Release();
m_pDataList = NULL;
}
//创建Fliter Graph
bool CDXGraph::Create(void)
{
m_bInit = false;
// Create filter graph
HRESULT hr = CoCreateInstance(CLSID_FilterGraph,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGraphBuilder,
(void**)&mGraph);
if (SUCCEEDED(hr))
{
m_bInit = true;
}
if (m_bInit)
{
// Media control interface
hr = mGraph->QueryInterface(IID_IMediaControl, (void **)&mMediaControl);
if (FAILED(hr))
{
m_bInit = false;
}
}
if (m_bInit)
{
// Media event interface
hr = mGraph->QueryInterface(IID_IMediaEventEx, (void **)&mEvent);
if (FAILED(hr))
{
m_bInit = false;
}
}
if (m_bInit)
{
// Media basic audio interface
hr = mGraph->QueryInterface(IID_IBasicAudio, (void **)&mBasicAudio);
if (FAILED(hr))
{
m_bInit = false;
}
}
if (m_bInit)
{
// Media seeking interface
hr = mGraph->QueryInterface(IID_IMediaSeeking, (void **)&mSeeking);
if (FAILED(hr))
{
m_bInit = false;
}
}
// construct source filter
// Media type
if (m_bInit)
{
//指定source filter输出pin上使用的媒体类型
CMediaType mt;
mt.majortype = MEDIATYPE_Stream;
mt.subtype = MEDIASUBTYPE_MPEG1Audio;
m_pSourceStream = new CMemStream(m_pDataList);
m_pSourceReader = new CMemReader(m_pSourceStream, &mt, &hr);
//增加一个引用计数,防止COM的自动删除
m_pSourceReader->AddRef();
//将Source Fliter加到Fliter Graph中
hr = mGraph->AddFilter(m_pSourceReader, NULL);
if (FAILED(hr))
{
m_bInit = false;
}
}
if (m_bInit)
{
// Waiting for event to start filter graph
//启动一个等待线程
::AfxBeginThread((AFX_THREADPROC)CDXGraph::WaitingThrd, this);
}
return m_bInit;
}
void CDXGraph::Release(void)
{
// Stop filter graph first
HRESULT hr;
if (mMediaControl != NULL)
{
hr = mMediaControl->Stop();
}
if (mGraph != NULL)
{
// remove the filter added before
mGraph->RemoveFilter(m_pSourceReader);//删除过滤器
// media event interface
SAFE_RELEASE(mEvent)
// media seeking interface
SAFE_RELEASE(mSeeking)
// media control interface
SAFE_RELEASE(mMediaControl)
// basic audio interface
SAFE_RELEASE(mBasicAudio)
// graph builder interface
SAFE_RELEASE(mGraph)
SAFE_DELETE(m_pSourceStream)
SAFE_DELETE(m_pSourceReader)
}
}
// When data buffer enough, start the filter graph
UINT CDXGraph::WaitingThrd(void * pParam)
{
CDXGraph * pGraph = (CDXGraph *) pParam;
if (pGraph != NULL && pGraph->m_pDataList != NULL)
{
//阻塞函数,询问数据接收队列管理器,是否已接收倒足够的数据
::WaitForSingleObject(pGraph->m_pDataList->m_hBufEnough, INFINITE);
if (!pGraph->IsRunning())
{
//开始构建完整的Fliter Granph
pGraph->StartGraph();
}
}
return 1;
}
//构建完整的Fliter Graph,并运行它
bool CDXGraph::StartGraph(void)
{
if (m_bInit)
{
//将Source Fliter的Pin输出的数据渲染播放
HRESULT hr = mGraph->Render(m_pSourceReader->GetPin(0));
if (FAILED(hr))
{
return false;
}
// run the filter graph
hr = mMediaControl->Run();
return true;
}
return false;
}
bool CDXGraph::ResetGraph(void)
{
CDXGraph * mFilterGraph = NULL;
if (mFilterGraph->IsRunning())
{
// If the filter graph running, release it first
mFilterGraph->Release();
}
// Reset the datalist
if (m_pDataList != NULL)
{
m_pDataList->ResetList();
ResetEvent(m_pDataList->m_hBufEnough);
}
// Create a new filter graph
Create();
return true;
}
IGraphBuilder * CDXGraph::GetGraph(void)
{
return mGraph;
}
IMediaEventEx * CDXGraph::GetEventHandle(void)
{
return mEvent;
}
// Connect filter from the upstream output pin to the downstream input pin
bool CDXGraph::ConnectFilters(IPin * inOutputPin, IPin * inInputPin,
const AM_MEDIA_TYPE * inMediaType)
{
if (mGraph && inOutputPin && inInputPin)
{
HRESULT hr = mGraph->ConnectDirect(inOutputPin, inInputPin, inMediaType);
return SUCCEEDED(hr) ? true : false;
}
return false;
}
void CDXGraph::DisconnectFilters(IPin * inOutputPin)
{
if (mGraph && inOutputPin)
{
HRESULT hr = mGraph->Disconnect(inOutputPin);
}
}
bool CDXGraph::Run(void)
{
if (mGraph && mMediaControl)
{
if (!IsRunning())
{
if (SUCCEEDED(mMediaControl->Run()))
{
return true;
}
}
else
{
return true;
}
}
return false;
}
bool CDXGraph::Stop(void)
{
if (mGraph && mMediaControl)
{
if (!IsStopped())
{
if (SUCCEEDED(mMediaControl->Stop()))
{
return true;
}
}
else
{
return true;
}
}
return false;
}
bool CDXGraph::Pause(void)
{
if (mGraph && mMediaControl)
{
if (!IsPaused())
{
if (SUCCEEDED(mMediaControl->Pause()))
{
return true;
}
}
else
{
return true;
}
}
return false;
}
bool CDXGraph::IsRunning(void)
{
if (mGraph && mMediaControl)
{
OAFilterState state = State_Stopped;
if (SUCCEEDED(mMediaControl->GetState(10, &state)))
{
return state == State_Running;
}
}
return false;
}
bool CDXGraph::IsStopped(void)
{
if (mGraph && mMediaControl)
{
OAFilterState state = State_Stopped;
if (SUCCEEDED(mMediaControl->GetState(10, &state)))
{
return state == State_Stopped;
}
}
return false;
}
bool CDXGraph::IsPaused(void)
{
if (mGraph && mMediaControl)
{
OAFilterState state = State_Stopped;
if (SUCCEEDED(mMediaControl->GetState(10, &state)))
{
return state == State_Paused;
}
}
return false;
}
// IMediaSeeking features
bool CDXGraph::GetCurrentPosition(double * outPosition)
{
if (mSeeking)
{
__int64 position = 0;
if (SUCCEEDED(mSeeking->GetCurrentPosition(&position)))
{
*outPosition = ((double)position) / 10000000.;
return true;
}
}
return false;
}
bool CDXGraph::GetStopPosition(double * outPosition)
{
if (mSeeking)
{
__int64 position = 0;
if (SUCCEEDED(mSeeking->GetStopPosition(&position)))
{
*outPosition = ((double)position) / 10000000.;
return true;
}
}
return false;
}
bool CDXGraph::SetCurrentPosition(double inPosition)
{
if (mSeeking)
{
__int64 one = 10000000;
__int64 position = (__int64)(one * inPosition);
HRESULT hr = mSeeking->SetPositions(&position, AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame,
0, AM_SEEKING_NoPositioning);
return SUCCEEDED(hr);
}
return false;
}
bool CDXGraph::SetStartStopPosition(double inStart, double inStop)
{
if (mSeeking)
{
__int64 one = 10000000;
__int64 startPos = (__int64)(one * inStart);
__int64 stopPos = (__int64)(one * inStop);
HRESULT hr = mSeeking->SetPositions(&startPos, AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame,
&stopPos, AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame);
return SUCCEEDED(hr);
}
return false;
}
bool CDXGraph::GetDuration(double * outDuration)
{
if (mSeeking)
{
__int64 length = 0;
if (SUCCEEDED(mSeeking->GetDuration(&length)))
{
*outDuration = ((double)length) / 10000000.;
return true;
}
}
return false;
}
bool CDXGraph::SetPlaybackRate(double inRate)
{
if (mSeeking)
{
if (SUCCEEDED(mSeeking->SetRate(inRate)))
{
return true;
}
}
return false;
}
bool CDXGraph::RenderFile(const char * inFile)
{
if (mGraph)
{
WCHAR szFilePath[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, inFile, -1, szFilePath, MAX_PATH);
if (SUCCEEDED(mGraph->RenderFile(szFilePath, NULL)))
{
return true;
}
}
return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -