1 #include "allocator.h"
2 #include "com.h"
3 #include "../wine/winerror.h"
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 static int AllocatorKeeper = 0;
8
9 struct _avm_list_t
10 {
11 struct _avm_list_t* next;
12 struct _avm_list_t* prev;
13 void* member;
14 };
15
avm_list_size(avm_list_t * head)16 static inline int avm_list_size(avm_list_t* head)
17 {
18 avm_list_t* it = head;
19 int i = 0;
20 if (it)
21 {
22 for (;;)
23 {
24 i++;
25 it = it->next;
26 if (it == head)
27 break;
28 }
29 }
30 return i;
31 }
32
avm_list_print(avm_list_t * head)33 static inline int avm_list_print(avm_list_t* head)
34 {
35 avm_list_t* it = head;
36 int i = 0;
37 printf("Head: %p\n", head);
38 if (it)
39 {
40 for (;;)
41 {
42 i++;
43 printf("%d: member: %p next: %p prev: %p\n",
44 i, it->member, it->next, it->prev);
45 it = it->next;
46 if (it == head)
47 break;
48 }
49 }
50 return i;
51 }
52
avm_list_add_head(avm_list_t * head,void * member)53 static inline avm_list_t* avm_list_add_head(avm_list_t* head, void* member)
54 {
55 avm_list_t* n = (avm_list_t*) malloc(sizeof(avm_list_t));
56 n->member = member;
57
58 if (!head)
59 {
60 head = n;
61 head->prev = head;
62 }
63
64 n->prev = head->prev;
65 head->prev = n;
66 n->next = head;
67
68 return n;
69 }
70
avm_list_add_tail(avm_list_t * head,void * member)71 static inline avm_list_t* avm_list_add_tail(avm_list_t* head, void* member)
72 {
73 avm_list_t* n = avm_list_add_head(head, member);
74 return (!head) ? n : head;
75 }
76
avm_list_del_head(avm_list_t * head)77 static inline avm_list_t* avm_list_del_head(avm_list_t* head)
78 {
79 avm_list_t* n = 0;
80
81 if (head)
82 {
83 if (head->next != head)
84 {
85 n = head->next;
86 head->prev->next = head->next;
87 head->next->prev = head->prev;
88 }
89 free(head);
90 }
91 return n;
92 }
93
avm_list_find(avm_list_t * head,void * member)94 static inline avm_list_t* avm_list_find(avm_list_t* head, void* member)
95 {
96 avm_list_t* it = head;
97 if (it)
98 {
99 for (;;)
100 {
101 if (it->member == member)
102 return it;
103 it = it->next;
104 if (it == head)
105 break;
106 }
107 }
108 return NULL;
109 }
110
MemAllocator_CreateAllocator(GUID * clsid,const GUID * iid,void ** ppv)111 static long MemAllocator_CreateAllocator(GUID* clsid, const GUID* iid, void** ppv)
112 {
113 IMemAllocator* p;
114 int result;
115 if (!ppv)
116 return -1;
117 *ppv = 0;
118 if (memcmp(clsid, &CLSID_MemoryAllocator, sizeof(GUID)))
119 return -1;
120
121 p = (IMemAllocator*) MemAllocatorCreate();
122 result = p->vt->QueryInterface((IUnknown*)p, iid, ppv);
123 p->vt->Release((IUnknown*)p);
124
125 return result;
126 }
127
MemAllocator_SetProperties(IMemAllocator * This,ALLOCATOR_PROPERTIES * pRequest,ALLOCATOR_PROPERTIES * pActual)128 static HRESULT STDCALL MemAllocator_SetProperties(IMemAllocator * This,
129 /* [in] */ ALLOCATOR_PROPERTIES *pRequest,
130 /* [out] */ ALLOCATOR_PROPERTIES *pActual)
131 {
132 MemAllocator* me = (MemAllocator*)This;
133 Debug printf("MemAllocator_SetProperties(%p) called\n", This);
134 if (!pRequest || !pActual)
135 return E_INVALIDARG;
136 if (pRequest->cBuffers<=0 || pRequest->cbBuffer<=0)
137 return E_FAIL;
138 if (me->used_list != 0 || me->free_list != 0)
139 return E_FAIL;
140
141 *pActual = *pRequest;
142 //if (pActual->cbBuffer == 2)
143 // pActual->cbBuffer = 576;
144
145 me->props = *pActual;
146
147 return 0;
148 }
149
MemAllocator_GetProperties(IMemAllocator * This,ALLOCATOR_PROPERTIES * pProps)150 static HRESULT STDCALL MemAllocator_GetProperties(IMemAllocator * This,
151 /* [out] */ ALLOCATOR_PROPERTIES *pProps)
152 {
153 Debug printf("MemAllocator_GetProperties(%p) called\n", This);
154 if (!pProps)
155 return E_INVALIDARG;
156 if (((MemAllocator*)This)->props.cbBuffer<0)
157 return E_FAIL;
158 *pProps=((MemAllocator*)This)->props;
159
160 return 0;
161 }
162
MemAllocator_Commit(IMemAllocator * This)163 static HRESULT STDCALL MemAllocator_Commit(IMemAllocator * This)
164 {
165 MemAllocator* me = (MemAllocator*)This;
166 int i;
167 Debug printf("MemAllocator_Commit(%p) called\n", This);
168 if (((MemAllocator*)This)->props.cbBuffer < 0)
169 return E_FAIL;
170 if (me->used_list || me->free_list)
171 return E_INVALIDARG;
172 for (i = 0; i < me->props.cBuffers; i++)
173 {
174 CMediaSample* sample = CMediaSampleCreate((IMemAllocator*)me,
175 me->props.cbBuffer);
176 if (!sample)
177 return E_OUTOFMEMORY;
178 //printf("FREEEEEEEEEEEE ADDED %p\n", sample);
179 me->free_list = avm_list_add_tail(me->free_list, sample);
180 //avm_list_print(me->free_list);
181 }
182
183 //printf("Added mem %p: lsz: %d %d size: %d\n", me, avm_list_size(me->free_list), me->props.cBuffers, me->props.cbBuffer);
184 return 0;
185 }
186
MemAllocator_Decommit(IMemAllocator * This)187 static HRESULT STDCALL MemAllocator_Decommit(IMemAllocator * This)
188 {
189 MemAllocator* me=(MemAllocator*)This;
190 Debug printf("MemAllocator_Decommit(%p) called\n", This);
191 //printf("Deleted mem %p: %d %d\n", me, me->free_list.size(), me->used_list.size());
192 while (me->used_list)
193 {
194 me->free_list = avm_list_add_tail(me->free_list,
195 (CMediaSample*) me->used_list->member);
196 me->used_list = avm_list_del_head(me->used_list);
197 }
198
199 while (me->free_list)
200 {
201 CMediaSample* sample = (CMediaSample*) me->free_list->member;
202 //printf("****************** Decommiting FREE %p\n", sample);
203 //sample->vt->Release((IUnknown*)sample);
204 CMediaSample_Destroy((CMediaSample*)sample);
205 me->free_list = avm_list_del_head(me->free_list);
206 }
207
208 return 0;
209 }
210
MemAllocator_GetBuffer(IMemAllocator * This,IMediaSample ** ppBuffer,REFERENCE_TIME * pStartTime,REFERENCE_TIME * pEndTime,DWORD dwFlags)211 static HRESULT STDCALL MemAllocator_GetBuffer(IMemAllocator * This,
212 /* [out] */ IMediaSample **ppBuffer,
213 /* [in] */ REFERENCE_TIME *pStartTime,
214 /* [in] */ REFERENCE_TIME *pEndTime,
215 /* [in] */ DWORD dwFlags)
216 {
217 MemAllocator* me = (MemAllocator*)This;
218 CMediaSample* sample;
219 (void)pStartTime;
220 (void)pEndTime;
221 (void)dwFlags;
222 Debug printf("MemAllocator_ReleaseBuffer(%p) called %d %d\n", This,
223 avm_list_size(me->used_list), avm_list_size(me->free_list));
224
225 if (!me->free_list)
226 {
227 Debug printf("No samples available\n");
228 return E_FAIL;//should block here if no samples are available
229 }
230
231 sample = (CMediaSample*) me->free_list->member;
232 me->free_list = avm_list_del_head(me->free_list);
233 me->used_list = avm_list_add_tail(me->used_list, sample);
234
235 *ppBuffer = (IMediaSample*) sample;
236 sample->vt->AddRef((IUnknown*) sample);
237 if (me->new_pointer)
238 {
239 if (me->modified_sample)
240 me->modified_sample->ResetPointer(me->modified_sample);
241 sample->SetPointer(sample, me->new_pointer);
242 me->modified_sample = sample;
243 me->new_pointer = 0;
244 }
245 return 0;
246 }
247
MemAllocator_ReleaseBuffer(IMemAllocator * This,IMediaSample * pBuffer)248 static HRESULT STDCALL MemAllocator_ReleaseBuffer(IMemAllocator* This,
249 /* [in] */ IMediaSample* pBuffer)
250 {
251 avm_list_t* l;
252 MemAllocator* me = (MemAllocator*)This;
253 Debug printf("MemAllocator_ReleaseBuffer(%p) called %d %d\n", This,
254 avm_list_size(me->used_list), avm_list_size(me->free_list));
255
256 l = avm_list_find(me->used_list, pBuffer);
257 if (l)
258 {
259 CMediaSample* sample = (CMediaSample*) l->member;
260 if (me->modified_sample == sample)
261 {
262 me->modified_sample->ResetPointer(me->modified_sample);
263 me->modified_sample = 0;
264 }
265 me->used_list = avm_list_del_head(me->used_list);
266 me->free_list = avm_list_add_head(me->free_list, sample);
267 //printf("****************** RELEASED OK %p %p\n", me->used_list, me->free_list);
268 return 0;
269 }
270 Debug printf("MemAllocator_ReleaseBuffer(%p) releasing unknown buffer!!!! %p\n", This, pBuffer);
271 return E_FAIL;
272 }
273
274
MemAllocator_SetPointer(MemAllocator * This,char * pointer)275 static void MemAllocator_SetPointer(MemAllocator* This, char* pointer)
276 {
277 This->new_pointer = pointer;
278 }
279
MemAllocator_ResetPointer(MemAllocator * This)280 static void MemAllocator_ResetPointer(MemAllocator* This)
281 {
282 if (This->modified_sample)
283 {
284 This->modified_sample->ResetPointer(This->modified_sample);
285 This->modified_sample = 0;
286 }
287 }
288
MemAllocator_Destroy(MemAllocator * This)289 static void MemAllocator_Destroy(MemAllocator* This)
290 {
291 Debug printf("MemAllocator_Destroy(%p) called (%d, %d)\n", This, This->refcount, AllocatorKeeper);
292 if (--AllocatorKeeper == 0)
293 UnregisterComClass(&CLSID_MemoryAllocator, MemAllocator_CreateAllocator);
294 free(This->vt);
295 free(This);
296 }
297
IMPLEMENT_IUNKNOWN(MemAllocator)298 IMPLEMENT_IUNKNOWN(MemAllocator)
299
300 MemAllocator* MemAllocatorCreate()
301 {
302 MemAllocator* This = (MemAllocator*) malloc(sizeof(MemAllocator));
303
304 if (!This)
305 return NULL;
306
307 Debug printf("MemAllocatorCreate() called -> %p\n", This);
308
309 This->refcount = 1;
310 This->props.cBuffers = 1;
311 This->props.cbBuffer = 65536; /* :/ */
312 This->props.cbAlign = This->props.cbPrefix = 0;
313
314 This->vt = (IMemAllocator_vt*) malloc(sizeof(IMemAllocator_vt));
315
316 if (!This->vt)
317 {
318 free(This);
319 return NULL;
320 }
321
322 This->vt->QueryInterface = MemAllocator_QueryInterface;
323 This->vt->AddRef = MemAllocator_AddRef;
324 This->vt->Release = MemAllocator_Release;
325 This->vt->SetProperties = MemAllocator_SetProperties;
326 This->vt->GetProperties = MemAllocator_GetProperties;
327 This->vt->Commit = MemAllocator_Commit;
328 This->vt->Decommit = MemAllocator_Decommit;
329 This->vt->GetBuffer = MemAllocator_GetBuffer;
330 This->vt->ReleaseBuffer = MemAllocator_ReleaseBuffer;
331
332 This->SetPointer = MemAllocator_SetPointer;
333 This->ResetPointer = MemAllocator_ResetPointer;
334
335 This->modified_sample = 0;
336 This->new_pointer = 0;
337 This->used_list = 0;
338 This->free_list = 0;
339
340 This->interfaces[0]=IID_IUnknown;
341 This->interfaces[1]=IID_IMemAllocator;
342
343 if (AllocatorKeeper++ == 0)
344 RegisterComClass(&CLSID_MemoryAllocator, MemAllocator_CreateAllocator);
345
346 return This;
347 }
348