如何设置播放停止时间

本主题介绍如何在使用媒体会话时设置播放的停止时间。

在播放开始前设置停止时间

在对拓扑进行排队播放之前,可以使用 MF_TOPONODE_MEDIASTOP 属性指定停止时间。 对于拓扑中的每个输出节点,请将 MF_TOPONODE_MEDIASTOP 的值设置为停止时间(以 100 纳秒为单位)。

请注意,在播放开始后设置此属性不起作用。 因此,请在调用 IMFMediaSession::Start 之前设置该属性。

以下代码演示如何在现有拓扑上设置停止时间。

template <class Q>
HRESULT GetCollectionObject(IMFCollection *pCollection, DWORD dwIndex, Q **ppObject)
{
    *ppObject = NULL;   // zero output

    IUnknown *pUnk = NULL;
    HRESULT hr = pCollection->GetElement(dwIndex, &pUnk);
    if (SUCCEEDED(hr))
    {
        hr = pUnk->QueryInterface(IID_PPV_ARGS(ppObject));
        pUnk->Release();
    }
    return hr;
}

HRESULT SetMediaStop(IMFTopology *pTopology, const LONGLONG& stop)
{
    IMFCollection *pCol = NULL;
    DWORD cNodes;

    HRESULT hr = pTopology->GetSourceNodeCollection(&pCol);
    if (SUCCEEDED(hr))
    {
        hr = pCol->GetElementCount(&cNodes);
    }
    if (SUCCEEDED(hr))
    {
        for (DWORD i = 0; i < cNodes; i++)
        {
            IMFTopologyNode *pNode;
            hr = GetCollectionObject(pCol, i, &pNode);
            if (SUCCEEDED(hr))
            {
                pNode->SetUINT64(MF_TOPONODE_MEDIASTOP, stop);
            }
            pNode->Release();
        }
    }
    SafeRelease(&pCol);
    return hr;
}

在播放开始后设置停止时间

有一种方法可在媒体会话开始后设置停止时间,即使用 IMFTopologyNodeAttributeEditor 接口。

重要

此接口存在严重限制,因为停止时间被指定为 32 位值。 这意味着可以使用此接口设置的最长停止时间为 0xFFFFFFFF,即刚刚超过 7 分钟。 此限制是由于结构定义不正确造成的。

 

若要使用 IMFTopologyNodeAttributeEditor 接口设置停止时间,请执行以下步骤。

  1. 调用 MFGetService,以从媒体会话获取 IMFTopologyNodeAttributeEditor 接口。

  2. 调用 IMFTopology::GetTopologyID,以获取播放拓扑的 ID。

  3. 对于拓扑中的每个输出节点,请调用 IMFTopologyNodeAttributeEditor::UpdateNodeAttributes。 此方法采用拓扑 ID 和指向 MFTOPONODE_ATTRIBUTE_UPDATE 结构的指针。 按如下所示初始化结构。

    成员
    NodeId 节点 ID。 若要获取节点 ID,请调用 IMFTopologyNode::GetTopoNodeID
    guidAttributeKey MF_TOPONODE_MEDIASTOP
    attrType MF_ATTRIBUTE_UINT64
    u64 停止时间(以 100 纳秒为单位)。

     

请务必正确设置 attrType 的值。 尽管 u64 是 32 位类型,但该方法要求将 attrType 设置为 MF_ATTRIBUTE_UINT64

以下代码演示了这些步骤。

HRESULT SetMediaStopDynamic(IMFMediaSession *pSession, IMFTopology *pTopology, const LONGLONG& stop)
{
    if (stop > MAXUINT32)
    {
        return E_INVALIDARG;
    }

    IMFTopologyNodeAttributeEditor *pAttr = NULL;
    IMFCollection *pCol = NULL;
    IMFTopologyNode *pNode = NULL;

    HRESULT hr = MFGetService(pSession, MF_TOPONODE_ATTRIBUTE_EDITOR_SERVICE, IID_PPV_ARGS(&pAttr));
    if (FAILED(hr))
    {
        goto done;
    }

    TOPOID id;
    hr = pTopology->GetTopologyID(&id);
    if (FAILED(hr))
    {
        goto done;
    }

    DWORD cNodes;
    hr = pTopology->GetSourceNodeCollection(&pCol);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pCol->GetElementCount(&cNodes);
    if (FAILED(hr))
    {
        goto done;
    }

    for (DWORD i = 0; i < cNodes; i++)
    {
        IMFTopologyNode *pNode;
        hr = GetCollectionObject(pCol, i, &pNode);
        if (FAILED(hr))
        {
            goto done;
        }

        TOPOID nodeID;
        hr = pNode->GetTopoNodeID(&nodeID);
        if (FAILED(hr))
        {
            goto done;
        }

        MFTOPONODE_ATTRIBUTE_UPDATE update;
        update.NodeId = nodeID;
        update.guidAttributeKey = MF_TOPONODE_MEDIASTOP;
        update.attrType = MF_ATTRIBUTE_UINT64;
        update.u64 = (UINT32)stop;

        hr = pAttr->UpdateNodeAttributes(id, 1, &update);
        if (FAILED(hr))
        {
            goto done;
        }
        SafeRelease(&pNode);
    }

done:
    SafeRelease(&pNode);
    SafeRelease(&pCol);
    SafeRelease(&pAttr);
    return hr;
}

音频/视频播放