Etapa 6: Controlar a reprodução

Este tópico é a etapa 6 do tutorial Como reproduzir arquivos de mídia com o Media Foundation. O código completo é mostrado no tópico Exemplo de Reprodução de Sessão de Mídia.

Este tópico contém as seguintes seções:

Iniciando a reprodução

Para iniciar a reprodução, chame IMFMediaSession::Start. O código a seguir mostra como começar a partir da posição de reprodução atual.

//  Start playback from the current position. 
HRESULT CPlayer::StartPlayback()
{
    assert(m_pSession != NULL);

    PROPVARIANT varStart;
    PropVariantInit(&varStart);

    HRESULT hr = m_pSession->Start(&GUID_NULL, &varStart);
    if (SUCCEEDED(hr))
    {
        // Note: Start is an asynchronous operation. However, we
        // can treat our state as being already started. If Start
        // fails later, we'll get an MESessionStarted event with
        // an error code, and we will update our state then.
        m_state = Started;
    }
    PropVariantClear(&varStart);
    return hr;
}

//  Start playback from paused or stopped.
HRESULT CPlayer::Play()
{
    if (m_state != Paused && m_state != Stopped)
    {
        return MF_E_INVALIDREQUEST;
    }
    if (m_pSession == NULL || m_pSource == NULL)
    {
        return E_UNEXPECTED;
    }
    return StartPlayback();
}

O método Start também pode especificar uma posição inicial em relação ao início do arquivo; consulte o tópico de referência da API para obter mais informações.

Pausando a reprodução

Para pausar a reprodução, chame IMFMediaSession::P ause.

//  Pause playback.
HRESULT CPlayer::Pause()    
{
    if (m_state != Started)
    {
        return MF_E_INVALIDREQUEST;
    }
    if (m_pSession == NULL || m_pSource == NULL)
    {
        return E_UNEXPECTED;
    }

    HRESULT hr = m_pSession->Pause();
    if (SUCCEEDED(hr))
    {
        m_state = Paused;
    }

    return hr;
}

Interrompendo a reprodução

Para interromper a reprodução, chame IMFMediaSession::Stop. Enquanto a reprodução é interrompida, a imagem de vídeo é desmarcada e a janela de vídeo é pintada com a cor da tela de fundo (preto por padrão).

// Stop playback.
HRESULT CPlayer::Stop()
{
    if (m_state != Started && m_state != Paused)
    {
        return MF_E_INVALIDREQUEST;
    }
    if (m_pSession == NULL)
    {
        return E_UNEXPECTED;
    }

    HRESULT hr = m_pSession->Stop();
    if (SUCCEEDED(hr))
    {
        m_state = Stopped;
    }
    return hr;
}

Repintamento da janela de vídeo

O EVR ( Renderizador de Vídeo Avançado ) desenha o vídeo na janela especificada pelo aplicativo. Isso ocorre em um thread separado e, na maioria das vezes, seu aplicativo não precisa gerenciar esse processo. No entanto, se a reprodução estiver pausada ou interrompida, o EVR deverá ser notificado sempre que a janela de vídeo receber uma mensagem WM_PAINT . Isso permite que o EVR repintar a janela. Para notificar o EVR, chame o método IMFVideoDisplayControl::RepaintVideo :

//  Repaint the video window. Call this method on WM_PAINT.

HRESULT CPlayer::Repaint()
{
    if (m_pVideoDisplay)
    {
        return m_pVideoDisplay->RepaintVideo();
    }
    else
    {
        return S_OK;
    }
}

O código a seguir mostra o manipulador da mensagem WM_PAINT . Essa função deve ser chamada do loop de mensagem do aplicativo.

//  Handler for WM_PAINT messages.
void OnPaint(HWND hwnd)
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);

    if (g_pPlayer && g_pPlayer->HasVideo())
    {
        // Video is playing. Ask the player to repaint.
        g_pPlayer->Repaint();
    }
    else
    {
        // The video is not playing, so we must paint the application window.
        RECT rc;
        GetClientRect(hwnd, &rc);
        FillRect(hdc, &rc, (HBRUSH) COLOR_WINDOW);
    }
    EndPaint(hwnd, &ps);
}

O HasVideo método retornará TRUE se o CPlayer objeto tiver um ponteiro IMFVideoDisplayControl válido. (Consulte a Etapa 1: Declarar a classe CPlayer.)

    BOOL          HasVideo() const { return (m_pVideoDisplay != NULL);  }

Redimensionando a janela de vídeo

Se você redimensionar a janela de vídeo, atualize o retângulo de destino no EVR chamando o método IMFVideoDisplayControl::SetVideoPosition :

//  Resize the video rectangle.
//
//  Call this method if the size of the video window changes.

HRESULT CPlayer::ResizeVideo(WORD width, WORD height)
{
    if (m_pVideoDisplay)
    {
        // Set the destination rectangle.
        // Leave the default source rectangle (0,0,1,1).

        RECT rcDest = { 0, 0, width, height };

        return m_pVideoDisplay->SetVideoPosition(NULL, &rcDest);
    }
    else
    {
        return S_OK;
    }
}

Próximo: Etapa 7: Desligar a sessão de mídia

Reprodução de áudio/vídeo

Como reproduzir arquivos de mídia com o Media Foundation