2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
4 * FILE: dll/directx/ksproxy/allocator.cpp
5 * PURPOSE: IKsAllocator interface
7 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
11 const GUID IID_IKsAllocatorEx
= {0x091bb63a, 0x603f, 0x11d1, {0xb0, 0x67, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02}};
12 const GUID IID_IKsAllocator
= {0x8da64899, 0xc0d9, 0x11d0, {0x84, 0x13, 0x00, 0x00, 0xf8, 0x22, 0xfe, 0x8a}};
14 class CKsAllocator
: public IKsAllocatorEx
,
15 public IMemAllocatorCallbackTemp
18 typedef std::stack
<IMediaSample
*>MediaSampleStack
;
19 typedef std::list
<IMediaSample
*>MediaSampleList
;
21 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
23 STDMETHODIMP_(ULONG
) AddRef()
25 InterlockedIncrement(&m_Ref
);
28 STDMETHODIMP_(ULONG
) Release()
30 InterlockedDecrement(&m_Ref
);
40 HANDLE STDMETHODCALLTYPE
KsGetAllocatorHandle();
41 KSALLOCATORMODE STDMETHODCALLTYPE
KsGetAllocatorMode();
42 HRESULT STDMETHODCALLTYPE
KsGetAllocatorStatus(PKSSTREAMALLOCATOR_STATUS AllocatorStatus
);
43 VOID STDMETHODCALLTYPE
KsSetAllocatorMode(KSALLOCATORMODE Mode
);
46 PALLOCATOR_PROPERTIES_EX STDMETHODCALLTYPE
KsGetProperties();
47 VOID STDMETHODCALLTYPE
KsSetProperties(PALLOCATOR_PROPERTIES_EX Properties
);
48 VOID STDMETHODCALLTYPE
KsSetAllocatorHandle(HANDLE AllocatorHandle
);
49 HANDLE STDMETHODCALLTYPE
KsCreateAllocatorAndGetHandle(IKsPin
* KsPin
);
52 HRESULT STDMETHODCALLTYPE
SetProperties(ALLOCATOR_PROPERTIES
*pRequest
, ALLOCATOR_PROPERTIES
*pActual
);
53 HRESULT STDMETHODCALLTYPE
GetProperties(ALLOCATOR_PROPERTIES
*pProps
);
54 HRESULT STDMETHODCALLTYPE
Commit();
55 HRESULT STDMETHODCALLTYPE
Decommit();
56 HRESULT STDMETHODCALLTYPE
GetBuffer(IMediaSample
**ppBuffer
, REFERENCE_TIME
*pStartTime
, REFERENCE_TIME
*pEndTime
, DWORD dwFlags
);
57 HRESULT STDMETHODCALLTYPE
ReleaseBuffer(IMediaSample
*pBuffer
);
59 //IMemAllocatorCallbackTemp
60 HRESULT STDMETHODCALLTYPE
SetNotify(IMemAllocatorNotifyCallbackTemp
*pNotify
);
61 HRESULT STDMETHODCALLTYPE
GetFreeCount(LONG
*plBuffersFree
);
65 virtual ~CKsAllocator(){}
66 VOID STDMETHODCALLTYPE
FreeMediaSamples();
70 KSALLOCATORMODE m_Mode
;
71 ALLOCATOR_PROPERTIES_EX m_Properties
;
72 IMemAllocatorNotifyCallbackTemp
*m_Notify
;
79 CRITICAL_SECTION m_CriticalSection
;
80 MediaSampleStack m_FreeList
;
81 MediaSampleList m_UsedList
;
89 CKsAllocator::QueryInterface(
93 if (IsEqualGUID(refiid
, IID_IUnknown
) ||
94 IsEqualGUID(refiid
, IID_IKsAllocator
) ||
95 IsEqualGUID(refiid
, IID_IKsAllocatorEx
))
97 *Output
= PVOID(this);
98 reinterpret_cast<IUnknown
*>(*Output
)->AddRef();
101 if (IsEqualGUID(refiid
, IID_IMemAllocator
) ||
102 IsEqualGUID(refiid
, IID_IMemAllocatorCallbackTemp
))
104 *Output
= (IMemAllocatorCallbackTemp
*)(this);
105 reinterpret_cast<IMemAllocatorCallbackTemp
*>(*Output
)->AddRef();
109 return E_NOINTERFACE
;
112 CKsAllocator::CKsAllocator() : m_Ref(0),
114 m_Mode(KsAllocatorMode_User
),
127 InitializeCriticalSection(&m_CriticalSection
);
131 //-------------------------------------------------------------------
136 CKsAllocator::SetProperties(
137 ALLOCATOR_PROPERTIES
*pRequest
,
138 ALLOCATOR_PROPERTIES
*pActual
)
140 SYSTEM_INFO SystemInfo
;
142 EnterCriticalSection(&m_CriticalSection
);
145 OutputDebugStringW(L
"CKsAllocator::SetProperties\n");
148 if (!pRequest
|| !pActual
)
151 // zero output properties
152 ZeroMemory(pActual
, sizeof(ALLOCATOR_PROPERTIES
));
155 GetSystemInfo(&SystemInfo
);
157 if (!pRequest
->cbAlign
|| (pRequest
->cbAlign
- 1) & SystemInfo
.dwAllocationGranularity
)
160 LeaveCriticalSection(&m_CriticalSection
);
161 return VFW_E_BADALIGN
;
164 if (m_Mode
== KsAllocatorMode_Kernel
)
166 // u can't change a kernel allocator
167 LeaveCriticalSection(&m_CriticalSection
);
168 return VFW_E_ALREADY_COMMITTED
;
173 // need to decommit first
174 LeaveCriticalSection(&m_CriticalSection
);
175 return VFW_E_ALREADY_COMMITTED
;
178 if (m_Allocated
!= m_FreeList
.size())
180 // outstanding buffers
181 LeaveCriticalSection(&m_CriticalSection
);
182 return VFW_E_BUFFERS_OUTSTANDING
;
185 pActual
->cbAlign
= m_cbAlign
= pRequest
->cbAlign
;
186 pActual
->cbBuffer
= m_cbBuffer
= pRequest
->cbBuffer
;
187 pActual
->cbPrefix
= m_cbPrefix
= pRequest
->cbPrefix
;
188 pActual
->cBuffers
= m_cBuffers
= pRequest
->cBuffers
;
190 LeaveCriticalSection(&m_CriticalSection
);
196 CKsAllocator::GetProperties(
197 ALLOCATOR_PROPERTIES
*pProps
)
202 pProps
->cbBuffer
= m_cbBuffer
;
203 pProps
->cBuffers
= m_cBuffers
;
204 pProps
->cbAlign
= m_cbAlign
;
205 pProps
->cbPrefix
= m_cbPrefix
;
212 CKsAllocator::Commit()
215 PUCHAR CurrentBuffer
;
216 IMediaSample
* Sample
;
219 //TODO integer overflow checks
220 EnterCriticalSection(&m_CriticalSection
);
223 OutputDebugStringW(L
"CKsAllocator::Commit\n");
226 if (m_Mode
== KsAllocatorMode_Kernel
)
228 /* no-op for kernel allocator */
229 LeaveCriticalSection(&m_CriticalSection
);
236 LeaveCriticalSection(&m_CriticalSection
);
240 if (m_cbBuffer
< 0 || m_cBuffers
< 0 || m_cbPrefix
< 0)
243 LeaveCriticalSection(&m_CriticalSection
);
244 return E_OUTOFMEMORY
;
247 LONG Size
= m_cbBuffer
+ m_cbPrefix
;
252 LONG Mod
= Size
% m_cbAlign
;
255 // calculate aligned size
256 Size
+= m_cbAlign
- Mod
;
260 LONG TotalSize
= Size
* m_cBuffers
;
266 // now allocate buffer
267 m_Buffer
= VirtualAlloc(NULL
, TotalSize
, MEM_COMMIT
, PAGE_READWRITE
);
270 LeaveCriticalSection(&m_CriticalSection
);
271 return E_OUTOFMEMORY
;
274 ZeroMemory(m_Buffer
, TotalSize
);
276 CurrentBuffer
= (PUCHAR
)m_Buffer
;
278 for (Index
= 0; Index
< m_cBuffers
; Index
++)
280 // construct media sample
281 hr
= CMediaSample_Constructor((IMemAllocator
*)this, CurrentBuffer
+ m_cbPrefix
, m_cbBuffer
, IID_IMediaSample
, (void**)&Sample
);
284 LeaveCriticalSection(&m_CriticalSection
);
285 return E_OUTOFMEMORY
;
289 m_FreeList
.push(Sample
);
293 CurrentBuffer
+= Size
;
296 // we are now commited
299 LeaveCriticalSection(&m_CriticalSection
);
305 CKsAllocator::Decommit()
307 EnterCriticalSection(&m_CriticalSection
);
310 OutputDebugStringW(L
"CKsAllocator::Decommit\n");
313 if (m_Mode
== KsAllocatorMode_Kernel
)
315 /* no-op for kernel allocator */
316 LeaveCriticalSection(&m_CriticalSection
);
322 if (m_Allocated
!= m_FreeList
.size())
324 // outstanding buffers
325 m_FreeSamples
= true;
326 LeaveCriticalSection(&m_CriticalSection
);
331 // no outstanding buffers
336 LeaveCriticalSection(&m_CriticalSection
);
343 CKsAllocator::GetBuffer(
344 IMediaSample
**ppBuffer
,
345 REFERENCE_TIME
*pStartTime
,
346 REFERENCE_TIME
*pEndTime
,
349 IMediaSample
* Sample
= NULL
;
352 return VFW_E_NOT_COMMITTED
;
356 EnterCriticalSection(&m_CriticalSection
);
358 if (!m_FreeList
.empty())
360 OutputDebugStringW(L
"CKsAllocator::GetBuffer HACK\n");
361 Sample
= m_FreeList
.top();
365 LeaveCriticalSection(&m_CriticalSection
);
367 if (dwFlags
& AM_GBF_NOWAIT
)
369 // never wait untill a buffer becomes available
373 while(Sample
== NULL
);
377 // no sample acquired
379 Sample
= m_UsedList
.back();
380 m_UsedList
.pop_back();
383 return VFW_E_TIMEOUT
;
389 // store sample in used list
390 m_UsedList
.push_front(Sample
);
398 CKsAllocator::ReleaseBuffer(
399 IMediaSample
*pBuffer
)
401 EnterCriticalSection(&m_CriticalSection
);
404 OutputDebugStringW(L
"CKsAllocator::ReleaseBuffer\n");
407 // media sample always 1 ref count in free list
410 // add the sample to the free list
411 m_FreeList
.push(pBuffer
);
417 if (m_FreeList
.size () == m_Allocated
)
425 //notify caller of an available buffer
426 m_Notify
->NotifyRelease();
429 LeaveCriticalSection(&m_CriticalSection
);
433 //-------------------------------------------------------------------
434 // IMemAllocatorCallbackTemp
438 CKsAllocator::SetNotify(
439 IMemAllocatorNotifyCallbackTemp
*pNotify
)
441 EnterCriticalSection(&m_CriticalSection
);
444 OutputDebugStringW(L
"CKsAllocator::SetNotify\n");
455 LeaveCriticalSection(&m_CriticalSection
);
461 CKsAllocator::GetFreeCount(
464 *plBuffersFree
= m_Allocated
- m_FreeList
.size();
468 //-------------------------------------------------------------------
473 CKsAllocator::KsGetAllocatorHandle()
480 CKsAllocator::KsGetAllocatorMode()
487 CKsAllocator::KsGetAllocatorStatus(
488 PKSSTREAMALLOCATOR_STATUS AllocatorStatus
)
494 CKsAllocator::KsSetAllocatorMode(
495 KSALLOCATORMODE Mode
)
500 //-------------------------------------------------------------------
503 PALLOCATOR_PROPERTIES_EX
505 CKsAllocator::KsGetProperties()
507 return &m_Properties
;
512 CKsAllocator::KsSetProperties(
513 PALLOCATOR_PROPERTIES_EX Properties
)
515 CopyMemory(&m_Properties
, Properties
, sizeof(ALLOCATOR_PROPERTIES_EX
));
520 CKsAllocator::KsSetAllocatorHandle(
521 HANDLE AllocatorHandle
)
523 m_hAllocator
= AllocatorHandle
;
529 CKsAllocator::KsCreateAllocatorAndGetHandle(
534 KSALLOCATOR_FRAMING AllocatorFraming
;
538 OutputDebugStringW(L
"CKsAllocator::KsCreateAllocatorAndGetHandle\n");
543 CloseHandle(m_hAllocator
);
547 // get pin IKsObject interface
548 hr
= KsPin
->QueryInterface(IID_IKsObject
, (void**)&pObject
);
553 hPin
= pObject
->KsGetObjectHandle();
555 //release IKsObject interface
558 if (!hPin
|| hPin
== INVALID_HANDLE_VALUE
)
561 //setup allocator framing
562 AllocatorFraming
.Frames
= m_Properties
.cBuffers
;
563 AllocatorFraming
.FrameSize
= m_Properties
.cbBuffer
;
564 AllocatorFraming
.FileAlignment
= (m_Properties
.cbAlign
-1);
565 AllocatorFraming
.OptionsFlags
= KSALLOCATOR_OPTIONF_SYSTEM_MEMORY
;
566 AllocatorFraming
.PoolType
= (m_Properties
.LogicalMemoryType
== KS_MemoryTypeKernelPaged
);
568 DWORD dwError
= KsCreateAllocator(hPin
, &AllocatorFraming
, &m_hAllocator
);
575 //-------------------------------------------------------------------
578 CKsAllocator::FreeMediaSamples()
582 for(Index
= 0; Index
< m_FreeList
.size(); Index
++)
584 IMediaSample
* Sample
= m_FreeList
.top();
589 m_FreeSamples
= false;
595 VirtualFree(m_Buffer
, 0, MEM_RELEASE
);
603 CKsAllocator_Constructor(
604 IUnknown
* pUnkOuter
,
609 OutputDebugStringW(L
"CKsAllocator_Constructor\n");
612 CKsAllocator
* handler
= new CKsAllocator();
615 return E_OUTOFMEMORY
;
617 if (FAILED(handler
->QueryInterface(riid
, ppv
)))
621 return E_NOINTERFACE
;