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