diff options
-rw-r--r-- | loader/dshow/DS_Filter.c | 177 | ||||
-rw-r--r-- | loader/dshow/DS_Filter.h | 39 | ||||
-rw-r--r-- | loader/dshow/Makefile | 44 | ||||
-rw-r--r-- | loader/dshow/allocator.c | 154 | ||||
-rw-r--r-- | loader/dshow/allocator.h | 49 | ||||
-rw-r--r-- | loader/dshow/cmediasample.c | 251 | ||||
-rw-r--r-- | loader/dshow/cmediasample.h | 96 | ||||
-rw-r--r-- | loader/dshow/guids.c | 61 | ||||
-rw-r--r-- | loader/dshow/guids.h | 90 | ||||
-rw-r--r-- | loader/dshow/inputpin.c | 667 | ||||
-rw-r--r-- | loader/dshow/inputpin.h | 265 | ||||
-rw-r--r-- | loader/dshow/interfaces.h | 417 | ||||
-rw-r--r-- | loader/dshow/iunk.h | 47 | ||||
-rw-r--r-- | loader/dshow/outputpin.c | 483 | ||||
-rw-r--r-- | loader/dshow/outputpin.h | 122 | ||||
-rw-r--r-- | loader/dshow/test.divx | bin | 0 -> 9294 bytes |
16 files changed, 2962 insertions, 0 deletions
diff --git a/loader/dshow/DS_Filter.c b/loader/dshow/DS_Filter.c new file mode 100644 index 0000000000..51d1c126dc --- /dev/null +++ b/loader/dshow/DS_Filter.c @@ -0,0 +1,177 @@ +#include <stdio.h> +#include <string.h> +#include "DS_Filter.h" +#include <except.h> +//#include "../loader/loader.h" +#include <string> +#define __MODULE__ "DirectShow generic filter" + +using namespace std; + +typedef long STDCALL (*GETCLASS) (const GUID*, const GUID*, void**); +extern "C" char* def_path; + +extern "C" int STDCALL LoadLibraryA(const char*); +extern "C" STDCALL void* GetProcAddress(int, const char*); +extern "C" int STDCALL FreeLibrary(int); + +DS_Filter::DS_Filter() + :m_iHandle(0), m_pFilter(0), m_pInputPin(0), + m_pOutputPin(0), m_pSrcFilter(0), + m_pOurInput(0), m_pOurOutput(0), + m_pImp(0), m_pAll(0), m_pParentFilter(0) +{ +} + +void DS_Filter::Create(string dllname, const GUID* id, AM_MEDIA_TYPE* in_fmt, AM_MEDIA_TYPE* out_fmt) +{ + try + { + string _fullname=def_path; + _fullname+="/"; + _fullname+=dllname; + m_iHandle= LoadLibraryA(_fullname.c_str()); + if(!m_iHandle)throw FATAL("Could not open DLL"); + GETCLASS func=(GETCLASS)GetProcAddress(m_iHandle, "DllGetClassObject"); + if(!func)throw FATAL("Illegal or corrupt DLL"); + + HRESULT result; + IClassFactory* factory=0; + IUnknown* object=0; + + result=func(id, &IID_IClassFactory, (void**)&factory); + if(result || (!factory)) throw FATAL("No such class object");; + + printf("# factory = %X\n",(unsigned int)factory); + printf("# factory->vt = %X\n",(unsigned int)factory->vt); + printf("# factory->vt->CreateInstance = %X\n",(unsigned int)factory->vt->CreateInstance); + + printf("Calling factory->vt->CreateInstance()\n"); + result=factory->vt->CreateInstance(factory, 0, &IID_IUnknown, (void**)&object); + printf("Calling factory->vt->Release()\n"); + +// result=factory->vt->CreateInstance(factory, 0, &IID_IUnknown, (void**)&object); + + printf("CreateInstance ok %x\n",result); + + factory->vt->Release((IUnknown*)factory); + if(result || (!object)) throw FATAL("Class factory failure"); + + result=object->vt->QueryInterface(object, &IID_IBaseFilter, (void**)&m_pFilter); + object->vt->Release((IUnknown*)object); + if(result || (!m_pFilter)) throw FATAL("Object does not have IBaseFilter interface"); + + IEnumPins* enum_pins=0; + // enumerate pins + result=m_pFilter->vt->EnumPins(m_pFilter, &enum_pins); + if(result || (!enum_pins)) throw FATAL("Could not enumerate pins"); + IPin* array[256]; + ULONG fetched; + enum_pins->vt->Reset(enum_pins); + result=enum_pins->vt->Next(enum_pins, (ULONG)256, (IPin**)array, &fetched); + printf("Pins enumeration returned %d pins, error is %x\n", fetched, result); + + for(int i=0; i<fetched; i++) + { + int direction=-1; + array[i]->vt->QueryDirection(array[i], (PIN_DIRECTION*)&direction); + if((!m_pInputPin)&&(direction==0)) + { + m_pInputPin=array[i]; + m_pInputPin->vt->AddRef((IUnknown*)m_pInputPin); + } + if((!m_pOutputPin)&&(direction==1)) + { + m_pOutputPin=array[i]; + m_pOutputPin->vt->AddRef((IUnknown*)m_pOutputPin); + } + array[i]->vt->Release((IUnknown*)(array[i])); + } + if(!m_pInputPin)throw FATAL("Input pin not found"); + if(!m_pOutputPin)throw FATAL("Output pin not found"); + + result=m_pInputPin->vt->QueryInterface((IUnknown*)m_pInputPin, &IID_IMemInputPin, (void**)&m_pImp); + if(result) + throw FATAL("Error getting IMemInputPin interface"); + m_pOurType=in_fmt; + m_pDestType=out_fmt; + result=m_pInputPin->vt->QueryAccept(m_pInputPin, m_pOurType); + if(result) throw FATAL("Source format is not accepted"); + + m_pParentFilter=new CBaseFilter2; + m_pSrcFilter=new CBaseFilter(*m_pOurType, m_pParentFilter); + m_pOurInput=m_pSrcFilter->GetPin(); + m_pOurInput->vt->AddRef((IUnknown*)m_pOurInput); + + result=m_pInputPin->vt->ReceiveConnection(m_pInputPin, m_pOurInput, m_pOurType); + if(result) throw FATAL("Error connecting to input pin"); + + m_pOurOutput=new COutputPin(*m_pDestType); + result=m_pOutputPin->vt->ReceiveConnection(m_pOutputPin, + m_pOurOutput, m_pDestType); + if(result)throw FATAL("Error connecting to output pin"); + m_iState=1; + } + catch(FatalError e) + { + e.PrintAll(); + if(m_pFilter)m_pFilter->vt->Release((IUnknown*)m_pFilter); + if(m_pOutputPin)m_pOutputPin->vt->Release((IUnknown*)m_pOutputPin); + if(m_pInputPin)m_pInputPin->vt->Release((IUnknown*)m_pInputPin); + if(m_pImp)m_pImp->vt->Release((IUnknown*)m_pImp); + if(m_pOurInput)m_pOurInput->vt->Release((IUnknown*)m_pOurInput); + delete m_pSrcFilter; + delete m_pParentFilter; + delete m_pOurOutput; + if(m_iHandle)FreeLibrary(m_iHandle); + throw; + } +} +void DS_Filter::Start() +{ + if(m_iState!=1) + return; + + HRESULT hr=m_pFilter->vt->Run(m_pFilter, 0); + if(hr!=0) + { + cerr<<"WARNING: m_Filter->Run() failed, error code "<<hex<<hr<<dec<<endl; + } + hr=m_pImp->vt->GetAllocator(m_pImp, &m_pAll); + if(hr) + { + cerr<<"Error getting IMemAllocator interface "<<hex<<hr<<dec<<endl; + m_pImp->vt->Release((IUnknown*)m_pImp); + return; + } + m_pImp->vt->NotifyAllocator(m_pImp, m_pAll, 0); + m_iState=2; + return; +} +void DS_Filter::Stop() +{ + if(m_iState!=2) + return; + m_pAll->vt->Release((IUnknown*)m_pAll); + m_pAll=0; + m_pFilter->vt->Stop(m_pFilter); + m_iState=1; + return; +} +DS_Filter::~DS_Filter() +{ + if(m_iState==0) + return; + if(m_iState==2)Stop(); + if(m_pInputPin)m_pInputPin->vt->Disconnect(m_pInputPin); + if(m_pOutputPin)m_pOutputPin->vt->Disconnect(m_pOutputPin); + if(m_pFilter)m_pFilter->vt->Release((IUnknown*)m_pFilter); + if(m_pOutputPin)m_pOutputPin->vt->Release((IUnknown*)m_pOutputPin); + if(m_pInputPin)m_pInputPin->vt->Release((IUnknown*)m_pInputPin); + if(m_pOurInput)m_pOurInput->vt->Release((IUnknown*)m_pOurInput); + if(m_pImp)m_pImp->vt->Release((IUnknown*)m_pImp); + delete m_pSrcFilter; + delete m_pParentFilter; + delete m_pOurOutput; + if(m_iHandle)FreeLibrary(m_iHandle); +} diff --git a/loader/dshow/DS_Filter.h b/loader/dshow/DS_Filter.h new file mode 100644 index 0000000000..1cb5a4d211 --- /dev/null +++ b/loader/dshow/DS_Filter.h @@ -0,0 +1,39 @@ +#ifndef DS_Filter_H +#define DS_Filter_H + +#include "interfaces.h" +#include "inputpin.h" +#include "outputpin.h" +#include <string> +using namespace std; +/** + User will allocate and fill format structures, call Create(), + and then set up m_pAll. +**/ +class DS_Filter +{ +protected: +public: + DS_Filter(); + virtual ~DS_Filter(); + void Create(string dllname, const GUID* id, AM_MEDIA_TYPE* in_fmt, AM_MEDIA_TYPE* out_fmt); + void Start(); + void Stop(); + int m_iHandle; + IBaseFilter* m_pFilter; + IPin* m_pInputPin; + IPin* m_pOutputPin; + + CBaseFilter* m_pSrcFilter; + CBaseFilter2* m_pParentFilter; + IPin* m_pOurInput; + COutputPin* m_pOurOutput; + + AM_MEDIA_TYPE *m_pOurType, *m_pDestType; + IMemAllocator* m_pAll; + IMemInputPin* m_pImp; + int m_iState; +protected: +}; + +#endif
\ No newline at end of file diff --git a/loader/dshow/Makefile b/loader/dshow/Makefile new file mode 100644 index 0000000000..3970cfcfd4 --- /dev/null +++ b/loader/dshow/Makefile @@ -0,0 +1,44 @@ + +LIBNAME = libDS_Filter.a + +include ../../config.mak + +SRCS = DS_Filter.cpp allocator.cpp cmediasample.cpp guids.cpp inputpin.cpp outputpin.cpp +OBJS = DS_Filter.o allocator.o cmediasample.o guids.o inputpin.o outputpin.o + +INCLUDE = -I. -I.. -I../wine +CFLAGS = $(OPTFLAGS) $(INCLUDE) + +.SUFFIXES: .cpp .o + +# .PHONY: all clean + +.cpp.o: + $(CC) -c $(CFLAGS) -o $@ $< + +$(LIBNAME): .depend $(OBJS) + $(AR) r $(LIBNAME) $(OBJS) + +test: test.cpp + $(CC) test.cpp $(CFLAGS) -o test -L. -lDS_Filter -L.. -lloader -ldl -lpthread -lstdc++ + +all: $(LIBNAME) + +clean: + rm -f *.o *.a *~ + +distclean: + rm -f Makefile.bak *.o *.a *~ .depend test test.raw + +dep: depend +depend: .depend + +.depend: Makefile ../../config.mak + makedepend -f- -- $(CFLAGS) -- $(SRCS) 1>.depend 2>/dev/null + +# +# include dependency files if they exist +# +ifneq ($(wildcard .depend),) +include .depend +endif diff --git a/loader/dshow/allocator.c b/loader/dshow/allocator.c new file mode 100644 index 0000000000..496d56c66f --- /dev/null +++ b/loader/dshow/allocator.c @@ -0,0 +1,154 @@ +#include <stdio.h> +#include "allocator.h" +#include <com.h> +#define E_NOTIMPL 0x80004001 +class AllocatorKeeper +{ +public: + AllocatorKeeper() + { + RegisterComClass(&CLSID_MemoryAllocator, MemAllocator::CreateAllocator); + } +}; +static AllocatorKeeper keeper; +GUID MemAllocator::interfaces[]= +{ + IID_IUnknown, + IID_IMemAllocator, +}; +IMPLEMENT_IUNKNOWN(MemAllocator) + +MemAllocator::MemAllocator() + :refcount(1) +{ + Debug printf("MemAllocator::MemAllocator() called\n"); + vt=new IMemAllocator_vt; + vt->QueryInterface = QueryInterface; + vt->AddRef = AddRef; + vt->Release = Release; + vt->SetProperties = SetProperties; + vt->GetProperties = GetProperties; + vt->Commit = Commit; + vt->Decommit = Decommit; + vt->GetBuffer = GetBuffer; + vt->ReleaseBuffer = ReleaseBuffer; + + props.cBuffers=1; + props.cbBuffer=65536;/* :/ */ + props.cbAlign=props.cbPrefix=0; +} + +long MemAllocator::CreateAllocator(GUID* clsid, GUID* iid, void** ppv) +{ + if(!ppv)return -1; + *ppv=0; + if(memcmp(clsid, &CLSID_MemoryAllocator, sizeof(GUID))) + return -1; + + IMemAllocator* p=new MemAllocator; + int result=p->vt->QueryInterface((IUnknown*)p, iid, ppv); + p->vt->Release((IUnknown*)p); + return result; +} + + +/* + long cBuffers; + long cbBuffer; + long cbAlign; + long cbPrefix; +*/ +HRESULT STDCALL MemAllocator::SetProperties ( + IMemAllocator * This, + /* [in] */ ALLOCATOR_PROPERTIES *pRequest, + /* [out] */ ALLOCATOR_PROPERTIES *pActual) +{ + Debug printf("MemAllocator::SetProperties() called\n"); + if(!pRequest)return 0x80004003; + if(!pActual)return 0x80004003; + if(pRequest->cBuffers<=0)return -1; + if(pRequest->cbBuffer<=0)return -1; + MemAllocator* me=(MemAllocator*)This; + if(me->used_list.size() || me->free_list.size())return -1; + me->props=*pRequest; + *pActual=*pRequest; + return 0; +} + +HRESULT STDCALL MemAllocator::GetProperties ( + IMemAllocator * This, + /* [out] */ ALLOCATOR_PROPERTIES *pProps) +{ + Debug printf("MemAllocator::GetProperties() called\n"); + if(!pProps)return -1; + if(((MemAllocator*)This)->props.cbBuffer<0)return -1; + *pProps=((MemAllocator*)This)->props; + return 0; +} + +HRESULT STDCALL MemAllocator::Commit ( + IMemAllocator * This) +{ + Debug printf("MemAllocator::Commit() called\n"); + MemAllocator* me=(MemAllocator*)This; + if(((MemAllocator*)This)->props.cbBuffer<0)return -1; + if(me->used_list.size() || me->free_list.size())return -1; + for(int i=0; i<me->props.cBuffers; i++) + me->free_list.push_back(new CMediaSample(me, me->props.cbBuffer)); + return 0; +} + +HRESULT STDCALL MemAllocator::Decommit ( + IMemAllocator * This) +{ + Debug printf("MemAllocator::Decommit() called\n"); + MemAllocator* me=(MemAllocator*)This; + list<CMediaSample*>::iterator it; + for(it=me->free_list.begin(); it!=me->free_list.end(); it++) + delete *it; + for(it=me->used_list.begin(); it!=me->used_list.end(); it++) + delete *it; + me->free_list.clear(); + me->used_list.clear(); + return 0; +} + +HRESULT STDCALL MemAllocator::GetBuffer ( + IMemAllocator * This, + /* [out] */ IMediaSample **ppBuffer, + /* [in] */ REFERENCE_TIME *pStartTime, + /* [in] */ REFERENCE_TIME *pEndTime, + /* [in] */ DWORD dwFlags) +{ + Debug printf("%x: MemAllocator::GetBuffer() called\n", This); + MemAllocator* me=(MemAllocator*)This; + if(me->free_list.size()==0) + { + Debug printf("No samples available\n"); + return -1;//should block here if no samples are available + } + list<CMediaSample*>::iterator it=me->free_list.begin(); + me->used_list.push_back(*it); + *ppBuffer=*it; + (*ppBuffer)->vt->AddRef((IUnknown*)*ppBuffer); + me->free_list.remove(*it); + return 0; +} + +HRESULT STDCALL MemAllocator::ReleaseBuffer ( + IMemAllocator * This, + /* [in] */ IMediaSample *pBuffer) +{ + Debug printf("%x: MemAllocator::ReleaseBuffer() called\n", This); + MemAllocator* me=(MemAllocator*)This; + list<CMediaSample*>::iterator it; + for(it=me->used_list.begin(); it!=me->used_list.end(); it++) + if(*it==pBuffer) + { + me->used_list.erase(it); + me->free_list.push_back((CMediaSample*)pBuffer); + return 0; + } + Debug printf("Releasing unknown buffer\n"); + return -1; +} diff --git a/loader/dshow/allocator.h b/loader/dshow/allocator.h new file mode 100644 index 0000000000..0b4917a0a9 --- /dev/null +++ b/loader/dshow/allocator.h @@ -0,0 +1,49 @@ +#ifndef ALLOCATOR_H +#define ALLOCATOR_H + +#include "interfaces.h" +#include "cmediasample.h" +#include <list> +#include "iunk.h" +#include "default.h" +using namespace std; +class MemAllocator: public IMemAllocator +{ + ALLOCATOR_PROPERTIES props; + list<CMediaSample*> used_list; + list<CMediaSample*> free_list; + static GUID interfaces[]; + DECLARE_IUNKNOWN(MemAllocator) +public: + MemAllocator(); + ~MemAllocator(){delete vt;} + static long CreateAllocator(GUID* clsid, GUID* iid, void** ppv); + + static HRESULT STDCALL SetProperties ( + IMemAllocator * This, + /* [in] */ ALLOCATOR_PROPERTIES *pRequest, + /* [out] */ ALLOCATOR_PROPERTIES *pActual); + + static HRESULT STDCALL GetProperties ( + IMemAllocator * This, + /* [out] */ ALLOCATOR_PROPERTIES *pProps); + + static HRESULT STDCALL Commit ( + IMemAllocator * This); + + static HRESULT STDCALL Decommit ( + IMemAllocator * This); + + static HRESULT STDCALL GetBuffer ( + IMemAllocator * This, + /* [out] */ IMediaSample **ppBuffer, + /* [in] */ REFERENCE_TIME *pStartTime, + /* [in] */ REFERENCE_TIME *pEndTime, + /* [in] */ DWORD dwFlags); + + static HRESULT STDCALL ReleaseBuffer ( + IMemAllocator * This, + /* [in] */ IMediaSample *pBuffer); +}; + +#endif diff --git a/loader/dshow/cmediasample.c b/loader/dshow/cmediasample.c new file mode 100644 index 0000000000..c54774ad82 --- /dev/null +++ b/loader/dshow/cmediasample.c @@ -0,0 +1,251 @@ +#include <stdio.h> +#include <string.h> +#include "cmediasample.h" +#define E_NOTIMPL 0x80004003 +CMediaSample::CMediaSample(IMemAllocator* allocator, long _size):refcount(0) +{ + vt=new IMediaSample_vt; + + vt->QueryInterface=QueryInterface; + vt->AddRef=AddRef; + vt->Release=Release; + vt->GetPointer=GetPointer ; + vt->GetSize=GetSize ; + vt->GetTime=GetTime ; + vt->SetTime=SetTime ; + vt->IsSyncPoint=IsSyncPoint ; + vt->SetSyncPoint=SetSyncPoint; + vt->IsPreroll=IsPreroll; + vt->SetPreroll=SetPreroll; + vt->GetActualDataLength=GetActualDataLength; + vt->SetActualDataLength=SetActualDataLength; + vt->GetMediaType=GetMediaType; + vt->SetMediaType=SetMediaType; + vt->IsDiscontinuity=IsDiscontinuity; + vt->SetDiscontinuity=SetDiscontinuity; + vt->GetMediaTime=GetMediaTime; + vt->SetMediaTime=SetMediaTime; + + all=allocator; + size=_size; + actual_size=0; + media_type.pbFormat=0; + isPreroll=0; + type_valid=0; + block=new char[size]; + Debug printf("%x: Creating media sample with size %d, buffer 0x%x\n", this, _size, block); +} +CMediaSample::~CMediaSample() +{ + Debug printf("%x: CMediaSample::~CMediaSample() called\n", this); + delete vt; + delete[] block; + if(media_type.pbFormat) + CoTaskMemFree(media_type.pbFormat); +} + +long STDCALL CMediaSample::QueryInterface ( + IUnknown * This, + /* [in] */ IID* iid, + /* [iid_is][out] */ void **ppv) +{ + Debug printf("CMediaSample::QueryInterface() called\n"); + if(!ppv)return 0x80004003; + if(!memcmp(iid, &IID_IUnknown, 16)) + { + *ppv=(void*)This; + This->vt->AddRef(This); + return 0; + } + if(!memcmp(iid, &IID_IMediaSample, 16)) + { + *ppv=(void*)This; + This->vt->AddRef(This); + return 0; + } + return 0x80004002; +} + +long STDCALL CMediaSample::AddRef ( + IUnknown * This) +{ + Debug printf("CMediaSample::AddRef() called\n"); + ((CMediaSample*)This)->refcount++; + return 0; +} + +long STDCALL CMediaSample::Release ( + IUnknown * This) +{ + Debug printf("%x: CMediaSample::Release() called, new refcount %d\n", This, + ((CMediaSample*)This)->refcount-1); + CMediaSample* parent=(CMediaSample*)This; + if(--((CMediaSample*)This)->refcount==0) + parent-> + all-> + vt-> + ReleaseBuffer( + (IMemAllocator*)(parent->all), + (IMediaSample*)This); + return 0; +} +HRESULT STDCALL CMediaSample::GetPointer ( + IMediaSample * This, + /* [out] */ BYTE **ppBuffer) +{ + Debug printf("%x: CMediaSample::GetPointer() called\n", This); + if(!ppBuffer)return 0x80004003; + *ppBuffer=(BYTE *)((CMediaSample*)This)->block; + return 0; +} + +long STDCALL CMediaSample::GetSize ( + IMediaSample * This) +{ + Debug printf("%x: CMediaSample::GetSize() called -> %d\n", This, ((CMediaSample*)This)->size); + return ((CMediaSample*)This)->size; +} + +HRESULT STDCALL CMediaSample::GetTime ( + IMediaSample * This, + /* [out] */ REFERENCE_TIME *pTimeStart, + /* [out] */ REFERENCE_TIME *pTimeEnd) +{ + Debug printf("%x: CMediaSample::GetTime() called\n", This); + return E_NOTIMPL; +} + +HRESULT STDCALL CMediaSample::SetTime ( + IMediaSample * This, + /* [in] */ REFERENCE_TIME *pTimeStart, + /* [in] */ REFERENCE_TIME *pTimeEnd) +{ + Debug printf("%x: CMediaSample::SetTime() called\n", This); + return E_NOTIMPL; +} + +HRESULT STDCALL CMediaSample::IsSyncPoint ( + IMediaSample * This) +{ + Debug printf("%x: CMediaSample::IsSyncPoint() called\n", This); + if(((CMediaSample*)This)->isSyncPoint)return 0; + return 1; +} + +HRESULT STDCALL CMediaSample::SetSyncPoint ( + IMediaSample * This, + long bIsSyncPoint) +{ + Debug printf("%x: CMediaSample::SetSyncPoint() called\n", This); + ((CMediaSample*)This)->isSyncPoint=bIsSyncPoint; + return 0; +} + +HRESULT STDCALL CMediaSample::IsPreroll ( + IMediaSample * This) +{ + Debug printf("%x: CMediaSample::IsPreroll() called\n", This); + if(((CMediaSample*)This)->isPreroll==0) + return 1;//S_FALSE + else + return 0;//S_OK +} + +HRESULT STDCALL CMediaSample::SetPreroll ( + IMediaSample * This, + long bIsPreroll) +{ + Debug printf("%x: CMediaSample::SetPreroll() called\n", This); + ((CMediaSample*)This)->isPreroll=bIsPreroll; + return 0; +} + +long STDCALL CMediaSample::GetActualDataLength ( + IMediaSample * This) +{ + Debug printf("%x: CMediaSample::GetActualDataLength() called -> %d\n", This, ((CMediaSample*)This)->actual_size); + return ((CMediaSample*)This)->actual_size; +} + +HRESULT STDCALL CMediaSample::SetActualDataLength ( + IMediaSample * This, + long __MIDL_0010) +{ + Debug printf("%x: CMediaSample::SetActualDataLength(%d) called\n", This, __MIDL_0010); + if(__MIDL_0010>((CMediaSample*)This)->size) + { + printf("%x: ERROR: CMediaSample buffer overflow\n", This); + } + ((CMediaSample*)This)->actual_size=__MIDL_0010; + return 0; +} + +HRESULT STDCALL CMediaSample::GetMediaType ( + IMediaSample * This, + AM_MEDIA_TYPE **ppMediaType) +{ + Debug printf("%x: CMediaSample::GetMediaType() called\n", This); + if(!ppMediaType) + return 0x80004003; + if(!((CMediaSample*)This)->type_valid) + { + *ppMediaType=0; + return 1; + } + AM_MEDIA_TYPE& t=((CMediaSample*)This)->media_type; +// if(t.pbFormat)CoTaskMemFree(t.pbFormat); + (*ppMediaType)=(AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)); + memcpy(*ppMediaType, &t, sizeof(AM_MEDIA_TYPE)); + (*ppMediaType)->pbFormat=(char*)CoTaskMemAlloc(t.cbFormat); + memcpy((*ppMediaType)->pbFormat, t.pbFormat, t.cbFormat); +// *ppMediaType=0; //media type was not changed + return 0; +} + +HRESULT STDCALL CMediaSample::SetMediaType ( + IMediaSample * This, + AM_MEDIA_TYPE *pMediaType) +{ + Debug printf("%x: CMediaSample::SetMediaType() called\n", This); + if(!pMediaType)return 0x80004003; + AM_MEDIA_TYPE& t=((CMediaSample*)This)->media_type; + if(t.pbFormat)CoTaskMemFree(t.pbFormat); + t=*pMediaType; + t.pbFormat=(char*)CoTaskMemAlloc(t.cbFormat); + memcpy(t.pbFormat, pMediaType->pbFormat, t.cbFormat); + ((CMediaSample*)This)->type_valid=1; + return 0; +} + +HRESULT STDCALL CMediaSample::IsDiscontinuity ( + IMediaSample * This) +{ + Debug printf("%x: CMediaSample::IsDiscontinuity() called\n", This); + return 1; +} + +HRESULT STDCALL CMediaSample::SetDiscontinuity ( + IMediaSample * This, + long bDiscontinuity) +{ + Debug printf("%x: CMediaSample::SetDiscontinuity() called\n", This); + return E_NOTIMPL; +} + +HRESULT STDCALL CMediaSample::GetMediaTime ( + IMediaSample * This, + /* [out] */ LONGLONG *pTimeStart, + /* [out] */ LONGLONG *pTimeEnd) +{ + Debug printf("%x: CMediaSample::GetMediaTime() called\n", This); + return E_NOTIMPL; +} + +HRESULT STDCALL CMediaSample::SetMediaTime ( + IMediaSample * This, + /* [in] */ LONGLONG *pTimeStart, + /* [in] */ LONGLONG *pTimeEnd) +{ + Debug printf("%x: CMediaSample::SetMediaTime() called\n", This); + return E_NOTIMPL; +} diff --git a/loader/dshow/cmediasample.h b/loader/dshow/cmediasample.h new file mode 100644 index 0000000000..3ad91330c7 --- /dev/null +++ b/loader/dshow/cmediasample.h @@ -0,0 +1,96 @@ +#ifndef _CMEDIASAMPLE_H +#define _CMEDIASAMPLE_H + +#include "interfaces.h" +#include "guids.h" +#include "default.h" +class CMediaSample: public IMediaSample +{ + IMemAllocator* all; + int size; + int actual_size; + char* block; + int refcount; + int isPreroll; + int isSyncPoint; + AM_MEDIA_TYPE media_type; + int type_valid; +public: + CMediaSample(IMemAllocator* allocator, long _size); + ~CMediaSample(); + + static long STDCALL QueryInterface ( + IUnknown * This, + /* [in] */ IID* riid, + /* [iid_is][out] */ void **ppvObject); + + static long STDCALL AddRef ( + IUnknown * This); + + static long STDCALL Release ( + IUnknown * This); + + static HRESULT STDCALL GetPointer ( + IMediaSample * This, + /* [out] */ BYTE **ppBuffer); + + static long STDCALL GetSize ( + IMediaSample * This); + + static HRESULT STDCALL GetTime ( + IMediaSample * This, + /* [out] */ REFERENCE_TIME *pTimeStart, + /* [out] */ REFERENCE_TIME *pTimeEnd); + + static HRESULT STDCALL SetTime ( + IMediaSample * This, + /* [in] */ REFERENCE_TIME *pTimeStart, + /* [in] */ REFERENCE_TIME *pTimeEnd); + + static HRESULT STDCALL IsSyncPoint ( + IMediaSample * This); + + static HRESULT STDCALL SetSyncPoint ( + IMediaSample * This, + long bIsSyncPoint); + + static HRESULT STDCALL IsPreroll ( + IMediaSample * This); + + static HRESULT STDCALL SetPreroll ( + IMediaSample * This, + long bIsPreroll); + + static long STDCALL GetActualDataLength ( + IMediaSample * This); + + static HRESULT STDCALL SetActualDataLength ( + IMediaSample * This, + long __MIDL_0010); + + static HRESULT STDCALL GetMediaType ( + IMediaSample * This, + AM_MEDIA_TYPE **ppMediaType); + + static HRESULT STDCALL SetMediaType ( + IMediaSample * This, + AM_MEDIA_TYPE *pMediaType); + + static HRESULT STDCALL IsDiscontinuity ( + IMediaSample * This); + + static HRESULT STDCALL SetDiscontinuity ( + IMediaSample * This, + long bDiscontinuity); + + static HRESULT STDCALL GetMediaTime ( + IMediaSample * This, + /* [out] */ LONGLONG *pTimeStart, + /* [out] */ LONGLONG *pTimeEnd); + + static HRESULT STDCALL SetMediaTime ( + IMediaSample * This, + /* [in] */ LONGLONG *pTimeStart, + /* [in] */ LONGLONG *pTimeEnd); +}; +#endif diff --git a/loader/dshow/guids.c b/loader/dshow/guids.c new file mode 100644 index 0000000000..c9f9163e21 --- /dev/null +++ b/loader/dshow/guids.c @@ -0,0 +1,61 @@ +#include "guids.h" +int DSHOW_DEBUG=0; + +GUID CLSID_DivxDecompressorCF={0x82CCd3E0, 0xF71A, 0x11D0, + { 0x9f, 0xe5, 0x00, 0x60, 0x97, 0x78, 0xaa, 0xaa}}; +GUID CLSID_IV50_Decoder={0x30355649, 0x0000, 0x0010, + {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +GUID IID_IBaseFilter={0x56a86895, 0x0ad4, 0x11ce, + {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; +GUID IID_IEnumPins={0x56a86892, 0x0ad4, 0x11ce, + {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; +GUID IID_IEnumMediaTypes={0x89c31040, 0x846b, 0x11ce, + {0x97, 0xd3, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; +GUID IID_IMemInputPin={0x56a8689d, 0x0ad4, 0x11ce, + {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; +GUID IID_IMemAllocator={0x56a8689c, 0x0ad4, 0x11ce, + {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; +GUID IID_IMediaSample={0x56a8689a, 0x0ad4, 0x11ce, + {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; + +GUID MEDIATYPE_Video={0x73646976, 0x0000, 0x0010, + {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +GUID GUID_NULL={0x0, 0x0, 0x0, + {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; +GUID FORMAT_VideoInfo={0x05589f80, 0xc356, 0x11ce, + {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; +GUID MEDIASUBTYPE_RGB565={0xe436eb7b, 0x524f, 0x11ce, + {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; +GUID MEDIASUBTYPE_RGB555={0xe436eb7c, 0x524f, 0x11ce, + {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; +GUID MEDIASUBTYPE_RGB24={0xe436eb7d, 0x524f, 0x11ce, + {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; +GUID MEDIASUBTYPE_RGB32={0xe436eb7e, 0x524f, 0x11ce, + {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; +GUID MEDIASUBTYPE_YUYV={0x56595559, 0x0000, 0x0010, + {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +GUID MEDIASUBTYPE_IYUV={0x56555949, 0x0000, 0x0010, + {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +GUID MEDIASUBTYPE_YVU9={0x39555659, 0x0000, 0x0010, + {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +GUID MEDIASUBTYPE_Y411={0x31313459, 0x0000, 0x0010, + {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +GUID MEDIASUBTYPE_Y41P={0x50313459, 0x0000, 0x0010, + {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +GUID MEDIASUBTYPE_YUY2={0x32595559, 0x0000, 0x0010, + {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +GUID MEDIASUBTYPE_YVYU={0x55595659, 0x0000, 0x0010, + {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +GUID MEDIASUBTYPE_UYVY={0x59565955, 0x0000, 0x0010, + {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +GUID MEDIASUBTYPE_Y211={0x31313259, 0x0000, 0x0010, + {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +GUID MEDIASUBTYPE_YV12={0x32315659, 0x0000, 0x0010, + {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +GUID CLSID_MemoryAllocator={0x1e651cc0, 0xb199, 0x11d0, + {0x82, 0x12, 0x00, 0xc0, 0x4f, 0xc3, 0x2c, 0x45}}; +GUID IID_DivxHidden={0x598eba01, 0xb49a, 0x11d2, + {0xa1, 0xc1, 0x00, 0x60, 0x97, 0x78, 0xaa, 0xaa +}}; +GUID IID_Iv50Hidden={0x665a4442, 0xd905, 0x11d0, + {0xa3, 0x0e, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}; diff --git a/loader/dshow/guids.h b/loader/dshow/guids.h new file mode 100644 index 0000000000..3a9b63897b --- /dev/null +++ b/loader/dshow/guids.h @@ -0,0 +1,90 @@ +#ifndef GUIDS_H +#define GUIDS_H +//#include <loader.h> +//#include <wine/winbase.h> +#include <com.h> +#include <formats.h> +extern int DSHOW_DEBUG; +#define Debug if(DSHOW_DEBUG) + +struct IUnknown; +typedef struct _MediaType +{ + GUID majortype; //0x0 + GUID subtype; //0x10 + int bFixedSizeSamples; //0x20 + int bTemporalCompression; //0x24 + unsigned long lSampleSize; //0x28 + GUID formattype; //0x2c + IUnknown *pUnk; //0x3c + unsigned long cbFormat; //0x40 + char *pbFormat; //0x44 +} AM_MEDIA_TYPE; +typedef enum +{ + PINDIR_INPUT = 0, + PINDIR_OUTPUT = PINDIR_INPUT + 1 +} PIN_DIRECTION; +typedef long long REFERENCE_TIME; +//typedef long long LONGLONG; +struct RECT32 +{ + int left, top, right, bottom; +}; +typedef struct tagVIDEOINFOHEADER { + + RECT32 rcSource; // The bit we really want to use + RECT32 rcTarget; // Where the video should go + unsigned long dwBitRate; // Approximate bit data rate + unsigned long dwBitErrorRate; // Bit error rate for this stream + REFERENCE_TIME AvgTimePerFrame; // Average time per frame (100ns units) + + BITMAPINFOHEADER bmiHeader; + +} VIDEOINFOHEADER; +typedef struct _AllocatorProperties +{ + long cBuffers; + long cbBuffer; + long cbAlign; + long cbPrefix; +} ALLOCATOR_PROPERTIES; +struct IBaseFilter; +typedef struct _PinInfo +{ + IBaseFilter *pFilter; + PIN_DIRECTION dir; + unsigned short achName[ 128 ]; +} PIN_INFO; + + +extern GUID IID_IBaseFilter; +extern GUID IID_IEnumPins; +extern GUID IID_IEnumMediaTypes; +extern GUID IID_IMemInputPin; +extern GUID IID_IMemAllocator; +extern GUID IID_IMediaSample; +extern GUID IID_DivxHidden; +extern GUID IID_Iv50Hidden; +extern GUID CLSID_DivxDecompressorCF; +extern GUID CLSID_IV50_Decoder; +extern GUID CLSID_MemoryAllocator; +extern GUID MEDIATYPE_Video; +extern GUID GUID_NULL; +extern GUID FORMAT_VideoInfo; +extern GUID MEDIASUBTYPE_RGB565; +extern GUID MEDIASUBTYPE_RGB555; +extern GUID MEDIASUBTYPE_RGB24; +extern GUID MEDIASUBTYPE_RGB32; +extern GUID MEDIASUBTYPE_YUYV; +extern GUID MEDIASUBTYPE_IYUV; +extern GUID MEDIASUBTYPE_YVU9; +extern GUID MEDIASUBTYPE_Y411; +extern GUID MEDIASUBTYPE_Y41P; +extern GUID MEDIASUBTYPE_YUY2; +extern GUID MEDIASUBTYPE_YVYU; +extern GUID MEDIASUBTYPE_UYVY; +extern GUID MEDIASUBTYPE_Y211; +extern GUID MEDIASUBTYPE_YV12; + +#endif diff --git a/loader/dshow/inputpin.c b/loader/dshow/inputpin.c new file mode 100644 index 0000000000..422d71b563 --- /dev/null +++ b/loader/dshow/inputpin.c @@ -0,0 +1,667 @@ +#include "inputpin.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#define E_NOTIMPL 0x80004001 +GUID CInputPin::interfaces[]= +{ + IID_IUnknown, +}; +IMPLEMENT_IUNKNOWN(CInputPin) + +GUID CRemotePin::interfaces[]= +{ + IID_IUnknown, +}; +IMPLEMENT_IUNKNOWN(CRemotePin) + +GUID CRemotePin2::interfaces[]= +{ + IID_IUnknown, +}; +IMPLEMENT_IUNKNOWN(CRemotePin2) + +GUID CBaseFilter::interfaces[]= +{ + IID_IUnknown, + IID_IBaseFilter, +}; +IMPLEMENT_IUNKNOWN(CBaseFilter) + +GUID CBaseFilter2::interfaces[]= +{ + IID_IUnknown, + IID_IBaseFilter, + {0x76c61a30, 0xebe1, 0x11cf, {0x89, 0xf9, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb}}, + {0xaae7e4e2, 0x6388, 0x11d1, {0x8d, 0x93, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2}}, + {0x02ef04dd, 0x7580, 0x11d1, {0xbe, 0xce, 0x00, 0xc0, 0x4f, 0xb6, 0xe9, 0x37}}, +}; +IMPLEMENT_IUNKNOWN(CBaseFilter2) + +class CEnumPins: public IEnumPins +{ + IPin* pin1; + IPin* pin2; + int counter; + static GUID interfaces[]; + DECLARE_IUNKNOWN(CEnumPins) +public: + CEnumPins(IPin*, IPin* =0); + ~CEnumPins(){delete vt;} + static long STDCALL Next ( + IEnumPins * This, + /* [in] */ unsigned long cMediaTypes, + /* [size_is][out] */ IPin **ppMediaTypes, + /* [out] */ unsigned long *pcFetched); + + static long STDCALL Skip ( + IEnumPins * This, + /* [in] */ unsigned long cMediaTypes); + + static long STDCALL Reset ( + IEnumPins * This); + + static long STDCALL Clone ( + IEnumPins * This, + /* [out] */ IEnumPins **ppEnum); + +}; +GUID CEnumPins::interfaces[]= +{ + IID_IUnknown, + IID_IEnumPins, +}; +IMPLEMENT_IUNKNOWN(CEnumPins) + +CEnumPins::CEnumPins(IPin* p, IPin* pp): pin1(p), pin2(pp), counter(0), refcount(1) +{ + vt=new IEnumPins_vt; + vt->QueryInterface = QueryInterface; + vt->AddRef = AddRef; + vt->Release = Release; + vt->Next = Next; + vt->Skip = Skip; + vt->Reset = Reset; + vt->Clone = Clone; +} + +long STDCALL CEnumPins::Next ( + IEnumPins * This, + /* [in] */ unsigned long cMediaTypes, + /* [size_is][out] */ IPin **ppMediaTypes, + /* [out] */ unsigned long *pcFetched) +{ + IPin* pin1=((CEnumPins*)This)->pin1; + IPin* pin2=((CEnumPins*)This)->pin2; + Debug printf("CEnumPins::Next() called\n"); + if(!ppMediaTypes)return 0x80004003; + if(!pcFetched && (cMediaTypes!=1))return 0x80004003; + if(cMediaTypes<=0)return 0; + int& counter=((CEnumPins*)This)->counter; + if(((counter==2) && pin2) || ((counter==1) && !pin2)) + { + if(pcFetched)*pcFetched=0; + return 1; + } + + if(pcFetched)*pcFetched=1; + if(counter==0) + { + *ppMediaTypes=pin1; + pin1->vt->AddRef((IUnknown*)pin1); + } + else + { + *ppMediaTypes=pin2; + pin2->vt->AddRef((IUnknown*)pin2); + } + counter++; + if(cMediaTypes==1)return 0; + return 1; +} + +long STDCALL CEnumPins::Skip ( + IEnumPins * This, + /* [in] */ unsigned long cMediaTypes) +{ + Debug printf("CEnumPins::Skip() called\n"); + return E_NOTIMPL; +} + +long STDCALL CEnumPins::Reset ( + IEnumPins * This) +{ + Debug printf("CEnumPins::Reset() called\n"); + ((CEnumPins*)This)->counter=0; + return 0; +} + +long STDCALL CEnumPins::Clone ( + IEnumPins * This, + /* [out] */ IEnumPins **ppEnum) +{ + Debug printf("CEnumPins::Clone() called\n"); + return E_NOTIMPL; +} + +CInputPin::CInputPin(CBaseFilter* p, const AM_MEDIA_TYPE& vh) + : refcount(1), type(vh), parent(p) +{ + vt=new IPin_vt; + vt->QueryInterface = QueryInterface; + vt->AddRef = AddRef; + vt->Release = Release; + vt->Connect = Connect; + vt->ReceiveConnection = ReceiveConnection; + vt->Disconnect=Disconnect; + vt->ConnectedTo = ConnectedTo; + vt->ConnectionMediaType = ConnectionMediaType; + vt->QueryPinInfo = QueryPinInfo; + vt->QueryDirection = QueryDirection; + vt->QueryId = QueryId; + vt->QueryAccept = QueryAccept; + vt->EnumMediaTypes = EnumMediaTypes; + vt->QueryInternalConnections = QueryInternalConnections; + vt->EndOfStream = EndOfStream; + vt->BeginFlush = BeginFlush; + vt->EndFlush = EndFlush; + vt->NewSegment = NewSegment; +} + +long STDCALL CInputPin::Connect ( + IPin * This, + /* [in] */ IPin *pReceivePin, + /* [in] */ AM_MEDIA_TYPE *pmt) +{ + Debug printf("CInputPin::Connect() called\n"); + return E_NOTIMPL; +} + +long STDCALL CInputPin::ReceiveConnection ( + IPin * This, + /* [in] */ IPin *pConnector, + /* [in] */ const AM_MEDIA_TYPE *pmt) +{ + Debug printf("CInputPin::ReceiveConnection() called\n"); + return E_NOTIMPL; +} + +long STDCALL CInputPin::Disconnect ( + IPin * This) +{ + Debug printf("CInputPin::Disconnect() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CInputPin::ConnectedTo ( + IPin * This, + /* [out] */ IPin **pPin) +{ + Debug printf("CInputPin::ConnectedTo() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CInputPin::ConnectionMediaType ( + IPin * This, + /* [out] */ AM_MEDIA_TYPE *pmt) +{ + Debug printf("CInputPin::ConnectionMediaType() called\n"); + if(!pmt)return 0x80004003; + *pmt=((CInputPin*)This)->type; + if(pmt->cbFormat>0) + { + pmt->pbFormat=(char *)CoTaskMemAlloc(pmt->cbFormat); + memcpy(pmt->pbFormat, ((CInputPin*)This)->type.pbFormat, pmt->cbFormat); + } + return 0; +} + +long STDCALL CInputPin::QueryPinInfo ( + IPin * This, + /* [out] */ PIN_INFO *pInfo) +{ + Debug printf("CInputPin::QueryPinInfo() called\n"); + pInfo->dir=PINDIR_OUTPUT; + CBaseFilter* parent=((CInputPin*)This)->parent; + pInfo->pFilter=parent; + parent->vt->AddRef((IUnknown*)parent); + pInfo->achName[0]=0; + return 0; +} + + +long STDCALL CInputPin::QueryDirection ( + IPin * This, + /* [out] */ PIN_DIRECTION *pPinDir) +{ + *pPinDir=PINDIR_OUTPUT; + Debug printf("CInputPin::QueryDirection() called\n"); + return 0; +} + + +long STDCALL CInputPin::QueryId ( + IPin * This, + /* [out] */ unsigned short* *Id) +{ + Debug printf("CInputPin::QueryId() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CInputPin::QueryAccept ( + IPin * This, + /* [in] */ const AM_MEDIA_TYPE *pmt) +{ + Debug printf("CInputPin::QueryAccept() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CInputPin::EnumMediaTypes ( + IPin * This, + /* [out] */ IEnumMediaTypes **ppEnum) +{ + Debug printf("CInputPin::EnumMediaTypes() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CInputPin::QueryInternalConnections ( + IPin * This, + /* [out] */ IPin **apPin, + /* [out][in] */ unsigned long *nPin) +{ + Debug printf("CInputPin::QueryInternalConnections() called\n"); + return E_NOTIMPL; +} + +long STDCALL CInputPin::EndOfStream ( + IPin * This) +{ + Debug printf("CInputPin::EndOfStream() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CInputPin::BeginFlush ( +IPin * This) +{ + Debug printf("CInputPin::BeginFlush() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CInputPin::EndFlush ( + IPin * This) +{ + Debug printf("CInputPin::EndFlush() called\n"); + return E_NOTIMPL; +} + +long STDCALL CInputPin::NewSegment ( + IPin * This, + /* [in] */ REFERENCE_TIME tStart, + /* [in] */ REFERENCE_TIME tStop, + /* [in] */ double dRate) +{ + Debug printf("CInputPin::NewSegment() called\n"); + return E_NOTIMPL; +} + + + + + + +CBaseFilter::CBaseFilter(const AM_MEDIA_TYPE& type, CBaseFilter2* parent) + : refcount(1) +{ + pin=new CInputPin(this, type); + unused_pin=new CRemotePin(this, parent->GetPin()); + vt=new IBaseFilter_vt; + vt->QueryInterface = QueryInterface; + vt->AddRef = AddRef; + vt->Release = Release; + vt->GetClassID = GetClassID; + vt->Stop = Stop; + vt->Pause = Pause; + vt->Run = Run; + vt->GetState = GetState; + vt->SetSyncSource = SetSyncSource; + vt->GetSyncSource = GetSyncSource; + vt->EnumPins = EnumPins; + vt->FindPin = FindPin; + vt->QueryFilterInfo = QueryFilterInfo; + vt->JoinFilterGraph = JoinFilterGraph; + vt->QueryVendorInfo = QueryVendorInfo; +} + +long STDCALL CBaseFilter::GetClassID ( + IBaseFilter * This, + /* [out] */ CLSID *pClassID) +{ + Debug printf("CBaseFilter::GetClassID() called\n"); + return E_NOTIMPL; +} + +long STDCALL CBaseFilter::Stop ( + IBaseFilter * This) +{ + Debug printf("CBaseFilter::Stop() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter::Pause ( + IBaseFilter * This) +{ + Debug printf("CBaseFilter::Pause() called\n"); + return E_NOTIMPL; +} + +long STDCALL CBaseFilter::Run ( + IBaseFilter * This, + REFERENCE_TIME tStart) +{ + Debug printf("CBaseFilter::Run() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter::GetState ( + IBaseFilter * This, + /* [in] */ unsigned long dwMilliSecsTimeout, +// /* [out] */ FILTER_STATE *State) + void* State) +{ + Debug printf("CBaseFilter::GetState() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter::SetSyncSource ( + IBaseFilter * This, + /* [in] */ IReferenceClock *pClock) +{ + Debug printf("CBaseFilter::SetSyncSource() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter::GetSyncSource ( + IBaseFilter * This, + /* [out] */ IReferenceClock **pClock) +{ + Debug printf("CBaseFilter::GetSyncSource() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter::EnumPins ( + IBaseFilter * This, + /* [out] */ IEnumPins **ppEnum) +{ + Debug printf("CBaseFilter::EnumPins() called\n"); + *ppEnum=new CEnumPins(((CBaseFilter*)This)->pin, ((CBaseFilter*)This)->unused_pin); + return 0; +} + + +long STDCALL CBaseFilter::FindPin ( + IBaseFilter * This, + /* [string][in] */ const unsigned short* Id, + /* [out] */ IPin **ppPin) +{ + Debug printf("CBaseFilter::FindPin() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter::QueryFilterInfo ( + IBaseFilter * This, +// /* [out] */ FILTER_INFO *pInfo) + void* pInfo) +{ + Debug printf("CBaseFilter::QueryFilterInfo() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter::JoinFilterGraph ( + IBaseFilter * This, + /* [in] */ IFilterGraph *pGraph, + /* [string][in] */ const unsigned short* pName) +{ + Debug printf("CBaseFilter::JoinFilterGraph() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter::QueryVendorInfo ( + IBaseFilter * This, + /* [string][out] */ unsigned short* *pVendorInfo) +{ + Debug printf("CBaseFilter::QueryVendorInfo() called\n"); + return E_NOTIMPL; +} + + +CBaseFilter2::CBaseFilter2() : refcount(1) +{ + pin=new CRemotePin2(this); + vt=new IBaseFilter_vt; + memset(vt, 0, sizeof (IBaseFilter_vt)); + vt->QueryInterface = QueryInterface; + vt->AddRef = AddRef; + vt->Release = Release; + vt->GetClassID = GetClassID; + vt->Stop = Stop; + vt->Pause = Pause; + vt->Run = Run; + vt->GetState = GetState; + vt->SetSyncSource = SetSyncSource; + vt->GetSyncSource = GetSyncSource; + vt->EnumPins = EnumPins; + vt->FindPin = FindPin; + vt->QueryFilterInfo = QueryFilterInfo; + vt->JoinFilterGraph = JoinFilterGraph; + vt->QueryVendorInfo = QueryVendorInfo; +} +CRemotePin2::CRemotePin2(CBaseFilter2* p):parent(p), + refcount(1) +{ + vt=new IPin_vt; + memset(vt, 0, sizeof (IPin_vt)); + vt->QueryInterface = QueryInterface; + vt->AddRef = AddRef; + vt->Release = Release; + vt->QueryPinInfo=QueryPinInfo; +} +CRemotePin::CRemotePin(CBaseFilter* pt, IPin* rpin): parent(pt), remote_pin(rpin), + refcount(1) +{ + vt=new IPin_vt; + memset(vt, 0, sizeof (IPin_vt)); + vt->QueryInterface = QueryInterface; + vt->AddRef = AddRef; + vt->Release = Release; + vt->QueryDirection = QueryDirection; + vt->ConnectedTo = ConnectedTo; + vt->ConnectionMediaType = ConnectionMediaType; + vt->QueryPinInfo = QueryPinInfo; +} + + + + + + + + + + + + +long STDCALL CBaseFilter2::GetClassID ( + IBaseFilter * This, + /* [out] */ CLSID *pClassID) +{ + Debug printf("CBaseFilter2::GetClassID() called\n"); + return E_NOTIMPL; +} + +long STDCALL CBaseFilter2::Stop ( + IBaseFilter * This) +{ + Debug printf("CBaseFilter2::Stop() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter2::Pause ( + IBaseFilter * This) +{ + Debug printf("CBaseFilter2::Pause() called\n"); + return E_NOTIMPL; +} + +long STDCALL CBaseFilter2::Run ( + IBaseFilter * This, + REFERENCE_TIME tStart) +{ + Debug printf("CBaseFilter2::Run() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter2::GetState ( + IBaseFilter * This, + /* [in] */ unsigned long dwMilliSecsTimeout, +// /* [out] */ FILTER_STATE *State) + void* State) +{ + Debug printf("CBaseFilter2::GetState() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter2::SetSyncSource ( + IBaseFilter * This, + /* [in] */ IReferenceClock *pClock) +{ + Debug printf("CBaseFilter2::SetSyncSource() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter2::GetSyncSource ( + IBaseFilter * This, + /* [out] */ IReferenceClock **pClock) +{ + Debug printf("CBaseFilter2::GetSyncSource() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter2::EnumPins ( + IBaseFilter * This, + /* [out] */ IEnumPins **ppEnum) +{ + Debug printf("CBaseFilter2::EnumPins() called\n"); + *ppEnum=new CEnumPins(((CBaseFilter2*)This)->pin); + return 0; +} + + +long STDCALL CBaseFilter2::FindPin ( + IBaseFilter * This, + /* [string][in] */ const unsigned short* Id, + /* [out] */ IPin **ppPin) +{ + Debug printf("CBaseFilter2::FindPin() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter2::QueryFilterInfo ( + IBaseFilter * This, +// /* [out] */ FILTER_INFO *pInfo) + void* pInfo) +{ + Debug printf("CBaseFilter2::QueryFilterInfo() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter2::JoinFilterGraph ( + IBaseFilter * This, + /* [in] */ IFilterGraph *pGraph, + /* [string][in] */ const unsigned short* pName) +{ + Debug printf("CBaseFilter2::JoinFilterGraph() called\n"); + return E_NOTIMPL; +} + + +long STDCALL CBaseFilter2::QueryVendorInfo ( + IBaseFilter * This, + /* [string][out] */ unsigned short* *pVendorInfo) +{ + Debug printf("CBaseFilter2::QueryVendorInfo() called\n"); + return E_NOTIMPL; +} + +long STDCALL CRemotePin::ConnectionMediaType ( + IPin * This, + /* [out] */ AM_MEDIA_TYPE *pmt) +{ + Debug printf("CRemotePin::ConnectionMediaType() called\n"); + return E_NOTIMPL; +} + +long STDCALL CRemotePin::QueryPinInfo ( + IPin * This, + /* [out] */ PIN_INFO *pInfo) +{ + Debug printf("CRemotePin::QueryPinInfo() called\n"); + pInfo->dir=PINDIR_INPUT; + CBaseFilter* parent=((CRemotePin*)This)->parent; + pInfo->pFilter=parent; + parent->vt->AddRef((IUnknown*)parent); + pInfo->achName[0]=0; + return 0; +} + long STDCALL CRemotePin2::QueryPinInfo ( + IPin * This, + /* [out] */ PIN_INFO *pInfo) + { + Debug printf("CRemotePin2::QueryPinInfo called\n"); + CBaseFilter2* parent=((CRemotePin2*)This)->parent; + pInfo->pFilter=(IBaseFilter*)parent; + parent->vt->AddRef((IUnknown*)parent); + pInfo->dir=PINDIR_OUTPUT; + pInfo->achName[0]=0; + return 0; + } + long STDCALL CRemotePin::ConnectedTo ( + IPin * This, + /* [out] */ IPin **pPin) + { + Debug printf("CRemotePin::ConnectedTo called\n"); + if(!pPin)return 0x80004003; + *pPin=((CRemotePin*)This)->remote_pin; + (*pPin)->vt->AddRef((IUnknown*)(*pPin)); + return 0; + } + long STDCALL CRemotePin::QueryDirection ( + IPin * This, + /* [out] */ PIN_DIRECTION *pPinDir) + { + Debug printf("CRemotePin::QueryDirection called\n"); + if(!pPinDir)return 0x80004003; + *pPinDir=PINDIR_INPUT; + return 0; + } diff --git a/loader/dshow/inputpin.h b/loader/dshow/inputpin.h new file mode 100644 index 0000000000..027d17fbc6 --- /dev/null +++ b/loader/dshow/inputpin.h @@ -0,0 +1,265 @@ +#ifndef INPUTPIN_H +#define INPUTPIN_H +#include "interfaces.h" +#include "guids.h" +#include "iunk.h" + +class CBaseFilter2; +class CBaseFilter: public IBaseFilter +{ + IPin* pin; + IPin* unused_pin; + static GUID interfaces[]; + DECLARE_IUNKNOWN(CBaseFilter) +public: + CBaseFilter(const AM_MEDIA_TYPE& vhdr, CBaseFilter2* parent); + ~CBaseFilter(){delete vt;pin->vt->Release((IUnknown*)pin);unused_pin->vt->Release((IUnknown*)unused_pin);} + + IPin* GetPin() {return pin;} + IPin* GetUnusedPin() {return unused_pin;} +// static long STDCALL QueryInterface(IUnknown* This, GUID* iid, void** ppv); +// static long STDCALL AddRef(IUnknown* This); +// static long STDCALL Release(IUnknown* This); + + static long STDCALL GetClassID ( + IBaseFilter * This, + /* [out] */ CLSID *pClassID); + + static long STDCALL Stop ( + IBaseFilter * This); + + static long STDCALL Pause ( + IBaseFilter * This); + + static long STDCALL Run ( + IBaseFilter * This, + REFERENCE_TIME tStart); + + static long STDCALL GetState ( + IBaseFilter * This, + /* [in] */ unsigned long dwMilliSecsTimeout, +// /* [out] */ FILTER_STATE *State); + void* State); + + static long STDCALL SetSyncSource ( + IBaseFilter * This, + /* [in] */ IReferenceClock *pClock); + + static long STDCALL GetSyncSource ( + IBaseFilter * This, + /* [out] */ IReferenceClock **pClock); + + static long STDCALL EnumPins ( + IBaseFilter * This, + /* [out] */ IEnumPins **ppEnum); + + static long STDCALL FindPin ( + IBaseFilter * This, + /* [string][in] */ const unsigned short* Id, + /* [out] */ IPin **ppPin); + + static long STDCALL QueryFilterInfo ( + IBaseFilter * This, +// /* [out] */ FILTER_INFO *pInfo); + void* pInfo); + + static long STDCALL JoinFilterGraph ( + IBaseFilter * This, + /* [in] */ IFilterGraph *pGraph, + /* [string][in] */ const unsigned short* pName); + + static long STDCALL QueryVendorInfo ( + IBaseFilter * This, + /* [string][out] */ unsigned short* *pVendorInfo); +}; +class CInputPin: public IPin +{ + AM_MEDIA_TYPE type; + CBaseFilter* parent; + static GUID interfaces[]; + DECLARE_IUNKNOWN(CInputPin) +public: + CInputPin(CBaseFilter* parent, const AM_MEDIA_TYPE& vhdr); + ~CInputPin(){delete vt;} +// IPin* GetPin(); + +// static long STDCALL QueryInterface(IUnknown* This, GUID* iid, void** ppv); +// static long STDCALL AddRef(IUnknown* This); +// static long STDCALL Release(IUnknown* This); + + static long STDCALL Connect ( + IPin * This, + /* [in] */ IPin *pReceivePin, + /* [in] */ AM_MEDIA_TYPE *pmt); + + static long STDCALL ReceiveConnection ( + IPin * This, + /* [in] */ IPin *pConnector, + /* [in] */ const AM_MEDIA_TYPE *pmt); + + static long STDCALL Disconnect ( + IPin * This); + + static long STDCALL ConnectedTo ( + IPin * This, + /* [out] */ IPin **pPin); + + static long STDCALL ConnectionMediaType ( + IPin * This, + /* [out] */ AM_MEDIA_TYPE *pmt); + + static long STDCALL QueryPinInfo ( + IPin * This, + /* [out] */ PIN_INFO *pInfo); + + static long STDCALL QueryDirection ( + IPin * This, + /* [out] */ PIN_DIRECTION *pPinDir); + + static long STDCALL QueryId ( + IPin * This, + /* [out] */ unsigned short* *Id); + + static long STDCALL QueryAccept ( + IPin * This, + /* [in] */ const AM_MEDIA_TYPE *pmt); + + static long STDCALL EnumMediaTypes ( + IPin * This, + /* [out] */ IEnumMediaTypes **ppEnum); + + static long STDCALL QueryInternalConnections ( + IPin * This, + /* [out] */ IPin **apPin, + /* [out][in] */ unsigned long *nPin); + + static long STDCALL EndOfStream ( + IPin * This); + + static long STDCALL BeginFlush ( + IPin * This); + + static long STDCALL EndFlush ( + IPin * This); + + static long STDCALL NewSegment ( + IPin * This, + /* [in] */ REFERENCE_TIME tStart, + /* [in] */ REFERENCE_TIME tStop, + /* [in] */ double dRate); +}; + +class CBaseFilter2: public IBaseFilter +{ + IPin* pin; + static GUID interfaces[]; + DECLARE_IUNKNOWN(CBaseFilter2) +public: + CBaseFilter2(); + ~CBaseFilter2(){delete vt;pin->vt->Release((IUnknown*)pin);} + IPin* GetPin() {return pin;} + +// static long STDCALL QueryInterface(IUnknown* This, GUID* iid, void** ppv); +// static long STDCALL AddRef(IUnknown* This); +// static long STDCALL Release(IUnknown* This); + static long STDCALL GetClassID ( + IBaseFilter * This, + /* [out] */ CLSID *pClassID); + + static long STDCALL Stop ( + IBaseFilter * This); + + static long STDCALL Pause ( + IBaseFilter * This); + + static long STDCALL Run ( + IBaseFilter * This, + REFERENCE_TIME tStart); + + static long STDCALL GetState ( + IBaseFilter * This, + /* [in] */ unsigned long dwMilliSecsTimeout, +// /* [out] */ FILTER_STATE *State); + void* State); + + static long STDCALL SetSyncSource ( + IBaseFilter * This, + /* [in] */ IReferenceClock *pClock); + + static long STDCALL GetSyncSource ( + IBaseFilter * This, + /* [out] */ IReferenceClock **pClock); + + static long STDCALL EnumPins ( + IBaseFilter * This, + /* [out] */ IEnumPins **ppEnum); + + static long STDCALL FindPin ( + IBaseFilter * This, + /* [string][in] */ const unsigned short* Id, + /* [out] */ IPin **ppPin); + + static long STDCALL QueryFilterInfo ( + IBaseFilter * This, +// /* [out] */ FILTER_INFO *pInfo); + void* pInfo); + + static long STDCALL JoinFilterGraph ( + IBaseFilter * This, + /* [in] */ IFilterGraph *pGraph, + /* [string][in] */ const unsigned short* pName); + + static long STDCALL QueryVendorInfo ( + IBaseFilter * This, + /* [string][out] */ unsigned short* *pVendorInfo); +}; + +class CRemotePin: public IPin +{ + CBaseFilter* parent; + IPin* remote_pin; + static GUID interfaces[]; + DECLARE_IUNKNOWN(CRemotePin) +public: + CRemotePin(CBaseFilter* pt, IPin* rpin); + ~CRemotePin(){delete vt;} + +// static long STDCALL QueryInterface(IUnknown* This, GUID* iid, void** ppv); +// static long STDCALL AddRef(IUnknown* This); +// static long STDCALL Release(IUnknown* This); + + static long STDCALL ConnectedTo ( + IPin * This, + /* [out] */ IPin **pPin); + + static long STDCALL QueryDirection ( + IPin * This, + /* [out] */ PIN_DIRECTION *pPinDir); + + static long STDCALL ConnectionMediaType ( + IPin * This, + /* [out] */ AM_MEDIA_TYPE *pmt); + + static long STDCALL QueryPinInfo ( + IPin * This, + /* [out] */ PIN_INFO *pInfo); + +}; + + +class CRemotePin2: public IPin +{ + CBaseFilter2* parent; + static GUID interfaces[]; + DECLARE_IUNKNOWN(CRemotePin2) +public: + CRemotePin2(CBaseFilter2* parent); + ~CRemotePin2(){delete vt;} + + static long STDCALL QueryPinInfo ( + IPin * This, + /* [out] */ PIN_INFO *pInfo); +}; + + +#endif diff --git a/loader/dshow/interfaces.h b/loader/dshow/interfaces.h new file mode 100644 index 0000000000..355264c666 --- /dev/null +++ b/loader/dshow/interfaces.h @@ -0,0 +1,417 @@ +/* + + Definition of important DirectShow interfaces. + Created using freely-available DirectX 8.0 SDK + ( http://msdn.microsoft.com ) + +*/ +#ifndef INTERFACES_H +#define INTERFACES_H + +#include "guids.h" +#include "default.h" +#include <com.h> +#ifndef STDCALL +#define STDCALL __attribute__((__stdcall__)) +#endif + +typedef GUID& REFIID; +typedef GUID CLSID; +typedef GUID IID; + +/* Sh*t. MSVC++ and g++ use different methods of storing vtables. */ + +struct IBaseFilter; +struct IReferenceClock; +struct IEnumPins; +struct IEnumMediaTypes; +struct IPin; +struct IFilterGraph; +struct IMemInputPin; +struct IMemAllocator; +struct IMediaSample; + +enum PIN_DIRECTION; + +class IClassFactory2 +{ +public: + virtual long STDCALL QueryInterface(GUID* iid, void** ppv) =0; + virtual long STDCALL AddRef() =0; + virtual long STDCALL Release() =0; + virtual long STDCALL CreateInstance(IUnknown* pUnkOuter, GUID* riid, void** ppvObject) =0; +}; + +struct IBaseFilter_vt: IUnknown_vt +{ + HRESULT STDCALL ( *GetClassID )( + IBaseFilter * This, + /* [out] */ CLSID *pClassID); + + HRESULT STDCALL ( *Stop )( + IBaseFilter * This); + + HRESULT STDCALL ( *Pause )( + IBaseFilter * This); + + HRESULT STDCALL ( *Run )( + IBaseFilter * This, + REFERENCE_TIME tStart); + + HRESULT STDCALL ( *GetState )( + IBaseFilter * This, + /* [in] */ unsigned long dwMilliSecsTimeout, +// /* [out] */ FILTER_STATE *State); + void* State); + + HRESULT STDCALL ( *SetSyncSource )( + IBaseFilter * This, + /* [in] */ IReferenceClock *pClock); + + HRESULT STDCALL ( *GetSyncSource )( + IBaseFilter * This, + /* [out] */ IReferenceClock **pClock); + + HRESULT STDCALL ( *EnumPins )( + IBaseFilter * This, + /* [out] */ IEnumPins **ppEnum); + + HRESULT STDCALL ( *FindPin )( + IBaseFilter * This, + /* [string][in] */ const unsigned short* Id, + /* [out] */ IPin **ppPin); + + HRESULT STDCALL ( *QueryFilterInfo )( + IBaseFilter * This, +// /* [out] */ FILTER_INFO *pInfo); + void* pInfo); + + HRESULT STDCALL ( *JoinFilterGraph )( + IBaseFilter * This, + /* [in] */ IFilterGraph *pGraph, + /* [string][in] */ const unsigned short* pName); + + HRESULT STDCALL ( *QueryVendorInfo )( + IBaseFilter * This, + /* [string][out] */ unsigned short* *pVendorInfo); + +}; + +struct IBaseFilter +{ + struct IBaseFilter_vt *vt; +}; + +struct IEnumPins_vt: IUnknown_vt +{ + HRESULT STDCALL ( *Next )( + IEnumPins * This, + /* [in] */ unsigned long cPins, + /* [size_is][out] */ IPin **ppPins, + /* [out] */ unsigned long *pcFetched); + + HRESULT STDCALL ( *Skip )( + IEnumPins * This, + /* [in] */ unsigned long cPins); + + HRESULT STDCALL ( *Reset )( + IEnumPins * This); + + HRESULT STDCALL ( *Clone )( + IEnumPins * This, + /* [out] */ IEnumPins **ppEnum); + +}; + +struct IEnumPins +{ + struct IEnumPins_vt *vt; +}; + + +struct IPin_vt: IUnknown_vt +{ + HRESULT STDCALL ( *Connect )( + IPin * This, + /* [in] */ IPin *pReceivePin, + /* [in] */ /*const*/ AM_MEDIA_TYPE *pmt); + + HRESULT STDCALL ( *ReceiveConnection )( + IPin * This, + /* [in] */ IPin *pConnector, + /* [in] */ const AM_MEDIA_TYPE *pmt); + + HRESULT STDCALL ( *Disconnect )( + IPin * This); + + HRESULT STDCALL ( *ConnectedTo )( + IPin * This, + /* [out] */ IPin **pPin); + + HRESULT STDCALL ( *ConnectionMediaType )( + IPin * This, + /* [out] */ AM_MEDIA_TYPE *pmt); + + HRESULT STDCALL ( *QueryPinInfo )( + IPin * This, + /* [out] */ PIN_INFO *pInfo); + + HRESULT STDCALL ( *QueryDirection )( + IPin * This, + /* [out] */ PIN_DIRECTION *pPinDir); + + HRESULT STDCALL ( *QueryId )( + IPin * This, + /* [out] */ unsigned short* *Id); + + HRESULT STDCALL ( *QueryAccept )( + IPin * This, + /* [in] */ const AM_MEDIA_TYPE *pmt); + + HRESULT STDCALL ( *EnumMediaTypes )( + IPin * This, + /* [out] */ IEnumMediaTypes **ppEnum); + + HRESULT STDCALL ( *QueryInternalConnections )( + IPin * This, + /* [out] */ IPin **apPin, + /* [out][in] */ unsigned long *nPin); + + HRESULT STDCALL ( *EndOfStream )( + IPin * This); + + HRESULT STDCALL ( *BeginFlush )( + IPin * This); + + HRESULT STDCALL ( *EndFlush )( + IPin * This); + + HRESULT STDCALL ( *NewSegment )( + IPin * This, + /* [in] */ REFERENCE_TIME tStart, + /* [in] */ REFERENCE_TIME tStop, + /* [in] */ double dRate); + +}; + +struct IPin +{ + IPin_vt *vt; +}; + +struct IEnumMediaTypes_vt: IUnknown_vt +{ + HRESULT STDCALL ( *Next )( + IEnumMediaTypes * This, + /* [in] */ unsigned long cMediaTypes, + /* [size_is][out] */ AM_MEDIA_TYPE **ppMediaTypes, + /* [out] */ unsigned long *pcFetched); + + HRESULT STDCALL ( *Skip )( + IEnumMediaTypes * This, + /* [in] */ unsigned long cMediaTypes); + + HRESULT STDCALL ( *Reset )( + IEnumMediaTypes * This); + + HRESULT STDCALL ( *Clone )( + IEnumMediaTypes * This, + /* [out] */ IEnumMediaTypes **ppEnum); +}; + +struct IEnumMediaTypes +{ + IEnumMediaTypes_vt *vt; +}; + + +struct IMemInputPin_vt: IUnknown_vt +{ + HRESULT STDCALL ( *GetAllocator )( + IMemInputPin * This, + /* [out] */ IMemAllocator **ppAllocator); + + HRESULT STDCALL ( *NotifyAllocator )( + IMemInputPin * This, + /* [in] */ IMemAllocator *pAllocator, + /* [in] */ int bReadOnly); + + HRESULT STDCALL ( *GetAllocatorRequirements )( + IMemInputPin * This, + /* [out] */ ALLOCATOR_PROPERTIES *pProps); + + HRESULT STDCALL ( *Receive )( + IMemInputPin * This, + /* [in] */ IMediaSample *pSample); + + HRESULT STDCALL ( *ReceiveMultiple )( + IMemInputPin * This, + /* [size_is][in] */ IMediaSample **pSamples, + /* [in] */ long nSamples, + /* [out] */ long *nSamplesProcessed); + + HRESULT STDCALL ( *ReceiveCanBlock )( + IMemInputPin * This); +}; + +struct IMemInputPin +{ + IMemInputPin_vt *vt; +}; + + + +struct IMemAllocator_vt: IUnknown_vt +{ + HRESULT STDCALL ( *SetProperties )( + IMemAllocator * This, + /* [in] */ ALLOCATOR_PROPERTIES *pRequest, + /* [out] */ ALLOCATOR_PROPERTIES *pActual); + + HRESULT STDCALL ( *GetProperties )( + IMemAllocator * This, + /* [out] */ ALLOCATOR_PROPERTIES *pProps); + + HRESULT STDCALL ( *Commit )( + IMemAllocator * This); + + HRESULT STDCALL ( *Decommit )( + IMemAllocator * This); + + HRESULT STDCALL ( *GetBuffer )( + IMemAllocator * This, + /* [out] */ IMediaSample **ppBuffer, + /* [in] */ REFERENCE_TIME *pStartTime, + /* [in] */ REFERENCE_TIME *pEndTime, + /* [in] */ unsigned long dwFlags); + + HRESULT STDCALL ( *ReleaseBuffer )( + IMemAllocator * This, + /* [in] */ IMediaSample *pBuffer); +}; + +struct IMemAllocator +{ + IMemAllocator_vt *vt; +}; + +struct IMediaSample_vt: IUnknown_vt +{ + HRESULT STDCALL ( *GetPointer )( + IMediaSample * This, + /* [out] */ unsigned char **ppBuffer); + + long STDCALL ( *GetSize )( + IMediaSample * This); + + HRESULT STDCALL ( *GetTime )( + IMediaSample * This, + /* [out] */ REFERENCE_TIME *pTimeStart, + /* [out] */ REFERENCE_TIME *pTimeEnd); + + HRESULT STDCALL ( *SetTime )( + IMediaSample * This, + /* [in] */ REFERENCE_TIME *pTimeStart, + /* [in] */ REFERENCE_TIME *pTimeEnd); + + HRESULT STDCALL ( *IsSyncPoint )( + IMediaSample * This); + + HRESULT STDCALL ( *SetSyncPoint )( + IMediaSample * This, + long bIsSyncPoint); + + HRESULT STDCALL ( *IsPreroll )( + IMediaSample * This); + + HRESULT STDCALL ( *SetPreroll )( + IMediaSample * This, + long bIsPreroll); + + long STDCALL ( *GetActualDataLength )( + IMediaSample * This); + + HRESULT STDCALL ( *SetActualDataLength )( + IMediaSample * This, + long __MIDL_0010); + + HRESULT STDCALL ( *GetMediaType )( + IMediaSample * This, + AM_MEDIA_TYPE **ppMediaType); + + HRESULT STDCALL ( *SetMediaType )( + IMediaSample * This, + AM_MEDIA_TYPE *pMediaType); + + HRESULT STDCALL ( *IsDiscontinuity )( + IMediaSample * This); + + HRESULT STDCALL ( *SetDiscontinuity )( + IMediaSample * This, + long bDiscontinuity); + + HRESULT STDCALL ( *GetMediaTime )( + IMediaSample * This, + /* [out] */ long long *pTimeStart, + /* [out] */ long long *pTimeEnd); + + HRESULT STDCALL ( *SetMediaTime )( + IMediaSample * This, + /* [in] */ long long *pTimeStart, + /* [in] */ long long *pTimeEnd); +}; + +struct IMediaSample +{ + struct IMediaSample_vt *vt; +}; + +struct IHidden; +struct IHidden_vt: IUnknown_vt +{ + HRESULT STDCALL ( *GetSmth )(IHidden * This, + int* pv); + HRESULT STDCALL ( *SetSmth )(IHidden * This, + int v1, int v2); + HRESULT STDCALL ( *GetSmth2 )(IHidden * This, + int* pv); + HRESULT STDCALL ( *SetSmth2 )(IHidden * This, + int v1, int v2); + HRESULT STDCALL ( *GetSmth3 )(IHidden * This, + int* pv); + HRESULT STDCALL ( *SetSmth3 )(IHidden * This, + int v1, int v2); + HRESULT STDCALL ( *GetSmth4 )(IHidden * This, + int* pv); + HRESULT STDCALL ( *SetSmth4 )(IHidden * This, + int v1, int v2); + HRESULT STDCALL ( *GetSmth5 )(IHidden * This, + int* pv); + HRESULT STDCALL ( *SetSmth5 )(IHidden * This, + int v1, int v2); + HRESULT STDCALL ( *GetSmth6 )(IHidden * This, + int* pv); +}; + +struct IHidden +{ + struct IHidden_vt *vt; +}; + +struct IHidden2; +struct IHidden2_vt: IUnknown_vt +{ + HRESULT STDCALL (*unk1) (); + HRESULT STDCALL (*unk2) (); + HRESULT STDCALL (*unk3) (); + HRESULT STDCALL (*DecodeGet) (IHidden2* This, int* region); + HRESULT STDCALL (*unk5) (); + HRESULT STDCALL (*DecodeSet) (IHidden2* This, int* region); + HRESULT STDCALL (*unk7) (); + HRESULT STDCALL (*unk8) (); +}; +struct IHidden2 +{ + struct IHidden2_vt *vt; +}; +#endif
\ No newline at end of file diff --git a/loader/dshow/iunk.h b/loader/dshow/iunk.h new file mode 100644 index 0000000000..cf07e9cea5 --- /dev/null +++ b/loader/dshow/iunk.h @@ -0,0 +1,47 @@ +#ifndef _iunk_h +#define _iunk_h +#include "interfaces.h" +#include "guids.h" +#define DECLARE_IUNKNOWN(CLASSNAME) \ + int refcount; \ + static long STDCALL QueryInterface (IUnknown * This, GUID* riid, void **ppvObject); \ + static long STDCALL AddRef (IUnknown * This); \ + static long STDCALL Release (IUnknown * This); + +#define IMPLEMENT_IUNKNOWN(CLASSNAME) \ +long STDCALL CLASSNAME ::QueryInterface (IUnknown * This, GUID* riid, void **ppvObject) \ +{ \ + Debug printf(#CLASSNAME "::QueryInterface() called\n");\ + if(!ppvObject)return 0x80004003; \ + CLASSNAME * me=( CLASSNAME *)This; \ + int i=0; \ + for(const GUID* r=me->interfaces; i<sizeof(CLASSNAME ::interfaces)/sizeof(CLASSNAME ::interfaces[0]); r++, i++) \ + if(!memcmp(r, riid, 16)) \ + { \ + This->vt->AddRef((IUnknown*)This); \ + *ppvObject=This; \ + return 0; \ + } \ + Debug printf("Failed\n"); \ + return 0x80004002; \ +} \ + \ +long STDCALL CLASSNAME ::AddRef ( \ + IUnknown * This) \ +{ \ + Debug printf(#CLASSNAME "::AddRef() called\n"); \ + CLASSNAME * me=( CLASSNAME *)This; \ + return ++(me->refcount); \ +} \ + \ +long STDCALL CLASSNAME ::Release ( \ + IUnknown * This) \ +{ \ + Debug printf(#CLASSNAME "::Release() called\n"); \ + CLASSNAME* me=( CLASSNAME *)This; \ + if(--(me->refcount) ==0) \ + delete ( CLASSNAME *) This; \ + return 0; \ +} + +#endif diff --git a/loader/dshow/outputpin.c b/loader/dshow/outputpin.c new file mode 100644 index 0000000000..cfb0f32aae --- /dev/null +++ b/loader/dshow/outputpin.c @@ -0,0 +1,483 @@ +#include "outputpin.h" +#include <string.h> +#include <stdio.h> +#include "allocator.h" +#include "iunk.h" +#define E_NOTIMPL 0x80004001 +/* + An object beyond interface IEnumMediaTypes. + Returned by COutputPin through call IPin::EnumMediaTypes(). +*/ + +class CEnumMediaTypes: public IEnumMediaTypes +{ + AM_MEDIA_TYPE type; + static GUID interfaces[]; + DECLARE_IUNKNOWN(CEnumMediaTypes) +public: + CEnumMediaTypes(const AM_MEDIA_TYPE&); + ~CEnumMediaTypes(){delete vt;} + static HRESULT STDCALL Next ( + IEnumMediaTypes * This, + /* [in] */ ULONG cMediaTypes, + /* [size_is][out] */ AM_MEDIA_TYPE **ppMediaTypes, + /* [out] */ ULONG *pcFetched); + + static HRESULT STDCALL Skip ( + IEnumMediaTypes * This, + /* [in] */ ULONG cMediaTypes); + + static HRESULT STDCALL Reset ( + IEnumMediaTypes * This); + + static HRESULT STDCALL Clone ( + IEnumMediaTypes * This, + /* [out] */ IEnumMediaTypes **ppEnum); + +}; +GUID CEnumMediaTypes::interfaces[]= +{ + IID_IUnknown, + IID_IEnumMediaTypes, +}; +IMPLEMENT_IUNKNOWN(CEnumMediaTypes) +CEnumMediaTypes::CEnumMediaTypes(const AM_MEDIA_TYPE& type) + :refcount(1) +{ + this->type=type; + vt=new IEnumMediaTypes_vt; + vt->QueryInterface = QueryInterface; + vt->AddRef = AddRef; + vt->Release = Release; + vt->Next = Next; + vt->Skip = Skip; + vt->Reset = Reset; + vt->Clone = Clone; +} + +HRESULT STDCALL CEnumMediaTypes::Next ( + IEnumMediaTypes * This, + /* [in] */ ULONG cMediaTypes, + /* [size_is][out] */ AM_MEDIA_TYPE **ppMediaTypes, + /* [out] */ ULONG *pcFetched) +{ + AM_MEDIA_TYPE& type=((CEnumMediaTypes*)This)->type; + Debug printf("CEnumMediaTypes::Next() called\n"); + if(!ppMediaTypes)return 0x80004003; + if(!pcFetched && (cMediaTypes!=1))return 0x80004003; + if(cMediaTypes<=0)return 0; + + if(pcFetched)*pcFetched=1; + ppMediaTypes[0]=(AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)); + memcpy(*ppMediaTypes, &type, sizeof(AM_MEDIA_TYPE)); + if(ppMediaTypes[0]->pbFormat) + { + ppMediaTypes[0]->pbFormat=(char *)CoTaskMemAlloc(ppMediaTypes[0]->cbFormat); + memcpy(ppMediaTypes[0]->pbFormat, type.pbFormat, ppMediaTypes[0]->cbFormat); + } + if(cMediaTypes==1)return 0; + return 1; +} +/* + I expect that these methods are unused. +*/ +HRESULT STDCALL CEnumMediaTypes::Skip ( + IEnumMediaTypes * This, + /* [in] */ ULONG cMediaTypes) +{ + Debug printf("CEnumMediaTypes::Skip() called\n"); + return E_NOTIMPL; +} + +HRESULT STDCALL CEnumMediaTypes::Reset ( + IEnumMediaTypes * This) +{ + Debug printf("CEnumMediaTypes::Reset() called\n"); + return 0; +} + +HRESULT STDCALL CEnumMediaTypes::Clone ( + IEnumMediaTypes * This, + /* [out] */ IEnumMediaTypes **ppEnum) +{ + Debug printf("CEnumMediaTypes::Clone() called\n"); + return E_NOTIMPL; +} + +/* + Implementation of output pin object. +*/ + +// Constructor + +COutputPin::COutputPin(const AM_MEDIA_TYPE& vh) :refcount(1), type(vh), remote(0), frame_pointer(0), frame_size_pointer(0) +{ + IPin::vt=new IPin_vt; + IPin::vt->QueryInterface = QueryInterface; + IPin::vt->AddRef = AddRef; + IPin::vt->Release = Release; + IPin::vt->Connect = Connect; + IPin::vt->ReceiveConnection = ReceiveConnection; + IPin::vt->Disconnect=Disconnect; + IPin::vt->ConnectedTo = ConnectedTo; + IPin::vt->ConnectionMediaType = ConnectionMediaType; + IPin::vt->QueryPinInfo = QueryPinInfo; + IPin::vt->QueryDirection = QueryDirection; + IPin::vt->QueryId = QueryId; + IPin::vt->QueryAccept = QueryAccept; + IPin::vt->EnumMediaTypes = EnumMediaTypes; + IPin::vt->QueryInternalConnections = QueryInternalConnections; + IPin::vt->EndOfStream = EndOfStream; + IPin::vt->BeginFlush = BeginFlush; + IPin::vt->EndFlush = EndFlush; + IPin::vt->NewSegment = NewSegment; + + IMemInputPin::vt=new IMemInputPin_vt; + IMemInputPin::vt->QueryInterface = M_QueryInterface; + IMemInputPin::vt->AddRef = M_AddRef; + IMemInputPin::vt->Release = M_Release; + IMemInputPin::vt->GetAllocator = GetAllocator; + IMemInputPin::vt->NotifyAllocator = NotifyAllocator; + IMemInputPin::vt->GetAllocatorRequirements = GetAllocatorRequirements; + IMemInputPin::vt->Receive = Receive; + IMemInputPin::vt->ReceiveMultiple = ReceiveMultiple; + IMemInputPin::vt->ReceiveCanBlock = ReceiveCanBlock; +} + +// IPin->IUnknown methods + +HRESULT STDCALL COutputPin::QueryInterface(IUnknown* This, GUID* iid, void** ppv) +{ + Debug printf("COutputPin::QueryInterface() called\n"); + if(!ppv)return 0x80004003; + if(!memcmp(iid, &IID_IUnknown, 16)) + { + *ppv=(void*)This; + This->vt->AddRef(This); + return 0; + } + if(!memcmp(iid, &IID_IMemInputPin, 16)) + { + *ppv=(void*)(This+1); + This->vt->AddRef(This); + return 0; + } + + Debug printf("Unknown interface : %08x-%04x-%04x-%02x%02x-" \ + "%02x%02x%02x%02x%02x%02x\n", + iid->f1, iid->f2, iid->f3, + (unsigned char)iid->f4[1], (unsigned char)iid->f4[0], + (unsigned char)iid->f4[2],(unsigned char)iid->f4[3],(unsigned char)iid->f4[4], + (unsigned char)iid->f4[5],(unsigned char)iid->f4[6],(unsigned char)iid->f4[7]); + return 0x80004002; +} +HRESULT STDCALL COutputPin::AddRef(IUnknown* This) +{ + Debug printf("COutputPin::AddRef() called\n"); + ((COutputPin*)This)->refcount++; + return 0; +} +HRESULT STDCALL COutputPin::Release(IUnknown* This) +{ + Debug printf("COutputPin::Release() called\n"); + if(--((COutputPin*)This)->refcount==0) + delete (COutputPin*)This; + return 0; +} + +// IPin methods + +HRESULT STDCALL COutputPin::Connect ( + IPin * This, + /* [in] */ IPin *pReceivePin, + /* [in] */ /* const */ AM_MEDIA_TYPE *pmt) +{ + Debug printf("COutputPin::Connect() called\n"); +/* + *pmt=((COutputPin*)This)->type; + if(pmt->cbFormat>0) + { + pmt->pbFormat=CoTaskMemAlloc(pmt->cbFormat); + memcpy(pmt->pbFormat, ((COutputPin*)This)->type.pbFormat, pmt->cbFormat); + } +*/ + return E_NOTIMPL; + // if I put return 0; here, it crashes +} + +HRESULT STDCALL COutputPin::ReceiveConnection ( + IPin * This, + /* [in] */ IPin *pConnector, + /* [in] */ const AM_MEDIA_TYPE *pmt) +{ + Debug printf("COutputPin::ReceiveConnection() called\n"); + ((COutputPin*)This)->remote=pConnector; + return 0; +} + +HRESULT STDCALL COutputPin::Disconnect ( + IPin * This) +{ + Debug printf("COutputPin::Disconnect() called\n"); + return 1; +} + + +HRESULT STDCALL COutputPin::ConnectedTo ( + IPin * This, + /* [out] */ IPin **pPin) +{ + Debug printf("COutputPin::ConnectedTo() called\n"); + if(!pPin)return 0x80004003; + *pPin=((COutputPin*)This)->remote; + return 0; +} + + + +HRESULT STDCALL COutputPin::ConnectionMediaType ( + IPin * This, + /* [out] */ AM_MEDIA_TYPE *pmt) +{ + Debug printf("CInputPin::ConnectionMediaType() called\n"); + if(!pmt)return 0x80004003; + *pmt=((COutputPin*)This)->type; + if(pmt->cbFormat>0) + { + pmt->pbFormat=(char *)CoTaskMemAlloc(pmt->cbFormat); + memcpy(pmt->pbFormat, ((COutputPin*)This)->type.pbFormat, pmt->cbFormat); + } + return 0; +} + +HRESULT STDCALL COutputPin::QueryPinInfo ( + IPin * This, + /* [out] */ PIN_INFO *pInfo) +{ + Debug printf("COutputPin::QueryPinInfo() called\n"); + return E_NOTIMPL; +} + + +HRESULT STDCALL COutputPin::QueryDirection ( + IPin * This, + /* [out] */ PIN_DIRECTION *pPinDir) +{ + Debug printf("COutputPin::QueryDirection() called\n"); + if(!pPinDir)return -1; + *pPinDir=PINDIR_INPUT; + return 0; +} + + +HRESULT STDCALL COutputPin::QueryId ( + IPin * This, + /* [out] */ LPWSTR *Id) +{ + Debug printf("COutputPin::QueryId() called\n"); + return E_NOTIMPL; +} + + +HRESULT STDCALL COutputPin::QueryAccept ( + IPin * This, + /* [in] */ const AM_MEDIA_TYPE *pmt) +{ + Debug printf("COutputPin::QueryAccept() called\n"); + return E_NOTIMPL; +} + + +HRESULT STDCALL COutputPin::EnumMediaTypes ( + IPin * This, + /* [out] */ IEnumMediaTypes **ppEnum) +{ + Debug printf("COutputPin::EnumMediaTypes() called\n"); + if(!ppEnum)return 0x80004003; + *ppEnum=new CEnumMediaTypes(((COutputPin*)This)->type); + return 0; +} + + +HRESULT STDCALL COutputPin::QueryInternalConnections ( + IPin * This, + /* [out] */ IPin **apPin, + /* [out][in] */ ULONG *nPin) +{ + Debug printf("COutputPin::QueryInternalConnections() called\n"); + return E_NOTIMPL; +} + +HRESULT STDCALL COutputPin::EndOfStream ( + IPin * This) +{ + Debug printf("COutputPin::EndOfStream() called\n"); + return E_NOTIMPL; +} + + +HRESULT STDCALL COutputPin::BeginFlush ( +IPin * This) +{ + Debug printf("COutputPin::BeginFlush() called\n"); + return E_NOTIMPL; +} + + +HRESULT STDCALL COutputPin::EndFlush ( + IPin * This) +{ + Debug printf("COutputPin::EndFlush() called\n"); + return E_NOTIMPL; +} + +HRESULT STDCALL COutputPin::NewSegment ( + IPin * This, + /* [in] */ REFERENCE_TIME tStart, + /* [in] */ REFERENCE_TIME tStop, + /* [in] */ double dRate) +{ + Debug printf("COutputPin::NewSegment(%ld,%ld,%f) called\n",tStart,tStop,dRate); + return 0; +} + + + + + + + + + + + + + + + + + + +// IMemInputPin->IUnknown methods + +HRESULT STDCALL COutputPin::M_QueryInterface(IUnknown* This, GUID* iid, void** ppv) +{ + Debug printf("COutputPin::QueryInterface() called\n"); + if(!ppv)return 0x80004003; + if(!memcmp(iid, &IID_IUnknown, 16)) + { + COutputPin* ptr=(COutputPin*)(This-1); + *ppv=(void*)ptr; + AddRef((IUnknown*)ptr); + return 0; + } +/* if(!memcmp(iid, &IID_IPin, 16)) + { + COutputPin* ptr=(COutputPin*)(This-1); + *ppv=(void*)ptr; + AddRef((IUnknown*)ptr); + return 0; + }*/ + if(!memcmp(iid, &IID_IMemInputPin, 16)) + { + *ppv=(void*)This; + This->vt->AddRef(This); + return 0; + } + Debug printf("Unknown interface : %08x-%04x-%04x-%02x%02x-" \ + "%02x%02x%02x%02x%02x%02x\n", + iid->f1, iid->f2, iid->f3, + (unsigned char)iid->f4[1], (unsigned char)iid->f4[0], + (unsigned char)iid->f4[2],(unsigned char)iid->f4[3],(unsigned char)iid->f4[4], + (unsigned char)iid->f4[5],(unsigned char)iid->f4[6],(unsigned char)iid->f4[7]); + return 0x80004002; +} +HRESULT STDCALL COutputPin::M_AddRef(IUnknown* This) +{ + Debug printf("COutputPin::AddRef() called\n"); + ((COutputPin*)(This-1))->refcount++; + return 0; +} +HRESULT STDCALL COutputPin::M_Release(IUnknown* This) +{ + Debug printf("COutputPin::Release() called\n"); + if(--((COutputPin*)(This-1))->refcount==0) + delete (COutputPin*)This; + return 0; +} + + + + +// IMemInputPin methods + +HRESULT STDCALL COutputPin::GetAllocator( + IMemInputPin * This, + /* [out] */ IMemAllocator **ppAllocator) +{ + Debug printf("COutputPin::GetAllocator(%x,%x) called\n",This->vt,ppAllocator); + *ppAllocator=new MemAllocator; + return 0; +} + +HRESULT STDCALL COutputPin::NotifyAllocator( + IMemInputPin * This, + /* [in] */ IMemAllocator *pAllocator, + /* [in] */ int bReadOnly) +{ + Debug printf("COutputPin::NotifyAllocator() called\n"); + return 0; +} + +HRESULT STDCALL COutputPin::GetAllocatorRequirements( + IMemInputPin * This, + /* [out] */ ALLOCATOR_PROPERTIES *pProps) +{ + Debug printf("COutputPin::GetAllocatorRequirements() called\n"); + return E_NOTIMPL; +} + +HRESULT STDCALL COutputPin::Receive( + IMemInputPin * This, + /* [in] */ IMediaSample *pSample) +{ + Debug printf("COutputPin::Receive() called\n"); + COutputPin& me=*(COutputPin*)This; + if(!pSample)return 0x80004003; + char* pointer; + if(pSample->vt->GetPointer(pSample, (BYTE **)&pointer)) + return -1; + int len=pSample->vt->GetActualDataLength(pSample); + if(len==0)len=pSample->vt->GetSize(pSample);//for iv50 + //if(me.frame_pointer)memcpy(me.frame_pointer, pointer, len); + *me.frame_pointer=pointer; + if(me.frame_size_pointer)*me.frame_size_pointer=len; +/* + FILE* file=fopen("./uncompr.bmp", "wb"); + char head[14]={0x42, 0x4D, 0x36, 0x10, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00}; + *(int*)(&head[2])=len+0x36; + fwrite(head, 14, 1, file); + fwrite(&((VIDEOINFOHEADER*)me.type.pbFormat)->bmiHeader, sizeof(BITMAPINFOHEADER), 1, file); + fwrite(pointer, len, 1, file); + fclose(file); +*/ +// pSample->vt->Release((IUnknown*)pSample); + return 0; +} + +HRESULT STDCALL COutputPin::ReceiveMultiple( + IMemInputPin * This, + /* [size_is][in] */ IMediaSample **pSamples, + /* [in] */ long nSamples, + /* [out] */ long *nSamplesProcessed) +{ + Debug printf("COutputPin::ReceiveMultiple() called\n"); + return E_NOTIMPL; +} + +HRESULT STDCALL COutputPin::ReceiveCanBlock( + IMemInputPin * This) +{ + Debug printf("COutputPin::ReceiveCanBlock() called\n"); + return E_NOTIMPL; +} diff --git a/loader/dshow/outputpin.h b/loader/dshow/outputpin.h new file mode 100644 index 0000000000..f1cc36ee5e --- /dev/null +++ b/loader/dshow/outputpin.h @@ -0,0 +1,122 @@ +/* "output pin" - the one that connects to output of filter. */ + +#ifndef OUTPUTPIN_H +#define OUTPUTPIN_H +#include "interfaces.h" +#include "guids.h" +#include "default.h" + +class COutputPin: public IPin, public IMemInputPin +{ + int refcount; + AM_MEDIA_TYPE type; + IPin* remote; + char** frame_pointer; + long* frame_size_pointer; +public: + COutputPin(const AM_MEDIA_TYPE& vhdr); + ~COutputPin(){delete IPin::vt; delete IMemInputPin::vt;} + void SetFramePointer(char** z){frame_pointer=z;} + void SetFrameSizePointer(long* z){frame_size_pointer=z;} + void SetNewFormat(const AM_MEDIA_TYPE& a){type=a;} + static HRESULT STDCALL QueryInterface(IUnknown* This, GUID* iid, void** ppv); + static HRESULT STDCALL AddRef(IUnknown* This); + static HRESULT STDCALL Release(IUnknown* This); + + static HRESULT STDCALL M_QueryInterface(IUnknown* This, GUID* iid, void** ppv); + static HRESULT STDCALL M_AddRef(IUnknown* This); + static HRESULT STDCALL M_Release(IUnknown* This); + + static HRESULT STDCALL Connect ( + IPin * This, + /* [in] */ IPin *pReceivePin, + /* [in] */ /*const */AM_MEDIA_TYPE *pmt); + + static HRESULT STDCALL ReceiveConnection ( + IPin * This, + /* [in] */ IPin *pConnector, + /* [in] */ const AM_MEDIA_TYPE *pmt); + + static HRESULT STDCALL Disconnect ( + IPin * This); + + static HRESULT STDCALL ConnectedTo ( + IPin * This, + /* [out] */ IPin **pPin); + + static HRESULT STDCALL ConnectionMediaType ( + IPin * This, + /* [out] */ AM_MEDIA_TYPE *pmt); + + static HRESULT STDCALL QueryPinInfo ( + IPin * This, + /* [out] */ PIN_INFO *pInfo); + + static HRESULT STDCALL QueryDirection ( + IPin * This, + /* [out] */ PIN_DIRECTION *pPinDir); + + static HRESULT STDCALL QueryId ( + IPin * This, + /* [out] */ LPWSTR *Id); + + static HRESULT STDCALL QueryAccept ( + IPin * This, + /* [in] */ const AM_MEDIA_TYPE *pmt); + + static HRESULT STDCALL EnumMediaTypes ( + IPin * This, + /* [out] */ IEnumMediaTypes **ppEnum); + + static HRESULT STDCALL QueryInternalConnections ( + IPin * This, + /* [out] */ IPin **apPin, + /* [out][in] */ ULONG *nPin); + + static HRESULT STDCALL EndOfStream ( + IPin * This); + + static HRESULT STDCALL BeginFlush ( + IPin * This); + + static HRESULT STDCALL EndFlush ( + IPin * This); + + static HRESULT STDCALL NewSegment ( + IPin * This, + /* [in] */ REFERENCE_TIME tStart, + /* [in] */ REFERENCE_TIME tStop, + /* [in] */ double dRate); + + + + + + + static HRESULT STDCALL GetAllocator( + IMemInputPin * This, + /* [out] */ IMemAllocator **ppAllocator) ; + + static HRESULT STDCALL NotifyAllocator( + IMemInputPin * This, + /* [in] */ IMemAllocator *pAllocator, + /* [in] */ int bReadOnly) ; + + static HRESULT STDCALL GetAllocatorRequirements( + IMemInputPin * This, + /* [out] */ ALLOCATOR_PROPERTIES *pProps) ; + + static HRESULT STDCALL Receive( + IMemInputPin * This, + /* [in] */ IMediaSample *pSample) ; + + static HRESULT STDCALL ReceiveMultiple( + IMemInputPin * This, + /* [size_is][in] */ IMediaSample **pSamples, + /* [in] */ long nSamples, + /* [out] */ long *nSamplesProcessed) ; + + static HRESULT STDCALL ReceiveCanBlock( + IMemInputPin * This) ; +}; +#endif diff --git a/loader/dshow/test.divx b/loader/dshow/test.divx Binary files differnew file mode 100644 index 0000000000..397f72989a --- /dev/null +++ b/loader/dshow/test.divx |