topical media & game development
hush-src-multi-GamePlayer-VMR9Subgraph.cpp / cpp
//------------------------------------------------------------------------------
// File: VMR9Subgraph.cpp
//
// Desc: DirectShow sample code - MultiVMR9 GamePlayer
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
include <stdafx.h>
include <MultiVMR9.h>
include <VMR9Subgraph.h>
include <vip.h>
// AE
HRESULT CVMR9Subgraph::CaptureAndRender(CComPtr<IMultiVMR9Wizard> pWizard, int num, WCHAR *wcPath)
{
HRESULT hr = S_OK;
CComPtr<IVMRFilterConfig9> pConfig;
CComPtr<IGraphBuilder> pGb;
//if( !wcPath )
//{
// return E_POINTER;
//}
USES_CONVERSION;
if (wcPath) {
wcsncpy( m_wcPath, wcPath, MAX_PATH);
_tcsncpy( m_achPath, W2T(wcPath), MAX_PATH);
}
// first, check that file exists
//if( INVALID_FILE_ATTRIBUTES == GetFileAttributes( m_achPath))
//{
// MessageBox(NULL, TEXT("Requested media file was not found"), TEXT("Error"), MB_OK);
//return VFW_E_NOT_FOUND;
//}
// AE
ICaptureGraphBuilder2 *pBuild = NULL;
CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild);
// create graph
hr = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IFilterGraph, (void**)&(m_pGraph.p) );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Failed to create the filter graph"), TEXT("Error"), MB_OK);
return hr;
}
// create and add VMR9
hr = CoCreateInstance( CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&(m_pVMR.p) );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Failed to create instance of VMR9"), TEXT("Error"), MB_OK);
return hr;
}
hr = m_pGraph->AddFilter( m_pVMR, L"VMR9");
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Failed to add VMR9 to the graph"), TEXT("Error"), MB_OK);
return hr;
}
// configure VMR9
hr = m_pVMR->QueryInterface( IID_IVMRFilterConfig9, (void**)&(pConfig.p) );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Cannot get IVMRFilterConfig9 from VMR9"), TEXT("Error"), MB_OK);
return hr;
}
// if wizard is provided, set VMR to the renderless code and attach to the wizard
if( pWizard )
{
// set VMR to the renderless mode
hr = pConfig->SetRenderingMode( VMR9Mode_Renderless );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Failed to set VMR9 to the renderless mode"), TEXT("Error"), MB_OK);
return hr;
}
hr = pWizard->Attach( m_pVMR, &m_dwID );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Failed to attach graph to the wizard"), TEXT("Error"), MB_OK);
return hr;
}
}
// try to render media source
hr = m_pGraph->QueryInterface( IID_IGraphBuilder, (void**)&(pGb.p) );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Cannot get IGraphBuilder from the filter graph"), TEXT("Error"), MB_OK);
return hr;
}
// AE
pBuild->SetFiltergraph(pGb);
IBaseFilter *pSource;
// FindCaptureDevice(&pSource);
//GetVideoInputFilter(&pSource, 0);
if (0) {//vip::find_video(0,0,&pSource,wcPath,0,0);
pGb->AddSourceFilter( wcPath, L"Video Source", &pSource);
//vip::find_capture0(&pSource,wcPath);
} else {
vip::find_capture(&pSource,0, num);
pGb->AddFilter(pSource, L"Video Capture");
}
//&MEDIATYPE_Video
pBuild->RenderStream(0, 0, pSource, 0, m_pVMR);
//pBuild->RenderStream(0, &MEDIATYPE_Video, pSource, 0, m_pVMR);
//pBuild->RenderStream(0, &MEDIATYPE_Audio, pSource, 0, NULL);
//hr = pGb->RenderFile( m_wcPath, NULL);
//if( FAILED(hr))
//{
// MessageBox(NULL, TEXT("Failed to render specified media file"), TEXT("Error"), MB_OK);
//return hr;
//}
hr = CheckVMRConnection();
if( FAILED(hr))
{
hr = pWizard->Detach( m_dwID );
MessageBox(NULL, TEXT("Application does not support this media type.\r\nTry some other media source"),
TEXT("Error"), MB_OK);
return hr;
}
// ok, all is rendered, now get MediaControl, MediaSeeking and continue
hr = m_pGraph->QueryInterface( IID_IMediaControl, (void**)&(m_pMc.p) );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Cannot find IMediaControl interface"), TEXT("Error"), MB_OK);
return hr;
}
hr = m_pGraph->QueryInterface( IID_IMediaSeeking, (void**)&(m_pMs.p) );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Cannot find IMediaSeeking interface"), TEXT("Error"), MB_OK);
return hr;
}
return hr;
}
****************************Public*Routine******************************\
CVMR9Subgraph
constructor
\*************************************************************************
CVMR9Subgraph::CVMR9Subgraph()
: m_dwID( NULL)
{
capture = 0;
m_wcPath[0] = L'\0';
m_achPath[0] = TEXT('\0');
}
****************************Public*Routine******************************\
CVMR9Subgraph
destructor
\*************************************************************************
CVMR9Subgraph::~CVMR9Subgraph()
{
}
****************************Public*Routine******************************\
BuildAndRender
Builds the filter graph to render the media file located at wcPath with use of VMR9;
if wizard is provided, VMR9 is set to the renderless mode and custom allocator-
presenter (which is pWizard in this sample) is advised.
Return values: errors from the filter graph and wizard
\*************************************************************************
HRESULT CVMR9Subgraph::BuildAndRender( WCHAR *wcPath, CComPtr<IMultiVMR9Wizard> pWizard )
{
HRESULT hr = S_OK;
CComPtr<IVMRFilterConfig9> pConfig;
CComPtr<IGraphBuilder> pGb;
ICaptureGraphBuilder2 *pBuild = NULL;
// CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
// CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild);
if( !wcPath )
{
return E_POINTER;
}
USES_CONVERSION;
wcsncpy( m_wcPath, wcPath, MAX_PATH);
_tcsncpy( m_achPath, W2T(wcPath), MAX_PATH);
// first, check that file exists
if( INVALID_FILE_ATTRIBUTES == GetFileAttributes( m_achPath))
{
MessageBox(NULL, TEXT("Requested media file was not found"), TEXT("Error"), MB_OK);
return VFW_E_NOT_FOUND;
}
// create graph
hr = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IFilterGraph, (void**)&(m_pGraph.p) );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Failed to create the filter graph"), TEXT("Error"), MB_OK);
return hr;
}
// create and add VMR9
hr = CoCreateInstance( CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&(m_pVMR.p) );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Failed to create instance of VMR9"), TEXT("Error"), MB_OK);
return hr;
}
hr = m_pGraph->AddFilter( m_pVMR, L"VMR9");
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Failed to add VMR9 to the graph"), TEXT("Error"), MB_OK);
return hr;
}
// configure VMR9
hr = m_pVMR->QueryInterface( IID_IVMRFilterConfig9, (void**)&(pConfig.p) );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Cannot get IVMRFilterConfig9 from VMR9"), TEXT("Error"), MB_OK);
return hr;
}
// if wizard is provided, set VMR to the renderless code and attach to the wizard
if( pWizard )
{
// set VMR to the renderless mode
hr = pConfig->SetRenderingMode( VMR9Mode_Renderless );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Failed to set VMR9 to the renderless mode"), TEXT("Error"), MB_OK);
return hr;
}
hr = pWizard->Attach( m_pVMR, &m_dwID );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Failed to attach graph to the wizard"), TEXT("Error"), MB_OK);
return hr;
}
}
// try to render media source
hr = m_pGraph->QueryInterface( IID_IGraphBuilder, (void**)&(pGb.p) );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Cannot get IGraphBuilder from the filter graph"), TEXT("Error"), MB_OK);
return hr;
}
//pBuild->RenderStream(0, 0, fSource, 0, g_filter);
//hr = pBuild->RenderStream(0, &MEDIATYPE_Audio, fSource, 0, NULL);
if (0) {
pBuild->SetFiltergraph(pGb);
IBaseFilter *pSource;
pGb->AddSourceFilter( wcPath, L"Video Source", &pSource);
hr = pBuild->RenderStream(0, 0, pSource, 0, m_pVMR);
} else {
hr = pGb->RenderFile( m_wcPath, NULL);
}
//hr = pGb->RenderStream(0, 0, pSource, 0, m_pVMR);
// &MEDIATYPE_Video
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Failed to render specified media file"), TEXT("Error"), MB_OK);
return hr;
}
hr = CheckVMRConnection();
if( FAILED(hr))
{
hr = pWizard->Detach( m_dwID );
MessageBox(NULL, TEXT("Application does not support this media type.\r\nTry some other media source"),
TEXT("Error"), MB_OK);
return hr;
}
// ok, all is rendered, now get MediaControl, MediaSeeking and continue
hr = m_pGraph->QueryInterface( IID_IMediaControl, (void**)&(m_pMc.p) );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Cannot find IMediaControl interface"), TEXT("Error"), MB_OK);
return hr;
}
hr = m_pGraph->QueryInterface( IID_IMediaSeeking, (void**)&(m_pMs.p) );
if( FAILED(hr))
{
MessageBox(NULL, TEXT("Cannot find IMediaSeeking interface"), TEXT("Error"), MB_OK);
return hr;
}
return hr;
}
****************************Public*Routine******************************\
CheckVMRConnection
\*************************************************************************
HRESULT CVMR9Subgraph::CheckVMRConnection()
{
HRESULT hr = S_OK;
bool bConnected = false;
CComPtr<IEnumPins> pEnum;
CComPtr<IPin> pPin;
if( !m_pVMR )
return E_UNEXPECTED;
hr = m_pVMR->EnumPins( &pEnum );
if( FAILED(hr))
return hr;
hr = pEnum->Next( 1, &pPin, NULL);
while( SUCCEEDED(hr) && pPin)
{
CComPtr<IPin> pConnectedPin;
hr = pPin->ConnectedTo( &pConnectedPin );
if( SUCCEEDED(hr) && pConnectedPin )
{
bConnected = true;
break;
}
pPin = NULL;
hr = pEnum->Next( 1, &pPin, NULL);
}// while
hr = (true == bConnected) ? S_OK : E_FAIL;
return hr;
}
****************************Public*Routine******************************\
Run
\*************************************************************************
HRESULT CVMR9Subgraph::Run()
{
HRESULT hr = S_OK;
if( !m_pMc )
{
return E_UNEXPECTED;
}
hr = m_pMc->Run();
return hr;
}
****************************Public*Routine******************************\
Pause
\*************************************************************************
HRESULT CVMR9Subgraph::Pause()
{
HRESULT hr = S_OK;
if( !m_pMc )
{
return E_UNEXPECTED;
}
hr = m_pMc->Pause();
return hr;
}
****************************Public*Routine******************************\
Stop
\*************************************************************************
HRESULT CVMR9Subgraph::Stop()
{
HRESULT hr = S_OK;
OAFilterState state;
if( !m_pMc )
{
return E_UNEXPECTED;
}
hr = m_pMc->Stop();
state = State_Running;
while( State_Stopped != state && SUCCEEDED(hr))
{
hr = m_pMc->GetState(100, &state);
Sleep(100);
}
return hr;
}
****************************Public*Routine******************************\
GetState
Returns OAFilterState from IMediaControl of the graph
Return values: errors from the filter graph and wizard
\*************************************************************************
OAFilterState CVMR9Subgraph::GetState()
{
OAFilterState state = State_Stopped;
if( m_pMc )
{
HRESULT hr = m_pMc->GetState( 20, &state );
}
return state;
}
****************************Public*Routine******************************\
SetTime
\*************************************************************************
HRESULT CVMR9Subgraph::SetTime( LONGLONG llCur)
{
HRESULT hr = S_OK;
LONGLONG llDur = 0L;
if( !m_pMs )
return E_FAIL;
hr = m_pMs->SetPositions( &llCur, AM_SEEKING_AbsolutePositioning,
&llDur, AM_SEEKING_NoPositioning);
return hr;
}
****************************Public*Routine******************************\
GetTimes
\*************************************************************************
HRESULT CVMR9Subgraph::GetTimes( LONGLONG& llCur, LONGLONG& llDur)
{
HRESULT hr = S_OK;
if( !m_pMs )
return E_FAIL;
hr = m_pMs->GetPositions( &llCur, &llDur );
return hr;
}
****************************Public*Routine******************************\
GetPathT, GetPathW
\*************************************************************************
void CVMR9Subgraph::GetPathT( TCHAR* achPath )
{
if( achPath )
{
_tcscpy( achPath, m_achPath);
}
}
void CVMR9Subgraph::GetPathW( WCHAR* wcPath )
{
if( wcPath )
{
wcscpy( wcPath, m_wcPath);
}
}
****************************Public*Routine******************************\
DestroyGraph
Stops the graph, destroys and removes all the filters (VMR9 is removed last)
\*************************************************************************
HRESULT CVMR9Subgraph::DestroyGraph()
{
HRESULT hr = S_OK;
OAFilterState state;
if( !m_pGraph )
{
return E_POINTER;
}
FILTER_INFO fi;
CComPtr<IMediaControl> pMc;
CComPtr<IEnumFilters> pEnum;
CComPtr<IBaseFilter> pFilter;
CComPtr<IBaseFilter> pVMR = NULL;
// 1. stop the graph
hr = m_pGraph->QueryInterface( IID_IMediaControl, (void**)&(pMc.p) );
if( FAILED(hr))
{
return hr;
}
do
{
hr = pMc->GetState(100, &state);
} while( S_OK == hr && State_Stopped != state );
hr = m_pGraph->EnumFilters( &(pEnum.p) );
if( FAILED(hr))
{
return hr;
}
// tear off
hr = pEnum->Next(1, &(pFilter.p), NULL);
while( S_OK == hr && pFilter )
{
hr = DisconnectPins( pFilter );
pFilter = NULL;
hr = pEnum->Next(1, &(pFilter.p), NULL);
}
pFilter = NULL;
// remove filters
hr = pEnum->Reset();
hr = pEnum->Next(1, &(pFilter.p), NULL);
while( S_OK == hr && pFilter )
{
hr = pFilter->QueryFilterInfo( &fi);
if( fi.pGraph)
fi.pGraph->Release();
if( 0 == wcscmp( fi.achName, L"VMR9"))
{
pVMR = pFilter;
}
hr = m_pGraph->RemoveFilter( pFilter);
pFilter = NULL;
hr = pEnum->Reset();
hr = pEnum->Next(1, &pFilter, NULL);
}
pFilter = NULL;
pEnum = NULL;
pVMR = NULL;
return S_OK;
}
****************************Public*Routine******************************\
DisconnectPins
Disconnects pins of a filter
\*************************************************************************
HRESULT CVMR9Subgraph::DisconnectPins( CComPtr<IBaseFilter> pFilter)
{
HRESULT hr = S_OK;
CComPtr<IEnumPins> pEnum;
CComPtr<IPin> pPin;
if( !pFilter )
{
return E_POINTER;
}
hr = pFilter->EnumPins( &pEnum );
if( FAILED(hr))
{
return hr;
}
hr = pEnum->Next( 1, &pPin, NULL);
while( S_OK == hr && pPin )
{
hr = pPin->Disconnect();
pPin = NULL;
hr = pEnum->Next( 1, &pPin, NULL);
}
pPin = NULL;
pEnum = NULL;
return S_OK;
}
(C) Æliens
20/2/2008
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.