2 * Modified for use with MPlayer, detailed changelog at
3 * http://svn.mplayerhq.hu/mplayer/trunk/
8 #include "loader/com.h"
9 #include "loader/wine/winerror.h"
13 static int AllocatorKeeper
= 0;
17 struct avm_list_t
* next
;
18 struct avm_list_t
* prev
;
22 static inline int avm_list_size(avm_list_t
* head
)
24 avm_list_t
* it
= head
;
39 static inline int avm_list_print(avm_list_t
* head
)
41 avm_list_t
* it
= head
;
43 printf("Head: %p\n", head
);
49 printf("%d: member: %p next: %p prev: %p\n",
50 i
, it
->member
, it
->next
, it
->prev
);
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
));
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
)
89 if (head
->next
!= head
)
92 head
->prev
->next
= head
->next
;
93 head
->next
->prev
= head
->prev
;
100 static inline avm_list_t
* avm_list_find(avm_list_t
* head
, void* member
)
102 avm_list_t
* it
= head
;
107 if (it
->member
== member
)
118 static long MemAllocator_CreateAllocator(GUID
* clsid
, const GUID
* iid
, void** ppv
)
125 if (memcmp(clsid
, &CLSID_MemoryAllocator
, sizeof(GUID
)))
128 p
= (IUnknown
*) MemAllocatorCreate();
129 result
= p
->vt
->QueryInterface(p
, iid
, ppv
);
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
)
144 if (pRequest
->cBuffers
<=0 || pRequest
->cbBuffer
<=0)
146 if (me
->used_list
!= 0 || me
->free_list
!= 0)
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
;
164 static HRESULT STDCALL
MemAllocator_GetProperties(IMemAllocator
* This
,
165 /* [out] */ ALLOCATOR_PROPERTIES
*pProps
)
167 Debug
printf("MemAllocator_GetProperties(%p) called\n", This
);
170 if (((MemAllocator
*)This
)->props
.cbBuffer
<0)
172 *pProps
=((MemAllocator
*)This
)->props
;
177 static HRESULT STDCALL
MemAllocator_Commit(IMemAllocator
* This
)
179 MemAllocator
* me
= (MemAllocator
*)This
;
181 Debug
printf("MemAllocator_Commit(%p) called\n", This
);
182 if (((MemAllocator
*)This
)->props
.cbBuffer
< 0)
184 if (me
->used_list
|| me
->free_list
)
186 for (i
= 0; i
< me
->props
.cBuffers
; i
++)
188 CMediaSample
* sample
= CMediaSampleCreate((IMemAllocator
*)me
,
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);
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
);
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
));
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
);
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
;
259 static HRESULT STDCALL
MemAllocator_ReleaseBuffer(IMemAllocator
* This
,
260 /* [in] */ IMediaSample
* pBuffer
)
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
);
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);
281 Debug
printf("MemAllocator_ReleaseBuffer(%p) releasing unknown buffer!!!! %p\n", This
, pBuffer
);
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
);
304 if (--AllocatorKeeper
== 0)
305 UnregisterComClass(&CLSID_MemoryAllocator
, MemAllocator_CreateAllocator
);
311 IMPLEMENT_IUNKNOWN(MemAllocator
)
313 MemAllocator
* MemAllocatorCreate()
315 MemAllocator
* This
= malloc(sizeof(MemAllocator
));
320 Debug
printf("MemAllocatorCreate() called -> %p\n", This
);
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
));
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;
354 This
->interfaces
[0]=IID_IUnknown
;
355 This
->interfaces
[1]=IID_IMemAllocator
;
358 if (AllocatorKeeper
++ == 0)
359 RegisterComClass(&CLSID_MemoryAllocator
, MemAllocator_CreateAllocator
);