diff options
-rw-r--r-- | loader/dshow/DS_Filter.c | 346 | ||||
-rw-r--r-- | loader/dshow/DS_Filter.h | 31 | ||||
-rw-r--r-- | loader/dshow/allocator.c | 306 | ||||
-rw-r--r-- | loader/dshow/allocator.h | 37 | ||||
-rw-r--r-- | loader/dshow/cmediasample.c | 211 | ||||
-rw-r--r-- | loader/dshow/cmediasample.h | 14 | ||||
-rw-r--r-- | loader/dshow/guids.c | 10 | ||||
-rw-r--r-- | loader/dshow/guids.h | 32 | ||||
-rw-r--r-- | loader/dshow/inputpin.c | 772 | ||||
-rw-r--r-- | loader/dshow/inputpin.h | 237 | ||||
-rw-r--r-- | loader/dshow/interfaces.h | 397 | ||||
-rw-r--r-- | loader/dshow/iunk.h | 47 | ||||
-rw-r--r-- | loader/dshow/outputpin.c | 321 | ||||
-rw-r--r-- | loader/dshow/outputpin.h | 26 |
14 files changed, 1491 insertions, 1296 deletions
diff --git a/loader/dshow/DS_Filter.c b/loader/dshow/DS_Filter.c index 7cb46c00eb..99124074be 100644 --- a/loader/dshow/DS_Filter.c +++ b/loader/dshow/DS_Filter.c @@ -1,223 +1,251 @@ #include "DS_Filter.h" -//#include "../loader/loader.h" -#include "libwin32.h" -//#include <string> +#include "driver.h" +#include "com.h" #include <stdio.h> #include <string.h> -#define __MODULE__ "DirectShow generic filter" - -using namespace std; - -extern "C" int STDCALL expLoadLibraryA(const char*); - typedef long STDCALL (*GETCLASS) (const GUID*, const GUID*, void**); -//extern "C" int STDCALL LoadLibraryA(const char*); //extern "C" STDCALL void* GetProcAddress(int, const char*); // STDCALL has to be first NetBSD -//extern "C" int STDCALL FreeLibrary(int); -DS_Filter::DS_Filter() +static void DS_Filter_Start(DS_Filter* This) { - m_iHandle = 0; - m_pFilter = 0; - m_pInputPin = 0; - m_pOutputPin = 0; - m_pSrcFilter = 0; - m_pParentFilter = 0; - m_pOurInput = 0; - m_pOurOutput = 0; - m_pAll = 0; - m_pImp = 0; - m_iState = 0; + HRESULT hr; + + if (This->m_iState != 1) + return; + + //Debug printf("DS_Filter_Start(%p)\n", This); + hr = This->m_pFilter->vt->Run(This->m_pFilter, 0); + if (hr != 0) + { + Debug printf("WARNING: m_Filter->Run() failed, error code %x\n", (int)hr); + } + hr = This->m_pImp->vt->GetAllocator(This->m_pImp, &This->m_pAll); + + if (hr || !This->m_pAll) + { + Debug printf("WARNING: error getting IMemAllocator interface %x\n", (int)hr); + This->m_pImp->vt->Release((IUnknown*)This->m_pImp); + return; + } + This->m_pImp->vt->NotifyAllocator(This->m_pImp, This->m_pAll, 0); + This->m_iState = 2; } -DS_Filter::~DS_Filter() +static void DS_Filter_Stop(DS_Filter* This) { - //cout << "Destruction of DS_FILTER" << endl; - Stop(); - destroy(); - //cout << "Destruction of DS_FILTER done" << endl; + if (This->m_iState == 2) + { + This->m_iState = 1; + //Debug printf("DS_Filter_Stop(%p)\n", This); + if (This->m_pFilter) + { + //printf("vt: %p\n", m_pFilter->vt); + //printf("vtstop %p\n", m_pFilter->vt->Stop); + This->m_pFilter->vt->Stop(This->m_pFilter); // causes weird crash ??? FIXME + } + else + printf("WARNING: DS_Filter::Stop() m_pFilter is NULL!\n"); + This->m_pAll->vt->Release((IUnknown*)This->m_pAll); + This->m_pAll = 0; + } } -void DS_Filter::destroy() +void DS_Filter_Destroy(DS_Filter* This) { - if (m_iState == 0) - return; - m_iState = 0; - - if (m_pOurInput) - m_pOurInput->vt->Release((IUnknown*)m_pOurInput); - 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_pImp) - m_pImp->vt->Release((IUnknown*)m_pImp); - - delete m_pOurOutput; - delete m_pParentFilter; - delete m_pSrcFilter; + This->Stop(This); + + This->m_iState = 0; + + if (This->m_pOurInput) + This->m_pOurInput->vt->Release((IUnknown*)This->m_pOurInput); + if (This->m_pInputPin) + This->m_pInputPin->vt->Disconnect(This->m_pInputPin); + if (This->m_pOutputPin) + This->m_pOutputPin->vt->Disconnect(This->m_pOutputPin); + if (This->m_pFilter) + This->m_pFilter->vt->Release((IUnknown*)This->m_pFilter); + if (This->m_pOutputPin) + This->m_pOutputPin->vt->Release((IUnknown*)This->m_pOutputPin); + if (This->m_pInputPin) + This->m_pInputPin->vt->Release((IUnknown*)This->m_pInputPin); + if (This->m_pImp) + This->m_pImp->vt->Release((IUnknown*)This->m_pImp); + + if (This->m_pOurOutput) + This->m_pOurOutput->vt->Release((IUnknown*)This->m_pOurOutput); + if (This->m_pParentFilter) + This->m_pSrcFilter->vt->Release((IUnknown*)This->m_pParentFilter); + if (This->m_pSrcFilter) + This->m_pSrcFilter->vt->Release((IUnknown*)This->m_pSrcFilter); // FIXME - we are still leaving few things allocated! - if (m_iHandle) - FreeLibrary(m_iHandle); + if (This->m_iHandle) + FreeLibrary(This->m_iHandle); + + free(This); + + CodecRelease(); } -void DS_Filter::Create(const char* dllname, const GUID* id, - AM_MEDIA_TYPE* in_fmt, - AM_MEDIA_TYPE* out_fmt) +DS_Filter* DS_FilterCreate(const char* dllname, const GUID* id, + AM_MEDIA_TYPE* in_fmt, + AM_MEDIA_TYPE* out_fmt) { - try + DS_Filter* This = (DS_Filter*) malloc(sizeof(DS_Filter)); + if (!This) + return NULL; + + CodecAlloc(); + + This->m_pFilter = NULL; + This->m_pInputPin = NULL; + This->m_pOutputPin = NULL; + This->m_pSrcFilter = NULL; + This->m_pParentFilter = NULL; + This->m_pOurInput = NULL; + This->m_pOurOutput = NULL; + This->m_pAll = NULL; + This->m_pImp = NULL; + This->m_iState = 0; + + This->Start = DS_Filter_Start; + This->Stop = DS_Filter_Stop; + + for (;;) { - m_iHandle = expLoadLibraryA(dllname); - if (!m_iHandle) + HRESULT result; + GETCLASS func; + struct IClassFactory* factory = NULL; + struct IUnknown* object = NULL; + IEnumPins* enum_pins = 0; + IPin* array[256]; + ULONG fetched; + unsigned int i; + + This->m_iHandle = LoadLibraryA(dllname); + if (!This->m_iHandle) { - char e[256]; - snprintf((char *)&e[0], 256, "Could not open DirectShow DLL: %.200s", dllname); - throw FATAL(e); + printf("Could not open DirectShow DLL: %.200s\n", dllname); + break; } - GETCLASS func = (GETCLASS)GetProcAddress(m_iHandle, "DllGetClassObject"); + func = (GETCLASS)GetProcAddress(This->m_iHandle, "DllGetClassObject"); if (!func) { - char e[256]; - snprintf((char *)&e[0], 256, "Illegal or corrupt DirectShow DLL: %.200s", dllname); - throw FATAL(e); + printf("Illegal or corrupt DirectShow DLL: %.200s\n", dllname); + break; } - - HRESULT result; - IClassFactory* factory = 0; result = func(id, &IID_IClassFactory, (void**)&factory); if (result || !factory) - throw FATAL("No such class object");; - - IUnknown* object = 0; + { + printf("No such class object\n"); + break; + } result = factory->vt->CreateInstance(factory, 0, &IID_IUnknown, (void**)&object); factory->vt->Release((IUnknown*)factory); if (result || !object) - throw FATAL("Class factory failure"); - - result = object->vt->QueryInterface(object, &IID_IBaseFilter, (void**)&m_pFilter); + { + printf("Class factory failure\n"); + break; + } + result = object->vt->QueryInterface(object, &IID_IBaseFilter, (void**)&This->m_pFilter); object->vt->Release((IUnknown*)object); - if (result || !m_pFilter) - throw FATAL("Object does not have IBaseFilter interface"); - - IEnumPins* enum_pins = 0; + if (result || !This->m_pFilter) + { + printf("Object does not have IBaseFilter interface\n"); + break; + } // enumerate pins - result = m_pFilter->vt->EnumPins(m_pFilter, &enum_pins); + result = This->m_pFilter->vt->EnumPins(This->m_pFilter, &enum_pins); if (result || !enum_pins) - throw FATAL("Could not enumerate pins"); + { + printf("Could not enumerate pins\n"); + break; + } - IPin* array[256]; - ULONG fetched; enum_pins->vt->Reset(enum_pins); result = enum_pins->vt->Next(enum_pins, (ULONG)256, (IPin**)array, &fetched); Debug printf("Pins enumeration returned %ld pins, error is %x\n", fetched, (int)result); - for (unsigned i = 0; i < fetched; i++) + for (i = 0; i < fetched; i++) { int direction = -1; array[i]->vt->QueryDirection(array[i], (PIN_DIRECTION*)&direction); - if (!m_pInputPin && direction == 0) + if (!This->m_pInputPin && direction == 0) { - m_pInputPin = array[i]; - m_pInputPin->vt->AddRef((IUnknown*)m_pInputPin); + This->m_pInputPin = array[i]; + This->m_pInputPin->vt->AddRef((IUnknown*)This->m_pInputPin); } - if (!m_pOutputPin && direction == 1) + if (!This->m_pOutputPin && direction == 1) { - m_pOutputPin = array[i]; - m_pOutputPin->vt->AddRef((IUnknown*)m_pOutputPin); + This->m_pOutputPin = array[i]; + This->m_pOutputPin->vt->AddRef((IUnknown*)This->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 (!This->m_pInputPin) + { + printf("Input pin not found\n"); + break; + } + if (!This->m_pOutputPin) + { + printf("Output pin not found\n"); + break; + } + result = This->m_pInputPin->vt->QueryInterface((IUnknown*)This->m_pInputPin, + &IID_IMemInputPin, + (void**)&This->m_pImp); 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); + { + printf("Error getting IMemInputPin interface\n"); + break; + } - result = m_pInputPin->vt->ReceiveConnection(m_pInputPin, - m_pOurInput, - m_pOurType); + This->m_pOurType = in_fmt; + This->m_pDestType = out_fmt; + result = This->m_pInputPin->vt->QueryAccept(This->m_pInputPin, This->m_pOurType); if (result) - throw FATAL("Error connecting to input pin"); + { + printf("Source format is not accepted\n"); + break; + } + This->m_pParentFilter = CBaseFilter2Create(); + This->m_pSrcFilter = CBaseFilterCreate(This->m_pOurType, This->m_pParentFilter); + This->m_pOurInput = This->m_pSrcFilter->GetPin(This->m_pSrcFilter); + This->m_pOurInput->vt->AddRef((IUnknown*)This->m_pOurInput); + + result = This->m_pInputPin->vt->ReceiveConnection(This->m_pInputPin, + This->m_pOurInput, + This->m_pOurType); + if (result) + { + printf("Error connecting to input pin\n"); + break; + } - m_pOurOutput = new COutputPin(*m_pDestType); + This->m_pOurOutput = COutputPinCreate(This->m_pDestType); - //extern void trapbug(); - //trapbug(); - result = m_pOutputPin->vt->ReceiveConnection(m_pOutputPin, - m_pOurOutput, - m_pDestType); + result = This->m_pOutputPin->vt->ReceiveConnection(This->m_pOutputPin, + (IPin*) This->m_pOurOutput, + This->m_pDestType); if (result) { //printf("Tracking ACELP %d 0%x\n", result); - throw FATAL("Error connecting to output pin"); + printf("Error connecting to output pin\n"); + break; } printf("Using DirectShow codec: %s\n", dllname); - m_iState = 1; - } - catch (FatalError e) - { - //e.PrintAll(); - destroy(); - throw; - } -} - -void DS_Filter::Start() -{ - if (m_iState != 1) - return; - - HRESULT hr=m_pFilter->vt->Run(m_pFilter, 0); - if (hr != 0) - { - Debug printf("WARNING: m_Filter->Run() failed, error code %x\n", (int)hr); + This->m_iState = 1; + break; } - hr = m_pImp->vt->GetAllocator(m_pImp, &m_pAll); - if (hr) - { - Debug printf("Error getting IMemAllocator interface %x\n", (int)hr); - m_pImp->vt->Release((IUnknown*)m_pImp); - return; - } - m_pImp->vt->NotifyAllocator(m_pImp, m_pAll, 0); - m_iState = 2; -} -void DS_Filter::Stop() -{ - if (m_iState == 2) + if (This->m_iState != 1) { - m_pAll->vt->Release((IUnknown*)m_pAll); - if (m_pFilter) - m_pFilter->vt->Stop(m_pFilter); // causes weird crash ??? FIXME - else - printf("m_pFilter is NULL!\n"); - m_pAll = 0; - m_iState = 1; + DS_Filter_Destroy(This); + This = 0; } + return This; } diff --git a/loader/dshow/DS_Filter.h b/loader/dshow/DS_Filter.h index 2f10849e2b..fd8166b11c 100644 --- a/loader/dshow/DS_Filter.h +++ b/loader/dshow/DS_Filter.h @@ -1,41 +1,46 @@ #ifndef DS_FILTER_H #define DS_FILTER_H -#include "interfaces.h" #include "inputpin.h" #include "outputpin.h" +#if defined(__cplusplus) +extern "C" { +#endif + /** User will allocate and fill format structures, call Create(), and then set up m_pAll. **/ -struct DS_Filter +typedef struct _DS_Filter DS_Filter; +struct _DS_Filter { - DS_Filter(); - virtual ~DS_Filter(); - 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; - void Create(const char* dllname, const GUID* id, AM_MEDIA_TYPE* in_fmt, AM_MEDIA_TYPE* out_fmt); - void SetPointer(char* pointer); - - void destroy(); + void ( *Start )(DS_Filter*); + void ( *Stop )(DS_Filter*); }; +DS_Filter* DS_FilterCreate(const char* dllname, const GUID* id, + AM_MEDIA_TYPE* in_fmt, AM_MEDIA_TYPE* out_fmt); +void DS_Filter_Destroy(DS_Filter* This); + +#if defined(__cplusplus) +} +#endif + #endif /* DS_FILTER_H */ diff --git a/loader/dshow/allocator.c b/loader/dshow/allocator.c index ce30e615d2..6b960c570e 100644 --- a/loader/dshow/allocator.c +++ b/loader/dshow/allocator.c @@ -3,62 +3,136 @@ #include "wine/winerror.h" #include <stdio.h> -//#undef Debug -//#define Debug +static int AllocatorKeeper = 0; -using namespace std; +static inline int avm_list_size(avm_list_t* head) +{ + avm_list_t* it = head; + int i = 0; + if (it) + { + for (;;) + { + i++; + it = it->next; + if (it == head) + break; + } + } + return i; +} -class AllocatorKeeper +static inline int avm_list_print(avm_list_t* head) { -public: - AllocatorKeeper() + avm_list_t* it = head; + int i = 0; + printf("Head: %p\n", head); + if (it) { - RegisterComClass(&CLSID_MemoryAllocator, MemAllocator::CreateAllocator); + for (;;) + { + i++; + printf("%d: member: %p next: %p prev: %p\n", + i, it->member, it->next, it->prev); + it = it->next; + if (it == head) + break; + } } - ~AllocatorKeeper() + return i; +} + +static inline avm_list_t* avm_list_add_head(avm_list_t* head, void* member) +{ + avm_list_t* n = (avm_list_t*) malloc(sizeof(avm_list_t)); + n->member = member; + + if (!head) { - UnregisterComClass(&CLSID_MemoryAllocator, MemAllocator::CreateAllocator); + head = n; + head->prev = head; } -}; -static AllocatorKeeper keeper; + n->prev = head->prev; + head->prev = n; + n->next = head; -GUID MemAllocator::interfaces[]= + return n; +} + +static inline avm_list_t* avm_list_add_tail(avm_list_t* head, void* member) { - IID_IUnknown, - IID_IMemAllocator, -}; + avm_list_t* n = avm_list_add_head(head, member); + return (!head) ? n : head; +} -IMPLEMENT_IUNKNOWN(MemAllocator) +static inline avm_list_t* avm_list_del_head(avm_list_t* head) +{ + avm_list_t* n = 0; + if (head) + { + if (head->next != head) + { + n = head->next; + head->prev->next = head->next; + head->next->prev = head->prev; + } + + free(head); + } + + return n; +} + +static inline avm_list_t* avm_list_find(avm_list_t* head, void* member) +{ + avm_list_t* it = head; + if (it) + { + for (;;) + { + if (it->member == member) + return it; + it = it->next; + if (it == head) + break; + } + } + return NULL; +} -long MemAllocator::CreateAllocator(GUID* clsid, GUID* iid, void** ppv) +static long MemAllocator_CreateAllocator(GUID* clsid, GUID* iid, void** ppv) { - if(!ppv)return -1; - *ppv=0; - if(memcmp(clsid, &CLSID_MemoryAllocator, sizeof(GUID))) + IMemAllocator* p; + int result; + 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 = (IMemAllocator*) MemAllocatorCreate(); + result = p->vt->QueryInterface((IUnknown*)p, iid, ppv); p->vt->Release((IUnknown*)p); + return result; } - static HRESULT STDCALL MemAllocator_SetProperties(IMemAllocator * This, /* [in] */ ALLOCATOR_PROPERTIES *pRequest, /* [out] */ ALLOCATOR_PROPERTIES *pActual) { - Debug printf("MemAllocator_SetProperties() called\n"); + MemAllocator* me = (MemAllocator*)This; + Debug printf("MemAllocator_SetProperties(%p) called\n", This); if (!pRequest || !pActual) return E_INVALIDARG; if (pRequest->cBuffers<=0 || pRequest->cbBuffer<=0) return E_FAIL; - MemAllocator* me = (MemAllocator*)This; - if (me->used_list.size() || me->free_list.size()) + if (me->used_list != 0 || me->free_list != 0) return E_FAIL; me->props = *pRequest; *pActual = *pRequest; + return 0; } @@ -71,34 +145,56 @@ static HRESULT STDCALL MemAllocator_GetProperties(IMemAllocator * This, if (((MemAllocator*)This)->props.cbBuffer<0) return E_FAIL; *pProps=((MemAllocator*)This)->props; + return 0; } static HRESULT STDCALL MemAllocator_Commit(IMemAllocator * This) { + MemAllocator* me = (MemAllocator*)This; + int i; Debug printf("MemAllocator_Commit(%p) called\n", This); - MemAllocator* me=(MemAllocator*)This; if (((MemAllocator*)This)->props.cbBuffer < 0) return E_FAIL; - if (me->used_list.size() || me->free_list.size()) + if (me->used_list || me->free_list) return E_INVALIDARG; - for(int i = 0; i<me->props.cBuffers; i++) - me->free_list.push_back(new CMediaSample(me, me->props.cbBuffer)); + for (i = 0; i < me->props.cBuffers; i++) + { + CMediaSample* sample = CMediaSampleCreate((IMemAllocator*)me, + me->props.cbBuffer); + //printf("FREEEEEEEEEEEE ADDED %p\n", sample); + + me->free_list = avm_list_add_tail(me->free_list, sample); + //avm_list_print(me->free_list); + } + //printf("Added mem %p: lsz: %d %d size: %d\n", me, avm_list_size(me->free_list), me->props.cBuffers, me->props.cbBuffer); return 0; } static HRESULT STDCALL MemAllocator_Decommit(IMemAllocator * This) { - Debug printf("MemAllocator_Decommit(%p) called\n", This); 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(); + Debug printf("MemAllocator_Decommit(%p) called\n", This); + //printf("Deleted mem %p: %d %d\n", me, me->free_list.size(), me->used_list.size()); + while (me->used_list) + { + CMediaSample* sample = (CMediaSample*) me->used_list->member; + //printf("****************** Decommiting USED %p\n", sample); + //sample->vt->Release((IUnknown*)sample); + CMediaSample_Destroy((CMediaSample*)sample); + me->used_list = avm_list_del_head(me->used_list); + } + + while (me->free_list) + { + CMediaSample* sample = (CMediaSample*) me->free_list->member; + //printf("****************** Decommiting FREE %p\n", sample); + //sample->vt->Release((IUnknown*)sample); + CMediaSample_Destroy((CMediaSample*)sample); + me->free_list = avm_list_del_head(me->free_list); + } + return 0; } @@ -108,71 +204,121 @@ static HRESULT STDCALL MemAllocator_GetBuffer(IMemAllocator * This, /* [in] */ REFERENCE_TIME *pEndTime, /* [in] */ DWORD dwFlags) { - Debug printf("MemAllocator_GetBuffer(%p) called\n", This); MemAllocator* me = (MemAllocator*)This; - if (me->free_list.size() == 0) + CMediaSample* sample; + Debug printf("MemAllocator_GetBuffer(%p) called %d %d\n", This, + avm_list_size(me->used_list), avm_list_size(me->free_list)); + if (!me->free_list) { Debug printf("No samples available\n"); return E_FAIL;//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); + + sample = (CMediaSample*) me->free_list->member; + me->free_list = avm_list_del_head(me->free_list); + me->used_list = avm_list_add_tail(me->used_list, sample); + + //printf("MemAllocator getbuffer: %p %d %d\n", sample, avm_list_size(me->used_list), avm_list_size(me->free_list)); + + *ppBuffer = (IMediaSample*) sample; + sample->vt->AddRef((IUnknown*) sample); if (me->new_pointer) { - if(me->modified_sample) - me->modified_sample->ResetPointer(); - (*it)->SetPointer(me->new_pointer); - me->modified_sample=*it; + if (me->modified_sample) + me->modified_sample->ResetPointer(me->modified_sample); + sample->SetPointer(sample, me->new_pointer); + me->modified_sample = sample; me->new_pointer = 0; } - me->free_list.remove(*it); return 0; } -static HRESULT STDCALL MemAllocator_ReleaseBuffer(IMemAllocator * This, - /* [in] */ IMediaSample *pBuffer) +static HRESULT STDCALL MemAllocator_ReleaseBuffer(IMemAllocator* This, + /* [in] */ IMediaSample* pBuffer) { - Debug printf("MemAllocator_ReleaseBuffer(%p) 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) + Debug printf("MemAllocator_ReleaseBuffer(%p) called %d %d\n", This, + avm_list_size(me->used_list), avm_list_size(me->free_list)); + + for (;;) + { + avm_list_t* l = avm_list_find(me->used_list, pBuffer); + if (l) { - me->used_list.erase(it); - me->free_list.push_back((CMediaSample*)pBuffer); - return 0; + CMediaSample* sample = (CMediaSample*) l->member; + me->used_list = avm_list_del_head(me->used_list); + me->free_list = avm_list_add_head(me->free_list, sample); + //printf("****************** RELEASED OK %p %p\n", me->used_list, me->free_list); + + return 0; } - Debug printf("Releasing unknown buffer\n"); + else + break; + } + Debug printf("MemAllocator_ReleaseBuffer(%p) releasing unknown buffer!!!! %p\n", This, pBuffer); return E_FAIL; } -MemAllocator::MemAllocator() + +static void MemAllocator_SetPointer(MemAllocator* This, char* pointer) { - Debug printf("MemAllocator::MemAllocator() called\n"); - vt = new IMemAllocator_vt; - vt->QueryInterface = QueryInterface; - vt->AddRef = AddRef; - vt->Release = Release; - vt->SetProperties = MemAllocator_SetProperties; - vt->GetProperties = MemAllocator_GetProperties; - vt->Commit = MemAllocator_Commit; - vt->Decommit = MemAllocator_Decommit; - vt->GetBuffer = MemAllocator_GetBuffer; - vt->ReleaseBuffer = MemAllocator_ReleaseBuffer; + This->new_pointer = pointer; +} - refcount = 1; - props.cBuffers = 1; - props.cbBuffer = 65536; /* :/ */ - props.cbAlign = props.cbPrefix = 0; +static void MemAllocator_ResetPointer(MemAllocator* This) +{ + if (This->modified_sample) + { + This->modified_sample->ResetPointer(This->modified_sample); + This->modified_sample = 0; + } +} - new_pointer=0; - modified_sample=0; +void MemAllocator_Destroy(MemAllocator* This) +{ + Debug printf("MemAllocator_Destroy(%p) called (%d, %d)\n", This, This->refcount, AllocatorKeeper); + if (--AllocatorKeeper == 0) + UnregisterComClass(&CLSID_MemoryAllocator, MemAllocator_CreateAllocator); + free(This->vt); + free(This); } -MemAllocator::~MemAllocator() +IMPLEMENT_IUNKNOWN(MemAllocator) + +MemAllocator* MemAllocatorCreate() { - Debug printf("MemAllocator::~MemAllocator() called\n"); - delete vt; + MemAllocator* This = (MemAllocator*) malloc(sizeof(MemAllocator)); + Debug printf("MemAllocatorCreate() called -> %p\n", This); + + This->refcount = 1; + This->props.cBuffers = 1; + This->props.cbBuffer = 65536; /* :/ */ + This->props.cbAlign = This->props.cbPrefix = 0; + + This->vt = (IMemAllocator_vt*) malloc(sizeof(IMemAllocator_vt)); + This->vt->QueryInterface = MemAllocator_QueryInterface; + This->vt->AddRef = MemAllocator_AddRef; + This->vt->Release = MemAllocator_Release; + This->vt->SetProperties = MemAllocator_SetProperties; + This->vt->GetProperties = MemAllocator_GetProperties; + This->vt->Commit = MemAllocator_Commit; + This->vt->Decommit = MemAllocator_Decommit; + This->vt->GetBuffer = MemAllocator_GetBuffer; + This->vt->ReleaseBuffer = MemAllocator_ReleaseBuffer; + + This->SetPointer = MemAllocator_SetPointer; + This->ResetPointer = MemAllocator_ResetPointer; + + This->new_pointer = 0; + This->modified_sample = 0; + This->used_list = 0; + This->free_list = 0; + + This->interfaces[0]=IID_IUnknown; + This->interfaces[1]=IID_IMemAllocator; + + if (AllocatorKeeper++ == 0) + RegisterComClass(&CLSID_MemoryAllocator, MemAllocator_CreateAllocator); + + return This; } diff --git a/loader/dshow/allocator.h b/loader/dshow/allocator.h index 1e9d7d5556..f853001d37 100644 --- a/loader/dshow/allocator.h +++ b/loader/dshow/allocator.h @@ -3,33 +3,30 @@ #include "interfaces.h" #include "cmediasample.h" -#include "iunk.h" -#include <list> +typedef struct avm_list_t +{ + struct avm_list_t* next; + struct avm_list_t* prev; + void* member; +} avm_list_t; -struct MemAllocator: public IMemAllocator +typedef struct _MemAllocator MemAllocator; +struct _MemAllocator { + IMemAllocator_vt* vt; ALLOCATOR_PROPERTIES props; - std::list<CMediaSample*> used_list; - std::list<CMediaSample*> free_list; + avm_list_t* used_list; + avm_list_t* free_list; char* new_pointer; CMediaSample* modified_sample; - static GUID interfaces[]; - DECLARE_IUNKNOWN(MemAllocator) - - MemAllocator(); - ~MemAllocator(); - void SetPointer(char* pointer) { new_pointer=pointer; } - void ResetPointer() - { - if (modified_sample) - { - modified_sample->ResetPointer(); - modified_sample=0; - } - } + GUID interfaces[2]; + DECLARE_IUNKNOWN(); - static long CreateAllocator(GUID* clsid, GUID* iid, void** ppv); + void ( *SetPointer )(MemAllocator* This, char* pointer); + void ( *ResetPointer )(MemAllocator* This); }; +MemAllocator* MemAllocatorCreate(); + #endif /* DS_ALLOCATOR_H */ diff --git a/loader/dshow/cmediasample.c b/loader/dshow/cmediasample.c index 983ddbaeea..d927bb2264 100644 --- a/loader/dshow/cmediasample.c +++ b/loader/dshow/cmediasample.c @@ -3,23 +3,23 @@ #include <stdio.h> #include <string.h> -static long STDCALL CMediaSample_QueryInterface(IUnknown * This, +static long STDCALL CMediaSample_QueryInterface(IUnknown* This, /* [in] */ IID* iid, /* [iid_is][out] */ void **ppv) { - Debug printf("CMediaSample_QueryInterface() called\n"); + Debug printf("CMediaSample_QueryInterface(%p) called\n", This); if (!ppv) return E_INVALIDARG; - if (!memcmp(iid, &IID_IUnknown, 16)) + if (memcmp(iid, &IID_IUnknown, sizeof(*iid)) == 0) { - *ppv=(void*)This; - This->vt->AddRef(This); + *ppv = (void*)This; + ((IMediaSample*) This)->vt->AddRef(This); return 0; } - if (!memcmp(iid, &IID_IMediaSample, 16)) + if (memcmp(iid, &IID_IMediaSample, sizeof(*iid)) == 0) { - *ppv=(void*)This; - This->vt->AddRef(This); + *ppv = (void*)This; + ((IMediaSample*) This)->vt->AddRef(This); return 0; } return E_NOINTERFACE; @@ -27,26 +27,39 @@ static long STDCALL CMediaSample_QueryInterface(IUnknown * This, static long STDCALL CMediaSample_AddRef(IUnknown* This) { - Debug printf("CMediaSample_AddRef() called\n"); + Debug printf("CMediaSample_AddRef(%p) called\n", This); ((CMediaSample*)This)->refcount++; return 0; } +void CMediaSample_Destroy(CMediaSample* This) +{ + + Debug printf("CMediaSample_Destroy(%p) called (ref:%d)\n", This, This->refcount); + free(This->vt); + free(This->own_block); + if (This->media_type.pbFormat) + CoTaskMemFree(This->media_type.pbFormat); + free(This); +} + static long STDCALL CMediaSample_Release(IUnknown* This) { - Debug printf("%p: CMediaSample_Release() called, new refcount %d\n", - This, ((CMediaSample*)This)->refcount-1); CMediaSample* parent=(CMediaSample*)This; - if (--((CMediaSample*)This)->refcount==0) + Debug printf("CMediaSample_Release(%p) called (new ref:%d)\n", + This, ((CMediaSample*)This)->refcount-1); + if (--((CMediaSample*)This)->refcount == 0) + { < |