BlueStrat BlueStrat - 3 months ago 31
C++ Question

Should I release the returned IMFSample of an internally allocated MFT output buffer?

Media Foundation Transform objects (MFT) may implement an output buffer allocation model where the buffers are allocated internally by the MFT object.

If this is the case, the internally allocated buffer is returned via the

pSample
member of an
MFT_OUTPUT_DATA_BUFFER
structure that is passed to the
IMFTransform::ProcessOutput()
method.

From the MFT_OUTPUT_DATA_BUFFER structure documentation:

typedef struct _MFT_OUTPUT_DATA_BUFFER {
DWORD dwStreamID;
IMFSample *pSample;
DWORD dwStatus;
IMFCollection *pEvents;
} MFT_OUTPUT_DATA_BUFFER;



pSample

Pointer to the
IMFSample
interface. Before calling
ProcessOutput
,
set this member equal to a valid
IMFSample
pointer or
NULL
. See
Remarks for more information.


From the IMFTransform::ProcessOutput documentation:

Output Buffers


The MFT returns output data for a stream through the
pSample
member
of the
MFT_OUTPUT_DATA_BUFFER
structure. This structure member is a
pointer to the
IMFSample
interface of a media sample. (See Media
Samples.) The media sample is allocated either by the caller or by the
MFT, depending on the MFT's allocation model.
To find the allocation
model, call
IMFTransform::GetOutputStreamInfo
and examine the
dwFlags
member of the
MFT_OUTPUT_STREAM_INFO
structure


...


If
pSample
is
NULL
and
dwFlags
does not contain the
MFT_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER
, the MFT provides a sample
for the output data. The MFT sets
pSample
to point to the sample
that it provides. The MFT can either allocate a new sample or re-use
an input sample.


The documentation does not mention if the returned
IMFSample
interface in this case should be released.
It seems this is not the case, since the documentation is very explicit that any events returned via the same struct should be released by the caller.

From the MFT_OUTPUT_DATA_BUFFER structure documentation:


pEvents

Before calling
ProcessOutput
, set this member to
NULL
. On output,
the MFT might set this member to a valid
IMFCollection

interface pointer. The pointer represents a collecton that contains
zero or more events. To get each event, call
IMFCollection::GetElement
and query the returned
IUnknown
pointer
for the
IMFMediaEvent
interface. When the
ProcessOutput
method
returns, the caller is responsible for releasing the
IMFCollection

pointer if the pointer is not
NULL
.



Can somebody confirm if the returned
IMFSample
interface should be released or not?


I think that If we should not release the returned interface, it should be documented explicitly, as it goes against the established COM way of releasing the interface once we have finished using it.

Answer

The caller is responsible to release the sample if the pointer was initialized with a non-NULL value by the MFT (as opposed to buffer allocated by the caller - in which case the MFT uses it but does not need to AddRef it in the structure).

Code snippet good for all modes (normal, "MFT can provide samples", "MFT provides samples"), it's not to be perfect though, just an illustration:

CComPtr<IMFSample> pSample;
// pSample is NULL or not
MFT_OUTPUT_DATA_BUFFER Buffer;
Buffer.pSample = pSample.Detach();
const HRESULT nResult = pTransform->ProcessOutput(...);
pSample.Attach(Buffer.pSample);
// pSample holds a valid properly ref'fed pointer
// No need to use Buffer.pSample below