ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

allocator.cpp
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS WDM Streaming ActiveMovie Proxy
00004  * FILE:            dll/directx/ksproxy/allocator.cpp
00005  * PURPOSE:         IKsAllocator interface
00006  *
00007  * PROGRAMMERS:     Johannes Anderwald (janderwald@reactos.org)
00008  */
00009 #include "precomp.h"
00010 
00011 const GUID IID_IKsAllocatorEx = {0x091bb63a, 0x603f, 0x11d1, {0xb0, 0x67, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02}};
00012 const GUID IID_IKsAllocator   = {0x8da64899, 0xc0d9, 0x11d0, {0x84, 0x13, 0x00, 0x00, 0xf8, 0x22, 0xfe, 0x8a}};
00013 
00014 class CKsAllocator : public IKsAllocatorEx,
00015                      public IMemAllocatorCallbackTemp
00016 {
00017 public:
00018     typedef std::stack<IMediaSample *>MediaSampleStack;
00019     typedef std::list<IMediaSample *>MediaSampleList;
00020 
00021     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
00022 
00023     STDMETHODIMP_(ULONG) AddRef()
00024     {
00025         InterlockedIncrement(&m_Ref);
00026         return m_Ref;
00027     }
00028     STDMETHODIMP_(ULONG) Release()
00029     {
00030         InterlockedDecrement(&m_Ref);
00031 
00032         if (!m_Ref)
00033         {
00034             delete this;
00035             return 0;
00036         }
00037         return m_Ref;
00038     }
00039     //IKsAllocator
00040     HANDLE STDMETHODCALLTYPE KsGetAllocatorHandle();
00041     KSALLOCATORMODE STDMETHODCALLTYPE KsGetAllocatorMode();
00042     HRESULT STDMETHODCALLTYPE KsGetAllocatorStatus(PKSSTREAMALLOCATOR_STATUS AllocatorStatus);
00043     VOID STDMETHODCALLTYPE KsSetAllocatorMode(KSALLOCATORMODE Mode);
00044 
00045     //IKsAllocatorEx
00046     PALLOCATOR_PROPERTIES_EX STDMETHODCALLTYPE KsGetProperties();
00047     VOID STDMETHODCALLTYPE KsSetProperties(PALLOCATOR_PROPERTIES_EX Properties);
00048     VOID STDMETHODCALLTYPE KsSetAllocatorHandle(HANDLE AllocatorHandle);
00049     HANDLE STDMETHODCALLTYPE KsCreateAllocatorAndGetHandle(IKsPin* KsPin);
00050 
00051     //IMemAllocator
00052     HRESULT STDMETHODCALLTYPE SetProperties(ALLOCATOR_PROPERTIES *pRequest, ALLOCATOR_PROPERTIES *pActual);
00053     HRESULT STDMETHODCALLTYPE GetProperties(ALLOCATOR_PROPERTIES *pProps);
00054     HRESULT STDMETHODCALLTYPE Commit();
00055     HRESULT STDMETHODCALLTYPE Decommit();
00056     HRESULT STDMETHODCALLTYPE GetBuffer(IMediaSample **ppBuffer, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime, DWORD dwFlags);
00057     HRESULT STDMETHODCALLTYPE ReleaseBuffer(IMediaSample *pBuffer);
00058 
00059     //IMemAllocatorCallbackTemp
00060     HRESULT STDMETHODCALLTYPE SetNotify(IMemAllocatorNotifyCallbackTemp *pNotify);
00061     HRESULT STDMETHODCALLTYPE GetFreeCount(LONG *plBuffersFree);
00062 
00063 
00064     CKsAllocator();
00065     virtual ~CKsAllocator(){}
00066     VOID STDMETHODCALLTYPE FreeMediaSamples();
00067 protected:
00068     LONG m_Ref;
00069     HANDLE m_hAllocator;
00070     KSALLOCATORMODE m_Mode;
00071     ALLOCATOR_PROPERTIES_EX m_Properties;
00072     IMemAllocatorNotifyCallbackTemp *m_Notify;
00073     ULONG m_Allocated;
00074     LONG m_cbBuffer;
00075     LONG m_cBuffers;
00076     LONG m_cbAlign;
00077     LONG m_cbPrefix;
00078     BOOL m_Commited;
00079     CRITICAL_SECTION m_CriticalSection;
00080     MediaSampleStack m_FreeList;
00081     MediaSampleList m_UsedList;
00082     LPVOID m_Buffer;
00083     BOOL m_FreeSamples;
00084 };
00085 
00086 
00087 HRESULT
00088 STDMETHODCALLTYPE
00089 CKsAllocator::QueryInterface(
00090     IN  REFIID refiid,
00091     OUT PVOID* Output)
00092 {
00093     if (IsEqualGUID(refiid, IID_IUnknown) ||
00094         IsEqualGUID(refiid, IID_IKsAllocator) ||
00095         IsEqualGUID(refiid, IID_IKsAllocatorEx))
00096     {
00097         *Output = PVOID(this);
00098         reinterpret_cast<IUnknown*>(*Output)->AddRef();
00099         return NOERROR;
00100     }
00101     if (IsEqualGUID(refiid, IID_IMemAllocator) ||
00102         IsEqualGUID(refiid, IID_IMemAllocatorCallbackTemp))
00103     {
00104         *Output = (IMemAllocatorCallbackTemp*)(this);
00105         reinterpret_cast<IMemAllocatorCallbackTemp*>(*Output)->AddRef();
00106         return NOERROR;
00107     }
00108 
00109     return E_NOINTERFACE;
00110 }
00111 
00112 CKsAllocator::CKsAllocator() : m_Ref(0), 
00113                                m_hAllocator(0), 
00114                                m_Mode(KsAllocatorMode_User),
00115                                m_Notify(0),
00116                                m_Allocated(0),
00117                                m_cbBuffer(0),
00118                                m_cBuffers(0),
00119                                m_cbAlign(0),
00120                                m_cbPrefix(0),
00121                                m_Commited(FALSE),
00122                                m_FreeList(),
00123                                m_UsedList(),
00124                                m_Buffer(0),
00125                                m_FreeSamples(FALSE)
00126 {
00127    InitializeCriticalSection(&m_CriticalSection);
00128 
00129 }
00130 
00131 //-------------------------------------------------------------------
00132 // IMemAllocator
00133 //
00134 HRESULT
00135 STDMETHODCALLTYPE
00136 CKsAllocator::SetProperties(
00137     ALLOCATOR_PROPERTIES *pRequest,
00138     ALLOCATOR_PROPERTIES *pActual)
00139 {
00140     SYSTEM_INFO SystemInfo;
00141 
00142     EnterCriticalSection(&m_CriticalSection);
00143 
00144 #ifdef KSPROXY_TRACE
00145     OutputDebugStringW(L"CKsAllocator::SetProperties\n");
00146 #endif
00147 
00148     if (!pRequest || !pActual)
00149         return E_POINTER;
00150 
00151     // zero output properties
00152     ZeroMemory(pActual, sizeof(ALLOCATOR_PROPERTIES));
00153 
00154     // get system info
00155     GetSystemInfo(&SystemInfo);
00156 
00157     if (!pRequest->cbAlign || (pRequest->cbAlign - 1) & SystemInfo.dwAllocationGranularity)
00158     {
00159         // bad alignment
00160         LeaveCriticalSection(&m_CriticalSection);
00161         return VFW_E_BADALIGN;
00162     }
00163 
00164     if (m_Mode == KsAllocatorMode_Kernel)
00165     {
00166         // u can't change a kernel allocator
00167         LeaveCriticalSection(&m_CriticalSection);
00168         return VFW_E_ALREADY_COMMITTED;
00169     }
00170 
00171     if (m_Commited)
00172     {
00173         // need to decommit first
00174         LeaveCriticalSection(&m_CriticalSection);
00175         return VFW_E_ALREADY_COMMITTED;
00176     }
00177 
00178     if (m_Allocated != m_FreeList.size())
00179     {
00180         // outstanding buffers
00181         LeaveCriticalSection(&m_CriticalSection);
00182         return VFW_E_BUFFERS_OUTSTANDING;
00183     }
00184 
00185     pActual->cbAlign = m_cbAlign = pRequest->cbAlign;
00186     pActual->cbBuffer = m_cbBuffer = pRequest->cbBuffer;
00187     pActual->cbPrefix = m_cbPrefix = pRequest->cbPrefix;
00188     pActual->cBuffers = m_cBuffers = pRequest->cBuffers;
00189 
00190     LeaveCriticalSection(&m_CriticalSection);
00191     return NOERROR;
00192 }
00193 
00194 HRESULT
00195 STDMETHODCALLTYPE
00196 CKsAllocator::GetProperties(
00197     ALLOCATOR_PROPERTIES *pProps)
00198 {
00199     if (!pProps)
00200         return E_POINTER;
00201 
00202     pProps->cbBuffer = m_cbBuffer;
00203     pProps->cBuffers = m_cBuffers;
00204     pProps->cbAlign = m_cbAlign;
00205     pProps->cbPrefix = m_cbPrefix;
00206 
00207     return NOERROR;
00208 }
00209 
00210 HRESULT
00211 STDMETHODCALLTYPE
00212 CKsAllocator::Commit()
00213 {
00214     LONG Index;
00215     PUCHAR CurrentBuffer;
00216     IMediaSample * Sample;
00217     HRESULT hr;
00218 
00219     //TODO integer overflow checks
00220     EnterCriticalSection(&m_CriticalSection);
00221 
00222 #ifdef KSPROXY_TRACE
00223     OutputDebugStringW(L"CKsAllocator::Commit\n");
00224 #endif
00225 
00226     if (m_Mode == KsAllocatorMode_Kernel)
00227     {
00228         /* no-op for kernel allocator */
00229        LeaveCriticalSection(&m_CriticalSection);
00230        return NOERROR;
00231     }
00232 
00233     if (m_Commited)
00234     {
00235         // already commited
00236         LeaveCriticalSection(&m_CriticalSection);
00237         return NOERROR;
00238     }
00239 
00240     if (m_cbBuffer < 0 || m_cBuffers < 0 || m_cbPrefix < 0)
00241     {
00242         // invalid parameter
00243         LeaveCriticalSection(&m_CriticalSection);
00244         return E_OUTOFMEMORY;
00245     }
00246 
00247     LONG Size = m_cbBuffer + m_cbPrefix;
00248 
00249     if (m_cbAlign > 1)
00250     {
00251         //check alignment
00252         LONG Mod = Size % m_cbAlign;
00253         if (Mod)
00254         {
00255             // calculate aligned size
00256             Size += m_cbAlign - Mod;
00257         }
00258     }
00259 
00260     LONG TotalSize = Size * m_cBuffers;
00261 
00262     assert(TotalSize);
00263     assert(m_cBuffers);
00264     assert(Size);
00265 
00266     // now allocate buffer
00267     m_Buffer = VirtualAlloc(NULL, TotalSize, MEM_COMMIT, PAGE_READWRITE);
00268     if (!m_Buffer)
00269     {
00270         LeaveCriticalSection(&m_CriticalSection);
00271         return E_OUTOFMEMORY;
00272     }
00273 
00274     ZeroMemory(m_Buffer, TotalSize);
00275 
00276     CurrentBuffer = (PUCHAR)m_Buffer;
00277 
00278     for (Index = 0; Index < m_cBuffers; Index++)
00279     {
00280         // construct media sample
00281         hr = CMediaSample_Constructor((IMemAllocator*)this, CurrentBuffer + m_cbPrefix, m_cbBuffer, IID_IMediaSample, (void**)&Sample);
00282         if (FAILED(hr))
00283         {
00284             LeaveCriticalSection(&m_CriticalSection);
00285             return E_OUTOFMEMORY;
00286         }
00287 
00288         // add to free list
00289         m_FreeList.push(Sample);
00290         m_Allocated++;
00291 
00292         //next sample buffer
00293         CurrentBuffer += Size;
00294     }
00295 
00296     // we are now commited
00297     m_Commited = true;
00298 
00299     LeaveCriticalSection(&m_CriticalSection);
00300     return S_OK;
00301 }
00302 
00303 HRESULT
00304 STDMETHODCALLTYPE
00305 CKsAllocator::Decommit()
00306 {
00307     EnterCriticalSection(&m_CriticalSection);
00308 
00309 #ifdef KSPROXY_TRACE
00310     OutputDebugStringW(L"CKsAllocator::Decommit\n");
00311 #endif
00312 
00313     if (m_Mode == KsAllocatorMode_Kernel)
00314     {
00315         /* no-op for kernel allocator */
00316         LeaveCriticalSection(&m_CriticalSection);
00317         return NOERROR;
00318     }
00319 
00320     m_Commited = false;
00321 
00322     if (m_Allocated != m_FreeList.size())
00323     {
00324         // outstanding buffers
00325         m_FreeSamples = true;
00326         LeaveCriticalSection(&m_CriticalSection);
00327         return NOERROR;
00328     }
00329     else
00330     {
00331         // no outstanding buffers
00332         // free to free them
00333         FreeMediaSamples();
00334     }
00335 
00336     LeaveCriticalSection(&m_CriticalSection);
00337     return NOERROR;
00338 }
00339 
00340 
00341 HRESULT
00342 STDMETHODCALLTYPE
00343 CKsAllocator::GetBuffer(
00344     IMediaSample **ppBuffer,
00345     REFERENCE_TIME *pStartTime,
00346     REFERENCE_TIME *pEndTime,
00347     DWORD dwFlags)
00348 {
00349     IMediaSample * Sample = NULL;
00350 
00351     if (!m_Commited)
00352         return VFW_E_NOT_COMMITTED;
00353 
00354     do
00355     {
00356         EnterCriticalSection(&m_CriticalSection);
00357 
00358         if (!m_FreeList.empty())
00359         {
00360             OutputDebugStringW(L"CKsAllocator::GetBuffer HACK\n");
00361             Sample = m_FreeList.top();
00362             m_FreeList.pop();
00363         }
00364 
00365         LeaveCriticalSection(&m_CriticalSection);
00366 
00367         if (dwFlags & AM_GBF_NOWAIT)
00368         {
00369             // never wait untill a buffer becomes available
00370             break;
00371         }
00372     }
00373     while(Sample == NULL);
00374 
00375     if (!Sample)
00376     {
00377         // no sample acquired
00378         //HACKKKKKKK
00379         Sample = m_UsedList.back();
00380         m_UsedList.pop_back();
00381 
00382         if (!Sample)
00383             return VFW_E_TIMEOUT;
00384     }
00385 
00386     // store result
00387     *ppBuffer = Sample;
00388 
00389    // store sample in used list
00390    m_UsedList.push_front(Sample);
00391 
00392     // done
00393     return NOERROR;
00394 }
00395 
00396 HRESULT
00397 STDMETHODCALLTYPE
00398 CKsAllocator::ReleaseBuffer(
00399     IMediaSample *pBuffer)
00400 {
00401     EnterCriticalSection(&m_CriticalSection);
00402 
00403 #ifdef KSPROXY_TRACE
00404     OutputDebugStringW(L"CKsAllocator::ReleaseBuffer\n");
00405 #endif
00406 
00407     // media sample always 1 ref count in free list
00408     pBuffer->AddRef();
00409 
00410     // add the sample to the free list
00411     m_FreeList.push(pBuffer);
00412 
00413 
00414     if (m_FreeSamples)
00415     {
00416         // pending de-commit
00417         if (m_FreeList.size () == m_Allocated)
00418         {
00419             FreeMediaSamples();
00420         }
00421     }
00422 
00423     if (m_Notify)
00424     {
00425         //notify caller of an available buffer
00426         m_Notify->NotifyRelease();
00427     }
00428 
00429     LeaveCriticalSection(&m_CriticalSection);
00430     return S_OK;
00431 }
00432 
00433 //-------------------------------------------------------------------
00434 // IMemAllocatorCallbackTemp
00435 //
00436 HRESULT
00437 STDMETHODCALLTYPE
00438 CKsAllocator::SetNotify(
00439     IMemAllocatorNotifyCallbackTemp *pNotify)
00440 {
00441     EnterCriticalSection(&m_CriticalSection);
00442 
00443 #ifdef KSPROXY_TRACE
00444     OutputDebugStringW(L"CKsAllocator::SetNotify\n");
00445 #endif
00446 
00447     if (pNotify)
00448         pNotify->AddRef();
00449 
00450     if (m_Notify)
00451         m_Notify->Release();
00452 
00453     m_Notify = pNotify;
00454 
00455     LeaveCriticalSection(&m_CriticalSection);
00456     return NOERROR;
00457 }
00458 
00459 HRESULT
00460 STDMETHODCALLTYPE
00461 CKsAllocator::GetFreeCount(
00462     LONG *plBuffersFree)
00463 {
00464     *plBuffersFree = m_Allocated - m_FreeList.size();
00465     return S_OK;
00466 }
00467 
00468 //-------------------------------------------------------------------
00469 // IKsAllocator
00470 //
00471 HANDLE
00472 STDMETHODCALLTYPE
00473 CKsAllocator::KsGetAllocatorHandle()
00474 {
00475     return m_hAllocator;
00476 }
00477 
00478 KSALLOCATORMODE
00479 STDMETHODCALLTYPE
00480 CKsAllocator::KsGetAllocatorMode()
00481 {
00482     return m_Mode;
00483 }
00484 
00485 HRESULT
00486 STDMETHODCALLTYPE
00487 CKsAllocator::KsGetAllocatorStatus(
00488     PKSSTREAMALLOCATOR_STATUS AllocatorStatus)
00489 {
00490     return NOERROR;
00491 }
00492 VOID
00493 STDMETHODCALLTYPE
00494 CKsAllocator::KsSetAllocatorMode(
00495     KSALLOCATORMODE Mode)
00496 {
00497     m_Mode = Mode;
00498 }
00499 
00500 //-------------------------------------------------------------------
00501 // IKsAllocatorEx
00502 //
00503 PALLOCATOR_PROPERTIES_EX
00504 STDMETHODCALLTYPE
00505 CKsAllocator::KsGetProperties()
00506 {
00507     return &m_Properties;
00508 }
00509 
00510 VOID
00511 STDMETHODCALLTYPE
00512 CKsAllocator::KsSetProperties(
00513     PALLOCATOR_PROPERTIES_EX Properties)
00514 {
00515     CopyMemory(&m_Properties, Properties, sizeof(ALLOCATOR_PROPERTIES_EX));
00516 }
00517 
00518 VOID
00519 STDMETHODCALLTYPE
00520 CKsAllocator::KsSetAllocatorHandle(
00521     HANDLE AllocatorHandle)
00522 {
00523     m_hAllocator = AllocatorHandle;
00524 }
00525 
00526 
00527 HANDLE
00528 STDMETHODCALLTYPE
00529 CKsAllocator::KsCreateAllocatorAndGetHandle(
00530     IKsPin* KsPin)
00531 {
00532     HRESULT hr;
00533     IKsObject * pObject;
00534     KSALLOCATOR_FRAMING AllocatorFraming;
00535     HANDLE hPin;
00536 
00537 #ifdef KSPROXY_TRACE
00538     OutputDebugStringW(L"CKsAllocator::KsCreateAllocatorAndGetHandle\n");
00539 #endif
00540 
00541     if (m_hAllocator)
00542     {
00543         CloseHandle(m_hAllocator);
00544         m_hAllocator = NULL;
00545     }
00546 
00547     // get pin IKsObject interface
00548     hr = KsPin->QueryInterface(IID_IKsObject, (void**)&pObject);
00549     if (FAILED(hr))
00550         return NULL;
00551 
00552     // get pin handle
00553     hPin = pObject->KsGetObjectHandle();
00554 
00555     //release IKsObject interface
00556     pObject->Release();
00557 
00558     if (!hPin || hPin == INVALID_HANDLE_VALUE)
00559         return NULL;
00560 
00561     //setup allocator framing
00562     AllocatorFraming.Frames = m_Properties.cBuffers;
00563     AllocatorFraming.FrameSize = m_Properties.cbBuffer;
00564     AllocatorFraming.FileAlignment = (m_Properties.cbAlign -1);
00565     AllocatorFraming.OptionsFlags = KSALLOCATOR_OPTIONF_SYSTEM_MEMORY;
00566     AllocatorFraming.PoolType = (m_Properties.LogicalMemoryType == KS_MemoryTypeKernelPaged);
00567 
00568     DWORD dwError = KsCreateAllocator(hPin, &AllocatorFraming, &m_hAllocator);
00569     if (dwError)
00570         return NULL;
00571 
00572     return m_hAllocator;
00573 }
00574 
00575 //-------------------------------------------------------------------
00576 VOID
00577 STDMETHODCALLTYPE
00578 CKsAllocator::FreeMediaSamples()
00579 {
00580     ULONG Index;
00581 
00582     for(Index = 0; Index < m_FreeList.size(); Index++)
00583     {
00584         IMediaSample * Sample = m_FreeList.top();
00585         m_FreeList.pop();
00586         delete Sample;
00587     }
00588 
00589     m_FreeSamples = false;
00590     m_Allocated = 0;
00591 
00592     if (m_Buffer)
00593     {
00594         // release buffer
00595         VirtualFree(m_Buffer, 0, MEM_RELEASE);
00596 
00597         m_Buffer = NULL;
00598     }
00599 }
00600 
00601 HRESULT
00602 WINAPI
00603 CKsAllocator_Constructor(
00604     IUnknown * pUnkOuter,
00605     REFIID riid,
00606     LPVOID * ppv)
00607 {
00608 #ifdef KSPROXY_TRACE
00609     OutputDebugStringW(L"CKsAllocator_Constructor\n");
00610 #endif
00611 
00612     CKsAllocator * handler = new CKsAllocator();
00613 
00614     if (!handler)
00615         return E_OUTOFMEMORY;
00616 
00617     if (FAILED(handler->QueryInterface(riid, ppv)))
00618     {
00619         /* not supported */
00620         delete handler;
00621         return E_NOINTERFACE;
00622     }
00623 
00624     return NOERROR;
00625 }

Generated on Sat May 26 2012 04:20:21 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.