ALLOC.H

//==========================================================================; 
//
// 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.
//
//--------------------------------------------------------------------------;
/* Allocator for sequential buffers
Like CBaseAllocator BUT always allocates the next buffer
*/

typedef CMediaSample *LPCMEDIASAMPLE;

class CSequentialAllocator : public CMemAllocator
{
public:
CSequentialAllocator(
LPUNKNOWN pUnk,
HRESULT *phr
);

~CSequentialAllocator();

STDMETHODIMP GetBuffer(
IMediaSample **ppBuffer,
REFERENCE_TIME * pStartTime,
REFERENCE_TIME * pEndTime,
DWORD dwFlags);

HRESULT Alloc();

/* Get buffer index */
int BufferIndex(PBYTE pbBuffer);

/* Given an address get the IMediaSample pointer -
NB needs optimizing
*/
CMediaSample *SampleFromBuffer(PBYTE pBuffer);

/* Add a buffer to the valid list */
void AddBuffer(CMediaSample *pSample);

/* Step through valid data */
HRESULT Advance(LONG lAdvance);

/* Get the valid part */
PBYTE GetValid(LONG *plValid);

/* Wrap end to go back to start */
HRESULT Wrap(void);

/* Flush the allocator - just discard all the data in it */
void Flush();

private:
PBYTE m_pbNext;
LPCMEDIASAMPLE *m_parSamples;

/* Simple wrap around buffer stuff */
LONG m_lValid;
PBYTE m_pbStartValid;
PBYTE m_pBuffer; /* Copy of CMemAllocator's which is private */
};

/* Allocator for subsamples */
class CSubAllocator : public CBaseAllocator
{
public:
CSubAllocator(
LPUNKNOWN pUnk,
HRESULT *phr,
CSequentialAllocator *pAlloc
) : CBaseAllocator(NAME("CSubAllocator"), pUnk, phr),
m_pAlloc(pAlloc)
{
}

CMediaSample *GetSample(PBYTE pbData, DWORD dwLen)
{
HRESULT hr = S_OK;
CMediaSample *pSample = new CMediaSample(
NAME("CMediaSample"),
this,
&hr,
pbData,
dwLen);
if (pSample != NULL) {

/* We only need to lock the first buffer because
the super allocator allocates samples sequentially
so it can't allocate subsequent samples until
the first one has been freed
*/
m_pAlloc->SampleFromBuffer(pbData)->AddRef();

/* AddRef() ourselves too to conform to the rules */
pSample->AddRef();

/* Make sure WE don't go away too ! */
AddRef();
}
return pSample;
}

STDMETHODIMP ReleaseBuffer(IMediaSample * pSample)
{
/* Free the superallocator's buffer */
CMediaSample *pMediaSample = (CMediaSample *)pSample;
PBYTE pBuffer;
pSample->GetPointer(&pBuffer);
m_pAlloc->SampleFromBuffer(pBuffer)->Release();
delete pMediaSample;

Release();
return NOERROR;
}


/* Must override Free() */
void Free() {}

private:
CSequentialAllocator *const m_pAlloc;
};


/* Track samples in buffer */