Como definir o tempo de parada de reprodução

Este tópico descreve como definir um tempo de parada para reprodução ao usar a Sessãode Mídia.

Definindo a hora de parada antes do início da reprodução

Antes de enfileirar uma topologia para reprodução, você pode especificar o tempo de parada usando o atributo MF_TOPONODE_MEDIASTOP. Para cada nó de saída na topologia, defina o valor da MF_TOPONODE_MEDIASTOP para o tempo de parada em unidades de 100 nanossegundos.

Observe que a configuração desse atributo após o início da reprodução não tem efeito. Portanto, defina o atributo antes de chamar IMFMediaSession::Start.

O código a seguir mostra como definir o tempo de parada em uma topologia existente.

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

Definindo o tempo de parada após o início da reprodução

Há uma maneira de definir o tempo de parada após a Sessão de Mídia iniciar a reprodução usando a interface IMFTopologyNodeAttributeEditor.

Importante

Essa interface tem uma limitação séria, pois o tempo de parada é especificado como um valor de 32 bits. Isso significa que o tempo máximo de parada que você pode definir usando essa interface é 0xFFFFFFFF ou pouco mais de sete minutos. Essa limitação ocorre devido a uma definição de estrutura incorreta.

 

Para definir o tempo de parada usando a interface IMFTopologyNodeAttributeEditor, execute as etapas a seguir.

  1. Chame MFGetService para obter a interface IMFTopologyNodeAttributeEditor da Sessão de Mídia.

  2. Chame IMFTopology::GetTopologyID para obter a ID da topologia de reprodução.

  3. Para cada nó de saída na topologia, chame IMFTopologyNodeAttributeEditor::UpdateNodeAttributes. Esse método usa a ID da topologia e um ponteiro para uma estrutura MFTOPONODE_ATTRIBUTE_UPDATE. Inicialize a estrutura da seguinte maneira.

    Membro Valor
    NodeId A ID do nó. Para obter a ID do nó, chame IMFTopologyNode::GetTopoNodeID.
    guidAttributeKey MF_TOPONODE_MEDIASTOP
    attrType MF_ATTRIBUTE_UINT64
    u64 O tempo de parada, em unidades de 100 nanossegundos.

     

Tenha cuidado para definir o valor de attrType corretamente. Embora u64 seja um tipo de 32 bits, o método exige que attrType seja definido como MF_ATTRIBUTE_UINT64.

O código a seguir mostra essas etapas.

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

Reprodução de áudio/vídeo