cleanup: Silence compilation warnings on MinGW-w64
[mplayer.git] / loader / dshow / allocator.c
blob744debf96845e65c2e900f084e970c126ee2c66f
1 /*
2 * Modified for use with MPlayer, detailed changelog at
3 * http://svn.mplayerhq.hu/mplayer/trunk/
4 */
6 #include "config.h"
7 #include "allocator.h"
8 #include "loader/com.h"
9 #include "loader/wine/winerror.h"
10 #include <stdio.h>
11 #include <stdlib.h>
13 static int AllocatorKeeper = 0;
15 struct avm_list_t
17 struct avm_list_t* next;
18 struct avm_list_t* prev;
19 void* member;
22 static inline int avm_list_size(avm_list_t* head)
24 avm_list_t* it = head;
25 int i = 0;
26 if (it)
28 for (;;)
30 i++;
31 it = it->next;
32 if (it == head)
33 break;
36 return i;
39 static inline int avm_list_print(avm_list_t* head)
41 avm_list_t* it = head;
42 int i = 0;
43 printf("Head: %p\n", head);
44 if (it)
46 for (;;)
48 i++;
49 printf("%d: member: %p next: %p prev: %p\n",
50 i, it->member, it->next, it->prev);
51 it = it->next;
52 if (it == head)
53 break;
56 return i;
59 static inline avm_list_t* avm_list_add_head(avm_list_t* head, void* member)
61 avm_list_t* n = malloc(sizeof(avm_list_t));
62 n->member = member;
64 if (!head)
66 head = n;
67 head->prev = head;
70 n->prev = head->prev;
71 head->prev = n;
72 n->next = head;
74 return n;
77 static inline avm_list_t* avm_list_add_tail(avm_list_t* head, void* member)
79 avm_list_t* n = avm_list_add_head(head, member);
80 return (!head) ? n : head;
83 static inline avm_list_t* avm_list_del_head(avm_list_t* head)
85 avm_list_t* n = 0;
87 if (head)
89 if (head->next != head)
91 n = head->next;
92 head->prev->next = head->next;
93 head->next->prev = head->prev;
95 free(head);
97 return n;
100 static inline avm_list_t* avm_list_find(avm_list_t* head, void* member)
102 avm_list_t* it = head;
103 if (it)
105 for (;;)
107 if (it->member == member)
108 return it;
109 it = it->next;
110 if (it == head)
111 break;
114 return NULL;
117 #ifdef WIN32_LOADER
118 static long MemAllocator_CreateAllocator(GUID* clsid, const GUID* iid, void** ppv)
120 IUnknown* p;
121 int result;
122 if (!ppv)
123 return -1;
124 *ppv = 0;
125 if (memcmp(clsid, &CLSID_MemoryAllocator, sizeof(GUID)))
126 return -1;
128 p = (IUnknown*) MemAllocatorCreate();
129 result = p->vt->QueryInterface(p, iid, ppv);
130 p->vt->Release(p);
132 return result;
134 #endif
136 static HRESULT STDCALL MemAllocator_SetProperties(IMemAllocator * This,
137 /* [in] */ ALLOCATOR_PROPERTIES *pRequest,
138 /* [out] */ ALLOCATOR_PROPERTIES *pActual)
140 MemAllocator* me = (MemAllocator*)This;
141 Debug printf("MemAllocator_SetProperties(%p) called\n", This);
142 if (!pRequest || !pActual)
143 return E_INVALIDARG;
144 if (pRequest->cBuffers<=0 || pRequest->cbBuffer<=0)
145 return E_FAIL;
146 if (me->used_list != 0 || me->free_list != 0)
147 return E_FAIL;
149 *pActual = *pRequest;
151 DirectShow DOCS ("Negotiating Allocators" chapter) says that allocator might not
152 honor the requested properties. Thus, since WMSP audio codecs requests bufer with two
153 bytes length for unknown reason, we should correct requested value. Otherwise above
154 codec don't want to load.
156 if (pActual->cbBuffer == 2)
157 pActual->cbBuffer = 10240; //Enough for WMSP codec
159 me->props = *pActual;
161 return 0;
164 static HRESULT STDCALL MemAllocator_GetProperties(IMemAllocator * This,
165 /* [out] */ ALLOCATOR_PROPERTIES *pProps)
167 Debug printf("MemAllocator_GetProperties(%p) called\n", This);
168 if (!pProps)
169 return E_INVALIDARG;
170 if (((MemAllocator*)This)->props.cbBuffer<0)
171 return E_FAIL;
172 *pProps=((MemAllocator*)This)->props;
174 return 0;
177 static HRESULT STDCALL MemAllocator_Commit(IMemAllocator * This)
179 MemAllocator* me = (MemAllocator*)This;
180 int i;
181 Debug printf("MemAllocator_Commit(%p) called\n", This);
182 if (((MemAllocator*)This)->props.cbBuffer < 0)
183 return E_FAIL;
184 if (me->used_list || me->free_list)
185 return E_INVALIDARG;
186 for (i = 0; i < me->props.cBuffers; i++)
188 CMediaSample* sample = CMediaSampleCreate((IMemAllocator*)me,
189 me->props.cbBuffer);
190 if (!sample)
191 return E_OUTOFMEMORY;
192 //printf("FREEEEEEEEEEEE ADDED %p\n", sample);
193 me->free_list = avm_list_add_tail(me->free_list, sample);
194 //avm_list_print(me->free_list);
197 //printf("Added mem %p: lsz: %d %d size: %d\n", me, avm_list_size(me->free_list), me->props.cBuffers, me->props.cbBuffer);
198 return 0;
201 static HRESULT STDCALL MemAllocator_Decommit(IMemAllocator * This)
203 MemAllocator* me=(MemAllocator*)This;
204 Debug printf("MemAllocator_Decommit(%p) called\n", This);
205 //printf("Deleted mem %p: %d %d\n", me, me->free_list.size(), me->used_list.size());
206 while (me->used_list)
208 me->free_list = avm_list_add_tail(me->free_list,
209 (CMediaSample*) me->used_list->member);
210 me->used_list = avm_list_del_head(me->used_list);
213 while (me->free_list)
215 CMediaSample* sample = (CMediaSample*) me->free_list->member;
216 //printf("****************** Decommiting FREE %p\n", sample);
217 //sample->vt->Release((IUnknown*)sample);
218 CMediaSample_Destroy((CMediaSample*)sample);
219 me->free_list = avm_list_del_head(me->free_list);
222 return 0;
225 static HRESULT STDCALL MemAllocator_GetBuffer(IMemAllocator * This,
226 /* [out] */ IMediaSample **ppBuffer,
227 /* [in] */ REFERENCE_TIME *pStartTime,
228 /* [in] */ REFERENCE_TIME *pEndTime,
229 /* [in] */ DWORD dwFlags)
231 MemAllocator* me = (MemAllocator*)This;
232 CMediaSample* sample;
233 Debug printf("MemAllocator_ReleaseBuffer(%p) called %d %d\n", This,
234 avm_list_size(me->used_list), avm_list_size(me->free_list));
236 if (!me->free_list)
238 Debug printf("No samples available\n");
239 return E_FAIL;//should block here if no samples are available
242 sample = (CMediaSample*) me->free_list->member;
243 me->free_list = avm_list_del_head(me->free_list);
244 me->used_list = avm_list_add_tail(me->used_list, sample);
246 *ppBuffer = (IMediaSample*) sample;
247 sample->vt->AddRef((IUnknown*) sample);
248 if (me->new_pointer)
250 if (me->modified_sample)
251 me->modified_sample->ResetPointer(me->modified_sample);
252 sample->SetPointer(sample, me->new_pointer);
253 me->modified_sample = sample;
254 me->new_pointer = 0;
256 return 0;
259 static HRESULT STDCALL MemAllocator_ReleaseBuffer(IMemAllocator* This,
260 /* [in] */ IMediaSample* pBuffer)
262 avm_list_t* l;
263 MemAllocator* me = (MemAllocator*)This;
264 Debug printf("MemAllocator_ReleaseBuffer(%p) called %d %d\n", This,
265 avm_list_size(me->used_list), avm_list_size(me->free_list));
267 l = avm_list_find(me->used_list, pBuffer);
268 if (l)
270 CMediaSample* sample = (CMediaSample*) l->member;
271 if (me->modified_sample == sample)
273 me->modified_sample->ResetPointer(me->modified_sample);
274 me->modified_sample = 0;
276 me->used_list = avm_list_del_head(me->used_list);
277 me->free_list = avm_list_add_head(me->free_list, sample);
278 //printf("****************** RELEASED OK %p %p\n", me->used_list, me->free_list);
279 return 0;
281 Debug printf("MemAllocator_ReleaseBuffer(%p) releasing unknown buffer!!!! %p\n", This, pBuffer);
282 return E_FAIL;
286 static void MemAllocator_SetPointer(MemAllocator* This, char* pointer)
288 This->new_pointer = pointer;
291 static void MemAllocator_ResetPointer(MemAllocator* This)
293 if (This->modified_sample)
295 This->modified_sample->ResetPointer(This->modified_sample);
296 This->modified_sample = 0;
300 static void MemAllocator_Destroy(MemAllocator* This)
302 Debug printf("MemAllocator_Destroy(%p) called (%d, %d)\n", This, This->refcount, AllocatorKeeper);
303 #ifdef WIN32_LOADER
304 if (--AllocatorKeeper == 0)
305 UnregisterComClass(&CLSID_MemoryAllocator, MemAllocator_CreateAllocator);
306 #endif
307 free(This->vt);
308 free(This);
311 IMPLEMENT_IUNKNOWN(MemAllocator)
313 MemAllocator* MemAllocatorCreate()
315 MemAllocator* This = malloc(sizeof(MemAllocator));
317 if (!This)
318 return NULL;
320 Debug printf("MemAllocatorCreate() called -> %p\n", This);
322 This->refcount = 1;
323 This->props.cBuffers = 1;
324 This->props.cbBuffer = 65536; /* :/ */
325 This->props.cbAlign = 1;
326 This->props.cbPrefix = 0;
328 This->vt = malloc(sizeof(IMemAllocator_vt));
330 if (!This->vt)
332 free(This);
333 return NULL;
336 This->vt->QueryInterface = MemAllocator_QueryInterface;
337 This->vt->AddRef = MemAllocator_AddRef;
338 This->vt->Release = MemAllocator_Release;
339 This->vt->SetProperties = MemAllocator_SetProperties;
340 This->vt->GetProperties = MemAllocator_GetProperties;
341 This->vt->Commit = MemAllocator_Commit;
342 This->vt->Decommit = MemAllocator_Decommit;
343 This->vt->GetBuffer = MemAllocator_GetBuffer;
344 This->vt->ReleaseBuffer = MemAllocator_ReleaseBuffer;
346 This->SetPointer = MemAllocator_SetPointer;
347 This->ResetPointer = MemAllocator_ResetPointer;
349 This->modified_sample = 0;
350 This->new_pointer = 0;
351 This->used_list = 0;
352 This->free_list = 0;
354 This->interfaces[0]=IID_IUnknown;
355 This->interfaces[1]=IID_IMemAllocator;
357 #ifdef WIN32_LOADER
358 if (AllocatorKeeper++ == 0)
359 RegisterComClass(&CLSID_MemoryAllocator, MemAllocator_CreateAllocator);
360 #endif
362 return This;