How can I read an additional video stream from wmv and avi file?
For wmv file I use my own directshow source filter based on the source of an existing wmv source firter.
I have tried to use IWMReaderCallbackAdvanced, IWMReaderAdvanced2.
But, I do not know, how to connect IWMReaderCallbackAdvanced and IWMReaderAdvanced2.
When using IWMReader in the function OnSample can not be reached samples from additional video streams.
The source code of existing working modules (3dtv.at filters are unavailable).
Can you help me?
Here is the code:
#include "stdafx.h"
#include <initguid.h>
using namespace std;
#undef INFORMATION_MESSAGE
#define TRY(hr, X) {hr = X; if(!SUCCEEDED(hr)) throw hr;}
const AMOVIESETUP_MEDIATYPE sudOpPinTypes =
{
&MEDIATYPE_Stream,
&MEDIASUBTYPE_NULL
};
const AMOVIESETUP_PIN sudOpPin =
{
L"Output",
FALSE,
TRUE,
FALSE,
TRUE,
&CLSID_NULL,
0,
1,
&sudOpPinTypes
};
const AMOVIESETUP_FILTER sudAsync =
{
&CLSID_ASFStereoFilter,
L"ASF WMVStereoFilter",
MERIT_UNLIKELY,
1,
&sudOpPin
};
CFactoryTemplate g_Templates[1] =
{
{
L"ASF WMVStereoFilter",
&CLSID_ASFStereoFilter,
CEncStereoFilter::CreateInstance,
NULL,
&sudAsync
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}
CEncStereoFilter::CEncStereoFilter(LPUNKNOWN pUnk, HRESULT *phr) :
CSource(NAME("Encrypted File Source"), pUnk, CLSID_ASFStereoFilter),
CSourceSeeking(NAME("Seek object"), pUnk, phr, &m_cStateLock),
m_bActive(FALSE), m_bPaused(FALSE), m_bSeek(FALSE), m_bEOF(FALSE), m_Helper(this)
{
CAutoLock cAutoLock(&m_cStateLock);
m_hAsyncEvent = CreateEvent(NULL, FALSE, FALSE, 0); *phr = WMCreateReader(NULL, 0, &m_pReader); *phr = m_pReader.QueryInterface<IWMReaderAdvanced2>(&m_pReaderAdvanced); }
CEncStereoFilter::~CEncStereoFilter()
{
Cleanup();
CloseHandle(m_hAsyncEvent); }
CUnknown* WINAPI CEncStereoFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
{
ASSERT(phr);
return (CUnknown*)(CSource*)(new CEncStereoFilter(pUnk, phr));
}
STDMETHODIMP CEncStereoFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
CHECK_GET_INTERFACE(IFileSourceFilter);
CHECK_GET_INTERFACE(IMediaSeeking);
return CSource::NonDelegatingQueryInterface(riid, ppv);
}
STDMETHODIMP CEncStereoFilter::Load(LPCOLESTR lpwszFileName, const AM_MEDIA_TYPE *pmt)
{
CAutoLock lck(&m_cStateLock);
USES_CONVERSION;
CheckPointer(lpwszFileName, E_POINTER);
HRESULT hRet = S_OK;
try
{
IWMReaderCallback* pWMCallback = (IWMReaderCallback*)&m_Helper;
m_pReader->Open(lpwszFileName, pWMCallback, 0);
IWMReaderCallbackAdvanced* pWMCallbackAdvanced = (IWMReaderCallbackAdvanced*)&m_Helper;
if(WaitForSingleObject(m_hAsyncEvent, INFINITE) == WAIT_TIMEOUT)
throw RPC_E_TIMEOUT;
TRY(hRet, m_hrAsync); GetWMStreamsAndMediaTypes(); CreateWMPins(); GetWMVDuration(lpwszFileName); m_File = lpwszFileName;
}
catch(HRESULT h)
{
hRet = h;
}
return hRet;
}
STDMETHODIMP CEncStereoFilter::GetCurFile(LPOLESTR * ppszFileName, AM_MEDIA_TYPE *pmt)
{
CheckPointer(ppszFileName, E_POINTER);
*ppszFileName = NULL;
wstring wsName = m_File;
if(!wsName.empty())
{
DWORD n = sizeof(WCHAR)*(1 + wsName.size());
*ppszFileName = (LPOLESTR) CoTaskMemAlloc( n );
CopyMemory(*ppszFileName, wsName.c_str(), n);
}
return S_OK;
}
STDMETHODIMP CEncStereoFilter::Run(REFERENCE_TIME tStart)
{
CAutoLock lock(&m_cStateLock);
if(m_bPaused)
m_pReader->Resume(); return CSource::Run(tStart);
}
STDMETHODIMP CEncStereoFilter::Pause()
{
CAutoLock lock(&m_cStateLock);
if(m_bActive)
{
m_pReader->Pause(); m_bPaused = TRUE;
}
return CSource::Pause();
}
STDMETHODIMP CEncStereoFilter::OnSample(DWORD dwOutputNum, QWORD qwSampleTime, QWORD qwSampleDuration, DWORD dwFlags, INSSBuffer *pSample, void *pvContext)
{
CEncWMVPin *pPin = (CEncWMVPin *)m_paStreams[dwOutputNum];
if(pPin->IsConnected())
{
CAutoLock lock(&pPin->m_cLock);
pSample->AddRef(); pPin->m_Samples.push(WMSample(dwFlags, pSample)); }
return S_OK;
}
STDMETHODIMP CEncStereoFilter::OnStreamSample(WORD wStreamNum, QWORD cnsSampleTime, QWORD cnsSampleDuration, DWORD dwFlags, INSSBuffer *pSample, void *pvContext)
{
CEncWMVPin *pPin = (CEncWMVPin *)m_paStreams[wStreamNum];
if(pPin->IsConnected())
{
CAutoLock lock(&pPin->m_cLock);
pSample->AddRef(); pPin->m_Samples.push(WMSample(dwFlags, pSample)); }
return S_OK;
}
STDMETHODIMP CEncStereoFilter::OnTime(QWORD cnsCurrentTime, void *pvContext)
{
return S_OK;
}
STDMETHODIMP CEncStereoFilter::OnStreamSelection(WORD wStreamCount, WORD *pStreamNumbers, WMT_STREAM_SELECTION *pSelections, void *pvContext)
{
return S_OK;
}
STDMETHODIMP CEncStereoFilter::OnOutputPropsChanged( DWORD dwOutputNum, WM_MEDIA_TYPE *pMediaType, void *pvContext)
{
return S_OK;
}
STDMETHODIMP CEncStereoFilter::AllocateForStream( WORD wStreamNum, DWORD cbBuffer, INSSBuffer **ppBuffer, void *pvContext)
{
return S_OK;
}
STDMETHODIMP CEncStereoFilter::AllocateForOutput(DWORD dwOutputNum, DWORD cbBuffer, INSSBuffer **ppBuffer, void *pvContext)
{
return S_OK;
}
STDMETHODIMP CEncStereoFilter::OnStatus(WMT_STATUS Status, HRESULT hr, WMT_ATTR_DATATYPE dwType, BYTE *pValue, void *pvContext)
{
bool bFireEvent = false;
switch(Status)
{
case WMT_CLOSED: case WMT_OPENED:
case WMT_STOPPED:
bFireEvent = true;
break;
case WMT_STARTED: m_bEOF = FALSE;
break;
case WMT_EOF: if(!m_bEOF)
m_bEOF = TRUE;
bFireEvent = true;
break;
}
if(bFireEvent)
{
m_hrAsync = hr;
SetEvent(m_hAsyncEvent);
}
return S_OK;
}
HRESULT CEncStereoFilter::ChangeStart()
{
if(m_State == State_Paused) {
m_pReader->Pause(); m_bSeek = TRUE; for(size_t i = 0; i < m_mtArray.size(); ++i)
{
CEncWMVPin* pPin = (CEncWMVPin*)m_paStreams[i];
if(pPin->ThreadExists())
{
pPin->DeliverBeginFlush(); pPin->Stop(); pPin->DeliverEndFlush(); pPin->Run(); }
}
m_pReader->Start(m_rtStart, 0, 1.0, 0); m_bSeek = FALSE; }
return S_OK;
}
void CEncStereoFilter::Cleanup()
{
for(size_t i = 0; i < m_mtArray.size(); ++i)
CoTaskMemFree(m_mtArray[i]); }
void CEncStereoFilter::GetWMVDuration(LPCOLESTR pwszFileName)
{
HRESULT hr;
CComQIPtr<IWMHeaderInfo3> pHdrInfo(m_pReader); WORD wStream = 0; WMT_ATTR_DATATYPE attrType = WMT_TYPE_QWORD;
WORD wSize = sizeof(QWORD);
TRY(hr, pHdrInfo->GetAttributeByName(&wStream, g_wszWMDuration, &attrType, (BYTE*)&m_rtDuration, &wSize));
}
void CEncStereoFilter::GetWMStreamsAndMediaTypes()
{
CAutoLock cAutoLock(&m_cStateLock);
CComQIPtr<IWMProfile> pProf(m_pReader);
HRESULT hr;
DWORD dwNumStreams;
pProf->GetStreamCount(&dwNumStreams); #ifdef INFORMATION_MESSAGE
wchar_t local_message[500];
const wchar_t const *local_caption = L"Information";
swprintf(local_message,sizeof(local_message)/sizeof(wchar_t),L"Streams count: %d",dwNumStreams);
::MessageBoxW(0,local_message,local_caption,MB_ICONINFORMATION);
#endif
CComPtr<IWMOutputMediaProps> local_pOutProps_Video;
CComPtr<IWMOutputMediaProps> local_pOutProps_Audio;
CComPtr<IWMOutputMediaProps> local_pOutProps_Text;
CComPtr<IWMOutputMediaProps> local_pOutProps_ScriptCommand;
CComPtr<IWMOutputMediaProps> local_pOutProps_Timecode;
for(size_t i = 0; i < dwNumStreams; ++i) {
CComPtr<IWMStreamConfig> pStreamConfig; pProf->GetStream(i, &pStreamConfig);
CComPtr<IWMOutputMediaProps> pOutProps; m_pReader->GetOutputProps(i, &pOutProps);
GUID local_stream_GUID;
pStreamConfig->GetStreamType(&local_stream_GUID);
if(pOutProps==NULL)
{
CComPtr<IWMMediaProps> local_pProps;
pStreamConfig.QueryInterface<IWMMediaProps>(&local_pProps);
local_pProps.CopyTo((IWMMediaProps **)&pOutProps);
}
if(pOutProps)
{
if
(
local_stream_GUID == MEDIATYPE_Video
)
{
pOutProps.CopyTo(&local_pOutProps_Video);
#ifdef INFORMATION_MESSAGE
::MessageBoxW(0,L"Stream type MEDIATYPE_Video",local_caption,MB_ICONINFORMATION);
#endif
}
else
if
(
local_stream_GUID == MEDIATYPE_Audio
)
{
pOutProps.CopyTo(&local_pOutProps_Audio);
#ifdef INFORMATION_MESSAGE
::MessageBoxW(0,L"Stream type MEDIATYPE_Audio",local_caption,MB_ICONINFORMATION);
#endif
}
else
if
(
local_stream_GUID == MEDIATYPE_Text
)
{
pOutProps.CopyTo(&local_pOutProps_Text);
#ifdef INFORMATION_MESSAGE
::MessageBoxW(0,L"Stream type MEDIATYPE_Text",local_caption,MB_ICONINFORMATION);
#endif
}
else
if
(
local_stream_GUID == MEDIATYPE_ScriptCommand
)
{
pOutProps.CopyTo(&local_pOutProps_ScriptCommand);
#ifdef INFORMATION_MESSAGE
::MessageBoxW(0,L"Stream type MEDIATYPE_ScriptCommand",local_caption,MB_ICONINFORMATION);
#endif
}
else
if
(
local_stream_GUID == MEDIATYPE_Timecode
)
{
pOutProps.CopyTo(&local_pOutProps_Timecode);
#ifdef INFORMATION_MESSAGE
::MessageBoxW(0,L"Stream type MEDIATYPE_Timecode",local_caption,MB_ICONINFORMATION);
#endif
}
}
else
{
if
(
local_stream_GUID == MEDIATYPE_Video
)
{
local_pOutProps_Video.CopyTo(&pOutProps);
#ifdef INFORMATION_MESSAGE
::MessageBoxW(0,L"Set Properties for Stream type MEDIATYPE_Video",local_caption,MB_ICONINFORMATION);
#endif
}
else
if
(
local_stream_GUID == MEDIATYPE_Audio
)
{
local_pOutProps_Audio.CopyTo(&pOutProps);
#ifdef INFORMATION_MESSAGE
::MessageBoxW(0,L"Set Properties for Stream type MEDIATYPE_Audio",local_caption,MB_ICONINFORMATION);
#endif
}
else
if
(
local_stream_GUID == MEDIATYPE_Text
)
{
local_pOutProps_Text.CopyTo(&pOutProps);
#ifdef INFORMATION_MESSAGE
::MessageBoxW(0,L"Set Properties for Stream type MEDIATYPE_Text",local_caption,MB_ICONINFORMATION);
#endif
}
else
if
(
local_stream_GUID == MEDIATYPE_ScriptCommand
)
{
local_pOutProps_ScriptCommand.CopyTo(&pOutProps);
#ifdef INFORMATION_MESSAGE
::MessageBoxW(0,L"Set Properties for Stream type MEDIATYPE_ScriptCommand",local_caption,MB_ICONINFORMATION);
#endif
}
else
if
(
local_stream_GUID == MEDIATYPE_Timecode
)
{
local_pOutProps_Timecode.CopyTo(&pOutProps);
#ifdef INFORMATION_MESSAGE
::MessageBoxW(0,L"Set Properties for Stream type MEDIATYPE_Timecode",local_caption,MB_ICONINFORMATION);
#endif
}
m_pReader->SetOutputProps(i, pOutProps);
}
if(pOutProps)
{
WORD cbName; wstring wsName;
TRY(hr, pStreamConfig->GetStreamName(NULL, &cbName));
wsName.resize(cbName);
pStreamConfig->GetStreamName((WCHAR*)wsName.data(), &cbName);
m_PinNames.push_back(wsName);
#ifdef INFORMATION_MESSAGE
wchar_t local_message[500];
swprintf(local_message,sizeof(local_message)/sizeof(wchar_t),L"Stream: %d\nStream name: %s",i,(WCHAR*)wsName.data());
::MessageBoxW(0,local_message,local_caption,MB_ICONINFORMATION);
#endif
DWORD cbSize;
AM_MEDIA_TYPE *pmt;
TRY(hr, pOutProps->GetMediaType(NULL, &cbSize));
pmt = (AM_MEDIA_TYPE *)CoTaskMemAlloc(cbSize);
TRY(hr, pOutProps->GetMediaType((WM_MEDIA_TYPE*)pmt, &cbSize));
m_mtArray.push_back(pmt);
}
}
}
void CEncStereoFilter::CreateWMPins()
{
CAutoLock cAutoLock(&m_cStateLock);
m_paStreams = (CSourceStream **) new CEncWMVPin*[m_mtArray.size()]; CComQIPtr<IWMReaderAdvanced> pAdv(m_pReader);
for(size_t i = 0; i < m_mtArray.size(); ++i)
{
HRESULT hr;
CEncWMVPin *pPin = new CEncWMVPin(&hr, this, (LPCWSTR)m_PinNames[i].c_str(), m_mtArray[i], i == 0);
if(hr==S_OK)
{
if(i == 0)
m_pFirstPin = pPin;
hr = pAdv->GetMaxOutputSampleSize(i, &pPin->m_dwSampleSize);
if(hr!=S_OK)
{
hr = pAdv->GetMaxStreamSampleSize(i,&pPin->m_dwSampleSize);
if(hr!=S_OK)
{
pPin->m_dwSampleSize = 2000*1500*4;
}
}
}
}
}
CEncWMVPin::CEncWMVPin(HRESULT *phr, CEncStereoFilter *pParent, LPCWSTR pPinName, AM_MEDIA_TYPE *pmt, BOOL bMaster) :
CSourceStream(NAME("WMV Source pin"),phr, pParent, pPinName), m_bMaster(bMaster)
{
CAutoLock lock(&m_cLock);
m_pParent = pParent;
m_mt = *pmt;
}
CEncWMVPin::~CEncWMVPin()
{
CAutoLock lock(&m_cLock);
while(!m_Samples.empty()) {
WMSample s = m_Samples.front();
m_Samples.pop();
s.pINSSBuffer->Release();
}
}
HRESULT CEncWMVPin::FillBuffer(IMediaSample *pms)
{
while(m_Samples.empty() && m_pParent->m_bActive && !m_pParent->m_bSeek && !m_pParent->m_bEOF)
Sleep(1);
if(m_pParent->m_bSeek)
{
pms->SetActualDataLength(0);
pms->SetDiscontinuity(TRUE);
return S_OK;
}
if(!m_pParent->m_bActive || m_pParent->m_bEOF)
return S_FALSE;
WMSample s;
{
CAutoLock lock(&m_cLock);
s = m_Samples.front();
m_Samples.pop();
}
DWORD dwLen;
BYTE *pDataDest, *pDataSrc;
if(SUCCEEDED(s.pINSSBuffer->GetBufferAndLength(&pDataSrc, &dwLen)))
{
pms->GetPointer(&pDataDest);
memcpy(pDataDest, pDataSrc, dwLen);
pms->SetActualDataLength(dwLen);
pms->SetDiscontinuity((s.dwFlags & WM_SF_DISCONTINUITY));
pms->SetSyncPoint(s.dwFlags & WM_SF_CLEANPOINT);
pms->SetTime(NULL, NULL);
}
s.pINSSBuffer->Release();
return S_OK;
}
HRESULT CEncWMVPin::GetMediaType(int iPosition, CMediaType *pmt)
{
if(!iPosition)
{
*pmt = m_mt;
return S_OK;
}
return VFW_S_NO_MORE_ITEMS;
}
HRESULT CEncWMVPin::CheckMediaType(const CMediaType *pmt)
{
if(*pmt == m_mt) return S_OK;
else
return S_FALSE;
}
HRESULT CEncWMVPin::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProperties)
{
CAutoLock cAutoLock(m_pFilter->pStateLock());
HRESULT hr = S_OK;
pProperties->cBuffers = 5;
pProperties->cbBuffer = m_dwSampleSize;
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pProperties,&Actual);
if(FAILED(hr)) return hr;
if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;
return S_OK;
}
HRESULT CEncWMVPin::Active()
{
CAutoLock lock(&m_cLock); m_pParent->m_bActive = TRUE; if(m_bMaster) m_pParent->m_pReader->Start(m_pParent->m_rtStart, 0, 1.0, 0);
return CSourceStream::Active(); }
HRESULT CEncWMVPin::Inactive()
{
if(m_bMaster) m_pParent->m_pReader->Stop();
m_pParent->m_bActive = FALSE; return CSourceStream::Inactive(); }
HRESULT CEncWMVPin::OnThreadStartPlay()
{
return DeliverNewSegment(m_pParent->m_rtStart, m_pParent->m_rtDuration, 1.0);
}
#pragma once
DEFINE_GUID(CLSID_ASFStereoFilter, 0x20FFACF7, 0xBC0F, 0x4AD5, 0x86, 0xEF, 0x53, 0x84, 0xEF, 0x96, 0xA3, 0xD7);
class CEncWMVPin;
struct WMSample
{
DWORD dwFlags;
INSSBuffer *pINSSBuffer;
WMSample(DWORD adwFlags, INSSBuffer *apINSSBuffer) :dwFlags(adwFlags), pINSSBuffer(apINSSBuffer) {}
WMSample() {}
};
class CWMVStereoFilterHelper : public CUnknown, public IWMReaderCallback, public IWMReaderCallbackAdvanced
{
CComPtr<IWMReaderCallback> m_pFilter;
CComPtr<IWMReaderCallbackAdvanced> m_pFilter_advanced;
public :
CWMVStereoFilterHelper(IWMReaderCallback *pFilter):
CUnknown(NAME("WMV StereoFilter Helper object"), 0),
m_pFilter(pFilter)
{
AddRef(); m_pFilter->QueryInterface<IWMReaderCallbackAdvanced>(&m_pFilter_advanced);
}
DECLARE_IUNKNOWN;
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
CHECK_GET_INTERFACE(IWMReaderCallback);
CHECK_GET_INTERFACE(IWMReaderCallbackAdvanced);
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
}
HRESULT STDMETHODCALLTYPE FORWARD6(OnSample, m_pFilter, DWORD, dwOutputNum, QWORD, cnsSampleTime, QWORD, cnsSampleDuration, DWORD, dwFlags, INSSBuffer*, pSample, void*, pvContext);
HRESULT STDMETHODCALLTYPE FORWARD5(OnStatus, m_pFilter, WMT_STATUS, Status, HRESULT, hr, WMT_ATTR_DATATYPE, dwType, BYTE*, pValue, void*, pvContext);
HRESULT STDMETHODCALLTYPE FORWARD6(OnStreamSample, m_pFilter_advanced, WORD ,wStreamNum, QWORD, cnsSampleTime, QWORD, cnsSampleDuration, DWORD, dwFlags, INSSBuffer *,pSample, void *,pvContext);
HRESULT STDMETHODCALLTYPE FORWARD2(OnTime, m_pFilter_advanced, QWORD, cnsCurrentTime, void *,pvContext);
HRESULT STDMETHODCALLTYPE FORWARD4(OnStreamSelection, m_pFilter_advanced, WORD, wStreamCount, WORD *,pStreamNumbers, WMT_STREAM_SELECTION *,pSelections, void *,pvContext);
HRESULT STDMETHODCALLTYPE FORWARD3(OnOutputPropsChanged, m_pFilter_advanced, DWORD, dwOutputNum, WM_MEDIA_TYPE *,pMediaType, void *,pvContext);
HRESULT STDMETHODCALLTYPE FORWARD4(AllocateForStream, m_pFilter_advanced, WORD, wStreamNum, DWORD, cbBuffer, INSSBuffer **,ppBuffer, void *,pvContext);
HRESULT STDMETHODCALLTYPE FORWARD4(AllocateForOutput, m_pFilter_advanced, DWORD, dwOutputNum, DWORD, cbBuffer, INSSBuffer **,ppBuffer, void *,pvContext);
};
class CEncStereoFilter : virtual public CSource, virtual public CSourceSeeking, public IFileSourceFilter, public IWMReaderCallback, public IWMReaderCallbackAdvanced
{
friend class CEncWMVPin;
wstring m_File;
void Cleanup();
HANDLE m_hAsyncEvent; HRESULT m_hrAsync; BOOL m_bEOF, m_bActive, m_bPaused, m_bSeek; vector<AM_MEDIA_TYPE*> m_mtArray; vector<wstring> m_PinNames; CEncWMVPin *m_pFirstPin; CWMVStereoFilterHelper m_Helper; CComPtr<IWMReader> m_pReader; CComPtr<IWMReaderAdvanced2> m_pReaderAdvanced; void GetWMVDuration(LPCOLESTR pwszFile); void GetWMStreamsAndMediaTypes(); void CreateWMPins(); public:
CEncStereoFilter(LPUNKNOWN pUnk, HRESULT *phr);
~CEncStereoFilter();
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { return CSource::GetOwner()->QueryInterface(riid,ppv); }
STDMETHODIMP_(ULONG) AddRef() { return CSource::GetOwner()->AddRef(); }
STDMETHODIMP_(ULONG) Release() { return CSource::GetOwner()->Release(); }
static CUnknown* WINAPI CreateInstance(LPUNKNOWN, HRESULT *);
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
STDMETHODIMP Load(LPCOLESTR lpwszFileName, const AM_MEDIA_TYPE *pmt);
STDMETHODIMP GetCurFile(LPOLESTR *ppszFileName, AM_MEDIA_TYPE *pmt);
STDMETHODIMP Run(REFERENCE_TIME rtStart);
STDMETHODIMP Pause();
STDMETHODIMP OnSample(DWORD dwOutputNum, QWORD cnsSampleTime, QWORD cnsSampleDuration, DWORD dwFlags, INSSBuffer *pSample, void *pvContext);
STDMETHODIMP OnStatus(WMT_STATUS Status, HRESULT hr, WMT_ATTR_DATATYPE dwType, BYTE *pValue, void *pvContext);
STDMETHODIMP OnStreamSample(WORD wStreamNum, QWORD cnsSampleTime, QWORD cnsSampleDuration, DWORD dwFlags, INSSBuffer *pSample, void *pvContext);
STDMETHODIMP OnTime(QWORD cnsCurrentTime, void *pvContext);
STDMETHODIMP OnStreamSelection(WORD wStreamCount, WORD *pStreamNumbers, WMT_STREAM_SELECTION *pSelections, void *pvContext);
STDMETHODIMP OnOutputPropsChanged( DWORD dwOutputNum, WM_MEDIA_TYPE *pMediaType, void *pvContext);
STDMETHODIMP AllocateForStream( WORD wStreamNum, DWORD cbBuffer, INSSBuffer **ppBuffer, void *pvContext);
STDMETHODIMP AllocateForOutput(DWORD dwOutputNum, DWORD cbBuffer, INSSBuffer **ppBuffer, void *pvContext);
HRESULT ChangeStart();
HRESULT ChangeStop() DUMMYIMPLEMENT;
HRESULT ChangeRate() DUMMYIMPLEMENT;
};
class CEncWMVPin : public CSourceStream
{
public:
CCritSec m_cLock; CEncStereoFilter *m_pParent; queue<WMSample> m_Samples; BOOL m_bMaster; DWORD m_dwSampleSize; CEncWMVPin(HRESULT *phr, CEncStereoFilter *pParent, LPCWSTR pPinName, AM_MEDIA_TYPE *pmt, BOOL bMaster);
~CEncWMVPin();
HRESULT FillBuffer(IMediaSample *pms);
HRESULT DecideBufferSize(IMemAllocator *pIMemAlloc, ALLOCATOR_PROPERTIES *pProperties);
HRESULT CheckMediaType(const CMediaType *pMediaType);
HRESULT GetMediaType(int iPosition, CMediaType *pmt);
HRESULT Active(void);
HRESULT Inactive();
HRESULT OnThreadStartPlay(void);
};