source: trunk/src/quartz/memalloc.c@ 6952

Last change on this file since 6952 was 6952, checked in by sandervl, 24 years ago

Wine 20011004 resync

File size: 8.4 KB
Line 
1/*
2 * Implementation of CLSID_MemoryAllocator.
3 *
4 * hidenori@a2.ctktv.ne.jp
5 */
6
7#include "config.h"
8
9#include "windef.h"
10#include "winbase.h"
11#include "wingdi.h"
12#include "winuser.h"
13#include "winerror.h"
14#include "wine/obj_base.h"
15#include "strmif.h"
16#include "uuids.h"
17
18#include "debugtools.h"
19DEFAULT_DEBUG_CHANNEL(quartz);
20
21#include "quartz_private.h"
22#include "memalloc.h"
23
24
25/***************************************************************************
26 *
27 * new/delete for CLSID_MemoryAllocator.
28 *
29 */
30
31/* can I use offsetof safely? - FIXME? */
32static QUARTZ_IFEntry IFEntries[] =
33{
34 { &IID_IMemAllocator, offsetof(CMemoryAllocator,memalloc)-offsetof(CMemoryAllocator,unk) },
35};
36
37static void QUARTZ_DestroyMemoryAllocator(IUnknown* punk)
38{
39 CMemoryAllocator_THIS(punk,unk);
40
41 CMemoryAllocator_UninitIMemAllocator( This );
42}
43
44HRESULT QUARTZ_CreateMemoryAllocator(IUnknown* punkOuter,void** ppobj)
45{
46 CMemoryAllocator* pma;
47 HRESULT hr;
48
49 TRACE("(%p,%p)\n",punkOuter,ppobj);
50
51 pma = (CMemoryAllocator*)QUARTZ_AllocObj( sizeof(CMemoryAllocator) );
52 if ( pma == NULL )
53 return E_OUTOFMEMORY;
54
55 QUARTZ_IUnkInit( &pma->unk, punkOuter );
56 hr = CMemoryAllocator_InitIMemAllocator( pma );
57 if ( FAILED(hr) )
58 {
59 QUARTZ_FreeObj( pma );
60 return hr;
61 }
62
63 pma->unk.pEntries = IFEntries;
64 pma->unk.dwEntries = sizeof(IFEntries)/sizeof(IFEntries[0]);
65 pma->unk.pOnFinalRelease = QUARTZ_DestroyMemoryAllocator;
66
67 *ppobj = (void*)(&pma->unk);
68
69 return S_OK;
70}
71
72
73/***************************************************************************
74 *
75 * CMemoryAllocator::IMemAllocator
76 *
77 */
78
79
80static HRESULT WINAPI
81IMemAllocator_fnQueryInterface(IMemAllocator* iface,REFIID riid,void** ppobj)
82{
83 CMemoryAllocator_THIS(iface,memalloc);
84
85 TRACE("(%p)->()\n",This);
86
87 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
88}
89
90static ULONG WINAPI
91IMemAllocator_fnAddRef(IMemAllocator* iface)
92{
93 CMemoryAllocator_THIS(iface,memalloc);
94
95 TRACE("(%p)->()\n",This);
96
97 return IUnknown_AddRef(This->unk.punkControl);
98}
99
100static ULONG WINAPI
101IMemAllocator_fnRelease(IMemAllocator* iface)
102{
103 CMemoryAllocator_THIS(iface,memalloc);
104
105 TRACE("(%p)->()\n",This);
106
107 return IUnknown_Release(This->unk.punkControl);
108}
109
110static HRESULT WINAPI
111IMemAllocator_fnSetProperties(IMemAllocator* iface,ALLOCATOR_PROPERTIES* pPropReq,ALLOCATOR_PROPERTIES* pPropActual)
112{
113 CMemoryAllocator_THIS(iface,memalloc);
114 long padding;
115 HRESULT hr;
116
117 TRACE( "(%p)->(%p,%p)\n", This, pPropReq, pPropActual );
118
119 if ( pPropReq == NULL || pPropActual == NULL )
120 return E_POINTER;
121 if ( pPropReq->cBuffers < 0 ||
122 pPropReq->cbBuffer < 0 ||
123 pPropReq->cbAlign < 0 ||
124 pPropReq->cbPrefix < 0 )
125 return E_INVALIDARG;
126
127 if ( ( pPropReq->cbAlign & (pPropReq->cbAlign-1) ) != 0 )
128 return E_INVALIDARG;
129
130 hr = NOERROR;
131
132 EnterCriticalSection( &This->csMem );
133
134 if ( This->pData != NULL || This->ppSamples != NULL )
135 {
136 /* if commited, properties must not be changed. */
137 hr = E_UNEXPECTED;
138 goto end;
139 }
140
141 This->prop.cBuffers = pPropReq->cBuffers;
142 This->prop.cbBuffer = pPropReq->cbBuffer;
143 This->prop.cbAlign = pPropReq->cbAlign;
144 This->prop.cbPrefix = pPropReq->cbPrefix;
145
146 if ( This->prop.cbAlign == 0 )
147 This->prop.cbAlign = 1;
148 padding = This->prop.cbAlign -
149 ( (This->prop.cbBuffer+This->prop.cbPrefix) % This->prop.cbAlign );
150
151 This->prop.cbBuffer += padding;
152
153 memcpy( pPropActual, &This->prop, sizeof(ALLOCATOR_PROPERTIES) );
154
155end:
156 LeaveCriticalSection( &This->csMem );
157
158 return hr;
159}
160
161static HRESULT WINAPI
162IMemAllocator_fnGetProperties(IMemAllocator* iface,ALLOCATOR_PROPERTIES* pProp)
163{
164 CMemoryAllocator_THIS(iface,memalloc);
165
166 TRACE( "(%p)->(%p)\n", This, pProp );
167
168 if ( pProp == NULL )
169 return E_POINTER;
170
171 EnterCriticalSection( &This->csMem );
172
173 memcpy( pProp, &This->prop, sizeof(ALLOCATOR_PROPERTIES) );
174
175 LeaveCriticalSection( &This->csMem );
176
177 return NOERROR;
178}
179
180static HRESULT WINAPI
181IMemAllocator_fnCommit(IMemAllocator* iface)
182{
183 CMemoryAllocator_THIS(iface,memalloc);
184 HRESULT hr;
185 LONG lBufSize;
186 LONG i;
187 BYTE* pCur;
188
189 TRACE( "(%p)->()\n", This );
190
191 EnterCriticalSection( &This->csMem );
192
193 hr = NOERROR;
194 if ( This->pData != NULL || This->ppSamples != NULL ||
195 This->prop.cBuffers <= 0 )
196 goto end;
197
198 lBufSize = This->prop.cBuffers *
199 (This->prop.cbBuffer + This->prop.cbPrefix) +
200 This->prop.cbAlign;
201 if ( lBufSize <= 0 )
202 lBufSize = 1;
203
204 This->pData = (BYTE*)QUARTZ_AllocMem( lBufSize );
205 if ( This->pData == NULL )
206 {
207 hr = E_OUTOFMEMORY;
208 goto end;
209 }
210
211 This->ppSamples = (CMemMediaSample**)QUARTZ_AllocMem(
212 sizeof(CMemMediaSample*) * This->prop.cBuffers );
213 if ( This->ppSamples == NULL )
214 {
215 hr = E_OUTOFMEMORY;
216 goto end;
217 }
218
219 for ( i = 0; i < This->prop.cBuffers; i++ )
220 This->ppSamples[i] = NULL;
221
222 pCur = This->pData + This->prop.cbAlign - ((This->pData-(BYTE*)NULL) & (This->prop.cbAlign-1));
223
224 for ( i = 0; i < This->prop.cBuffers; i++ )
225 {
226 hr = QUARTZ_CreateMemMediaSample(
227 pCur, (This->prop.cbBuffer + This->prop.cbPrefix),
228 iface, &This->ppSamples[i] );
229 if ( FAILED(hr) )
230 goto end;
231 pCur += (This->prop.cbBuffer + This->prop.cbPrefix);
232 }
233
234 hr = NOERROR;
235end:
236 if ( FAILED(hr) )
237 IMemAllocator_Decommit(iface);
238
239 LeaveCriticalSection( &This->csMem );
240
241 return hr;
242}
243
244static HRESULT WINAPI
245IMemAllocator_fnDecommit(IMemAllocator* iface)
246{
247 CMemoryAllocator_THIS(iface,memalloc);
248 HRESULT hr;
249 LONG i;
250 BOOL bBlock;
251
252 TRACE( "(%p)->()\n", This );
253
254 EnterCriticalSection( &This->csMem );
255
256 hr = NOERROR;
257
258 if ( This->pData == NULL && This->ppSamples == NULL )
259 goto end;
260
261 while ( 1 )
262 {
263 bBlock = FALSE;
264 i = 0;
265
266 ResetEvent( This->hEventSample );
267
268 while ( 1 )
269 {
270 if ( i >= This->prop.cBuffers )
271 break;
272
273 if ( This->ppSamples[i] != NULL )
274 {
275 if ( This->ppSamples[i]->ref == 0 )
276 {
277 QUARTZ_DestroyMemMediaSample( This->ppSamples[i] );
278 This->ppSamples[i] = NULL;
279 }
280 else
281 {
282 bBlock = TRUE;
283 }
284 }
285 i++;
286 }
287
288 if ( !bBlock )
289 {
290 QUARTZ_FreeMem(This->ppSamples);
291 This->ppSamples = NULL;
292 QUARTZ_FreeMem(This->pData);
293 This->pData = NULL;
294 hr = NOERROR;
295 break;
296 }
297
298 WaitForSingleObject( This->hEventSample, INFINITE );
299 }
300
301end:
302 LeaveCriticalSection( &This->csMem );
303
304 return hr;
305}
306
307static HRESULT WINAPI
308IMemAllocator_fnGetBuffer(IMemAllocator* iface,IMediaSample** ppSample,REFERENCE_TIME* prtStart,REFERENCE_TIME* prtEnd,DWORD dwFlags)
309{
310 CMemoryAllocator_THIS(iface,memalloc);
311 LONG i;
312 HRESULT hr;
313
314 TRACE( "(%p)->(%p,%p,%p,%lu)\n", This, ppSample, prtStart, prtEnd, dwFlags );
315
316 if ( ppSample == NULL )
317 return E_POINTER;
318
319 EnterCriticalSection( &This->csMem );
320
321 hr = NOERROR;
322
323 if ( This->pData == NULL || This->ppSamples == NULL ||
324 This->prop.cBuffers <= 0 )
325 {
326 hr = E_FAIL; /* FIXME? */
327 goto end;
328 }
329
330 while ( 1 )
331 {
332 ResetEvent( This->hEventSample );
333
334 for ( i = 0; i < This->prop.cBuffers; i++ )
335 {
336 if ( This->ppSamples[i]->ref == 0 )
337 {
338 *ppSample = (IMediaSample*)(This->ppSamples[i]);
339 IMediaSample_AddRef( *ppSample );
340 hr = NOERROR;
341 goto end;
342 }
343 }
344
345 if ( dwFlags & AM_GBF_NOWAIT )
346 {
347 hr = E_FAIL; /* FIXME? */
348 goto end;
349 }
350
351 WaitForSingleObject( This->hEventSample, INFINITE );
352 }
353
354end:
355 LeaveCriticalSection( &This->csMem );
356
357 return hr;
358}
359
360static HRESULT WINAPI
361IMemAllocator_fnReleaseBuffer(IMemAllocator* iface,IMediaSample* pSample)
362{
363 CMemoryAllocator_THIS(iface,memalloc);
364
365 TRACE( "(%p)->(%p)\n", This, pSample );
366 SetEvent( This->hEventSample );
367
368 return NOERROR;
369}
370
371
372
373static ICOM_VTABLE(IMemAllocator) imemalloc =
374{
375 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
376 /* IUnknown fields */
377 IMemAllocator_fnQueryInterface,
378 IMemAllocator_fnAddRef,
379 IMemAllocator_fnRelease,
380 /* IMemAllocator fields */
381 IMemAllocator_fnSetProperties,
382 IMemAllocator_fnGetProperties,
383 IMemAllocator_fnCommit,
384 IMemAllocator_fnDecommit,
385 IMemAllocator_fnGetBuffer,
386 IMemAllocator_fnReleaseBuffer,
387};
388
389
390HRESULT CMemoryAllocator_InitIMemAllocator( CMemoryAllocator* pma )
391{
392 TRACE("(%p)\n",pma);
393
394 ICOM_VTBL(&pma->memalloc) = &imemalloc;
395
396 ZeroMemory( &pma->prop, sizeof(pma->prop) );
397 pma->hEventSample = (HANDLE)NULL;
398 pma->pData = NULL;
399 pma->ppSamples = NULL;
400
401 pma->hEventSample = CreateEventA( NULL, TRUE, FALSE, NULL );
402 if ( pma->hEventSample == (HANDLE)NULL )
403 return E_OUTOFMEMORY;
404
405 InitializeCriticalSection( &pma->csMem );
406
407 return NOERROR;
408}
409
410void CMemoryAllocator_UninitIMemAllocator( CMemoryAllocator* pma )
411{
412 TRACE("(%p)\n",pma);
413
414 IMemAllocator_Decommit( (IMemAllocator*)(&pma->memalloc) );
415
416 DeleteCriticalSection( &pma->csMem );
417
418 if ( pma->hEventSample != (HANDLE)NULL )
419 CloseHandle( pma->hEventSample );
420}
Note: See TracBrowser for help on using the repository browser.