Passaggio 6: Controllare la riproduzione

Questo argomento è il passaggio 6 dell'esercitazione Come riprodurre file multimediali con Media Foundation. Il codice completo è illustrato nell'argomento Esempio di riproduzione di sessioni multimediali.

In questo argomento sono incluse le sezioni seguenti:

Avvio della riproduzione

Per avviare la riproduzione, chiama IMFMediaSession::Start. Il codice seguente mostra come iniziare dalla posizione di riproduzione corrente.

//  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();
}

Il metodo Start può anche specificare una posizione iniziale rispetto all'inizio del file; per altre informazioni, vedere l'argomento di riferimento sulle API.

Sospensione della riproduzione

Per sospendere la riproduzione, chiama 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;
}

Arresto della riproduzione

Per arrestare la riproduzione, chiama IMFMediaSession::Stop. Durante l'arresto della riproduzione, l'immagine video viene cancellata e la finestra del video viene disegnata con il colore di sfondo (nero per impostazione predefinita).

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

Aggiornamento della finestra video

L'EVR (Enhanced Video Renderer) disegna il video nella finestra specificata dall'applicazione. Ciò si verifica in un thread separato e, per la maggior parte, l'applicazione non deve gestire questo processo. Se la riproduzione viene sospesa o arrestata, tuttavia, l'EVR deve ricevere una notifica ogni volta che la finestra video riceve un messaggio di WM_PAINT . Ciò consente all'EVR di ridipingere la finestra. Per inviare una notifica a EVR, chiamare il metodo 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;
    }
}

Il codice seguente mostra il gestore per il messaggio di WM_PAINT . Questa funzione deve essere chiamata dal ciclo di messaggi dell'applicazione.

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

Il HasVideo metodo restituisce TRUE se l'oggetto CPlayer ha un puntatore IMFVideoDisplayControl valido. Vedi Passaggio 1: Dichiarare la classe CPlayer.

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

Ridimensionamento della finestra video

Se si ridimensiona la finestra video, aggiornare il rettangolo di destinazione in EVR chiamando il metodo 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;
    }
}

Passaggio 7: Arrestare la sessione multimediale

Riproduzione di audio/video

Come riprodurre file multimediali con Media Foundation