2 * Implementation of CLSID_MemoryAllocator.
4 * hidenori@a2.ctktv.ne.jp
18 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(quartz);
21 #include "quartz_private.h"
25 /***************************************************************************
27 * new/delete for CLSID_MemoryAllocator.
31 /* can I use offsetof safely? - FIXME? */
32 static QUARTZ_IFEntry IFEntries[] =
34 { &IID_IMemAllocator, offsetof(CMemoryAllocator,memalloc)-offsetof(CMemoryAllocator,unk) },
37 static void QUARTZ_DestroyMemoryAllocator(IUnknown* punk)
39 CMemoryAllocator_THIS(punk,unk);
41 CMemoryAllocator_UninitIMemAllocator( This );
44 HRESULT QUARTZ_CreateMemoryAllocator(IUnknown* punkOuter,void** ppobj)
46 CMemoryAllocator* pma;
49 TRACE("(%p,%p)\n",punkOuter,ppobj);
51 pma = (CMemoryAllocator*)QUARTZ_AllocObj( sizeof(CMemoryAllocator) );
55 QUARTZ_IUnkInit( &pma->unk, punkOuter );
56 hr = CMemoryAllocator_InitIMemAllocator( pma );
59 QUARTZ_FreeObj( pma );
63 pma->unk.pEntries = IFEntries;
64 pma->unk.dwEntries = sizeof(IFEntries)/sizeof(IFEntries[0]);
65 pma->unk.pOnFinalRelease = QUARTZ_DestroyMemoryAllocator;
67 *ppobj = (void*)(&pma->unk);
73 /***************************************************************************
75 * CMemoryAllocator::IMemAllocator
80 IMemAllocator_LockUnusedBuffer(CMemoryAllocator* This,IMediaSample** ppSample)
85 TRACE("(%p) try to enter critical section\n",This);
86 EnterCriticalSection( &This->csMem );
87 TRACE("(%p) enter critical section\n",This);
89 if ( This->pData == NULL || This->ppSamples == NULL ||
90 This->prop.cBuffers <= 0 )
92 hr = VFW_E_NOT_COMMITTED;
97 for ( i = 0; i < This->prop.cBuffers; i++ )
99 if ( This->ppSamples[i] == NULL )
101 hr = VFW_E_NOT_COMMITTED;
104 if ( This->ppSamples[i]->ref == 0 )
106 *ppSample = (IMediaSample*)(This->ppSamples[i]);
107 IMediaSample_AddRef( *ppSample );
115 LeaveCriticalSection( &This->csMem );
116 TRACE("(%p) leave critical section\n",This);
121 /* TRUE = all samples are released */
123 IMemAllocator_ReleaseUnusedBuffer(CMemoryAllocator* This)
128 TRACE("(%p) try to enter critical section\n",This);
129 EnterCriticalSection( &This->csMem );
130 TRACE("(%p) enter critical section\n",This);
132 if ( This->pData == NULL || This->ppSamples == NULL ||
133 This->prop.cBuffers <= 0 )
136 for ( i = 0; i < This->prop.cBuffers; i++ )
138 if ( This->ppSamples[i]->ref == 0 )
140 QUARTZ_DestroyMemMediaSample( This->ppSamples[i] );
141 This->ppSamples[i] = NULL;
151 QUARTZ_FreeMem(This->ppSamples);
152 This->ppSamples = NULL;
153 QUARTZ_FreeMem(This->pData);
158 LeaveCriticalSection( &This->csMem );
159 TRACE("(%p) leave critical section\n",This);
165 static HRESULT WINAPI
166 IMemAllocator_fnQueryInterface(IMemAllocator* iface,REFIID riid,void** ppobj)
168 CMemoryAllocator_THIS(iface,memalloc);
170 TRACE("(%p)->()\n",This);
172 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
176 IMemAllocator_fnAddRef(IMemAllocator* iface)
178 CMemoryAllocator_THIS(iface,memalloc);
180 TRACE("(%p)->()\n",This);
182 return IUnknown_AddRef(This->unk.punkControl);
186 IMemAllocator_fnRelease(IMemAllocator* iface)
188 CMemoryAllocator_THIS(iface,memalloc);
190 TRACE("(%p)->()\n",This);
192 return IUnknown_Release(This->unk.punkControl);
195 static HRESULT WINAPI
196 IMemAllocator_fnSetProperties(IMemAllocator* iface,ALLOCATOR_PROPERTIES* pPropReq,ALLOCATOR_PROPERTIES* pPropActual)
198 CMemoryAllocator_THIS(iface,memalloc);
202 TRACE( "(%p)->(%p,%p)\n", This, pPropReq, pPropActual );
204 if ( pPropReq == NULL || pPropActual == NULL )
206 if ( pPropReq->cBuffers < 0 ||
207 pPropReq->cbBuffer < 0 ||
208 pPropReq->cbAlign < 0 ||
209 pPropReq->cbPrefix < 0 )
211 TRACE("pPropReq is invalid\n");
215 if ( pPropReq->cbAlign == 0 ||
216 ( pPropReq->cbAlign & (pPropReq->cbAlign-1) ) != 0 )
218 WARN("cbAlign is invalid - %ld\n",pPropReq->cbAlign);
219 return VFW_E_BADALIGN;
224 EnterCriticalSection( &This->csMem );
226 if ( This->pData != NULL || This->ppSamples != NULL )
228 /* if commited, properties must not be changed. */
229 TRACE("already commited\n");
234 This->prop.cBuffers = pPropReq->cBuffers;
235 This->prop.cbBuffer = pPropReq->cbBuffer;
236 This->prop.cbAlign = pPropReq->cbAlign;
237 This->prop.cbPrefix = pPropReq->cbPrefix;
239 if ( This->prop.cbAlign == 0 )
240 This->prop.cbAlign = 1;
241 padding = This->prop.cbAlign -
242 ( (This->prop.cbBuffer+This->prop.cbPrefix) % This->prop.cbAlign );
244 This->prop.cbBuffer += padding;
246 memcpy( pPropActual, &This->prop, sizeof(ALLOCATOR_PROPERTIES) );
249 LeaveCriticalSection( &This->csMem );
251 TRACE("returned successfully.\n");
256 static HRESULT WINAPI
257 IMemAllocator_fnGetProperties(IMemAllocator* iface,ALLOCATOR_PROPERTIES* pProp)
259 CMemoryAllocator_THIS(iface,memalloc);
261 TRACE( "(%p)->(%p)\n", This, pProp );
266 EnterCriticalSection( &This->csMem );
268 memcpy( pProp, &This->prop, sizeof(ALLOCATOR_PROPERTIES) );
270 LeaveCriticalSection( &This->csMem );
275 static HRESULT WINAPI
276 IMemAllocator_fnCommit(IMemAllocator* iface)
278 CMemoryAllocator_THIS(iface,memalloc);
284 TRACE( "(%p)->()\n", This );
286 EnterCriticalSection( &This->csMem );
289 /* FIXME - handle in Decommitting */
290 if ( This->pData != NULL || This->ppSamples != NULL ||
291 This->prop.cBuffers <= 0 )
294 lBufSize = This->prop.cBuffers *
295 (This->prop.cbBuffer + This->prop.cbPrefix) +
300 This->pData = (BYTE*)QUARTZ_AllocMem( lBufSize );
301 if ( This->pData == NULL )
307 This->ppSamples = (CMemMediaSample**)QUARTZ_AllocMem(
308 sizeof(CMemMediaSample*) * This->prop.cBuffers );
309 if ( This->ppSamples == NULL )
315 for ( i = 0; i < This->prop.cBuffers; i++ )
316 This->ppSamples[i] = NULL;
318 pCur = This->pData + This->prop.cbAlign - ((This->pData-(BYTE*)NULL) & (This->prop.cbAlign-1));
320 for ( i = 0; i < This->prop.cBuffers; i++ )
322 hr = QUARTZ_CreateMemMediaSample(
323 pCur, (This->prop.cbBuffer + This->prop.cbPrefix),
324 iface, &This->ppSamples[i] );
327 pCur += (This->prop.cbBuffer + This->prop.cbPrefix);
333 IMemAllocator_Decommit(iface);
335 LeaveCriticalSection( &This->csMem );
340 static HRESULT WINAPI
341 IMemAllocator_fnDecommit(IMemAllocator* iface)
343 CMemoryAllocator_THIS(iface,memalloc);
345 TRACE( "(%p)->()\n", This );
349 ResetEvent( This->hEventSample );
351 /* to avoid deadlock, don't hold critical section while blocking */
352 if ( IMemAllocator_ReleaseUnusedBuffer(This) )
355 WaitForSingleObject( This->hEventSample, INFINITE );
361 static HRESULT WINAPI
362 IMemAllocator_fnGetBuffer(IMemAllocator* iface,IMediaSample** ppSample,REFERENCE_TIME* prtStart,REFERENCE_TIME* prtEnd,DWORD dwFlags)
364 CMemoryAllocator_THIS(iface,memalloc);
367 TRACE( "(%p)->(%p,%p,%p,%lu)\n", This, ppSample, prtStart, prtEnd, dwFlags );
369 if ( ppSample == NULL )
374 ResetEvent( This->hEventSample );
376 /* to avoid deadlock, don't hold critical section while blocking */
377 hr = IMemAllocator_LockUnusedBuffer(This,ppSample);
378 if ( ( hr != VFW_E_TIMEOUT ) || ( dwFlags & AM_GBF_NOWAIT ) )
381 WaitForSingleObject( This->hEventSample, INFINITE );
389 static HRESULT WINAPI
390 IMemAllocator_fnReleaseBuffer(IMemAllocator* iface,IMediaSample* pSample)
392 CMemoryAllocator_THIS(iface,memalloc);
394 TRACE( "(%p)->(%p)\n", This, pSample );
395 SetEvent( This->hEventSample );
402 static ICOM_VTABLE(IMemAllocator) imemalloc =
404 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
405 /* IUnknown fields */
406 IMemAllocator_fnQueryInterface,
407 IMemAllocator_fnAddRef,
408 IMemAllocator_fnRelease,
409 /* IMemAllocator fields */
410 IMemAllocator_fnSetProperties,
411 IMemAllocator_fnGetProperties,
412 IMemAllocator_fnCommit,
413 IMemAllocator_fnDecommit,
414 IMemAllocator_fnGetBuffer,
415 IMemAllocator_fnReleaseBuffer,
419 HRESULT CMemoryAllocator_InitIMemAllocator( CMemoryAllocator* pma )
423 ICOM_VTBL(&pma->memalloc) = &imemalloc;
425 ZeroMemory( &pma->prop, sizeof(pma->prop) );
426 pma->hEventSample = (HANDLE)NULL;
428 pma->ppSamples = NULL;
430 pma->hEventSample = CreateEventA( NULL, TRUE, FALSE, NULL );
431 if ( pma->hEventSample == (HANDLE)NULL )
432 return E_OUTOFMEMORY;
434 InitializeCriticalSection( &pma->csMem );
439 void CMemoryAllocator_UninitIMemAllocator( CMemoryAllocator* pma )
443 IMemAllocator_Decommit( (IMemAllocator*)(&pma->memalloc) );
445 DeleteCriticalSection( &pma->csMem );
447 if ( pma->hEventSample != (HANDLE)NULL )
448 CloseHandle( pma->hEventSample );