ReactOS  0.4.12-dev-685-gf36cbf7
allocator.cpp
Go to the documentation of this file.
1 /*
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
6  *
7  * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
8  */
9 #include "precomp.h"
10 
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}};
13 
14 class CKsAllocator : public IKsAllocatorEx,
16 {
17 public:
18  typedef std::stack<IMediaSample *>MediaSampleStack;
19  typedef std::list<IMediaSample *>MediaSampleList;
20 
22 
24  {
26  return m_Ref;
27  }
29  {
31 
32  if (!m_Ref)
33  {
34  delete this;
35  return 0;
36  }
37  return m_Ref;
38  }
39  //IKsAllocator
41  KSALLOCATORMODE STDMETHODCALLTYPE KsGetAllocatorMode();
44 
45  //IKsAllocatorEx
46  PALLOCATOR_PROPERTIES_EX STDMETHODCALLTYPE KsGetProperties();
47  VOID STDMETHODCALLTYPE KsSetProperties(PALLOCATOR_PROPERTIES_EX Properties);
50 
51  //IMemAllocator
58 
59  //IMemAllocatorCallbackTemp
62 
63 
64  CKsAllocator();
65  virtual ~CKsAllocator(){}
67 protected:
70  KSALLOCATORMODE m_Mode;
71  ALLOCATOR_PROPERTIES_EX m_Properties;
84 };
85 
86 
87 HRESULT
90  IN REFIID refiid,
91  OUT PVOID* Output)
92 {
93  if (IsEqualGUID(refiid, IID_IUnknown) ||
94  IsEqualGUID(refiid, IID_IKsAllocator) ||
96  {
97  *Output = PVOID(this);
98  reinterpret_cast<IUnknown*>(*Output)->AddRef();
99  return NOERROR;
100  }
101  if (IsEqualGUID(refiid, IID_IMemAllocator) ||
102  IsEqualGUID(refiid, IID_IMemAllocatorCallbackTemp))
103  {
104  *Output = (IMemAllocatorCallbackTemp*)(this);
105  reinterpret_cast<IMemAllocatorCallbackTemp*>(*Output)->AddRef();
106  return NOERROR;
107  }
108 
109  return E_NOINTERFACE;
110 }
111 
113  m_hAllocator(0),
114  m_Mode(KsAllocatorMode_User),
115  m_Notify(0),
116  m_Allocated(0),
117  m_cbBuffer(0),
118  m_cBuffers(0),
119  m_cbAlign(0),
120  m_cbPrefix(0),
121  m_Committed(FALSE),
122  m_FreeList(),
123  m_UsedList(),
124  m_Buffer(0),
125  m_FreeSamples(FALSE)
126 {
128 
129 }
130 
131 //-------------------------------------------------------------------
132 // IMemAllocator
133 //
134 HRESULT
137  ALLOCATOR_PROPERTIES *pRequest,
138  ALLOCATOR_PROPERTIES *pActual)
139 {
140  SYSTEM_INFO SystemInfo;
141 
143 
144 #ifdef KSPROXY_TRACE
145  OutputDebugStringW(L"CKsAllocator::SetProperties\n");
146 #endif
147 
148  if (!pRequest || !pActual)
149  return E_POINTER;
150 
151  // zero output properties
152  ZeroMemory(pActual, sizeof(ALLOCATOR_PROPERTIES));
153 
154  // get system info
155  GetSystemInfo(&SystemInfo);
156 
157  if (!pRequest->cbAlign || (pRequest->cbAlign - 1) & SystemInfo.dwAllocationGranularity)
158  {
159  // bad alignment
161  return VFW_E_BADALIGN;
162  }
163 
164  if (m_Mode == KsAllocatorMode_Kernel)
165  {
166  // u can't change a kernel allocator
169  }
170 
171  if (m_Committed)
172  {
173  // need to decommit first
176  }
177 
178  if (m_Allocated != m_FreeList.size())
179  {
180  // outstanding buffers
183  }
184 
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;
189 
191  return NOERROR;
192 }
193 
194 HRESULT
197  ALLOCATOR_PROPERTIES *pProps)
198 {
199  if (!pProps)
200  return E_POINTER;
201 
202  pProps->cbBuffer = m_cbBuffer;
203  pProps->cBuffers = m_cBuffers;
204  pProps->cbAlign = m_cbAlign;
205  pProps->cbPrefix = m_cbPrefix;
206 
207  return NOERROR;
208 }
209 
210 HRESULT
213 {
214  LONG Index;
216  IMediaSample * Sample;
217  HRESULT hr;
218 
219  //TODO integer overflow checks
221 
222 #ifdef KSPROXY_TRACE
223  OutputDebugStringW(L"CKsAllocator::Commit\n");
224 #endif
225 
226  if (m_Mode == KsAllocatorMode_Kernel)
227  {
228  /* no-op for kernel allocator */
230  return NOERROR;
231  }
232 
233  if (m_Committed)
234  {
235  // already committed
237  return NOERROR;
238  }
239 
240  if (m_cbBuffer < 0 || m_cBuffers < 0 || m_cbPrefix < 0)
241  {
242  // invalid parameter
244  return E_OUTOFMEMORY;
245  }
246 
248 
249  if (m_cbAlign > 1)
250  {
251  //check alignment
252  LONG Mod = Size % m_cbAlign;
253  if (Mod)
254  {
255  // calculate aligned size
256  Size += m_cbAlign - Mod;
257  }
258  }
259 
260  LONG TotalSize = Size * m_cBuffers;
261 
262  assert(TotalSize);
264  assert(Size);
265 
266  // now allocate buffer
268  if (!m_Buffer)
269  {
271  return E_OUTOFMEMORY;
272  }
273 
274  ZeroMemory(m_Buffer, TotalSize);
275 
277 
278  for (Index = 0; Index < m_cBuffers; Index++)
279  {
280  // construct media sample
281  hr = CMediaSample_Constructor((IMemAllocator*)this, CurrentBuffer + m_cbPrefix, m_cbBuffer, IID_IMediaSample, (void**)&Sample);
282  if (FAILED(hr))
283  {
285  return E_OUTOFMEMORY;
286  }
287 
288  // add to free list
289  m_FreeList.push(Sample);
290  m_Allocated++;
291 
292  //next sample buffer
293  CurrentBuffer += Size;
294  }
295 
296  // we are now committed
297  m_Committed = true;
298 
300  return S_OK;
301 }
302 
303 HRESULT
306 {
308 
309 #ifdef KSPROXY_TRACE
310  OutputDebugStringW(L"CKsAllocator::Decommit\n");
311 #endif
312 
313  if (m_Mode == KsAllocatorMode_Kernel)
314  {
315  /* no-op for kernel allocator */
317  return NOERROR;
318  }
319 
320  m_Committed = false;
321 
322  if (m_Allocated != m_FreeList.size())
323  {
324  // outstanding buffers
325  m_FreeSamples = true;
327  return NOERROR;
328  }
329  else
330  {
331  // no outstanding buffers
332  // free to free them
334  }
335 
337  return NOERROR;
338 }
339 
340 
341 HRESULT
344  IMediaSample **ppBuffer,
345  REFERENCE_TIME *pStartTime,
346  REFERENCE_TIME *pEndTime,
347  DWORD dwFlags)
348 {
349  IMediaSample * Sample = NULL;
350 
351  if (!m_Committed)
352  return VFW_E_NOT_COMMITTED;
353 
354  do
355  {
357 
358  if (!m_FreeList.empty())
359  {
360  OutputDebugStringW(L"CKsAllocator::GetBuffer HACK\n");
361  Sample = m_FreeList.top();
362  m_FreeList.pop();
363  }
364 
366 
367  if (dwFlags & AM_GBF_NOWAIT)
368  {
369  // never wait untill a buffer becomes available
370  break;
371  }
372  }
373  while(Sample == NULL);
374 
375  if (!Sample)
376  {
377  // no sample acquired
378  //HACKKKKKKK
379  Sample = m_UsedList.back();
380  m_UsedList.pop_back();
381 
382  if (!Sample)
383  return VFW_E_TIMEOUT;
384  }
385 
386  // store result
387  *ppBuffer = Sample;
388 
389  // store sample in used list
390  m_UsedList.push_front(Sample);
391 
392  // done
393  return NOERROR;
394 }
395 
396 HRESULT
400 {
402 
403 #ifdef KSPROXY_TRACE
404  OutputDebugStringW(L"CKsAllocator::ReleaseBuffer\n");
405 #endif
406 
407  // media sample always 1 ref count in free list
408  pBuffer->AddRef();
409 
410  // add the sample to the free list
411  m_FreeList.push(pBuffer);
412 
413 
414  if (m_FreeSamples)
415  {
416  // pending de-commit
417  if (m_FreeList.size () == m_Allocated)
418  {
420  }
421  }
422 
423  if (m_Notify)
424  {
425  //notify caller of an available buffer
427  }
428 
430  return S_OK;
431 }
432 
433 //-------------------------------------------------------------------
434 // IMemAllocatorCallbackTemp
435 //
436 HRESULT
440 {
442 
443 #ifdef KSPROXY_TRACE
444  OutputDebugStringW(L"CKsAllocator::SetNotify\n");
445 #endif
446 
447  if (pNotify)
448  pNotify->AddRef();
449 
450  if (m_Notify)
451  m_Notify->Release();
452 
453  m_Notify = pNotify;
454 
456  return NOERROR;
457 }
458 
459 HRESULT
462  LONG *plBuffersFree)
463 {
464  *plBuffersFree = m_Allocated - m_FreeList.size();
465  return S_OK;
466 }
467 
468 //-------------------------------------------------------------------
469 // IKsAllocator
470 //
471 HANDLE
474 {
475  return m_hAllocator;
476 }
477 
478 KSALLOCATORMODE
481 {
482  return m_Mode;
483 }
484 
485 HRESULT
488  PKSSTREAMALLOCATOR_STATUS AllocatorStatus)
489 {
490  return NOERROR;
491 }
492 VOID
495  KSALLOCATORMODE Mode)
496 {
497  m_Mode = Mode;
498 }
499 
500 //-------------------------------------------------------------------
501 // IKsAllocatorEx
502 //
503 PALLOCATOR_PROPERTIES_EX
506 {
507  return &m_Properties;
508 }
509 
510 VOID
513  PALLOCATOR_PROPERTIES_EX Properties)
514 {
515  CopyMemory(&m_Properties, Properties, sizeof(ALLOCATOR_PROPERTIES_EX));
516 }
517 
518 VOID
522 {
524 }
525 
526 
527 HANDLE
530  IKsPin* KsPin)
531 {
532  HRESULT hr;
533  IKsObject * pObject;
535  HANDLE hPin;
536 
537 #ifdef KSPROXY_TRACE
538  OutputDebugStringW(L"CKsAllocator::KsCreateAllocatorAndGetHandle\n");
539 #endif
540 
541  if (m_hAllocator)
542  {
544  m_hAllocator = NULL;
545  }
546 
547  // get pin IKsObject interface
548  hr = KsPin->QueryInterface(IID_IKsObject, (void**)&pObject);
549  if (FAILED(hr))
550  return NULL;
551 
552  // get pin handle
553  hPin = pObject->KsGetObjectHandle();
554 
555  //release IKsObject interface
556  pObject->Release();
557 
558  if (!hPin || hPin == INVALID_HANDLE_VALUE)
559  return NULL;
560 
561  //setup allocator framing
566  AllocatorFraming.PoolType = (m_Properties.LogicalMemoryType == KS_MemoryTypeKernelPaged);
567 
569  if (dwError)
570  return NULL;
571 
572  return m_hAllocator;
573 }
574 
575 //-------------------------------------------------------------------
576 VOID
579 {
580  ULONG Index;
581 
582  for(Index = 0; Index < m_FreeList.size(); Index++)
583  {
584  IMediaSample * Sample = m_FreeList.top();
585  m_FreeList.pop();
586  Sample->Release();
587  }
588 
589  m_FreeSamples = false;
590  m_Allocated = 0;
591 
592  if (m_Buffer)
593  {
594  // release buffer
596 
597  m_Buffer = NULL;
598  }
599 }
600 
601 HRESULT
602 WINAPI
604  IUnknown * pUnkOuter,
605  REFIID riid,
606  LPVOID * ppv)
607 {
608 #ifdef KSPROXY_TRACE
609  OutputDebugStringW(L"CKsAllocator_Constructor\n");
610 #endif
611 
613 
614  if (!handler)
615  return E_OUTOFMEMORY;
616 
617  if (FAILED(handler->QueryInterface(riid, ppv)))
618  {
619  /* not supported */
620  delete handler;
621  return E_NOINTERFACE;
622  }
623 
624  return NOERROR;
625 }
LONG m_cbPrefix
Definition: allocator.cpp:77
CRITICAL_SECTION m_CriticalSection
Definition: allocator.cpp:79
#define IN
Definition: typedefs.h:38
#define VFW_E_BADALIGN
Definition: vfwmsgs.h:53
#define REFIID
Definition: guiddef.h:113
#define CloseHandle
Definition: compat.h:398
MediaSampleList m_UsedList
Definition: allocator.cpp:81
#define E_NOINTERFACE
Definition: winerror.h:2364
HRESULT hr
Definition: shlfolder.c:183
HRESULT STDMETHODCALLTYPE KsGetAllocatorStatus(PKSSTREAMALLOCATOR_STATUS AllocatorStatus)
Definition: allocator.cpp:487
_In_ ULONG Mode
Definition: hubbusif.h:303
#define NOERROR
Definition: winerror.h:2354
DWORD dwAllocationGranularity
Definition: winbase.h:1132
const GUID IID_IKsObject
ALLOCATOR_PROPERTIES_EX m_Properties
Definition: allocator.cpp:71
REFIID riid
Definition: precomp.h:44
unsigned char * PUCHAR
Definition: retypes.h:3
HRESULT STDMETHODCALLTYPE SetNotify(IMemAllocatorNotifyCallbackTemp *pNotify)
Definition: allocator.cpp:438
_In_ PKSALLOCATOR_FRAMING AllocatorFraming
Definition: ks.h:4547
REFIID LPVOID * ppv
Definition: atlbase.h:39
IMemAllocatorNotifyCallbackTemp * m_Notify
Definition: allocator.cpp:72
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
#define assert(x)
Definition: debug.h:53
#define ZeroMemory
Definition: winbase.h:1635
STDMETHODIMP_(ULONG) Release()
Definition: allocator.cpp:28
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
HRESULT STDMETHODCALLTYPE ReleaseBuffer(IMediaSample *pBuffer)
Definition: allocator.cpp:398
#define MEM_COMMIT
Definition: nt_native.h:1313
KSALLOCATORMODE STDMETHODCALLTYPE KsGetAllocatorMode()
Definition: allocator.cpp:480
HRESULT STDMETHODCALLTYPE Decommit()
Definition: allocator.cpp:305
PALLOCATOR_PROPERTIES_EX STDMETHODCALLTYPE KsGetProperties()
Definition: allocator.cpp:505
HRESULT STDMETHODCALLTYPE GetFreeCount(LONG *plBuffersFree)
Definition: allocator.cpp:461
HANDLE STDMETHODCALLTYPE KsGetAllocatorHandle()
Definition: allocator.cpp:473
void WINAPI SHIM_OBJ_NAME() OutputDebugStringW(LPCWSTR lpOutputString)
Definition: ignoredbgout.c:23
HANDLE STDMETHODCALLTYPE KsCreateAllocatorAndGetHandle(IKsPin *KsPin)
Definition: allocator.cpp:529
virtual ~CKsAllocator()
Definition: allocator.cpp:65
#define KSALLOCATOR_OPTIONF_SYSTEM_MEMORY
Definition: ks.h:1721
LPVOID NTAPI VirtualAlloc(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flAllocationType, IN DWORD flProtect)
Definition: virtmem.c:74
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
LONG m_cbAlign
Definition: allocator.cpp:76
long LONG
Definition: pedump.c:60
HRESULT WINAPI CMediaSample_Constructor(IMemAllocator *Allocator, BYTE *pBuffer, ULONG BufferSize, REFIID riid, LPVOID *ppv)
#define STDMETHODIMP
Definition: basetyps.h:43
ULONG Release()
#define VFW_E_ALREADY_COMMITTED
Definition: vfwmsgs.h:54
BOOL m_FreeSamples
Definition: allocator.cpp:83
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:697
smooth NULL
Definition: ftsmooth.c:416
PVOID pBuffer
HRESULT STDMETHODCALLTYPE Commit()
Definition: allocator.cpp:212
ULONG Frames
Definition: ks.h:1700
KSDDKAPI DWORD NTAPI KsCreateAllocator(HANDLE ConnectionHandle, PKSALLOCATOR_FRAMING AllocatorFraming, PHANDLE AllocatorHandle)
Definition: ksuser.c:107
void * PVOID
Definition: retypes.h:9
HRESULT STDMETHODCALLTYPE GetBuffer(IMediaSample **ppBuffer, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime, DWORD dwFlags)
Definition: allocator.cpp:343
HRESULT STDMETHODCALLTYPE GetProperties(ALLOCATOR_PROPERTIES *pProps)
Definition: allocator.cpp:196
IN PVOID IN PVOID IN USHORT IN USHORT IN PINTERFACE Interface
Definition: pci.h:359
unsigned int BOOL
Definition: ntddk_ex.h:94
#define VFW_E_TIMEOUT
Definition: vfwmsgs.h:85
KSALLOCATORMODE m_Mode
Definition: allocator.cpp:70
LONGLONG REFERENCE_TIME
Definition: dmusicks.h:9
VOID STDMETHODCALLTYPE KsSetAllocatorMode(KSALLOCATORMODE Mode)
Definition: allocator.cpp:494
LONG HRESULT
Definition: typedefs.h:77
const GUID IID_IUnknown
#define CopyMemory
Definition: winbase.h:1633
static const UCHAR Index[8]
Definition: usbohci.c:18
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
nsrefcnt Release()
unsigned long DWORD
Definition: ntddk_ex.h:95
const GUID IID_IKsAllocatorEx
Definition: allocator.cpp:11
LPVOID m_Buffer
Definition: allocator.cpp:82
ULONG AddRef()
LONG m_cbBuffer
Definition: allocator.cpp:74
STDMETHODIMP_(ULONG) AddRef()
Definition: allocator.cpp:23
static const WCHAR L[]
Definition: oid.c:1250
#define InterlockedDecrement
Definition: armddk.h:52
Definition: arc.h:85
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
VOID STDMETHODCALLTYPE FreeMediaSamples()
Definition: allocator.cpp:578
#define WINAPI
Definition: msvc.h:20
ULONG PoolType
Definition: ks.h:1698
LONG m_cBuffers
Definition: allocator.cpp:75
const GUID IID_IKsAllocator
Definition: allocator.cpp:12
_In_ PKSALLOCATOR_FRAMING _Out_ PHANDLE AllocatorHandle
Definition: ks.h:4547
#define S_OK
Definition: intsafe.h:59
#define InterlockedIncrement
Definition: armddk.h:53
HRESULT STDMETHODCALLTYPE SetProperties(ALLOCATOR_PROPERTIES *pRequest, ALLOCATOR_PROPERTIES *pActual)
Definition: allocator.cpp:136
#define VFW_E_BUFFERS_OUTSTANDING
Definition: vfwmsgs.h:55
static PVOID CurrentBuffer
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
Definition: sysinfo.c:142
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4021
MediaSampleStack m_FreeList
Definition: allocator.cpp:80
#define VFW_E_NOT_COMMITTED
Definition: vfwmsgs.h:56
#define MEM_RELEASE
Definition: nt_native.h:1316
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
HRESULT WINAPI CKsAllocator_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv)
Definition: allocator.cpp:603
BOOL NTAPI VirtualFree(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD dwFreeType)
Definition: virtmem.c:128
std::list< IMediaSample * > MediaSampleList
Definition: allocator.cpp:19
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7782
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
ULONG FileAlignment
Definition: ks.h:1702
#define E_POINTER
Definition: winerror.h:2365
VOID STDMETHODCALLTYPE KsSetAllocatorHandle(HANDLE AllocatorHandle)
Definition: allocator.cpp:520
nsrefcnt AddRef()
std::stack< IMediaSample * > MediaSampleStack
Definition: allocator.cpp:18
ULONG FrameSize
Definition: ks.h:1701
STDMETHODIMP QueryInterface(REFIID InterfaceId, PVOID *Interface)
Definition: allocator.cpp:89
ULONG m_Allocated
Definition: allocator.cpp:73
BOOL m_Committed
Definition: allocator.cpp:78
VOID STDMETHODCALLTYPE KsSetProperties(PALLOCATOR_PROPERTIES_EX Properties)
Definition: allocator.cpp:512
HANDLE m_hAllocator
Definition: allocator.cpp:69
ULONG OptionsFlags
Definition: ks.h:1692
#define PAGE_READWRITE
Definition: nt_native.h:1304