Condividi tramite


Introduzione a MFPlay

[MFPlay è disponibile per l'uso nei sistemi operativi specificati nella sezione Requisiti. Potrebbe essere modificato o non disponibile nelle versioni successive. ]

MFPlay è un'API per la creazione di applicazioni di riproduzione multimediale in C++.

Questo argomento include le sezioni seguenti:

Requisiti

MFPlay richiede Windows 7.

Informazioni su MFPlay

MFPlay ha un modello di programmazione semplice, fornendo al tempo stesso il set principale di funzionalità necessarie per la maggior parte delle applicazioni di riproduzione. Un'applicazione crea un oggetto lettore che controlla la riproduzione. Per riprodurre un file multimediale, l'oggetto lettore crea un elemento multimediale, che può essere usato per ottenere informazioni sul contenuto del file multimediale. L'applicazione controlla la riproduzione tramite metodi sull'interfaccia IMFPMediaPlayer dell'oggetto lettore. Facoltativamente, l'applicazione può ricevere notifiche degli eventi tramite un'interfaccia di callback Il diagramma seguente illustra questo processo.

conceptual diagram: application and player point to each other, both point to media item, which points to media file

Riproduzione di un file multimediale

Per riprodurre un file multimediale, chiamare la funzione MFPCreateMediaPlayer.

// Global variables
IMFPMediaPlayer *g_pPlayer = NULL;

const WCHAR *sURL = L"C:\\Users\\Public\\Videos\\example.wmv";

HRESULT PlayVideo(HWND hwnd, const WCHAR* sURL)
{
    // Create the player object and play a video file.

    return MFPCreateMediaPlayer(
        sURL,
        TRUE,   // Start playback automatically?
        0,      // Flags.
        NULL,   // Callback pointer.
        hwnd,
        &g_pPlayer
        );
}

La funzione MFPCreateMediaPlayer crea una nuova istanza dell'oggetto lettore MFPlay. La funzione accetta i parametri seguenti:

  • Il primo parametro è l'URL del file da aprire. Può trattarsi di un file locale o di un file in un server multimediale.
  • Il secondo parametro specifica se la riproduzione viene avviata automaticamente. Impostando questo parametro su TRUE, il file verrà riprodotto non appena MFPlay lo carica.
  • Il terzo parametro imposta varie opzioni. Per le opzioni predefinite, passare zero (0).
  • Il quarto parametro è un puntatore a un'interfaccia di callback facoltativa. Questo parametro può essere NULL, come illustrato. Il callback è descritto nella sezione Ricezione di eventi dal lettore.
  • Il quinto parametro è un handle per la finestra dell'applicazione. Se il file multimediale contiene un flusso video, il video verrà visualizzato all'interno dell'area client di questa finestra. Per la riproduzione solo audio, questo parametro può essere NULL.

L'ultimo parametro riceve un puntatore all'interfaccia IMFPMediaPlayer dell'oggetto giocatore.

Prima dell'arresto dell'applicazione, assicurarsi di rilasciare il puntatore IMFPMediaPlayer. È possibile eseguire questa operazione nel gestore di messaggi WM_CLOedizione Standard.

void OnClose(HWND /*hwnd*/)
{
    SafeRelease(&g_pPlayer);
    SafeRelease(&g_pPlayerCB);
    PostQuitMessage(0);
}

Nota

In questo esempio viene usata la funzione Cassaforte Release per rilasciare i puntatori all'interfaccia.

 

Per una riproduzione video semplice, questo è tutto il codice necessario. Il resto di questa esercitazione mostrerà come aggiungere altre funzionalità, a partire da come controllare la riproduzione.

Controllo della riproduzione

Il codice illustrato nella sezione precedente riproduce il file multimediale fino a raggiungere la fine del file. Puoi arrestare e avviare la riproduzione chiamando i metodi seguenti sull'interfaccia IMFPMediaPlayer :

  • IMFPMediaPlayer::P ause sospende la riproduzione. Mentre la riproduzione è sospesa, viene visualizzato il fotogramma video più recente e l'audio è invisibile all'utente.
  • IMFPMediaPlayer::Stop arresta la riproduzione. Non viene visualizzato alcun video e la posizione di riproduzione viene reimpostata all'inizio del file.
  • IMFPMediaPlayer::P lay riprende la riproduzione dopo l'arresto o la sospensione.

Il codice seguente sospende o riprende la riproduzione quando si preme LA BARRA SPAZIATRICE.

//-------------------------------------------------------------------
// OnKeyDown
//
// Handles the WM_KEYDOWN message.
//-------------------------------------------------------------------

void OnKeyDown(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags)
{
    HRESULT hr = S_OK;

    switch (vk)
    {
    case VK_SPACE:

        // Toggle between playback and paused/stopped.
        if (g_pPlayer)
        {
            MFP_MEDIAPLAYER_STATE state = MFP_MEDIAPLAYER_STATE_EMPTY;
            
            g_pPlayer->GetState(&state);

            if (state == MFP_MEDIAPLAYER_STATE_PAUSED ||  
                state == MFP_MEDIAPLAYER_STATE_STOPPED)
            {
                g_pPlayer->Play();
            }
            else if (state == MFP_MEDIAPLAYER_STATE_PLAYING)
            {
                g_pPlayer->Pause();
            }
        }
        break;
    }
}

Questo esempio chiama il metodo IMFPMediaPlayer::GetState per ottenere lo stato di riproduzione corrente (sospeso, arrestato o riprodotto) e sospende o riprende di conseguenza.

Ricezione di eventi dal lettore

MFPlay usa un'interfaccia di callback per inviare eventi all'applicazione. Esistono due motivi per questo callback:

  • La riproduzione avviene in un thread separato. Durante la riproduzione, alcuni eventi possono verificarsi, ad esempio raggiungere la fine del file. MFPlay usa il callback per notificare all'applicazione l'evento.
  • Molti dei metodi IMFPMediaPlayer sono asincroni, ovvero restituiscono prima del completamento dell'operazione. I metodi asincroni consentono di avviare un'operazione dal thread dell'interfaccia utente che potrebbe richiedere molto tempo, senza che l'interfaccia utente venga bloccata. Al termine dell'operazione, MFPlay segnala il callback.

Per ricevere notifiche di callback, implementare l'interfaccia IMFPMediaPlayerCallback . Questa interfaccia eredita IUnknown e definisce un singolo metodo OnMediaPlayerEvent. Per configurare il callback, passare un puntatore all'implementazione IMFPMediaPlayerCallback nel parametro pCallback della funzione MFPCreateMediaPlayer.

Di seguito è riportato il primo esempio di questa esercitazione, modificato per includere il callback.

// Global variables.
IMFPMediaPlayer *g_pPlayer = NULL;
IMFPMediaPlayerCallback *g_pCallback = NULL;

// Call an application-defined function to create the callback object.
hr = CreateMyCallback(&g_pCallback);

// Create the player object and play a video file.

const WCHAR *sURL = L"C:\\Users\\Public\\Videos\\example.wmv";

if (SUCCEEDED(hr))
{
    hr = MFPCreateMediaPlayer(
        sURL,
        TRUE,        // Start playback automatically?
        0,           // Flags.
        g_pCallback, // Callback pointer.
        hwnd,
        &g_pPlayer
        );
}

Il metodo OnMediaPlayerEvent ha un singolo parametro, ovvero un puntatore alla struttura MFP_EVENT_HEADER. Il membro eEventType di questa struttura indica quale evento si è verificato. Ad esempio, all'avvio della riproduzione, MFPlay invia l'evento MFP_EVENT_TYPE_PLAY .

Ogni tipo di evento ha una struttura di dati corrispondente che contiene informazioni per tale evento. Ognuna di queste strutture inizia con una struttura MFP_EVENT_HEADER. Nel callback eseguire il cast del puntatore MFP_EVENT_HEADER alla struttura di dati specifica dell'evento. Ad esempio, se il tipo di evento è MFP_PLAY_EVENT, la struttura dei dati è MFP_PLAY_EVENT. Il codice seguente illustra come gestire questo evento nel callback.

void STDMETHODCALLTYPE MediaPlayerCallback::OnMediaPlayerEvent(
    MFP_EVENT_HEADER *pEventHeader
    )
{
    switch (pEventHeader->eEventType)
    {
    case MFP_EVENT_TYPE_PLAY:
        OnPlay(MFP_GET_PLAY_EVENT(pEventHeader));
        break;

    // Other event types (not shown).

    }
}

// Function to handle the event.
void OnPlay(MFP_PLAY_EVENT *pEvent)
{
    if (FAILED(pEvent->header.hrEvent))
    {  
        // Error occurred during playback.
    }  
}

In questo esempio viene utilizzato l'evento MFP_GET_PLAY_EVENT per eseguire il cast del puntatore pEventHeader a una struttura MFP_PLAY_EVENT. HRESULT dell'operazione che ha attivato l'evento viene archiviato nel campo hrEvent della struttura.

Per un elenco di tutti i tipi di evento e delle strutture di dati corrispondenti, vedere MFP_EVENT_TYPE.

Nota sul threading: per impostazione predefinita, MFPlay richiama il callback dallo stesso thread che ha chiamato MFPCreateMediaPlayer. Questo thread deve avere un ciclo di messaggi. In alternativa, puoi passare il flag MFP_OPTION_FRedizione Enterprise_THREADED_CALLBACK nel parametro creationOptions di MFPCreateMediaPlayer. Questo flag fa sì che MFPlay richiami i callback da un thread separato. Entrambe le opzioni hanno implicazioni per l'applicazione. L'opzione predefinita indica che il callback non può eseguire alcuna operazione che attende il ciclo di messaggi, ad esempio l'attesa di un'azione dell'interfaccia utente, perché blocca la routine della finestra. L'opzione free-threaded consente di usare sezioni critiche per proteggere tutti i dati a cui si accede nel callback. Nella maggior parte dei casi, l'opzione predefinita è più semplice.

Recupero di informazioni su un file multimediale

Quando si apre un file multimediale in MFPlay, il lettore crea un oggetto denominato elemento multimediale che rappresenta il file multimediale. Questo oggetto espone l'interfaccia IMFPMediaItem , che è possibile utilizzare per ottenere informazioni sul file multimediale. Molte delle strutture di eventi MFPlay contengono un puntatore all'elemento multimediale corrente. Puoi anche ottenere l'elemento multimediale corrente chiamando IMFPMediaPlayer::GetMediaItem sul lettore.

Due metodi particolarmente utili sono IMFPMediaItem::HasVideo e IMFPMediaItem::HasAudio. Questi metodi consentono di verificare se l'origine multimediale contiene video o audio.

Ad esempio, il codice seguente verifica se il file multimediale corrente contiene un flusso video.

IMFPMediaItem *pItem;
BOOL bHasVideo = FALSE;
BOOL bIsSelected = FALSE;

hr = g_pPlayer->GetMediaItem(TRUE, &pItem);
if (SUCCEEDED(hr))
{
    hr = pItem->HasVideo(&bHasVideo, &bIsSelected);
    pItem->Release();
}

Se il file di origine contiene un flusso video selezionato per la riproduzione, bHasVideo e bIsSelected sono entrambi impostati su TRUE.

Gestione della riproduzione video

Quando MFPlay riproduce un file video, disegna il video nella finestra specificata nella funzione MFPCreateMediaPlayer. Ciò si verifica in un thread separato di proprietà della pipeline di riproduzione di Microsoft Media Foundation. Nella maggior parte dei casi, l'applicazione non deve gestire questo processo. Tuttavia, esistono due situazioni in cui l'applicazione deve notificare a MFPlay di aggiornare il video.

  • Se la riproduzione viene sospesa o arrestata, MFPlay deve ricevere una notifica ogni volta che la finestra video dell'applicazione riceve un messaggio WM_PAINT. Ciò consente a MFPlay di ridipingere la finestra.
  • Se la finestra viene ridimensionata, MFPlay deve ricevere una notifica in modo che possa ridimensionare il video in modo che corrisponda alle nuove dimensioni della finestra.

Il metodo IMFPMediaPlayer::UpdateVideo gestisce entrambi i casi. Chiamare questo metodo sia all'interno del WM_PAINT che WM_SIZE gestori di messaggi per la finestra video.

Importante

Chiamare la funzione GDI BeginPaint prima di chiamare UpdateVideo.

 

IMFPMediaPlayer *g_pPlayer;   // MFPlay player object

void OnSize(HWND hwnd, UINT state, int cx, int cy)
{
    HDC hdc;
    PAINTSTRUCT ps;

    if (g_pPlayer && (state == SIZE_RESTORED))
    {
        hdc = BeginPaint(hwnd, &ps);
        g_pPlayer->UpdateVideo();
         EndPaint(hwnd, &ps);
    }
}

void OnPaint(HWND hwnd)
{
    HDC hdc;
    PAINTSTRUCT ps;

    hdc = BeginPaint(hwnd, &ps);
    if (g_pPlayer)
    {
        g_pPlayer->UpdateVideo();
    }
      EndPaint(hwnd, &ps);
}

A meno che non si specifichi diversamente, MFPlay visualizza il video con le proporzioni corrette, utilizzando la casella di testo, se necessario. Se non vuoi mantenere le proporzioni, chiama IMFPMediaPlayer::SetAspectRatioMode con il flag MFVideoARMode_None. In questo modo MFPlay allunga il video per riempire l'intero rettangolo, senza letterboxing.This will cause MFPlay to stretch the video to fill the entire rectangle, with no letterboxing. In genere è consigliabile usare l'impostazione predefinita e lasciare che MFPlay letterbox il video. Il colore predefinito della casella di lettere è nero, ma puoi modificarlo chiamando IMFPMediaPlayer::SetBorderColor.

Limitazioni di MFPlay

La versione corrente di MFPlay presenta le limitazioni seguenti:

  • MFPlay non supporta il contenuto protetto da DRM.
  • Per impostazione predefinita, MFPlay non supporta i protocolli di streaming di rete. Per altre informazioni, vedere IMFPMediaPlayer::CreateMediaItemFromURL.
  • MFPlay non supporta playlist lato server (SSPLs) o altri tipi di origine che riproducono più di un segmento. In termini tecnici, MFPlay interrompe la riproduzione dopo la prima presentazione e ignora tutti gli eventi MENewPresentation dall'origine multimediale.
  • MFPlay non supporta transizioni senza interruzioni tra le origini multimediali.
  • MFPlay non supporta la combinazione di più flussi video.
  • Solo i formati multimediali supportati in modo nativo in Media Foundation sono supportati da MFPlay. Sono inclusi componenti di Media Foundation di terze parti che potrebbero essere installati nel sistema.

Uso di MFPlay per la riproduzione audio/video