Поделиться через


Начало работы с MFPlay

[MFPlay доступен для использования в операционных системах, указанных в разделе "Требования". Он может быть изменен или недоступен в последующих версиях. ]

MFPlay — это API для создания приложений воспроизведения мультимедиа в C++.

Этот раздел состоит из следующих подразделов.

Requirements

Для MFPlay требуется Windows 7.

О MFPlay

MFPlay имеет простую модель программирования, предоставляя основной набор функций, необходимых большинству приложений воспроизведения. Приложение создает объект проигрывателя, который управляет воспроизведением. Для воспроизведения файла мультимедиа объект проигрывателя создает элемент мультимедиа, который можно использовать для получения сведений о содержимом файла мультимедиа. Приложение управляет воспроизведением с помощью методов в интерфейсе IMFPMediaPlayer объекта проигрывателя. При необходимости приложение может получать уведомления о событиях через интерфейс обратного вызова, на следующей схеме показан этот процесс.

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

Воспроизведение файла мультимедиа

Чтобы воспроизвести файл мультимедиа, вызовите функцию 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
        );
}

Функция MFPCreateMediaPlayer создает новый экземпляр объекта проигрывателя MFPlay. Функция принимает следующие параметры:

  • Первый параметр — ЭТО URL-адрес открываемого файла. Это может быть локальный файл или файл на сервере мультимедиа.
  • Второй параметр указывает, запускается ли воспроизведение автоматически. Установив для этого параметра значение TRUE, файл будет воспроизводиться сразу после загрузки MFPlay.
  • Третий параметр задает различные параметры. Для параметров по умолчанию передайте ноль (0).
  • Четвертый параметр — это указатель на необязательный интерфейс обратного вызова. Этот параметр может иметь значение NULL, как показано ниже. Обратный вызов описан в разделе "Получение событий от проигрывателя".
  • Пятый параметр — это дескриптор окна приложения. Если файл мультимедиа содержит видеопоток, видео будет отображаться в клиентской области этого окна. Для воспроизведения только для звука этот параметр может иметь значение NULL.

Последний параметр получает указатель на интерфейс IMFPMediaPlayer объекта проигрывателя.

Прежде чем приложение завершит работу, обязательно выпустите указатель МВФPMediaPlayer . Это можно сделать в обработчике сообщений WM_CLOSE .

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

Примечание.

В этом примере функция Сейф Release используется для выпуска указателей интерфейса.

 

Для простого воспроизведения видео это весь нужный код. В оставшейся части этого руководства показано, как добавить дополнительные функции, начиная с управления воспроизведением.

Управление воспроизведением

Код, показанный в предыдущем разделе, будет воспроизводить файл мультимедиа до тех пор, пока он не достигнет конца файла. Вы можете остановить и начать воспроизведение, вызвав следующие методы в интерфейсе IMFPMediaPlayer :

  • IMFPMediaPlayer::P ause приостанавливает воспроизведение. При приостановке воспроизведения отображается последний видеокадр, а звук безмолвный.
  • IMFPMediaPlayer::Stop останавливает воспроизведение. Видео не отображается, а положение воспроизведения сбрасывается до начала файла.
  • IMFPMediaPlayer::P lay возобновляет воспроизведение после остановки или приостановки.

Следующий код приостанавливает или возобновляет воспроизведение при нажатии ПРОБЕЛА.

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

В этом примере вызывается метод IMFPMediaPlayer::GetState , чтобы получить текущее состояние воспроизведения (приостановлено, остановлено или воспроизведено) и приостанавливается или возобновляется соответствующим образом.

Получение событий от проигрывателя

MFPlay использует интерфейс обратного вызова для отправки событий в приложение. Существует две причины для обратного вызова:

  • Воспроизведение происходит в отдельном потоке. Во время воспроизведения могут возникать определенные события, такие как достижение конца файла. MFPlay использует обратный вызов для уведомления приложения о событии.
  • Многие методы IMFPMediaPlayer являются асинхронными, то есть возвращаются до завершения операции. Асинхронные методы позволяют запускать операцию из потока пользовательского интерфейса, что может занять много времени, не вызывая блокировку пользовательского интерфейса. После завершения операции MFPlay сообщает обратному вызову.

Для получения уведомлений обратного вызова реализуйте интерфейс МВФPMediaPlayerCallback . Этот интерфейс наследует IUnknown и определяет один метод OnMediaPlayerEvent. Чтобы настроить обратный вызов, передайте указатель на реализацию IMFPMediaPlayerCallback в параметре pCallback функции MFPCreateMediaPlayer.

Ниже приведен первый пример из этого руководства, измененный для включения обратного вызова.

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

Метод OnMediaPlayerEvent имеет один параметр, который является указателем на структуру MFP_EVENT_HEADER. Элемент eEventType этой структуры указывает, какое событие произошло. Например, при запуске воспроизведения MFPlay отправляет событие MFP_EVENT_TYPE_PLAY .

Каждый тип события имеет соответствующую структуру данных, содержащую сведения для этого события. Каждая из этих структур начинается с MFP_EVENT_HEADER структуры. В обратном вызове приведите указатель MFP_EVENT_HEADER на структуру данных для конкретного события. Например, если тип события MFP_PLAY_EVENT, структура данных MFP_PLAY_EVENT. В следующем коде показано, как обрабатывать это событие в обратном вызове.

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

В этом примере используется событие MFP_GET_PLAY_EVENT для приведения указателя pEventHeader к структуре MFP_PLAY_EVENT. HRESULT из операции, которая активировала событие, хранится в поле hrEvent структуры.

Список всех типов событий и соответствующих структур данных см . в MFP_EVENT_TYPE.

Примечание о потоке. По умолчанию MFPlay вызывает обратный вызов из того же потока, который называется MFPCreateMediaPlayer. Этот поток должен иметь цикл сообщений. Кроме того, можно передать флаг MFP_OPTION_FREE_THREADED_CALLBACK в параметре creationOptions MFPCreateMediaPlayer. Этот флаг приводит к тому, что MFPlay вызывает обратные вызовы из отдельного потока. Любой из вариантов имеет последствия для приложения. Параметр по умолчанию означает, что обратный вызов не может сделать все, что ожидает цикла сообщений, например ожидание действия пользовательского интерфейса, так как это блокирует процедуру окна. Параметр free-threaded означает, что необходимо использовать критические разделы для защиты всех данных, к которым вы обращаетесь в обратном вызове. В большинстве случаев параметр по умолчанию прост.

Получение сведений о файле мультимедиа

При открытии файла мультимедиа в MFPlay проигрыватель создает объект, называемый элементом мультимедиа, который представляет файл мультимедиа. Этот объект предоставляет интерфейс IMFPMediaItem , который можно использовать для получения сведений о файле мультимедиа. Многие структуры событий MFPlay содержат указатель на текущий элемент мультимедиа. Вы также можете получить текущий элемент мультимедиа, вызвав МВФPMediaPlayer::GetMediaItem на проигрывателе.

Два особенно полезных метода : IMFPMediaItem::HasVideo и МВФPMediaItem::HasAudio. Эти методы запрашивают, содержит ли источник мультимедиа видео или звук.

Например, следующий код проверяет, содержит ли текущий файл мультимедиа видеопоток.

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

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

Если исходный файл содержит видеопоток, выбранный для воспроизведения, bHasVideo и bIsSelected имеют значение TRUE.

Управление воспроизведением видео

Когда MFPlay воспроизводит видеофайл, он рисует видео в окне, указанном в функции MFPCreateMediaPlayer. Это происходит в отдельном потоке, принадлежаемом конвейеру воспроизведения Microsoft Media Foundation. В большинстве случаев приложению не нужно управлять этим процессом. Однако существует две ситуации, когда приложение должно уведомить MFPlay об обновлении видео.

  • Если воспроизведение приостановлено или остановлено, MFPlay должно быть уведомлено, когда окно видео приложения получает сообщение WM_PAINT. Это позволяет MFPlay перенаправить окно.
  • Если окно изменено, MFPlay должно быть уведомлено, чтобы оно адаптировало видео к новому размеру окна.

Метод IMFPMediaPlayer::UpdateVideo обрабатывает оба случая. Вызовите этот метод как в WM_PAINT, так и в обработчики сообщений WM_SIZE для окна видео.

Важно!

Вызовите функцию GDI BeginPaint перед вызовом 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);
}

Если вы не указали другое, MFPlay отображает видео в правильном соотношении пропорций, используя почтовые ящики при необходимости. Если вы не хотите сохранить пропорции, вызовите МВФPMediaPlayer::SetAspectRatioMode с флагом MFVideoARMode_None . Это приведет к тому, что MFPlay растягивает видео для заполнения всего прямоугольника без букв. Как правило, следует использовать параметр по умолчанию и разрешить MFPlay почтовый ящик видео. Цвет почтового ящика по умолчанию черный, но его можно изменить, вызвав МВФPMediaPlayer::SetBorderColor.

Ограничения MFPlay

Текущая версия MFPlay имеет следующие ограничения:

  • MFPlay не поддерживает содержимое, защищенное drM.
  • По умолчанию MFPlay не поддерживает протоколы потоковой передачи сети. Дополнительные сведения см. в разделе МВФPMediaPlayer::CreateMediaItemFromURL.
  • MFPlay не поддерживает списки воспроизведения на стороне сервера (SSP) или другие типы источников, которые играют более одного сегмента. В технических терминах MFPlay останавливает воспроизведение после первой презентации и игнорирует любые события MENewPresentation из источника мультимедиа.
  • MFPlay не поддерживает простой переход между источниками мультимедиа.
  • MFPlay не поддерживает сочетание нескольких видеопотоков.
  • Только форматы мультимедиа, поддерживаемые в собственном коде в Media Foundation, поддерживаются MFPlay. (Это включает сторонние компоненты Media Foundation, которые могут быть установлены в системе.)

Использование MFPlay для воспроизведения звука и видео