共用方式為


將輸出節點系結至媒體接收

本主題描述如何在媒體會話外部使用拓撲載入器,初始化拓撲中的輸出節點。 輸出節點一開始包含下列其中一項:

在後者的情況下, IMFActivate 指標必須先轉換成 IMFStreamSink 指標,拓撲載入器才能解析拓撲。 在大部分情況下,此程式的運作方式如下:

  1. 應用程式會將媒體會話上的部分拓撲排入佇列。
  2. 針對所有輸出節點,媒體會話會將 IMFActivate 指標轉換為 IMFStreamSink 指標。 此程式稱為將輸出節點 系結 至媒體接收。
  3. 媒體會話會將修改過的拓撲傳送至 IMFTopoLoader::Load 方法。

不過,如果您使用拓撲載入器直接 (媒體 sesssion) 外部,您的應用程式必須在呼叫 IMFTopoLoader::Load之前系結輸出節點。 若要系結輸出節點,請執行下列動作:

  1. 呼叫 IMFTopologyNode::GetObject 以取得節點的物件指標。
  2. 查詢 IMFStreamSink 介面的物件指標。 如果此呼叫成功,則不會再執行任何動作,因此請略過其餘步驟。
  3. 如果上一個步驟失敗,請查詢 IMFActivate 介面的物件指標。
  4. 呼叫 IMFActivate::ActivateObject來建立媒體接收。 指定 IID_IMFMediaSink 以取得媒體接收之 IMFMediaSink 介面的指標。
  5. 查詢 MF_TOPONODE_STREAMID屬性的 節點。 這個屬性的值是這個節點之資料流程接收的識別碼。 如果未設定 MF_TOPONODE_STREAMID 屬性,則預設資料流程識別碼為零。
  6. 媒體接收上可能已經有適當的資料流程接收。 若要檢查,請在媒體接收上呼叫 IMFMediaSink::GetStreamSinkById 。 如果資料流程接收存在,此方法會傳回其 IMFStreamSink 介面的指標。 如果此呼叫失敗,請嘗試呼叫 IMFMediaSink::AddStreamSink來新增資料流程接收。 如果兩個呼叫失敗,這表示媒體接收不支援要求的資料流程識別碼,而且未正確設定此拓撲節點。 傳回錯誤碼並略過下一個步驟。
  7. 呼叫 IMFTopologyNode::SetObject,傳入上一個步驟中的 IMFStreamSink 指標。 此呼叫會取代節點的物件指標,讓節點包含資料流程接收的指標,而不是啟用物件的指標。

下列程式碼示範如何系結輸出節點。

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

注意

此範例會使用 SafeRelease 函式來釋放介面指標。

 

下一個範例示範如何系結拓撲中的所有輸出節點。 此範例會使用 IMFTopology::GetOutputNodeCollection 方法,從拓撲取得輸出節點的集合。 然後,它會呼叫上述範例中每個節點上所顯示的函式。

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

進階拓撲建置

媒體接收

IMFTopoLoader