⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alloc.cpp

📁 T264是中国的视频编码自由组织合力开发的264编解码程序
💻 CPP
字号:
//==========================================================================;////  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);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -