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