alloc.cpp
资源名称:h264src.zip [点击查看]
上传用户:sunbaby
上传日期:2013-05-31
资源大小:242k
文件大小:8k
源码类别:
mpeg/mp3
开发平台:
Visual C++
- //==========================================================================;
- //
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- // PURPOSE.
- //
- // Copyright (c) 1996 - 1997 Microsoft Corporation. All Rights Reserved.
- //
- //--------------------------------------------------------------------------;
- /* Sequential allocator methods */
- #include "stdafx.h"
- #include <streams.h>
- #include "alloc.h"
- CSequentialAllocator::CSequentialAllocator(
- LPUNKNOWN pUnk,
- HRESULT *phr
- ) : CMemAllocator(TEXT("CSequential Allocator"), pUnk, phr),
- m_pbNext(m_pBuffer),
- m_parSamples(NULL),
- m_lValid(0),
- m_pbStartValid(NULL)
- {
- }
- CSequentialAllocator::~CSequentialAllocator()
- {
- if (m_parSamples != NULL) {
- delete [] m_parSamples;
- }
- }
- STDMETHODIMP CSequentialAllocator::GetBuffer(
- IMediaSample **ppBuffer,
- REFERENCE_TIME * pStartTime,
- REFERENCE_TIME * pEndTime,
- DWORD dwFlags
- )
- {
- /* Like the normal version except we will only allocate the NEXT
- buffer
- */
- UNREFERENCED_PARAMETER(pStartTime);
- UNREFERENCED_PARAMETER(pEndTime);
- UNREFERENCED_PARAMETER(dwFlags);
- CMediaSample *pSample = NULL;
- *ppBuffer = NULL;
- for (;;)
- {
- { // scope for lock
- CAutoLock cObjectLock(this);
- /* Check we are committed */
- if (!m_bCommitted) {
- return VFW_E_NOT_COMMITTED;
- }
- /* Check if the one we want is there */
- CMediaSample *pSearch = m_lFree.Head();
- while (pSearch) {
- PBYTE pbBuffer;
- pSearch->GetPointer(&pbBuffer);
- if (pbBuffer == m_pbNext) {
- m_lFree.Remove(pSearch);
- pSample = pSearch;
- ASSERT(m_lSize == pSample->GetSize());
- m_pbNext += m_lSize;
- if (m_pbNext == m_pBuffer + m_lSize * m_lCount) {
- m_pbNext = m_pBuffer;
- }
- break;
- } else {
- pSearch = m_lFree.Next(pSearch);
- }
- }
- if (pSample == NULL) {
- /* If there were some samples but just not ours someone
- else may be waiting
- */
- if (m_lFree.GetCount() != 0) {
- NotifySample();
- }
- SetWaiting();
- }
- }
- /* If we didn't get a sample then wait for the list to signal */
- if (pSample) {
- break;
- }
- ASSERT(m_hSem != NULL);
- DbgLog((LOG_TRACE, 4, TEXT("Waiting - %d buffers available"),
- m_lFree.GetCount()));
- WaitForSingleObject(m_hSem, INFINITE);
- }
- #ifdef VFW_S_CANT_CUE
- /* Addref the buffer up to one. On release
- back to zero instead of being deleted, it will requeue itself by
- calling the ReleaseBuffer member function. NOTE the owner of a
- media sample must always be derived from CBaseAllocator */
- ASSERT(pSample->m_cRef == 0);
- pSample->m_cRef = 1;
- *ppBuffer = pSample;
- #else
- /* This QueryInterface should addref the buffer up to one. On release
- back to zero instead of being deleted, it will requeue itself by
- calling the ReleaseBuffer member function. NOTE the owner of a
- media sample must always be derived from CBaseAllocator */
- HRESULT hr = pSample->QueryInterface(IID_IMediaSample, (void **)ppBuffer);
- /* For each sample outstanding, we need to AddRef ourselves on his behalf
- he cannot do it, as there is no correct ordering of his release and his
- call to ReleaseBuffer as both could destroy him. We release this count
- in ReleaseBuffer, called when the sample's count drops to zero */
- AddRef();
- #endif
- return NOERROR;
- }
- HRESULT CSequentialAllocator::Alloc()
- {
- CAutoLock lck(this);
- if (m_parSamples != NULL) {
- delete [] m_parSamples;
- }
- m_parSamples = new LPCMEDIASAMPLE[m_lCount];
- if (m_parSamples == NULL) {
- return E_OUTOFMEMORY;
- }
- HRESULT hr = CMemAllocator::Alloc();
- if (S_OK == hr) {
- ASSERT(m_lCount == m_lFree.GetCount());
- /* Find the smallest */
- CMediaSample *pSample = m_lFree.Head();
- m_pBuffer = (PBYTE)(DWORD)-1;
- for (; pSample != NULL; pSample = m_lFree.Next(pSample)) {
- PBYTE pbTemp;
- pSample->GetPointer(&pbTemp);
- if (m_pBuffer > pbTemp) {
- m_pBuffer = pbTemp;
- }
- }
- pSample = m_lFree.Head();
- for ( ;pSample != NULL; pSample = m_lFree.Next(pSample)) {
- PBYTE pbTemp;
- pSample->GetPointer(&pbTemp);
- m_parSamples[BufferIndex(pbTemp)] = pSample;
- }
- }
- m_pbStartValid = m_pBuffer;
- m_pbNext = m_pBuffer;
- ASSERT(m_lValid == 0);
- return hr;
- }
- /* Get buffer index */
- int CSequentialAllocator::BufferIndex(PBYTE pbBuffer)
- {
- int iPos = (pbBuffer - m_pBuffer) / m_lSize;
- // xxx
- /*ASSERT(iPos < m_lCount);*/
- return iPos;
- }
- /* Given an address get the IMediaSample pointer -
- NB needs optimizing
- */
- CMediaSample *CSequentialAllocator::SampleFromBuffer(PBYTE pBuffer)
- {
- return m_parSamples[BufferIndex(pBuffer)];
- }
- /* Add a buffer to the valid list */
- void CSequentialAllocator::AddBuffer(CMediaSample *pSample)
- {
- /* Don't get fooled by 0 length buffers ! */
- if (pSample->GetActualDataLength() == 0) {
- return;
- }
- pSample->AddRef();
- #ifdef DEBUG
- PBYTE pbBuffer;
- pSample->GetPointer(&pbBuffer);
- ASSERT(m_pbStartValid + m_lValid == pbBuffer);
- #endif
- m_lValid += pSample->GetActualDataLength();
- }
- /* Step through valid data */
- HRESULT CSequentialAllocator::Advance(LONG lAdvance)
- {
- /* For every sample boundary we step over we should Release()
- a buffer
- */
- int iStart = BufferIndex(m_pbStartValid);
- int iEnd = BufferIndex(m_pbStartValid + lAdvance);
- m_lValid -= lAdvance;
- m_pbStartValid += lAdvance;
- /* If we're at the end and the last buffer wasn't full move on
- to the next
- */
- if (m_lValid == 0 &&
- (m_pbStartValid - m_pBuffer) % m_lSize != 0) {
- iEnd++;
- m_pbStartValid = m_pBuffer + m_lSize * iEnd;
- }
- while (iStart != iEnd) {
- m_parSamples[iStart]->Release();
- iStart++;
- }
- /*
- ASSERT(m_lValid <= (m_lCount * m_lSize) / 2);
- */
- /*
- If we're already into the last buffer and about to wrap
- NOTE m_Valid CAN be > m_lSize - hit it with a huge
- PROGRAM_STREAM_DIRECTORY packet (can be almost 64K)
- */
- if (m_pbStartValid + m_lValid == m_pBuffer + m_lSize * m_lCount) {
- return Wrap();
- } else {
- return S_OK;
- }
- }
- /* Get the valid part */
- PBYTE CSequentialAllocator::GetValid(LONG *plValid)
- {
- *plValid = m_lValid;
- return m_pbStartValid;
- }
- /* Wrap end to go back to start */
- HRESULT CSequentialAllocator::Wrap(void)
- {
- if (m_lValid != 0) {
- /* Make sure the copy will work */
- ASSERT(m_lValid <= (m_lSize * m_lCount) / 2);
- IMediaSample *pSample;
- /* These samples will be AddRef'd already */
- int nBuffers = (m_lValid + m_lSize - 1) / m_lSize;
- ASSERT(nBuffers <= m_lCount / 2);
- for (int i = 0; i < nBuffers; i++) {
- HRESULT hr = GetBuffer(&pSample, NULL, NULL, 0);
- if (FAILED(hr)) {
- return hr;
- }
- ASSERT(pSample == m_parSamples[i]);
- }
- /* Now copy the data back to the start */
- CopyMemory((PVOID)(m_pBuffer + m_lSize * nBuffers - m_lValid),
- (PVOID)m_pbStartValid,
- m_lValid);
- m_pbStartValid = m_pBuffer + m_lSize * nBuffers - m_lValid;
- /* Release the last buffers since we've effectively
- transferred the ref count to the first one
- */
- for ( ; nBuffers > 0; nBuffers--) {
- m_parSamples[m_lCount - nBuffers]->Release();
- }
- } else {
- m_pbStartValid = m_pBuffer;
- }
- return S_OK;
- }
- /* Flush the allocator - just discard all the data in it */
- void CSequentialAllocator::Flush()
- {
- Advance(m_lValid);
- }