Binden von Ausgabeknoten an Mediensenken

In diesem Thema wird beschrieben, wie Sie die Ausgabeknoten in einer Topologie initialisieren, wenn Sie den Topologieladeprogramm außerhalb der Mediensitzung verwenden. Ein Ausgabeknoten enthält zunächst eine der folgenden Komponenten:

Im letzteren Fall muss der IMFActivate-Zeiger in einen IMFStreamSink-Zeiger konvertiert werden, bevor der Topologieladeprogramm die Topologie auflöst. In den meisten Szenarien funktioniert der Prozess wie folgt:

  1. Die Anwendung stellt eine partielle Topologie in der Mediensitzung in die Warteschlange.
  2. Für alle Ausgabeknoten konvertiert die Mediensitzung IMFActivate-Zeiger in IMFStreamSink-Zeiger . Dieser Prozess wird als Binden des Ausgabeknotens an eine Mediensenke bezeichnet.
  3. Die Mediensitzung sendet die geänderte Topologie an die IMFTopoLoader::Load-Methode .

Wenn Sie den Topologieladeprogramm jedoch direkt (außerhalb der Medienabsesssion) verwenden, muss Ihre Anwendung die Ausgabeknoten vor dem Aufrufen von IMFTopoLoader::Load binden. Gehen Sie wie folgt vor, um einen Ausgabeknoten zu binden:

  1. Rufen Sie IMFTopologyNode::GetObject auf, um den Objektzeiger des Knotens abzurufen.
  2. Fragen Sie den Objektzeiger für die IMFStreamSink-Schnittstelle ab. Wenn dieser Aufruf erfolgreich ist, müssen Sie nichts mehr tun. Überspringen Sie also die verbleibenden Schritte.
  3. Wenn der vorherige Schritt fehlgeschlagen ist, fragen Sie den Objektzeiger für die IMFActivate-Schnittstelle ab .
  4. Erstellen Sie die Mediensenke, indem Sie IMFActivate::ActivateObject aufrufen. Geben Sie IID_IMFMediaSink an, um einen Zeiger auf die IMFMediaSink-Schnittstelle der Mediensenke zu erhalten.
  5. 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 attribut MF_TOPONODE_STREAMID nicht festgelegt ist, ist der Standarddatenstrombezeichner null.
  6. Die entsprechende Streamsenke ist möglicherweise bereits auf der Mediensenke vorhanden. Rufen Sie zur Überprüfung IMFMediaSink::GetStreamSinkById auf der Mediensenke auf. Wenn die Streamsenke vorhanden ist, gibt die Methode einen Zeiger auf ihre IMFStreamSink-Schnittstelle zurück. Wenn dieser Aufruf fehlschlägt, versuchen Sie, eine neue Streamsenke hinzuzufügen, indem Sie IMFMediaSink::AddStreamSink aufrufen. Wenn beide Aufrufe fehlschlagen, bedeutet dies, dass die Mediensenke den angeforderten Streambezeichner nicht unterstützt und dieser Topologieknoten nicht ordnungsgemäß konfiguriert ist. Geben Sie einen Fehlercode zurück, und überspringen Sie den nächsten Schritt.
  7. Rufen Sie IMFTopologyNode::SetObject auf, und übergeben Sie den IMFStreamSink-Zeiger aus dem vorherigen Schritt. Dieser Aufruf ersetzt den Objektzeiger des Knotens, sodass der Knoten anstelle eines Zeigers auf das Aktivierungsobjekt einen Zeiger auf die Streamsenke enthält.

Der folgende Code zeigt, wie sie einen Ausgabeknoten binden.

// 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 Schnittstellenzeiger freizugeben.

 

Im nächsten Beispiel wird gezeigt, wie alle Ausgabeknoten in einer Topologie gebunden werden. In diesem Beispiel wird die IMFTopology::GetOutputNodeCollection-Methode verwendet, um eine Auflistung von Ausgabeknoten aus der Topologie abzurufen. Anschließend wird die im vorherigen Beispiel gezeigte Funktion auf jedem dieser Knoten nacheinander aufgerufen.

// 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;
}

Erweiterte Topologieerstellung

Mediensenken

IMFTopoLoader