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
);