Microsoft DirectX 8.0

CBaseAllocator Class

CBaseAllocator class hierarchy

Abstract base class that implements an allocator. Allocators expose the IMemAllocator interface.

Declaration: Amfilter.h

An allocator is an object that allocates memory buffers. The allocator maintains a list of available buffers. When a client (generally a filter) requests a buffer, the allocator retrieves one from the list. The client fills the buffer with data, and might pass the buffer to another object. Eventually the buffer is released and the allocator returns it to the list of available buffers.

Each buffer is encapsulated by an object called a media sample. Media samples are a way to package pointers to memory blocks within the Component Object Model (COM) framework. Media samples expose the IMediaSample interface, and are implemented using the CMediaSample class. A media sample contains a pointer to the associated buffer, which can be accessed by calling the IMediaSample::GetPointer method.

Typically, the allocator will allocate a contiguous block of memory. Then it creates media samples that contain pointers to addresses within that block. The following illustration shows the relationship between the allocator, the media samples, and the memory block.

How an Allocator Delivers Samples

To use an allocator, perform the following steps:

  1. Call the SetProperties method to specify the buffer requirements, including the number of buffers and the size of each buffer.
  2. Call the Commit method to allocate the buffers.
  3. Call the GetBuffer method to retrieve media samples. This method blocks until the next sample becomes available.
  4. When you are done with each sample, call the IUnknown::Release method on the sample. The sample is not deleted when its reference count reaches zero. Instead, the sample returns to the allocator's free list.
  5. When you are done using the allocator, call the Decommit method to free the memory for the buffers.

The Commit method calls the virtual method Alloc, which allocates the memory for the buffers. The Decommit method calls the pure virtual method Free, which frees the memory. Derived classes must override these two methods.

The CMemAllocator base class derives from CBaseAllocator. The filter base classes use the CMemAllocator class.

Protected Member Variables
m_lFreePointer to a list of available (free) media samples.
m_hSemSemaphore that is signaled when a sample becomes available.
m_lWaitingCount of threads waiting for samples.
m_lCountNumber of buffers to provide.
m_lAllocatedNumber of buffers currently allocated.
m_lSizeSize of each buffer.
m_lAlignmentAlignment of each buffer.
m_lPrefixPrefix of each buffer.
m_bChangedFlag indicating whether the buffer requirements have changed.
m_bCommittedFlag indicating whether the allocator has been committed.
m_bDecommitInProgressFlag indicating whether a decommit operation is in progress.
m_pNotifyPointer to a callback interface, which is called when samples are released.
m_fEnableReleaseCallbackFlag indicating whether the release callback is enabled.
Protected Methods
AllocAllocates memory for the buffers. Virtual.
Public Methods
CBaseAllocatorConstructor method.
~CBaseAllocatorDestructor method.
SetNotifySpecifies a callback method to be called each time a sample is released.
GetFreeCountRetrieves the number of media samples that are not in use.
NotifySampleReleases any threads that are waiting for samples.
SetWaitingIncrements the count of waiting threads.
Pure Virtual Methods
FreeReleases the buffer memory during a decommit operation, after the last media sample is released.
IMemAllocator Methods
SetPropertiesSpecifies the number of buffers to allocate and the size of each buffer.
GetPropertiesRetrieves the number of buffers that the allocator will create, and the buffer properties.
CommitAllocates the memory for the buffers.
DecommitDecommits the buffers.
GetBufferRetrieves a media sample that contains a buffer.
ReleaseBufferReturns a media sample to the list of free media samples.

CBaseAllocator.m_lFree

CBaseAllocator Class

Pointer to a list of available (free) media samples.

Syntax

CSampleList m_lFree;

CBaseAllocator.m_hSem

CBaseAllocator Class

Semaphore that is signaled when a sample becomes available.

Syntax

HANDLE m_hSem;

CBaseAllocator.m_lWaiting

CBaseAllocator Class

Count of threads waiting for samples.

Syntax

long m_lWaiting

CBaseAllocator.m_lCount

CBaseAllocator Class

Number of buffers to provide. The SetProperties method sets this value. The buffers are not allocated until the Commit method is called. The current number of allocated buffers is specifies by the m_lAllocated member variable.

Syntax

long m_lCount;

CBaseAllocator.m_lAllocated

CBaseAllocator Class

Number of buffers currently allocated.

Syntax

long m_lAllocated;

CBaseAllocator.m_lSize

CBaseAllocator Class

Size of each buffer.

Syntax

long m_lSize;

CBaseAllocator.m_lAlignment

CBaseAllocator Class

Alignment of each buffer. The address of each buffer must be an even multiple of this value. The prefix must be calculated into the alignment; see m_lPrefix.

Syntax

long m_lAlignment;

CBaseAllocator.m_lPrefix

CBaseAllocator Class

Prefix of each buffer, in bytes. If the value is non-zero, each buffer pointer returned by the GetBuffer method is preceded by a block of bytes of size m_lPrefix. This memory block is called the prefix. The m_lSize member variable does not include the prefix value.

Syntax

long m_lPrefix;

CBaseAllocator.m_bChanged

CBaseAllocator Class

Flag indicating whether the buffer requirements have changed. The SetProperties method sets the value to TRUE. In a derived class, the pure virtual method Alloc should set the value back to FALSE. Once buffers have been allocated, there is no need to re-allocate them while m_bChanged is FALSE.

Syntax

BOOL m_bChanged;

CBaseAllocator.m_bCommitted

CBaseAllocator Class

Flag indicating whether the allocator has been committed.

Syntax

BOOL m_bCommitted;

CBaseAllocator.m_bDecommitInProgress

CBaseAllocator Class

Flag indicating whether a decommit operation is in progress. The value is TRUE after the Decommit method is called, but before all the buffers have been released. If the value is TRUE, the GetBuffer method fails. Also, the allocator should not deleted itself while the value is TRUE.

Syntax

BOOL m_bDecommitInProgress;

CBaseAllocator.m_pNotify

CBaseAllocator Class

Pointer to a callback interface, which is called when samples are released.

Syntax

IMemAllocatorNotifyCallbackTemp *m_pNotify;

CBaseAllocator.m_fEnableReleaseCallback

CBaseAllocator Class

Flag indicating whether the release callback is enabled. This flag is set in the constructor method. If the value is FALSE, calling the SetNotify method causes an assertion to fire (in debug builds).

Syntax

BOOL m_fEnableReleaseCallback;

CBaseAllocator::Alloc

CBaseAllocator Class

Allocates memory for the buffers.

Syntax

virtual HRESULT Alloc(void);

Return Value

Returns one of the following HRESULT values.

S_FALSEBuffer requirements have not changed.
S_OKBuffer requirements have changed.
VFW_E_SIZENOTSETBuffer requirements were not set.

Remarks

This method is called by the Commit method.

In the base class, this method does not allocate any memory. It returns an error if the buffer requirements were not set, S_FALSE if the requirements have not changed, and S_OK if the requirements have changed.

A derived class should override this method to perform the actual memory allocation. Typically, the derived class will perform the following steps:

  1. Call the base class implementation, to determine whether the memory truly needs allocating.
  2. Allocate memory.
  3. Create CMediaSample objects that contain chunks of memory from step 2.
  4. Add each CMediaSample object to the list of free samples (m_lFree).

For an example, see CMemAllocator::Alloc.

CBaseAllocator::CBaseAllocator

CBaseAllocator Class

Constructor method.

Syntax

CBaseAllocator(
    TCHAR *pName,
    LPUNKNOWN pUnk,
    HRESULT *phr,
    BOOL bEvent = TRUE,
    BOOL fEnableReleaseCallback  = FALSE
);

Parameters

pName
Pointer to a string containing the name of the allocator.
pUnk
Pointer to the owner of this object. If the object is aggregated, pass a pointer to the aggregating object's IUnknown interface. Otherwise, set this parameter to NULL.
phr
Pointer to a variable that receives an HRESULT value indicating the success or failure of the method.
bEvent
Boolean value indicating whether to create a semaphore. If TRUE, the allocator creates a semaphore (m_hSem), which is signaled whenever a sample becomes available. Set the value to FALSE if you are implementing a derived class that does not require a semaphore.
fEnableReleaseCallback
Boolean value indicating whether the release callback mechanism is enabled. Set the value to TRUE if you want to supply a callback interface, which is called when buffers are released. Specify the callback by calling the SetNotify method.

CBaseAllocator::~CBaseAllocator

CBaseAllocator Class

Destructor method.

Syntax

~CBaseAllocator(void);

Syntax

Always call the Decommit method before destroying the object. The base-class destructor cannot call Decommit, because that method calls the pure virtual method Free. Derived classes should override this destructor and call Decommit.

CBaseAllocator::Commit

CBaseAllocator Class

Allocates the memory for the buffers. Implements the IMemAllocator::Commit method.

Syntax

HRESULT Commit(void);

Return Value

Returns an HRESULT value. Possible values include those in the following list.

S_OKSuccess.
VFW_E_SIZENOTSETBuffer requirements were not specified.

Remarks

Before calling this method, call the SetProperties method to specify the buffer requirements.

This method calls the virtual method Alloc to allocate the memory for the buffers. Derived classes can override Alloc. If a decommit operation is pending, it is cancelled.

You must call this method before calling the GetBuffer method.

CBaseAllocator::Decommit

CBaseAllocator Class

Decommits the buffers. Implements the IMemAllocator::Decommit method.

Syntax

HRESULT Decommit(void);

Return Value

Returns S_OK.

Remarks

After this method is called, calls to the GetBuffer method will fail. As samples are released, they get returned to the free list. When the last sample is returned, the allocator calls the Free method, which releases the allocated memory. (In the base class, Free is a pure virtual method.)

In addition, this method releases any threads that are blocked on GetBuffer calls. The calls to GetBuffer fail.

CBaseAllocator::Free

CBaseAllocator Class

Releases the buffer memory during a decommit operation, after the last media sample is released.

Syntax

virtual void Free(void) PURE; 

Remarks

After the Decommit method is called, the allocator calls this method when it releases the last media sample. The derived class must implement this method.

CBaseAllocator::GetBuffer

CBaseAllocator Class

Retrieves a media sample that contains a buffer. Implements the IMemAllocator::GetBuffer method.

Syntax

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

Parameters

ppBuffer
Address of a variable that receives a pointer to the buffer's IMediaSample interface.
pStartTime
Pointer to the start time of the sample.
pEndTime
Pointer to the end time of the sample.
dwFlags
Bitwise combination of zero or more flags. The base class supports the following flag:
  • AM_GBF_NOWAIT: Do not wait for a buffer to become available.

Return Value

Returns one of the following HRESULT values.

S_OKSuccess.
VFW_E_NOT_COMMITTEDAllocator was not committed.
VFW_E_TIMEOUTTimed out.

Remarks

Unless the caller specifies the AM_GBF_NOWAIT flag in dwFlags, this method blocks until the next sample is available.

The retrieved media sample has a valid pointer to the allocated buffer. The caller is responsible for setting any other properties on the sample, such as the time stamps, the media times, or the sync-point property. For more information, see IMediaSample.

In the base class, the pStartTime and pEndTime parameters are ignored. Derived classes can use these values. For example, the allocator for the Video Renderer filter uses these values to synchronize switching between Microsoft® DirectDraw® surfaces.

If the method needs to wait on a sample, it increments the count of waiting objects (m_lCount) and the calls WaitForSingleObject function on the semaphore (m_hSem). When a sample becomes available, it calls the IBaseAllocator::ReleaseBuffer method on the allocator, which increases the semaphore count by m_lCount (thereby releasing the waiting threads) and sets m_lCount back to zero.

CBaseAllocator::GetFreeCount

CBaseAllocator Class

Retrieves the number of media samples that are not in use.

Syntax

HRESULT GetFreeCount(
    LONG *plBuffersFree
);

Parameters

plBuffersFree
Address of a variable that receives the number of samples that are not in use.

Return Value

Returns S_OK.

Remarks

This value includes samples on the free list (m_lFree) and samples that were deleted.

CBaseAllocator::GetProperties

CBaseAllocator Class

Retrieves the number of buffers that the allocator will create, and the buffer properties. Implements the IMemAllocator::GetProperties method.

Syntax

HRESULT GetProperties(
    ALLOCATOR_PROPERTIES *pProps
);

Parameters

pProps
Pointer to an ALLOCATOR_PROPERTIES structure that receives the allocator properties.

Return Value

Returns S_OK.

CBaseAllocator::NotifySample

CBaseAllocator Class

Releases any threads that are waiting for samples.

Syntax

void NotifySample(void);

Remarks

When there are threads waiting for samples, the value of m_lWaiting is greater than zero. If m_lWaiting is greater than zero, this method calls the ReleaseSemaphore function on the m_hSem semaphore, activating any waiting threads. It also resets m_lWaiting to zero.

This method is called from within the ReleaseBuffer method, when a sample is returned to the free list; and from the Decommit method, when the allocator is decommitted.

CBaseAllocator::ReleaseBuffer

CBaseAllocator Class

Returns a media sample to the list of free media samples. Implements the IMemAllocator::ReleaseBuffer method.

Syntax

HRESULT ReleaseBuffer(
    IMediaSample *pSample
);

Parameters

pSample
Pointer to the IMediaSample interface of the media sample object.

Return Value

Returns S_OK.

Remarks

When a media sample's reference count reaches zero, the sample calls ReleaseBuffer with itself as the parameter. This method performs the following actions.

CBaseAllocator::SetNotify

CBaseAllocator Class

Specifies a callback method to be called each time a sample is released.

Syntax

HRESULT SetNotify(
    IMemAllocatorNotifyCallbackTemp *pNotify
);

Parameters

pNotify
Pointer to an IMemAllocatorNotifyCallbackTemp interface, implemented by the caller.

Return Value

Returns S_OK.

Remarks

This method sets the m_pNotify member variable equal to pNotify and increments the reference count on the interface. If m_pNotify is non-NULL, the ReleaseBuffer method calls IMemAllocatorNotifyCallbackTemp::NotifyRelease. The call can occur in any context, so when you implement the NotifyRelease method, be careful not to make calls that could block. For example, limit the method to setting an event or posting a message for another thread.

CBaseAllocator::SetProperties

CBaseAllocator Class

Specifies the number of buffers to allocate and the size of each buffer. Implements the IMemAllocator::SetProperties method.

Syntax

HRESULT SetProperties(
    ALLOCATOR_PROPERTIES *pRequest,
    ALLOCATOR_PROPERTIES *pActual
);

Parameters

pRequest
Pointer to an ALLOCATOR_PROPERTIES structure that contains the buffer requirements.
pActual
Pointer to an ALLOCATOR_PROPERTIES structure that receives the actual buffer properties.

Return Value

Returns one of the following HRESULT values.

S_OKSuccess.
E_POINTERNULL pointer argument.
VFW_E_ALREADY_COMMITTEDCannot change allocated memory while the filter is active.
VFW_E_BADALIGNAn invalid alignment was specified.
VFW_E_BUFFERS_OUTSTANDINGOne or more buffers are still active.

Remarks

This method specifies the buffer requirements, but does not allocate any buffers. Call the Commit method to allocate buffers.

The caller allocates two ALLOCATOR_PROPERTIES structures. The pRequest parameter contains the caller's buffer requirements, including the number of buffers and the size of each buffer. When the method returns, the pActual parameter contains the actual buffer properties, as set by the allocator. In the base class, assuming that the method succeeds, the actual properties always match the requested properties. Derived classes might override this behavior.

The allocator must not be committed, and must not have outstanding buffers. In the base class, the alignment must equal 1. The CMemAllocator class overrides this requirement.

CBaseAllocator::SetWaiting

CBaseAllocator Class

Increments the count of waiting threads.

Syntax

void SetWaiting(void);

Remarks

This method increments the m_lWaiting member variable. If a thread is blocked in the CBaseAllocator::GetBuffer method, the allocator calls SetWaiting and then waits for the m_hSem semaphore to be signalled. The ReleaseBuffer method signals the semaphore and sets m_lWaiting back to zero.