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
)
117 static long MemAllocator_CreateAllocator(GUID
* clsid
, const GUID
* iid
, void** ppv
)
124 if (memcmp(clsid
, &CLSID_MemoryAllocator
, sizeof(GUID
)))
127 p
= (IUnknown
*) MemAllocatorCreate();
128 result
= p
->vt
->QueryInterface(p
, iid
, ppv
);
134 static HRESULT STDCALL
MemAllocator_SetProperties(IMemAllocator
* This
,
135 /* [in] */ ALLOCATOR_PROPERTIES
*pRequest
,
136 /* [out] */ ALLOCATOR_PROPERTIES
*pActual
)
138 MemAllocator
* me
= (MemAllocator
*)This
;
139 Debug
printf("MemAllocator_SetProperties(%p) called\n", This
);
140 if (!pRequest
|| !pActual
)
142 if (pRequest
->cBuffers
<=0 || pRequest
->cbBuffer
<=0)
144 if (me
->used_list
!= 0 || me
->free_list
!= 0)
147 *pActual
= *pRequest
;
149 DirectShow DOCS ("Negotiating Allocators" chapter) says that allocator might not
150 honor the requested properties. Thus, since WMSP audio codecs requests bufer with two
151 bytes length for unknown reason, we should correct requested value. Otherwise above
152 codec don't want to load.
154 if (pActual
->cbBuffer
== 2)
155 pActual
->cbBuffer
= 10240; //Enough for WMSP codec
157 me
->props
= *pActual
;
162 static HRESULT STDCALL
MemAllocator_GetProperties(IMemAllocator
* This
,
163 /* [out] */ ALLOCATOR_PROPERTIES
*pProps
)
165 Debug
printf("MemAllocator_GetProperties(%p) called\n", This
);
168 if (((MemAllocator
*)This
)->props
.cbBuffer
<0)
170 *pProps
=((MemAllocator
*)This
)->props
;
175 static HRESULT STDCALL
MemAllocator_Commit(IMemAllocator
* This
)
177 MemAllocator
* me
= (MemAllocator
*)This
;
179 Debug
printf("MemAllocator_Commit(%p) called\n", This
);
180 if (((MemAllocator
*)This
)->props
.cbBuffer
< 0)
182 if (me
->used_list
|| me
->free_list
)
184 for (i
= 0; i
< me
->props
.cBuffers
; i
++)
186 CMediaSample
* sample
= CMediaSampleCreate((IMemAllocator
*)me
,
189 return E_OUTOFMEMORY
;
190 //printf("FREEEEEEEEEEEE ADDED %p\n", sample);
191 me
->free_list
= avm_list_add_tail(me
->free_list
, sample
);
192 //avm_list_print(me->free_list);
195 //printf("Added mem %p: lsz: %d %d size: %d\n", me, avm_list_size(me->free_list), me->props.cBuffers, me->props.cbBuffer);
199 static HRESULT STDCALL
MemAllocator_Decommit(IMemAllocator
* This
)
201 MemAllocator
* me
=(MemAllocator
*)This
;
202 Debug
printf("MemAllocator_Decommit(%p) called\n", This
);
203 //printf("Deleted mem %p: %d %d\n", me, me->free_list.size(), me->used_list.size());
204 while (me
->used_list
)
206 me
->free_list
= avm_list_add_tail(me
->free_list
,
207 (CMediaSample
*) me
->used_list
->member
);
208 me
->used_list
= avm_list_del_head(me
->used_list
);
211 while (me
->free_list
)
213 CMediaSample
* sample
= (CMediaSample
*) me
->free_list
->member
;
214 //printf("****************** Decommiting FREE %p\n", sample);
215 //sample->vt->Release((IUnknown*)sample);
216 CMediaSample_Destroy((CMediaSample
*)sample
);
217 me
->free_list
= avm_list_del_head(me
->free_list
);
223 static HRESULT STDCALL
MemAllocator_GetBuffer(IMemAllocator
* This
,
224 /* [out] */ IMediaSample
**ppBuffer
,
225 /* [in] */ REFERENCE_TIME
*pStartTime
,
226 /* [in] */ REFERENCE_TIME
*pEndTime
,
227 /* [in] */ DWORD dwFlags
)
229 MemAllocator
* me
= (MemAllocator
*)This
;
230 CMediaSample
* sample
;
231 Debug
printf("MemAllocator_ReleaseBuffer(%p) called %d %d\n", This
,
232 avm_list_size(me
->used_list
), avm_list_size(me
->free_list
));
236 Debug
printf("No samples available\n");
237 return E_FAIL
;//should block here if no samples are available
240 sample
= (CMediaSample
*) me
->free_list
->member
;
241 me
->free_list
= avm_list_del_head(me
->free_list
);
242 me
->used_list
= avm_list_add_tail(me
->used_list
, sample
);
244 *ppBuffer
= (IMediaSample
*) sample
;
245 sample
->vt
->AddRef((IUnknown
*) sample
);
248 if (me
->modified_sample
)
249 me
->modified_sample
->ResetPointer(me
->modified_sample
);
250 sample
->SetPointer(sample
, me
->new_pointer
);
251 me
->modified_sample
= sample
;
257 static HRESULT STDCALL
MemAllocator_ReleaseBuffer(IMemAllocator
* This
,
258 /* [in] */ IMediaSample
* pBuffer
)
261 MemAllocator
* me
= (MemAllocator
*)This
;
262 Debug
printf("MemAllocator_ReleaseBuffer(%p) called %d %d\n", This
,
263 avm_list_size(me
->used_list
), avm_list_size(me
->free_list
));
265 l
= avm_list_find(me
->used_list
, pBuffer
);
268 CMediaSample
* sample
= (CMediaSample
*) l
->member
;
269 if (me
->modified_sample
== sample
)
271 me
->modified_sample
->ResetPointer(me
->modified_sample
);
272 me
->modified_sample
= 0;
274 me
->used_list
= avm_list_del_head(me
->used_list
);
275 me
->free_list
= avm_list_add_head(me
->free_list
, sample
);
276 //printf("****************** RELEASED OK %p %p\n", me->used_list, me->free_list);
279 Debug
printf("MemAllocator_ReleaseBuffer(%p) releasing unknown buffer!!!! %p\n", This
, pBuffer
);
284 static void MemAllocator_SetPointer(MemAllocator
* This
, char* pointer
)
286 This
->new_pointer
= pointer
;
289 static void MemAllocator_ResetPointer(MemAllocator
* This
)
291 if (This
->modified_sample
)
293 This
->modified_sample
->ResetPointer(This
->modified_sample
);
294 This
->modified_sample
= 0;
298 static void MemAllocator_Destroy(MemAllocator
* This
)
300 Debug
printf("MemAllocator_Destroy(%p) called (%d, %d)\n", This
, This
->refcount
, AllocatorKeeper
);
302 if (--AllocatorKeeper
== 0)
303 UnregisterComClass(&CLSID_MemoryAllocator
, MemAllocator_CreateAllocator
);
309 IMPLEMENT_IUNKNOWN(MemAllocator
)
311 MemAllocator
* MemAllocatorCreate()
313 MemAllocator
* This
= malloc(sizeof(MemAllocator
));
318 Debug
printf("MemAllocatorCreate() called -> %p\n", This
);
321 This
->props
.cBuffers
= 1;
322 This
->props
.cbBuffer
= 65536; /* :/ */
323 This
->props
.cbAlign
= 1;
324 This
->props
.cbPrefix
= 0;
326 This
->vt
= malloc(sizeof(IMemAllocator_vt
));
334 This
->vt
->QueryInterface
= MemAllocator_QueryInterface
;
335 This
->vt
->AddRef
= MemAllocator_AddRef
;
336 This
->vt
->Release
= MemAllocator_Release
;
337 This
->vt
->SetProperties
= MemAllocator_SetProperties
;
338 This
->vt
->GetProperties
= MemAllocator_GetProperties
;
339 This
->vt
->Commit
= MemAllocator_Commit
;
340 This
->vt
->Decommit
= MemAllocator_Decommit
;
341 This
->vt
->GetBuffer
= MemAllocator_GetBuffer
;
342 This
->vt
->ReleaseBuffer
= MemAllocator_ReleaseBuffer
;
344 This
->SetPointer
= MemAllocator_SetPointer
;
345 This
->ResetPointer
= MemAllocator_ResetPointer
;
347 This
->modified_sample
= 0;
348 This
->new_pointer
= 0;
352 This
->interfaces
[0]=IID_IUnknown
;
353 This
->interfaces
[1]=IID_IMemAllocator
;
356 if (AllocatorKeeper
++ == 0)
357 RegisterComClass(&CLSID_MemoryAllocator
, MemAllocator_CreateAllocator
);