Creating Output Nodes
An output node represents a stream sink on a media sink. There are two ways to initialize an output node:
- From a pointer to the stream sink.
- From a pointer to an activation object for the media sink.
If you are going to load the topology inside the protected media path (PMP), you must use an activation object, so that the media sink can be created inside the protected process. The first approach (using a pointer to the stream sink) does not work with the PMP.
To create an output node from a stream sink, do the following:
- Create an instance of the media sink.
- Use the media sink's IMFMediaSink interface to get a pointer to the desired stream sink. (The IMFMediaSink interface has several methods that return pointers to a stream sink.)
- Call MFCreateTopologyNode with the MF_TOPOLOGY_OUTPUT_NODE flag to create the output node.
- Call IMFTopologyNode::SetObject and pass in a pointer to the stream sink's IMFStreamSink interface.
- Set the MF_TOPONODE_NOSHUTDOWN_ON_REMOVE attribute to FALSE (optional but recommended).
- Call IMFTopology::AddNode to add the node to the topology.
The following example creates and initializes an output node from a stream sink.
HRESULT AddOutputNode(
IMFTopology *pTopology, // Topology.
IMFStreamSink *pStreamSink, // Stream sink.
IMFTopologyNode **ppNode // Receives the node pointer.
)
{
IMFTopologyNode *pNode = NULL;
HRESULT hr = S_OK;
// Create the node.
hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &pNode);
// Set the object pointer.
if (SUCCEEDED(hr))
{
hr = pNode->SetObject(pStreamSink);
}
// Add the node to the topology.
if (SUCCEEDED(hr))
{
hr = pTopology->AddNode(pNode);
}
if (SUCCEEDED(hr))
{
hr = pNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, TRUE);
}
// Return the pointer to the caller.
if (SUCCEEDED(hr))
{
*ppNode = pNode;
(*ppNode)->AddRef();
}
if (pNode)
{
pNode->Release();
}
return hr;
}
When the application shuts down the Media Session, the Media Session automatically shuts down the media sink. Therefore, you cannot re-use the media sink with another instance of the Media Session.
Any trusted media sink must provide an activation object, so that the media sink can be created inside the protected process. For more information, see Activation Objects. The particular function that creates the activation object will depend on the media sink.
To create an output node from an activation object, do the following:
- Create the activation object and get a pointer to the activation object's IMFActivate interface.
- Call MFCreateTopologyNode with the MF_TOPOLOGY_OUTPUT_NODE flag to create the output node.
- Optionally, set the MF_TOPONODE_STREAMID attribute on the node to specify the stream identifier of the stream sink. If you omit this attribute, the node defaults to using stream sink 0.
- Set the MF_TOPONODE_NOSHUTDOWN_ON_REMOVE attribute to TRUE (optional but recommended).
- Call IMFTopologyNode::SetObject and pass in the IMFActivate pointer.
- Call IMFTopology::AddNode to add the node to the topology.
The following example creates and initializes an output node from an activation object.
// Add an output node to a topology.
HRESULT AddOutputNode(
IMFTopology *pTopology, // Topology.
IMFActivate *pActivate, // Media sink activation object.
DWORD dwId, // Identifier of the stream sink.
IMFTopologyNode **ppNode) // Receives the node pointer.
{
IMFTopologyNode *pNode = NULL;
// Create the node.
HRESULT hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &pNode);
if (FAILED(hr))
{
goto done;
}
// Set the object pointer.
hr = pNode->SetObject(pActivate);
if (FAILED(hr))
{
goto done;
}
// Set the stream sink ID attribute.
hr = pNode->SetUINT32(MF_TOPONODE_STREAMID, dwId);
if (FAILED(hr))
{
goto done;
}
hr = pNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE);
if (FAILED(hr))
{
goto done;
}
// Add the node to the topology.
hr = pTopology->AddNode(pNode);
if (FAILED(hr))
{
goto done;
}
// Return the pointer to the caller.
*ppNode = pNode;
(*ppNode)->AddRef();
done:
SafeRelease(&pNode);
return hr;
}