From d8f527422632a9ef995fa83ab5499a5ffc39eaf6 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Fri, 24 Nov 2006 17:07:22 +0000 Subject: [PATCH] Windows port updates --- Makefile.nmake | 14 +- dsallocator.cc | 23 ++- dsallocator.h | 8 +- dssourcefilter.cc | 425 +++++++++++++++++++++++++++++++++++----- dssourcefilter.h | 48 ++++- dssourcepin.cc | 482 +++++++++++++++++++++++++++++++++++++++++----- dssourcepin.h | 65 +++++-- 7 files changed, 924 insertions(+), 141 deletions(-) diff --git a/Makefile.nmake b/Makefile.nmake index fad4573..c7cd27e 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -1,12 +1,12 @@ CXXFLAGS_DEV = -g -O0 -Wall -Woverloaded-virtual -Wshadow -Werror -DDEV -D_GNU_SOURCE $(INCLUDES) -CXXFLAGS_REL = /I"$(DXSDK_DIR)\Include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "NEW_DEMUXER" /nologo /EHsc /MD /GS /W3 /c /TP +CXXFLAGS_REL = /I"$(DXSDK_DIR)\Include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "NEW_DEMUXER" /nologo /EHsc /MD /GS /W3 /c /TP LDFLAGS = /INCREMENTAL:NO /NOLOGO /NODEFAULTLIB /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /LIBPATH:"$(DXSDK_DIR)\Lib\x86" -LIBS = Msvcrt.lib Ws2_32.lib shlwapi.lib d3d9.lib d3dx9.lib Iphlpapi.lib strmbase.lib Strmiids.lib winmm.lib MSVCPRT.lib atls.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib -CROSSLIBS = +LIBS = Msvcrt.lib Ws2_32.lib shlwapi.lib d3d9.lib d3dx9.lib Iphlpapi.lib Strmiids.lib winmm.lib MSVCPRT.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib +CROSSLIBS = !include "objects.mk" @@ -19,7 +19,7 @@ OBJECTS = $(OBJECTS1) $(OBJECTSWIN) default: release #dev -release:: +release:: CXXFLAGS= $(CXXFLAGS_REL) release:: vompclient.exe @@ -27,7 +27,7 @@ release:: vompclient.exe vompclient.exe: $(OBJECTS) vompwin.res link $(LDFLAGS) /OUT:"vompclient.exe" $(LIBS) $(OBJECTS) vompwin.res - + $(OBJECTS): $*.cc @@ -37,7 +37,7 @@ vompwin.res:vompwin.rc $(RC) /fo"vompwin.res" "vompwin.rc" clean: - del *.o + del *.o del vompclient.exe - del fonts\*.o + del fonts\*.o diff --git a/dsallocator.cc b/dsallocator.cc index 713d280..37faf2d 100644 --- a/dsallocator.cc +++ b/dsallocator.cc @@ -22,7 +22,6 @@ DsAllocator::DsAllocator() { - CAutoLock locked(&objCritSec); surfallocnotify=NULL; refcount=1; @@ -31,7 +30,6 @@ DsAllocator::DsAllocator() { } DsAllocator::~DsAllocator() { - CAutoLock locked(&objCritSec); CleanupSurfaces(); } @@ -44,28 +42,32 @@ void DsAllocator::CleanupSurfaces() { } HRESULT STDMETHODCALLTYPE DsAllocator::InitializeDevice(DWORD_PTR userid,VMR9AllocationInfo* allocinf,DWORD*numbuf){ - CAutoLock locked(&objCritSec); if (!surfallocnotify) return S_FALSE; + Lock(); CleanupSurfaces(); surfaces.resize(*numbuf); - return surfallocnotify->AllocateSurfaceHelper(allocinf,numbuf,&surfaces.at(0)); + HRESULT hres= surfallocnotify->AllocateSurfaceHelper(allocinf,numbuf,&surfaces.at(0)); + Unlock(); + return hres; } void DsAllocator::LostDevice() { - CAutoLock locked(&objCritSec); if (!surfallocnotify) return ; + Lock(); CleanupSurfaces(); IDirect3DDevice9 *d3ddev; d3ddev=((OsdWin*)Osd::getInstance())->getD3dDev(); HMONITOR hmon=((OsdWin*)Osd::getInstance())->getD3d()->GetAdapterMonitor(D3DADAPTER_DEFAULT); surfallocnotify->ChangeD3DDevice(d3ddev,hmon); + Unlock(); } HRESULT STDMETHODCALLTYPE DsAllocator::TerminateDevice(DWORD_PTR userid){ - CAutoLock locked(&objCritSec); + Lock(); CleanupSurfaces(); + Unlock(); return S_OK; //Do nothing } HRESULT STDMETHODCALLTYPE DsAllocator::GetSurface(DWORD_PTR userid,DWORD surfindex,DWORD surfflags, IDirect3DSurface9** surf) @@ -73,19 +75,22 @@ HRESULT STDMETHODCALLTYPE DsAllocator::GetSurface(DWORD_PTR userid,DWORD surfind if (surfindex>=surfaces.size()) return E_FAIL; if (surf==NULL) return E_POINTER; - CAutoLock locked(&objCritSec); + Lock(); surfaces[surfindex]->AddRef(); *surf=surfaces[surfindex]; + Unlock(); return S_OK; } HRESULT STDMETHODCALLTYPE DsAllocator::AdviseNotify(IVMRSurfaceAllocatorNotify9* allnoty){ - CAutoLock locked(&objCritSec); + Lock(); surfallocnotify=allnoty; IDirect3DDevice9 *d3ddev; //OK lets set the direct3d object from the osd d3ddev=((OsdWin*)Osd::getInstance())->getD3dDev(); HMONITOR hmon=((OsdWin*)Osd::getInstance())->getD3d()->GetAdapterMonitor(D3DADAPTER_DEFAULT); - return surfallocnotify->SetD3DDevice(d3ddev,hmon); + HRESULT hres=surfallocnotify->SetD3DDevice(d3ddev,hmon); + Unlock(); + return hres; } diff --git a/dsallocator.h b/dsallocator.h index 52b08cb..05ed4da 100644 --- a/dsallocator.h +++ b/dsallocator.h @@ -23,14 +23,16 @@ #include using namespace std; #include -#include + #include +#include #include +#include "mutex.h" -class DsAllocator: public IVMRSurfaceAllocator9, IVMRImagePresenter9 { +class DsAllocator: public IVMRSurfaceAllocator9, IVMRImagePresenter9,Mutex { public: DsAllocator(); virtual ~DsAllocator(); @@ -55,7 +57,7 @@ public: protected: vector surfaces; - CCritSec objCritSec; + //CCritSec objCritSec; IVMRSurfaceAllocatorNotify9* surfallocnotify; void CleanupSurfaces(); LONG refcount; diff --git a/dssourcefilter.cc b/dssourcefilter.cc index c779dfd..8689b8c 100644 --- a/dssourcefilter.cc +++ b/dssourcefilter.cc @@ -1,5 +1,5 @@ /* - Copyright 2004-2005 Chris Tallon + Copyright 2004-2006 Marten Richter This file is part of VOMP. @@ -19,85 +19,404 @@ */ #include "dssourcefilter.h" -DsSourceFilter::DsSourceFilter():CBaseFilter("Vomp Source Filter",NULL,&crit_sec,_uuidof(this)) +#define AUDIOPIN_NAME L"Audio" +#define VIDEOPIN_NAME L"Video" + +class DsSFEnumPins: public IEnumPins { +public: + DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos=0); + virtual ~DsSFEnumPins(); + virtual HRESULT STDMETHODCALLTYPE Next(ULONG numpin,IPin **pins,ULONG *fetched); + virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin); + virtual HRESULT STDMETHODCALLTYPE Reset(); + virtual HRESULT STDMETHODCALLTYPE Clone(IEnumPins **enuma); + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); +protected: + DsSourcePin* audiopin; + DsSourcePin* videopin; + DsSourceFilter *filter; + ULONG curpos; + volatile long refs; +}; + +DsSFEnumPins::DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos){ + audiopin=audio; + videopin=video; + curpos=pos; + filter=filt; + filt->AddRef(); +} + +DsSFEnumPins::~DsSFEnumPins(){ + filter->Release(); +} + +HRESULT STDMETHODCALLTYPE DsSFEnumPins::Next(ULONG numpin,IPin **pins,ULONG *fetched) { + int i; + if (fetched==NULL) return E_POINTER; + if (pins==NULL) return E_POINTER; + *fetched=0; + + for (i=0;(iAddRef(); pins[i]=(IPin*)audiopin;break; + case 1: videopin->AddRef(); pins[i]=(IPin*)videopin;break; + }; + (*fetched)++; + curpos++; + } + if ((*fetched)!=numpin) return S_FALSE; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSFEnumPins::Skip(ULONG numpin){ + curpos+=numpin; + if (curpos>2) return S_FALSE; + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSFEnumPins::Reset(){ + curpos=0; + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSFEnumPins::Clone(IEnumPins **enuma){ + if (enuma==NULL) return E_POINTER; + *enuma=new DsSFEnumPins(audiopin,videopin,filter,curpos); + (*enuma)->AddRef(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSFEnumPins::QueryInterface(REFIID id,void ** object){ + if (object==NULL) return E_POINTER; + if (id==IID_IUnknown ||id == IID_IEnumPins) { + *object=(IUnknown*)this; + ((IUnknown*)object)->AddRef(); + return NOERROR; + } else { + *object=NULL; + return E_NOINTERFACE; + } +} + + + +ULONG STDMETHODCALLTYPE DsSFEnumPins::AddRef(){ + InterlockedIncrement(&refs); + long tempref=refs; + if (tempref>1) return tempref; + else return 1; +} + +ULONG STDMETHODCALLTYPE DsSFEnumPins::Release(){ + long tempref=InterlockedDecrement(&refs); + + if (tempref==0) { + refs++; + delete this; + return NULL; + } else { + if (tempref>1) return tempref; + else return 1; + } +} + + + + + + + +DsSourceFilter::DsSourceFilter() { - //add audio pin - HRESULT res; - audiopin=new DsSourcePin(this,&crit_sec,&res,L"Vomp Audio Out",true); - videopin=new DsSourcePin(this,&crit_sec,&res,L"Vomp Video Out",false); + //add audio pin + HRESULT res; + audiopin=new DsSourcePin(this,&res,L"Vomp Audio Out",true); + videopin=new DsSourcePin(this,&res,L"Vomp Video Out",false); + filtergraph=NULL; + clock=NULL; + mystate=State_Stopped; + laststart=0; + refs=0; + InitializeCriticalSection(&filterlock); } DsSourceFilter::~DsSourceFilter() { - if (audiopin) delete audiopin; - if (videopin) delete videopin; + if (audiopin) delete audiopin; + if (videopin) delete videopin; + if (clock) { + clock->Release(); + clock=NULL; + } + DeleteCriticalSection(&filterlock); + +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::GetClassID(CLSID *clsid){ + if (clsid==NULL) return E_POINTER; + *clsid=_uuidof(this); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryInterface(REFIID id,void ** object){ + if (object==NULL) return E_POINTER; + if (id==IID_IUnknown) { + *object=(IUnknown*)this; + ((IUnknown*)object)->AddRef(); + return NOERROR; + } else if (id==IID_IBaseFilter) { + *object=(IBaseFilter*)this; + ((IBaseFilter*)object)->AddRef(); + return NOERROR; + } else if (id==IID_IMediaFilter) { + *object=(IMediaFilter*)this; + ((IMediaFilter*)object)->AddRef(); + return NOERROR; + }else { + *object=NULL; + return E_NOINTERFACE; + } +} + +ULONG STDMETHODCALLTYPE DsSourceFilter::AddRef(){ + InterlockedIncrement(&refs); + long tempref=refs; + if (tempref>1) return tempref; + else return 1; +} +ULONG STDMETHODCALLTYPE DsSourceFilter::Release(){ + long tempref=InterlockedDecrement(&refs); + + if (tempref==0) { + //refs++; + delete this; + return NULL; + } else { + if (tempref>1) return tempref; + else return 1; + } } +/*IBaseFilter*/ +HRESULT STDMETHODCALLTYPE DsSourceFilter::EnumPins(IEnumPins **enumar){ + if (enumar==NULL) return E_POINTER; + *enumar=new DsSFEnumPins(audiopin,videopin, this); + (*enumar)->AddRef(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::FindPin(LPCWSTR iden,IPin **pin){ + if (pin==NULL) return E_POINTER; + + if (wcscmp(AUDIOPIN_NAME,iden)==NULL) { + *pin=(IPin*)audiopin; + (*pin)->AddRef(); + return S_OK; + } + if (wcscmp(VIDEOPIN_NAME,iden)==NULL) { + *pin=(IPin*)videopin; + (*pin)->AddRef(); + return S_OK; + } + + *pin=NULL; + return VFW_E_NOT_FOUND; +} +HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryFilterInfo(FILTER_INFO *info){ + if (info==NULL) return E_POINTER; + wcsncpy(info->achName,L"VompWinFilter", sizeof(info->achName)/sizeof(WCHAR)); + info->pGraph=filtergraph; + if (info->pGraph!=NULL) info->pGraph->AddRef(); + return NOERROR; +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::JoinFilterGraph(IFilterGraph *graph,LPCWSTR name){ + //Should we lock + EnterCriticalSection(&filterlock); + filtergraph=graph; + filtergraph->AddRef(); + //We ignore the name + LeaveCriticalSection(&filterlock); + + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryVendorInfo(LPWSTR *vendinf) { + return E_NOTIMPL; +} + + +/*IMediaFilter*/ +HRESULT STDMETHODCALLTYPE DsSourceFilter::GetState(DWORD timeout,FILTER_STATE *state){ + if (state==NULL) return E_POINTER; + *state=mystate; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::SetSyncSource(IReferenceClock *uhr){ + EnterCriticalSection(&filterlock); + if (clock!=NULL) { + clock->Release(); + } + if (uhr!=NULL) { + uhr->AddRef(); + } + clock=uhr; + LeaveCriticalSection(&filterlock); + + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSourceFilter::GetSyncSource(IReferenceClock **uhr){ + if (uhr==NULL) return E_POINTER; + EnterCriticalSection(&filterlock); + if (clock!=NULL) clock->AddRef(); + *uhr=clock; + LeaveCriticalSection(&filterlock); + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::Stop(){ + EnterCriticalSection(&filterlock); + HRESULT aphres=S_OK; + HRESULT vphres=S_OK; + + if (audiopin->IsConnected()){ + aphres=audiopin->Inactive(); + } + if (videopin->IsConnected()){ + vphres=videopin->Inactive(); + } + + mystate=State_Stopped; + LeaveCriticalSection(&filterlock); + if (aphres!=S_OK) return aphres; + if (vphres!=S_OK) return vphres; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSourceFilter::Pause(){ + EnterCriticalSection(&filterlock); + HRESULT aphres; + HRESULT vphres; + + if (audiopin->IsConnected()){ + aphres=audiopin->Active(); + if (aphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return aphres; + } + } + if (videopin->IsConnected()){ + vphres=videopin->Active(); + if (vphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return vphres; + } + } + + mystate=State_Paused; + LeaveCriticalSection(&filterlock); + + + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSourceFilter::Run(REFERENCE_TIME start){ + + HRESULT aphres; + HRESULT vphres; + EnterCriticalSection(&filterlock); + + if (mystate==State_Stopped) { + HRESULT phres=Pause(); + if (phres!=S_OK) return phres; + } + + laststart=start; + + + if (audiopin->IsConnected()){ + aphres=audiopin->Run(start); + if (aphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return aphres; + } + } + + if (videopin->IsConnected()){ + vphres=videopin->Run(start); + if (vphres!=S_OK) { + LeaveCriticalSection(&filterlock); + return vphres; + } + } + + mystate=State_Running; + LeaveCriticalSection(&filterlock); + + + return S_OK; +} + + + int DsSourceFilter::GetPinCount() { - return 2; //audio and video + return 2; //audio and video } -CBasePin *DsSourceFilter::GetPin(int n){ - switch (n) { - case 0: - return audiopin; - case 1: - return videopin; - default: - return 0; - }; -} + int DsSourceFilter::getCurrentAudioMediaSample(IMediaSample** ms) { - if (!audiopin || !IsActive()) { - return 0; - } - if (audiopin->GetDeliveryBuffer(ms,NULL,NULL,0)!=S_OK) { - return 0; - } - return 1; + if (!audiopin || !IsActive()) { + return 0; + } + if (audiopin->getCurrentMediaSample(ms)!=S_OK) { + return 0; + } + return 1; } int DsSourceFilter::getCurrentVideoMediaSample(IMediaSample** ms) { - if (!videopin || !IsActive()) { - return 0; - } - if (videopin->GetDeliveryBuffer(ms,NULL,NULL,0)!=S_OK) { - return 0; - } - return 1; + if (!videopin || !IsActive()) { + return 0; + } + if (videopin->getCurrentMediaSample(ms)!=S_OK) { + return 0; + } + return 1; } int DsSourceFilter::DeliverAudioMediaSample(IMediaSample* ms) { - if (!audiopin || !IsActive()) { - ms->Release(); - return 0; - } - if (audiopin->Deliver(ms)!=S_OK) { - ms->Release(); - return 0; - } - ms->Release(); - return 1; + if (!audiopin || !IsActive()) { + ms->Release(); + return 0; + } + if (audiopin->deliver(ms)!=S_OK) { + ms->Release(); + return 0; + } + ms->Release(); + return 1; } int DsSourceFilter::DeliverVideoMediaSample(IMediaSample* ms) { - if (!videopin || !IsActive()) { - ms->Release(); - return 0; - } - if (videopin->Deliver(ms)!=S_OK) { - ms->Release(); - return 0; - } - ms->Release(); - return 1; + if (!videopin || !IsActive()) { + ms->Release(); + return 0; + } + if (videopin->deliver(ms)!=S_OK) { + ms->Release(); + return 0; + } + ms->Release(); + return 1; } + diff --git a/dssourcefilter.h b/dssourcefilter.h index c23c995..3535db0 100644 --- a/dssourcefilter.h +++ b/dssourcefilter.h @@ -22,27 +22,63 @@ #define DSSOURCEFILTER_H +#include "mutex.h" #include "dssourcepin.h" + [uuid("EB87AB22-7A95-49c3-8CCE-2F6D61A87009")] -class DsSourceFilter: public CBaseFilter { +class DsSourceFilter: public IBaseFilter { +friend class DsSourcePin; public: DsSourceFilter(); ~DsSourceFilter(); - CCritSec* GetLock(){return &crit_sec;}; virtual int GetPinCount(); - virtual CBasePin *GetPin(int n); int getCurrentAudioMediaSample(IMediaSample** ms); int DeliverAudioMediaSample(IMediaSample* ms); int getCurrentVideoMediaSample(IMediaSample** ms); int DeliverVideoMediaSample(IMediaSample* ms); - REFERENCE_TIME getStartOffset(){return m_tStart;}; + REFERENCE_TIME getStartOffset(){return laststart;}; + BOOL IsActive() {EnterCriticalSection(&filterlock); + FILTER_STATE tempstate=mystate;LeaveCriticalSection(&filterlock); + return (tempstate==State_Running) || (tempstate==State_Paused);}; + +/* IUnknown */ + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); +/*IPersist*/ + virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *clsid); + +/*IBaseFilter*/ + virtual HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **enumar); + virtual HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR iden,IPin **pin); + virtual HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *info); + virtual HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *graph,LPCWSTR name); + virtual HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *vendinf); +/*IMediaFilter*/ + virtual HRESULT STDMETHODCALLTYPE GetState(DWORD timeout,FILTER_STATE *state); + virtual HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *uhr); + virtual HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **uhr); + virtual HRESULT STDMETHODCALLTYPE Stop(); + virtual HRESULT STDMETHODCALLTYPE Pause(); + virtual HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME start); + + DsSourcePin *GetAudioPin() {return audiopin;}; + DsSourcePin *GetVideoPin() {return videopin;}; + + protected: - CCritSec crit_sec; DsSourcePin *audiopin; DsSourcePin *videopin; + IFilterGraph* filtergraph; + IReferenceClock* clock; + FILTER_STATE mystate; + REFERENCE_TIME laststart; + CRITICAL_SECTION filterlock; + + volatile long refs; }; -#endif +#endif diff --git a/dssourcepin.cc b/dssourcepin.cc index fab2c86..88319a4 100644 --- a/dssourcepin.cc +++ b/dssourcepin.cc @@ -1,50 +1,406 @@ -/* - Copyright 2004-2005 Chris Tallon - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "dssourcepin.h" -#include "dssourcefilter.h" -#include -#include - -DsSourcePin::DsSourcePin(DsSourceFilter *pFilter, - CCritSec *pLock,HRESULT *phr,LPCWSTR pName,bool audio): -CBaseOutputPin(NAME("dssourcepin"),pFilter,pLock,phr,pName) -{ - isaudiopin=audio; - m_pFilter=pFilter; - +/* + Copyright 2004-2005 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "dssourcepin.h" +#include "dssourcefilter.h" +#include +#include + + +class DsSFEnumMediaTypes: public IEnumMediaTypes { +public: + DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos=0); + virtual ~DsSFEnumMediaTypes(); + virtual HRESULT STDMETHODCALLTYPE Next(ULONG nummedia, AM_MEDIA_TYPE **pins,ULONG *fetched); + virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin); + virtual HRESULT STDMETHODCALLTYPE Reset(); + virtual HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **enuma); + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); +protected: + DsSourcePin* parent; + ULONG curpos; + volatile long refs; +}; + +DsSFEnumMediaTypes::DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos){ + parent=papa; + curpos=pos; + parent->AddRef(); + refs=0; +} + +DsSFEnumMediaTypes::~DsSFEnumMediaTypes(){ + parent->Release(); +} + +HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Next(ULONG numpin, AM_MEDIA_TYPE **pins,ULONG *fetched) { + int i; + if (fetched==NULL) return E_POINTER; + if (pins==NULL) return E_POINTER; + *fetched=0; + + for (i=0;(iGetMediaType(curpos+i,pins[i])!=S_OK) return S_FALSE; + curpos++; + (*fetched)++; + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Skip(ULONG numpin){ + curpos+=numpin; + if (curpos>1) return S_FALSE; + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Reset(){ + curpos=0; + return S_OK; +} +HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Clone(IEnumMediaTypes **enuma){ + if (enuma==NULL) return E_POINTER; + *enuma=new DsSFEnumMediaTypes(parent,curpos); + (*enuma)->AddRef(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::QueryInterface(REFIID id,void ** object){ + if (object==NULL) return E_POINTER; + if (id==IID_IUnknown ||id == IID_IEnumMediaTypes) { + *object=(IUnknown*)this; + ((IUnknown*)object)->AddRef(); + return NOERROR; + } else { + *object=NULL; + return E_NOINTERFACE; + } } -DsSourcePin::~DsSourcePin() -{ - + +ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::AddRef(){ + InterlockedIncrement(&refs); + long tempref=refs; + if (tempref>1) return tempref; + else return 1; +} + +ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::Release(){ + long tempref=InterlockedDecrement(&refs); + + if (tempref==0) { + refs++; + delete this; + return NULL; + } else { + if (tempref>1) return tempref; + else return 1; + } +} + + +void CopyMType(AM_MEDIA_TYPE* dest,const AM_MEDIA_TYPE*source) { + memcpy(dest,source,sizeof(AM_MEDIA_TYPE)); + if (source->pbFormat!=NULL) { + dest->pbFormat=(BYTE*)CoTaskMemAlloc(dest->cbFormat); + memcpy(dest->pbFormat,source->pbFormat,dest->cbFormat); + } +} +void ReleaseMType(AM_MEDIA_TYPE* free) { + if (free->cbFormat!=NULL) CoTaskMemFree(free->pbFormat); + free->pbFormat=NULL; +} + +DsSourcePin::DsSourcePin(DsSourceFilter *pFilter, + HRESULT *phr,LPCWSTR pName,bool audio) +{ + isaudiopin=audio; + m_pFilter=pFilter; + connected=NULL; + connectedinput=NULL; + allocator=NULL; + + + +} + +DsSourcePin::~DsSourcePin() +{ + + +} + +HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInterface(REFIID id,void ** object){ + if (object==NULL) return E_POINTER; + if (id==IID_IUnknown) { + *object=(IUnknown*)this; + ((IUnknown*)object)->AddRef(); + return NOERROR; + } else if (id==IID_IPin) { + *object=(IPin*)this; + ((IPin*)object)->AddRef(); + return NOERROR; + } else { + *object=NULL; + return E_NOINTERFACE; + } } -HRESULT DsSourcePin::GetMediaType(int iPosition, CMediaType *pmt) +ULONG STDMETHODCALLTYPE DsSourcePin::AddRef(){ + return m_pFilter->AddRef(); + +} +ULONG STDMETHODCALLTYPE DsSourcePin::Release(){ + return m_pFilter->Release(); +} + + +/*IPin*/ +HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype) { + if (pinempf==NULL) return E_POINTER; + EnterCriticalSection(&m_pFilter->filterlock); + + if (connected!=NULL) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_ALREADY_CONNECTED;} + if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;} + + + bool gotmt=false; + + if (mtype!=NULL) { + if (CheckMediaType(mtype)==S_OK){ + if (pinempf->ReceiveConnection((IPin*)this,mtype)==S_OK) { + CopyMType(&medtype,mtype); + LeaveCriticalSection(&m_pFilter->filterlock); + } else { + LeaveCriticalSection(&m_pFilter->filterlock); + CoTaskMemFree(mtype->pbFormat); + return VFW_E_TYPE_NOT_ACCEPTED; + } + + } else { + LeaveCriticalSection(&m_pFilter->filterlock); + CoTaskMemFree(mtype->pbFormat); + return VFW_E_TYPE_NOT_ACCEPTED; + } + CoTaskMemFree(mtype->pbFormat); + }else { + IEnumMediaTypes * emt; + EnumMediaTypes(&emt); + AM_MEDIA_TYPE emtype_np; + AM_MEDIA_TYPE * emtype; + emtype=&emtype_np; + ULONG fetched=0; + while (emt->Next(1,&emtype,&fetched)==S_OK) { + if (CheckMediaType(emtype)==S_OK){ + if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) { + + CopyMType(&medtype,emtype); + CoTaskMemFree(emtype->pbFormat); + gotmt=true; + break; + } + + } + CoTaskMemFree(emtype->pbFormat); + } + emt->Release(); + if (gotmt==false) { + pinempf->EnumMediaTypes(&emt); + while (emt->Next(1,&emtype,&fetched)==S_OK) { + if (CheckMediaType(emtype)==S_OK){ + if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) { + connected=pinempf; + CopyMType(&medtype,emtype); + CoTaskMemFree(emtype->pbFormat); + gotmt=true; + break; + } + + } + CoTaskMemFree(emtype->pbFormat); + } + emt->Release(); + if (gotmt==false) { + LeaveCriticalSection(&m_pFilter->filterlock); + return VFW_E_NO_ACCEPTABLE_TYPES; + } + } + } + + if (pinempf->QueryInterface(IID_IMemInputPin,(void**)&connectedinput)!=S_OK) { + LeaveCriticalSection(&m_pFilter->filterlock); + connectedinput->Release(); + connectedinput=NULL; + return VFW_E_NO_TRANSPORT; + } + ALLOCATOR_PROPERTIES eigenall; + ZeroMemory(&eigenall,sizeof(eigenall)); + connectedinput->GetAllocatorRequirements(&eigenall); + if (eigenall.cbAlign==0) eigenall.cbAlign=1; + connectedinput->GetAllocator(&allocator); + if (DecideBufferSize(allocator,&eigenall)==S_OK) { + if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){ + connected=pinempf; + LeaveCriticalSection(&m_pFilter->filterlock); + return S_OK; + } + } + if (allocator!=NULL) allocator->Release(); + allocator=NULL; + + if (CoCreateInstance(CLSID_MemoryAllocator,0,CLSCTX_INPROC_SERVER, + IID_IMemAllocator,(void **)allocator)==S_OK) { + if (DecideBufferSize(allocator,&eigenall)==S_OK) { + if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){ + connected=pinempf; + LeaveCriticalSection(&m_pFilter->filterlock); + return S_OK; + } + } + } + if (allocator!=NULL) allocator->Release(); + allocator=NULL; + LeaveCriticalSection(&m_pFilter->filterlock); + return VFW_E_NO_TRANSPORT; + + + + +} +HRESULT STDMETHODCALLTYPE DsSourcePin::ReceiveConnection(IPin *connect, + const AM_MEDIA_TYPE *mtype){ + return VFW_E_TYPE_NOT_ACCEPTED; //We have only output pins +} + HRESULT STDMETHODCALLTYPE DsSourcePin::Disconnect() { + EnterCriticalSection(&m_pFilter->filterlock); + if (connected!=NULL) { + if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;} + /*TODO: Decommit allocator*/ + allocator->Decommit(); + allocator->Release(); + allocator=NULL; + ReleaseMType(&medtype); + connectedinput->Release(); + connectedinput=NULL; + connected->Release(); + connected=NULL; + LeaveCriticalSection(&m_pFilter->filterlock); + return S_OK; + } + LeaveCriticalSection(&m_pFilter->filterlock); + return S_FALSE; + } + + HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectedTo(IPin **pin){ + if (pin==NULL) return E_POINTER; + IPin* pinn=connected; + *pin=pinn; + if (connected!=NULL) { + pinn->AddRef(); + return S_OK; + } else { + return VFW_E_NOT_CONNECTED; + } + } + HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectionMediaType(AM_MEDIA_TYPE *mtype){ + if (mtype==NULL) return E_POINTER; + if (connected!=NULL){ + CopyMType(mtype,&medtype); + return S_OK; + } else { + ZeroMemory(mtype,sizeof(mtype)); + return VFW_E_NOT_CONNECTED; + } + } + HRESULT STDMETHODCALLTYPE DsSourcePin::QueryPinInfo(PIN_INFO *info){ + if (info==NULL) return E_POINTER; + info->dir=PINDIR_OUTPUT; + info->pFilter=(IBaseFilter*)m_pFilter; + if (isaudiopin) wcscpy(info->achName,L"Audio"); + else wcscpy(info->achName,L"Video"); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE DsSourcePin::QueryDirection(PIN_DIRECTION *dir){ + if (dir==NULL) return E_POINTER; + *dir=PINDIR_OUTPUT; + return S_OK; + } + HRESULT STDMETHODCALLTYPE DsSourcePin::QueryId(LPWSTR *id){ + if (id==NULL) return E_POINTER; + *id=(LPWSTR)CoTaskMemAlloc(12); + if (*id==NULL) return E_OUTOFMEMORY; + + + if (isaudiopin) wcscpy(*id,L"Audio"); + else wcscpy(*id, L"Video"); + return S_OK; + } + HRESULT STDMETHODCALLTYPE DsSourcePin::QueryAccept(const AM_MEDIA_TYPE *mtype) { + if (mtype==NULL) return S_FALSE; + if (CheckMediaType(mtype)==S_OK) return S_OK; + else return S_FALSE; + } + HRESULT STDMETHODCALLTYPE DsSourcePin::EnumMediaTypes(IEnumMediaTypes **enuma){ +if (enuma==NULL) return E_POINTER; + *enuma=new DsSFEnumMediaTypes( this); + (*enuma)->AddRef(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInternalConnections(IPin **pin,ULONG *numpin){ + return E_NOTIMPL; +} +HRESULT STDMETHODCALLTYPE DsSourcePin::EndOfStream(){ + return E_UNEXPECTED; //we are a output pin! +} + +HRESULT STDMETHODCALLTYPE DsSourcePin::NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate){ + return E_UNEXPECTED;//we are a output pin! +} + +HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){ + if (allocator!=NULL) return allocator->GetBuffer(ms,NULL,NULL,0); + else return E_NOINTERFACE; +} + +HRESULT DsSourcePin::deliver(IMediaSample * ms){ + //EnterCriticalSection(&m_pFilter->filterlock); + HRESULT hres; + if (connectedinput!=NULL)hres= connectedinput->Receive(ms); + else hres= VFW_E_NOT_CONNECTED; + //LeaveCriticalSection(&m_pFilter->filterlock); + return hres; + +} + +HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt) { HRESULT hr; - ASSERT(pmt); - pmt->InitMediaType(); + if (isaudiopin){ if (iPosition==0) { - pmt->SetType(&MEDIATYPE_Audio); + ZeroMemory(pmt,sizeof(*pmt)); + pmt->lSampleSize = 1; + pmt->bFixedSizeSamples = TRUE; + pmt->majortype=MEDIATYPE_Audio; MPEG1WAVEFORMAT wfe; ZeroMemory(&wfe,sizeof(wfe)); wfe.wfx.cbSize=22; @@ -59,10 +415,12 @@ HRESULT DsSourcePin::GetMediaType(int iPosition, CMediaType *pmt) wfe.fwHeadModeExt=1; wfe.wHeadEmphasis=1; wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT; - pmt->SetSubtype(&MEDIASUBTYPE_MPEG2_AUDIO); - pmt->SetFormatType(&FORMAT_WaveFormatEx); - pmt->SetFormat((BYTE*)&wfe,sizeof(wfe)); - pmt->SetSampleSize(0); + pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO; + pmt->formattype=FORMAT_WaveFormatEx; + pmt->cbFormat=sizeof(wfe); + pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe)); + memcpy(pmt->pbFormat,&wfe,sizeof(wfe)); + pmt->lSampleSize=0; hr=S_OK; @@ -71,10 +429,13 @@ HRESULT DsSourcePin::GetMediaType(int iPosition, CMediaType *pmt) } } else { if (iPosition == 0) { - pmt->SetType(&MEDIATYPE_Video); + ZeroMemory(pmt,sizeof(*pmt)); + pmt->lSampleSize = 1; + pmt->bFixedSizeSamples = TRUE; + pmt->majortype=MEDIATYPE_Video; hr=S_OK; - pmt->SetSubtype(&MEDIASUBTYPE_MPEG2_VIDEO); - pmt->SetFormatType(&FORMAT_MPEG2Video); + pmt->subtype=MEDIASUBTYPE_MPEG2_VIDEO; + pmt->formattype=FORMAT_MPEG2Video; MPEG2VIDEOINFO hdr; ZeroMemory(&hdr,sizeof(hdr)); @@ -83,7 +444,10 @@ HRESULT DsSourcePin::GetMediaType(int iPosition, CMediaType *pmt) hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader); hdr.hdr.bmiHeader.biWidth = 720; hdr.hdr.bmiHeader.biHeight = 568; - pmt->SetFormat((BYTE*)&hdr,sizeof(hdr)); + pmt->cbFormat=sizeof(hdr); + pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(hdr)); + memcpy(pmt->pbFormat,&hdr,sizeof(hdr)); + } else { hr=VFW_S_NO_MORE_ITEMS; } @@ -91,11 +455,26 @@ HRESULT DsSourcePin::GetMediaType(int iPosition, CMediaType *pmt) return hr ; } +HRESULT DsSourcePin::Inactive() { + if (allocator!=NULL) return allocator->Decommit(); + return VFW_E_NO_ALLOCATOR; +} + +HRESULT DsSourcePin::Active() { + if (allocator!=NULL) return allocator->Commit(); + return VFW_E_NO_ALLOCATOR; +} + + +HRESULT DsSourcePin::Run(REFERENCE_TIME reftime){ + return NOERROR; +} + // No description -HRESULT DsSourcePin::CheckMediaType(const CMediaType *pmt) +HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt) { HRESULT res; - ASSERT (pmt); + if (isaudiopin) { bool subtype=false; #if 0 /* For future demands ac3 */ @@ -120,9 +499,9 @@ HRESULT DsSourcePin::CheckMediaType(const CMediaType *pmt) HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){ HRESULT hr; - CAutoLock al(m_pFilter->GetLock()); - CheckPointer(pa, E_POINTER); - CheckPointer(all_pp, E_POINTER); + + if (pa==NULL)return E_POINTER; + if (all_pp==NULL) return E_POINTER; if (isaudiopin) { if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024) { @@ -152,3 +531,4 @@ HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *al return S_OK; } + diff --git a/dssourcepin.h b/dssourcepin.h index 4fe80d3..2871592 100644 --- a/dssourcepin.h +++ b/dssourcepin.h @@ -1,5 +1,5 @@ /* - Copyright 2004-2005 Chris Tallon + Copyright 2004-2006 Marten Richter This file is part of VOMP. @@ -21,28 +21,69 @@ #ifndef DSPINFILTER_H #define DSPINFILTER_H -#include +#include + +#include + + class DsSourceFilter; [uuid("17F931AB-9A87-4c65-B99E-84F5BC5F7B09")] -class DsSourcePin: public CBaseOutputPin { +class DsSourcePin: public IPin { + public: - DsSourcePin(DsSourceFilter *pFilter, - CCritSec *pLock,HRESULT *phr,LPCWSTR pName,bool audio); - ~DsSourcePin(); + DsSourcePin(DsSourceFilter *pFilter,HRESULT *phr,LPCWSTR pName,bool audio); + ~DsSourcePin(); + BOOL IsConnected() {return (connected!=NULL);}; + HRESULT getCurrentMediaSample(IMediaSample**ms); + HRESULT deliver(IMediaSample * ms); + + virtual HRESULT DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp); + + HRESULT Inactive(); + HRESULT Active(); + HRESULT Run(REFERENCE_TIME reftime); + /*IPin*/ + + virtual HRESULT STDMETHODCALLTYPE Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype); + virtual HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *connect,const AM_MEDIA_TYPE *mtype); + virtual HRESULT STDMETHODCALLTYPE Disconnect(); + virtual HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pin); + virtual HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *mtype); + virtual HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *info); + virtual HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *dir); + virtual HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *id); + virtual HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *mtype); + virtual HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **enuma); + virtual HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **pin,ULONG *numpin); + virtual HRESULT STDMETHODCALLTYPE EndOfStream(); + virtual HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate); + /* IUnknown */ + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); + virtual HRESULT STDMETHODCALLTYPE BeginFlush(){return E_UNEXPECTED;}; + virtual HRESULT STDMETHODCALLTYPE EndFlush(){return E_UNEXPECTED;}; + virtual HRESULT GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt); + + - virtual HRESULT DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp); protected: - virtual HRESULT CheckMediaType(const CMediaType *pmt); - virtual HRESULT GetMediaType(int iPosition, CMediaType *pmt); - bool isaudiopin; - DsSourceFilter *m_pFilter; + virtual HRESULT CheckMediaType(const AM_MEDIA_TYPE *pmt); + + bool isaudiopin; + DsSourceFilter *m_pFilter; + IPin* connected; + IMemInputPin* connectedinput; + AM_MEDIA_TYPE medtype; + IMemAllocator* allocator; + }; -#endif \ No newline at end of file +#endif -- 2.39.2