Binden von Ausgabeknoten an Mediensenken
In diesem Thema wird beschrieben, wie die Ausgabeknoten in einer Topologie initialisiert werden, wenn Sie das Topologielader außerhalb der Mediensitzung verwenden. Ein Ausgabeknoten enthält zunächst einen der folgenden:
Im letzteren Fall muss der 1000011111111555555555111555511111111555111111101111111111155111111111111111115511111111111111111 In den meisten Szenarien funktioniert der Prozess wie folgt:
- Die Anwendung stellt eine Teiltopologie in der Mediensitzung in die Warteschlange.
- Für alle Ausgabeknoten konvertiert die Mediensitzung die ZEIGER FÜR DIE MEDIENAKTIVIERUNG in DIE ZEIGER DESTStreamSink-Zeigers. Dieser Prozess wird als Binden des Ausgabeknotens an eine Mediensenke bezeichnet.
- Die Mediensitzung sendet die geänderte Topologie an die METHODETOPOLOGYTopoLoader::Load.
Wenn Sie jedoch das Topologielader direkt (außerhalb der Mediensesssion) verwenden, muss Ihre Anwendung die Ausgabeknoten binden, bevor SIE DENKtopoLoader::Load aufruft. Gehen Sie wie folgt vor, um einen Ausgabeknoten zu binden:
- Rufen Sie DIE TOPOLOGIENode::GetObject auf, um den Objektzeiger des Knotens zu erhalten.
- Fragen Sie den Objektzeiger für die BENUTZEROBERFLÄCHEStreamSink-Schnittstelle ab. Wenn dieser Aufruf erfolgreich ist, müssen Sie nichts weiter tun. Überspringen Sie daher die verbleibenden Schritte.
- Wenn im vorherigen Schritt ein Fehler auft ist, fragen Sie den Objektzeiger für die BERACTIVate-Schnittstelle ab.
- Erstellen Sie die Mediensenke, indem Sie DENKActivate::ActivateObject aufrufen. Geben Sie IID _ -15555555 AN, um einen Zeiger auf die BENUTZEROBERFLÄCHE DER MEDIENSenke zu erhalten.
- Fragen Sie den Knoten nach dem MF _ TOPONODE _ STREAMID-Attribut ab. Der Wert dieses Attributs ist der Bezeichner der Streamsenke für diesen Knoten. Wenn das MF _ TOPONODE _ STREAMID-Attribut nicht festgelegt ist, ist der Standardstreambezeichner 0 (null).
- Die entsprechende Streamsenke ist möglicherweise bereits in der Mediensenke vorhanden. Um dies zu überprüfen, rufen Sie FÜR DIE Mediensenke DENKMediaSink::GetStreamSinkById auf. Wenn die Streamsenke vorhanden ist, gibt die -Methode einen Zeiger auf ihre DURCHSTREAMStreamSink-Schnittstelle zurück. Wenn dieser Aufruf fehlschlägt, versuchen Sie, eine neue Streamsenke hinzuzufügen, indem Sie DENKMediaSink::AddStreamSink aufrufen. Wenn beide Aufrufe fehlschlagen, bedeutet dies, dass die Mediensenke den angeforderten Datenstrombezeichner nicht unterstützt und dieser Topologieknoten nicht ordnungsgemäß konfiguriert ist. Geben Sie einen Fehlercode zurück, und überspringen Sie den nächsten Schritt.
- Rufen Sie DIE TOPOLOGIENode::SetObject auf,und übergeben Sie den GENERATORStreamSink-Zeiger aus dem vorherigen Schritt. Dieser Aufruf ersetzt den Objektzeiger des Knotens, sodass der Knoten einen Zeiger auf die Streamsenke anstelle eines Zeigers auf das Aktivierungsobjekt enthält.
Der folgende Code zeigt, wie ein Ausgabeknoten gebunden wird.
// BindOutputNode
// Sets the IMFStreamSink pointer on an output node.
HRESULT BindOutputNode(IMFTopologyNode *pNode)
{
IUnknown *pNodeObject = NULL;
IMFActivate *pActivate = NULL;
IMFStreamSink *pStream = NULL;
IMFMediaSink *pSink = NULL;
// Get the node's object pointer.
HRESULT hr = pNode->GetObject(&pNodeObject);
if (FAILED(hr))
{
return hr;
}
// The object pointer should be one of the following:
// 1. An activation object for the media sink.
// 2. The stream sink.
// If it's #2, then we're already done.
// First, check if it's an activation object.
hr = pNodeObject->QueryInterface(IID_PPV_ARGS(&pActivate));
if (SUCCEEDED(hr))
{
DWORD dwStreamID = 0;
// The object pointer is an activation object.
// Try to create the media sink.
hr = pActivate->ActivateObject(IID_PPV_ARGS(&pSink));
// Look up the stream ID. (Default to zero.)
if (SUCCEEDED(hr))
{
dwStreamID = MFGetAttributeUINT32(pNode, MF_TOPONODE_STREAMID, 0);
}
// Now try to get or create the stream sink.
// Check if the media sink already has a stream sink with the requested ID.
if (SUCCEEDED(hr))
{
hr = pSink->GetStreamSinkById(dwStreamID, &pStream);
if (FAILED(hr))
{
// Try to add a new stream sink.
hr = pSink->AddStreamSink(dwStreamID, NULL, &pStream);
}
}
// Replace the node's object pointer with the stream sink.
if (SUCCEEDED(hr))
{
hr = pNode->SetObject(pStream);
}
}
else
{
// Not an activation object. Is it a stream sink?
hr = pNodeObject->QueryInterface(IID_PPV_ARGS(&pStream));
}
SafeRelease(&pNodeObject);
SafeRelease(&pActivate);
SafeRelease(&pStream);
SafeRelease(&pSink);
return hr;
}
Hinweis
In diesem Beispiel wird die SafeRelease-Funktion verwendet, um Schnittstellenzeigener frei zu geben.
Das nächste Beispiel zeigt, wie alle Ausgabeknoten in einer Topologie gebunden werden. In diesem Beispiel wird die METHODETOPOLOGY::GetOutputNodeCollection verwendet, um eine Auflistung von Ausgabeknoten aus der Topologie zu erhalten. Anschließend wird die im vorherigen Beispiel gezeigte Funktion auf jedem dieser Knoten nacheinander aufruft.
// BindOutputNodes
// Sets the IMFStreamSink pointers on all of the output nodes in a topology.
HRESULT BindOutputNodes(IMFTopology *pTopology)
{
DWORD cNodes = 0;
IMFCollection *pCol = NULL;
IUnknown *pUnk = NULL;
IMFTopologyNode *pNode = NULL;
// Get the collection of output nodes.
HRESULT hr = pTopology->GetOutputNodeCollection(&pCol);
// Enumerate all of the nodes in the collection.
if (SUCCEEDED(hr))
{
hr = pCol->GetElementCount(&cNodes);
}
if (SUCCEEDED(hr))
{
for (DWORD i = 0; i < cNodes; i++)
{
hr = pCol->GetElement(i, &pUnk);
if (FAILED(hr)) { break; }
hr = pUnk->QueryInterface(IID_IMFTopologyNode, (void**)&pNode);
if (FAILED(hr)) { break; }
// Bind this node.
hr = BindOutputNode(pNode);
if (FAILED(hr)) { break; }
}
}
SafeRelease(&pCol);
SafeRelease(&pUnk);
SafeRelease(&pNode);
return hr;
}