Cómo establecer el tiempo de detención de reproducción

En este tema se describe cómo establecer un tiempo de detención para la reproducción cuando se usa la sesión multimedia.

Establecer la hora de detención antes de que comience la reproducción

Antes de poner en cola una topología para la reproducción, puede especificar la hora de detención mediante el atributo MF_TOPONODE_MEDIASTOP. Para cada nodo de salida de la topología, establezca el valor del argumento MF_TOPONODE_MEDIASTOP en la hora de detención en unidades de 100 nanosegundos.

Tenga en cuenta que establecer este atributo después de que se inicie la reproducción no tiene ningún efecto. Por lo tanto, establezca el atributo antes de llamar a IMFMediaSession::Start.

El siguiente código muestra cómo establecer la hora de parada en una topología 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;
}

Establecer la hora de detención después de que se haya iniciado la reproducción

Existe una forma de establecer el tiempo de detención después de que la sesión multimedia inicie la reproducción, utilizando la interfaz IMFTopologyNodeAttributeEditor.

Importante

Esta interfaz tiene una limitación grave, ya que el tiempo de detención se especifica como un valor de 32 bits. Esto significa que el tiempo máximo de detención que se puede establecer mediante esta interfaz es 0xFFFFFFFF, es decir, algo más de 7 minutos. Esta limitación se debe a una definición de estructura incorrecta.

 

Para establecer el tiempo de detención mediante la interfaz IMFTopologyNodeAttributeEditor, realice los pasos siguientes.

  1. Llame a MFGetService para obtener la interfaz IMFTopologyNodeAttributeEditor desde la sesión multimedia.

  2. Llame a IMFTopology::GetTopologyID para obtener el identificador de la topología de reproducción.

  3. Para cada nodo de salida de la topología, llame a IMFTopologyNodeAttributeEditor::UpdateNodeAttributes. Este método toma el identificador de topología y un puntero a una estructura MFTOPONODE_ATTRIBUTE_UPDATE. Inicialice la estructura como se indica a continuación.

    Miembro Valor
    NodeId El identificador del nodo. Para obtener el identificador de nodo, llame a IMFTopologyNode::GetTopoNodeID.
    guidAttributeKey MF_TOPONODE_MEDIASTOP
    attrType MF_ATTRIBUTE_UINT64
    u64 Tiempo de detención, en unidades de 100 nanosegundos.

     

Tenga cuidado de establecer correctamente el valor de attrType. Aunque u64 es un tipo de 32 bits, el método requiere que attrType se establezca en MF_ATTRIBUTE_UINT64.

El siguiente código muestra estos pasos:

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

Reproducción de audio y vídeo