MF(三)拓扑



   拓扑是代表着Media Session 中的管道,代表着数据流。 Media Session 用拓扑来控制着数据流的走向。
   拓扑是由结点组成,结点是管道中的对象, 每一个节点可能是 Media Source, MFT, Media Sinks,节点之间用线连接起来,表示数据流的路径。 结点分为四种类型:
   1. Source Node: 代表数据源, Media Source
   2. Transform Node: 代表 MFT, 处理单元/对象
   3. Output Node: 代码了数据的消耗者, Media Sink
   4. Tee Node: 代表数据流的一份拷贝
 
   可以通过调用函数MFCreateTopology 来创建拓扑, 这个函数返回一个指针,指向IMFTopology 接口。
   刚刚创建的拓扑中是不包含任何结点的, 可以调用函数 MFCreateTopologyNode 来创建拓扑结点, 这个函数返回一个指针,指向  IMFTopologyNode 接口。 创建节点的时候,必须要指点结点类型。
   对于不同的节点类型的创建,有些细节的区别:
   1. Source Nodes
      - 在调用函数MFCreateTopologyNode 时,需要传递参数MF_TOPOLOGY_SOURCESTREAM_NODE
      - 必须有一个指针指向 Media Source。  hr = pNode->SetUnknown(MF_TOPONODE_SOURCE, pSource);
      - 必须有一个指针指向 Presentation Descriptor。
      - 必须有一个指针指向 Stream Descriptor
      - 调用 IMFTopology::AddNode, 把新创建的所有拓扑结点加入拓扑中

      参考代码如下:

     

// Add a source node to a topology.
HRESULT AddSourceNode(
    IMFTopology *pTopology,           // Topology.
    IMFMediaSource *pSource,          // Media source.
    IMFPresentationDescriptor *pPD,   // Presentation descriptor.
    IMFStreamDescriptor *pSD,         // Stream descriptor.
    IMFTopologyNode **ppNode)         // Receives the node pointer.
{
    IMFTopologyNode *pNode = NULL;

    // Create the node.
    HRESULT hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &pNode);
    if (FAILED(hr))
    {
        goto done;
    }

    // Set the attributes.
    hr = pNode->SetUnknown(MF_TOPONODE_SOURCE, pSource);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pPD);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, pSD);
    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;
}



  2. Transform Nodes
     - 创建 MFT 实例,得到 IMFTransform 接口
     - 调用函数MFCreateTopologyNode, 传递参数 MF_TOPOLOGY_TRANSFORM_NODE
     - 调用 IMFTopologyNode::SetObject 设置MFT 对象(传递 IMFTransform 指针)
     - 调用 IMFTopology::AddNode 把结点加入拓扑中

      参考代码如下:

HRESULT AddTransformNode(
    IMFTopology *pTopology,     // Topology.
    IMFTransform *pMFT,         // MFT.
    IMFTopologyNode **ppNode    // Receives the node pointer.
    )
{
    *ppNode = NULL;

    IMFTopologyNode *pNode = NULL;
    
    // Create the node.
    HRESULT hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &pNode);

    // Set the object pointer.
    if (SUCCEEDED(hr))
    {
        hr = pNode->SetObject(pMFT);
    }

    // Add the node to the topology.
    if (SUCCEEDED(hr))
    {
        hr = pTopology->AddNode(pNode);
    }

    // Return the pointer to the caller.
    if (SUCCEEDED(hr))
    {
        *ppNode = pNode;
        (*ppNode)->AddRef();
    }

    SafeRelease(&pNode);
    return hr;
}



  3. Output Nodes (创建节点从 stream Sink)
     - 创建一个Media Sink 实例,通过 IMFMediaSink 接口得到想要的Stream Sink
     - 调用函数MFCreateTopologyNode, 传递参数 MF_TOPOLOGY_OUTPUT_NODE
     - IMFTopologyNode::SetObject, 设置Stream Sink 对象(传递  IMFStreamSink 指针)
     - 设置属性 MF_TOPONODE_NOSHUTDOWN_ON_REMOVE  为 FALSE (推荐)
     - 调用IMFTopology::AddNode 把结点加入拓扑中

      参考代码如下:

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



   4. Output Nodes (创建节点从 Activation Object)
     - 创建 Activation Object ,得到 IMFActivate  接口
     - 调用函数MFCreateTopologyNode, 传递参数 MF_TOPOLOGY_OUTPUT_NODE
     - 设置属性 MF_TOPONODE_NOSHUTDOWN_ON_REMOVE  为 TRUE (推荐)
     -  IMFTopologyNode::SetObject 传递 IMFActivate  指针
     - 调用IMFTopology::AddNode 把结点加入拓扑中

参考代码如下:

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


   拓扑结点之间相互连接关系是通过 IMFTopologyNode::ConnectOutput 函数来设置的,可以把上下游的关系建立起来。

你可能感兴趣的:(Media,Foundataion)