aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--loader/dshow/DS_Filter.c177
-rw-r--r--loader/dshow/DS_Filter.h39
-rw-r--r--loader/dshow/Makefile44
-rw-r--r--loader/dshow/allocator.c154
-rw-r--r--loader/dshow/allocator.h49
-rw-r--r--loader/dshow/cmediasample.c251
-rw-r--r--loader/dshow/cmediasample.h96
-rw-r--r--loader/dshow/guids.c61
-rw-r--r--loader/dshow/guids.h90
-rw-r--r--loader/dshow/inputpin.c667
-rw-r--r--loader/dshow/inputpin.h265
-rw-r--r--loader/dshow/interfaces.h417
-rw-r--r--loader/dshow/iunk.h47
-rw-r--r--loader/dshow/outputpin.c483
-rw-r--r--loader/dshow/outputpin.h122
-rw-r--r--loader/dshow/test.divxbin0 -> 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
new file mode 100644
index 0000000000..397f72989a
--- /dev/null
+++ b/loader/dshow/test.divx
Binary files differ