Настройка времени остановки воспроизведения

В этом разделе описывается, как задать время остановки воспроизведения при использовании сеанса мультимедиа.

Установка времени остановки перед началом воспроизведения

Перед очередью топологии для воспроизведения можно указать время остановки с помощью атрибута 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. Вызовите МВФTopology::GetTopologyID , чтобы получить идентификатор топологии воспроизведения.

  3. Для каждого выходного узла в топологии вызовите МВФTopologyNodeAttributeEditor::UpdateNodeAttributes. Этот метод принимает идентификатор топологии и указатель на структуру MFTOPONODE_ATTRIBUTE_UPDATE . Инициализировать структуру следующим образом.

    Элемент Значение
    NodeId Идентификатор узла. Чтобы получить идентификатор узла, вызовите 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;
}

Воспроизведение звука и видео