168
|
1 #include "allocator.h"
|
2069
|
2 #include "com.h"
|
|
3 #include "wine/winerror.h"
|
1545
|
4 #include <stdio.h>
|
7386
|
5 #include <stdlib.h>
|
1545
|
6
|
3056
|
7 static int AllocatorKeeper = 0;
|
1545
|
8
|
7386
|
9 struct _avm_list_t
|
|
10 {
|
|
11 struct _avm_list_t* next;
|
|
12 struct _avm_list_t* prev;
|
|
13 void* member;
|
|
14 };
|
|
15
|
3056
|
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 }
|
713
|
32
|
3056
|
33 static inline int avm_list_print(avm_list_t* head)
|
168
|
34 {
|
3056
|
35 avm_list_t* it = head;
|
|
36 int i = 0;
|
|
37 printf("Head: %p\n", head);
|
|
38 if (it)
|
1545
|
39 {
|
3056
|
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 }
|
168
|
49 }
|
3056
|
50 return i;
|
|
51 }
|
|
52
|
|
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)
|
1545
|
59 {
|
3056
|
60 head = n;
|
|
61 head->prev = head;
|
1545
|
62 }
|
3056
|
63
|
|
64 n->prev = head->prev;
|
|
65 head->prev = n;
|
|
66 n->next = head;
|
|
67
|
|
68 return n;
|
|
69 }
|
1545
|
70
|
3056
|
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 }
|
1545
|
76
|
3056
|
77 static inline avm_list_t* avm_list_del_head(avm_list_t* head)
|
168
|
78 {
|
3056
|
79 avm_list_t* n = 0;
|
3467
|
80
|
3056
|
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 }
|
168
|
93
|
3056
|
94 static inline avm_list_t* avm_list_find(avm_list_t* head, void* member)
|
168
|
95 {
|
3056
|
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
|
7386
|
111 static long MemAllocator_CreateAllocator(GUID* clsid, const GUID* iid, void** ppv)
|
3056
|
112 {
|
|
113 IMemAllocator* p;
|
|
114 int result;
|
|
115 if (!ppv)
|
|
116 return -1;
|
|
117 *ppv = 0;
|
|
118 if (memcmp(clsid, &CLSID_MemoryAllocator, sizeof(GUID)))
|
168
|
119 return -1;
|
1545
|
120
|
3056
|
121 p = (IMemAllocator*) MemAllocatorCreate();
|
|
122 result = p->vt->QueryInterface((IUnknown*)p, iid, ppv);
|
168
|
123 p->vt->Release((IUnknown*)p);
|
3056
|
124
|
168
|
125 return result;
|
|
126 }
|
|
127
|
1545
|
128 static HRESULT STDCALL MemAllocator_SetProperties(IMemAllocator * This,
|
|
129 /* [in] */ ALLOCATOR_PROPERTIES *pRequest,
|
|
130 /* [out] */ ALLOCATOR_PROPERTIES *pActual)
|
168
|
131 {
|
3056
|
132 MemAllocator* me = (MemAllocator*)This;
|
|
133 Debug printf("MemAllocator_SetProperties(%p) called\n", This);
|
1545
|
134 if (!pRequest || !pActual)
|
|
135 return E_INVALIDARG;
|
|
136 if (pRequest->cBuffers<=0 || pRequest->cbBuffer<=0)
|
|
137 return E_FAIL;
|
3056
|
138 if (me->used_list != 0 || me->free_list != 0)
|
1545
|
139 return E_FAIL;
|
3467
|
140
|
1545
|
141 *pActual = *pRequest;
|
3467
|
142 //if (pActual->cbBuffer == 2)
|
|
143 // pActual->cbBuffer = 576;
|
|
144
|
|
145 me->props = *pActual;
|
3056
|
146
|
168
|
147 return 0;
|
|
148 }
|
|
149
|
1545
|
150 static HRESULT STDCALL MemAllocator_GetProperties(IMemAllocator * This,
|
|
151 /* [out] */ ALLOCATOR_PROPERTIES *pProps)
|
168
|
152 {
|
1545
|
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;
|
168
|
158 *pProps=((MemAllocator*)This)->props;
|
3056
|
159
|
168
|
160 return 0;
|
|
161 }
|
|
162
|
1545
|
163 static HRESULT STDCALL MemAllocator_Commit(IMemAllocator * This)
|
168
|
164 {
|
3056
|
165 MemAllocator* me = (MemAllocator*)This;
|
|
166 int i;
|
1545
|
167 Debug printf("MemAllocator_Commit(%p) called\n", This);
|
|
168 if (((MemAllocator*)This)->props.cbBuffer < 0)
|
|
169 return E_FAIL;
|
3056
|
170 if (me->used_list || me->free_list)
|
1545
|
171 return E_INVALIDARG;
|
3056
|
172 for (i = 0; i < me->props.cBuffers; i++)
|
|
173 {
|
|
174 CMediaSample* sample = CMediaSampleCreate((IMemAllocator*)me,
|
|
175 me->props.cbBuffer);
|
3467
|
176 if (!sample)
|
|
177 return E_OUTOFMEMORY;
|
3056
|
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);
|
168
|
184 return 0;
|
|
185 }
|
|
186
|
1545
|
187 static HRESULT STDCALL MemAllocator_Decommit(IMemAllocator * This)
|
168
|
188 {
|
3056
|
189 MemAllocator* me=(MemAllocator*)This;
|
1545
|
190 Debug printf("MemAllocator_Decommit(%p) called\n", This);
|
3056
|
191 //printf("Deleted mem %p: %d %d\n", me, me->free_list.size(), me->used_list.size());
|
|
192 while (me->used_list)
|
|
193 {
|
3467
|
194 me->free_list = avm_list_add_tail(me->free_list,
|
|
195 (CMediaSample*) me->used_list->member);
|
3056
|
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);
|
3467
|
205 me->free_list = avm_list_del_head(me->free_list);
|
3056
|
206 }
|
|
207
|
168
|
208 return 0;
|
|
209 }
|
|
210
|
1545
|
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)
|
168
|
216 {
|
1545
|
217 MemAllocator* me = (MemAllocator*)This;
|
3056
|
218 CMediaSample* sample;
|
3467
|
219 Debug printf("MemAllocator_ReleaseBuffer(%p) called %d %d\n", This,
|
3056
|
220 avm_list_size(me->used_list), avm_list_size(me->free_list));
|
3467
|
221
|
3056
|
222 if (!me->free_list)
|
168
|
223 {
|
|
224 Debug printf("No samples available\n");
|
1545
|
225 return E_FAIL;//should block here if no samples are available
|
|
226 }
|
3056
|
227
|
|
228 sample = (CMediaSample*) me->free_list->member;
|
|
229 me->free_list = avm_list_del_head(me->free_list);
|
|
230 me->used_list = avm_list_add_tail(me->used_list, sample);
|
|
231
|
|
232 *ppBuffer = (IMediaSample*) sample;
|
|
233 sample->vt->AddRef((IUnknown*) sample);
|
1545
|
234 if (me->new_pointer)
|
713
|
235 {
|
3056
|
236 if (me->modified_sample)
|
|
237 me->modified_sample->ResetPointer(me->modified_sample);
|
|
238 sample->SetPointer(sample, me->new_pointer);
|
|
239 me->modified_sample = sample;
|
1545
|
240 me->new_pointer = 0;
|
713
|
241 }
|
168
|
242 return 0;
|
|
243 }
|
|
244
|
3056
|
245 static HRESULT STDCALL MemAllocator_ReleaseBuffer(IMemAllocator* This,
|
|
246 /* [in] */ IMediaSample* pBuffer)
|
168
|
247 {
|
3467
|
248 avm_list_t* l;
|
1545
|
249 MemAllocator* me = (MemAllocator*)This;
|
3056
|
250 Debug printf("MemAllocator_ReleaseBuffer(%p) called %d %d\n", This,
|
|
251 avm_list_size(me->used_list), avm_list_size(me->free_list));
|
|
252
|
3467
|
253 l = avm_list_find(me->used_list, pBuffer);
|
|
254 if (l)
|
3056
|
255 {
|
3467
|
256 CMediaSample* sample = (CMediaSample*) l->member;
|
|
257 if (me->modified_sample == sample)
|
168
|
258 {
|
3467
|
259 me->modified_sample->ResetPointer(me->modified_sample);
|
|
260 me->modified_sample = 0;
|
168
|
261 }
|
3467
|
262 me->used_list = avm_list_del_head(me->used_list);
|
|
263 me->free_list = avm_list_add_head(me->free_list, sample);
|
|
264 //printf("****************** RELEASED OK %p %p\n", me->used_list, me->free_list);
|
|
265 return 0;
|
3056
|
266 }
|
|
267 Debug printf("MemAllocator_ReleaseBuffer(%p) releasing unknown buffer!!!! %p\n", This, pBuffer);
|
1545
|
268 return E_FAIL;
|
168
|
269 }
|
1545
|
270
|
3056
|
271
|
|
272 static void MemAllocator_SetPointer(MemAllocator* This, char* pointer)
|
|
273 {
|
|
274 This->new_pointer = pointer;
|
|
275 }
|
|
276
|
|
277 static void MemAllocator_ResetPointer(MemAllocator* This)
|
1545
|
278 {
|
3056
|
279 if (This->modified_sample)
|
|
280 {
|
|
281 This->modified_sample->ResetPointer(This->modified_sample);
|
|
282 This->modified_sample = 0;
|
|
283 }
|
|
284 }
|
1545
|
285
|
8292
|
286 static void MemAllocator_Destroy(MemAllocator* This)
|
3056
|
287 {
|
|
288 Debug printf("MemAllocator_Destroy(%p) called (%d, %d)\n", This, This->refcount, AllocatorKeeper);
|
|
289 if (--AllocatorKeeper == 0)
|
|
290 UnregisterComClass(&CLSID_MemoryAllocator, MemAllocator_CreateAllocator);
|
|
291 free(This->vt);
|
|
292 free(This);
|
1545
|
293 }
|
|
294
|
3056
|
295 IMPLEMENT_IUNKNOWN(MemAllocator)
|
|
296
|
|
297 MemAllocator* MemAllocatorCreate()
|
1545
|
298 {
|
3056
|
299 MemAllocator* This = (MemAllocator*) malloc(sizeof(MemAllocator));
|
3467
|
300
|
|
301 if (!This)
|
|
302 return NULL;
|
|
303
|
3056
|
304 Debug printf("MemAllocatorCreate() called -> %p\n", This);
|
|
305
|
|
306 This->refcount = 1;
|
|
307 This->props.cBuffers = 1;
|
|
308 This->props.cbBuffer = 65536; /* :/ */
|
|
309 This->props.cbAlign = This->props.cbPrefix = 0;
|
|
310
|
|
311 This->vt = (IMemAllocator_vt*) malloc(sizeof(IMemAllocator_vt));
|
3467
|
312
|
|
313 if (!This->vt)
|
|
314 {
|
|
315 free(This);
|
|
316 return NULL;
|
|
317 }
|
|
318
|
3056
|
319 This->vt->QueryInterface = MemAllocator_QueryInterface;
|
|
320 This->vt->AddRef = MemAllocator_AddRef;
|
|
321 This->vt->Release = MemAllocator_Release;
|
|
322 This->vt->SetProperties = MemAllocator_SetProperties;
|
|
323 This->vt->GetProperties = MemAllocator_GetProperties;
|
|
324 This->vt->Commit = MemAllocator_Commit;
|
|
325 This->vt->Decommit = MemAllocator_Decommit;
|
|
326 This->vt->GetBuffer = MemAllocator_GetBuffer;
|
|
327 This->vt->ReleaseBuffer = MemAllocator_ReleaseBuffer;
|
|
328
|
|
329 This->SetPointer = MemAllocator_SetPointer;
|
|
330 This->ResetPointer = MemAllocator_ResetPointer;
|
|
331
|
3467
|
332 This->modified_sample = 0;
|
3056
|
333 This->new_pointer = 0;
|
|
334 This->used_list = 0;
|
|
335 This->free_list = 0;
|
|
336
|
|
337 This->interfaces[0]=IID_IUnknown;
|
|
338 This->interfaces[1]=IID_IMemAllocator;
|
|
339
|
|
340 if (AllocatorKeeper++ == 0)
|
|
341 RegisterComClass(&CLSID_MemoryAllocator, MemAllocator_CreateAllocator);
|
|
342
|
|
343 return This;
|
1545
|
344 }
|