Microsoft DirectX 8.0 |
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.
To use an allocator, perform the following steps:
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_lFree | Pointer to a list of available (free) media samples. |
m_hSem | Semaphore that is signaled when a sample becomes available. |
m_lWaiting | Count of threads waiting for samples. |
m_lCount | Number of buffers to provide. |
m_lAllocated | Number of buffers currently allocated. |
m_lSize | Size of each buffer. |
m_lAlignment | Alignment of each buffer. |
m_lPrefix | Prefix of each buffer. |
m_bChanged | Flag indicating whether the buffer requirements have changed. |
m_bCommitted | Flag indicating whether the allocator has been committed. |
m_bDecommitInProgress | Flag indicating whether a decommit operation is in progress. |
m_pNotify | Pointer to a callback interface, which is called when samples are released. |
m_fEnableReleaseCallback | Flag indicating whether the release callback is enabled. |
Protected Methods | |
Alloc | Allocates memory for the buffers. Virtual. |
Public Methods | |
CBaseAllocator | Constructor method. |
~CBaseAllocator | Destructor method. |
SetNotify | Specifies a callback method to be called each time a sample is released. |
GetFreeCount | Retrieves the number of media samples that are not in use. |
NotifySample | Releases any threads that are waiting for samples. |
SetWaiting | Increments the count of waiting threads. |
Pure Virtual Methods | |
Free | Releases the buffer memory during a decommit operation, after the last media sample is released. |
IMemAllocator Methods | |
SetProperties | Specifies the number of buffers to allocate and the size of each buffer. |
GetProperties | Retrieves the number of buffers that the allocator will create, and the buffer properties. |
Commit | Allocates the memory for the buffers. |
Decommit | Decommits the buffers. |
GetBuffer | Retrieves a media sample that contains a buffer. |
ReleaseBuffer | Returns a media sample to the list of free media samples. |
Pointer to a list of available (free) media samples.
Syntax
CSampleList m_lFree;
Semaphore that is signaled when a sample becomes available.
Syntax
HANDLE m_hSem;
Count of threads waiting for samples.
Syntax
long m_lWaiting
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;
Number of buffers currently allocated.
Syntax
long m_lAllocated;
Size of each buffer.
Syntax
long m_lSize;
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;
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;
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;
Flag indicating whether the allocator has been committed.
Syntax
BOOL m_bCommitted;
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;
Pointer to a callback interface, which is called when samples are released.
Syntax
IMemAllocatorNotifyCallbackTemp *m_pNotify;
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;
Allocates memory for the buffers.
Syntax
virtual HRESULT Alloc(void);
Return Value
Returns one of the following HRESULT values.
S_FALSE Buffer requirements have not changed. S_OK Buffer requirements have changed. VFW_E_SIZENOTSET Buffer 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:
- Call the base class implementation, to determine whether the memory truly needs allocating.
- Allocate memory.
- Create CMediaSample objects that contain chunks of memory from step 2.
- Add each CMediaSample object to the list of free samples (m_lFree).
For an example, see CMemAllocator::Alloc.
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.
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.
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_OK Success. VFW_E_SIZENOTSET Buffer 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.
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.
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.
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_OK Success. VFW_E_NOT_COMMITTED Allocator was not committed. VFW_E_TIMEOUT Timed 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.
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.
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.
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.
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.
- Returns the media sample to the free list (m_lFree).
- Calls the NotifySample method, which releases any threads that are blocked on calls to the GetBuffer method.
- If the SetNotify method was called previously, calls the IMemAllocatorNotifyCallbackTemp::NotifyRelease method.
- When the last sample is released, if there is a pending Decommit call, calls the Free method to release the buffer memory. (In the base class, Free is a pure virtual method.)
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.
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_OK Success. E_POINTER NULL pointer argument. VFW_E_ALREADY_COMMITTED Cannot change allocated memory while the filter is active. VFW_E_BADALIGN An invalid alignment was specified. VFW_E_BUFFERS_OUTSTANDING One 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.
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.