次の方法で共有


MFPlay の概要

[MFPlay は、「要件」セクションで指定されているオペレーティング システムで使用できます。 それより後のバージョンでは、変更されるか、使用できなくなる場合があります。 ]

MFPlay は、C++ でメディア再生アプリケーションを作成するための API です。

このトピックは、次のセクションで構成されています。

要件

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 プレーヤー オブジェクトの新しいインスタンスが作成されます。 この関数は、次のパラメーターを受け取ります。

  • 1 番目のパラメーターは、開くファイルの URL です。 これは、ローカル ファイルでも、メディア サーバー上のファイルでもかまいません。
  • 2 番目のパラメーターでは、再生を自動的に開始するかどうかを指定します。 このパラメーターを TRUE に設定すると、ファイルは MFPlay によって読み込まれるとすぐに再生されます。
  • 3 番目のパラメーターでは、さまざまなオプションを設定します。 既定のオプションを使う場合は、ゼロ (0) を渡します。
  • 4 番目のパラメーターは省略可能で、コールバック インターフェイスへのポインターです。 示されているように、このパラメーターは NULL でもかまいません。 コールバックについては、「プレーヤーからのイベントの受信」セクションで説明します。
  • 5 番目のパラメーターは、アプリケーション ウィンドウへのハンドルです。 メディア ファイルにビデオ ストリームが含まれている場合、このウィンドウのクライアント領域内にビデオが表示されます。 オーディオのみの再生の場合は、このパラメーターを NULL にできます。

最後のパラメーターは、プレーヤー オブジェクトの IMFPMediaPlayer インターフェイスへのポインターを受け取ります。

アプリケーションをシャットダウンする前に、必ず IMFPMediaPlayer ポインターを解放してください。 これは、WM_CLOSE メッセージ ハンドラーで行うことができます。

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

Note

この例では、SafeRelease 関数を使ってインターフェイス ポインターを解放しています。

 

簡単なビデオ再生の場合、必要なコードはこれですべてです。 このチュートリアルの残りの部分では、さらに機能を追加する方法について説明します。最初は再生を制御する方法です。

再生の制御

前のセクションで示したコードは、ファイルの最後に達するまでメディア ファイルを再生します。 IMFPMediaPlayer インターフェイスで次のメソッドを呼び出すと、再生を停止および開始できます。

  • IMFPMediaPlayer::Pause は、再生を一時停止します。 再生が一時停止されている間、最新のビデオ フレームが表示され、オーディオは無音状態です。
  • IMFPMediaPlayer::Stop は、再生を停止します。 ビデオは表示されなくなり、再生位置はファイルの先頭にリセットされます。
  • IMFPMediaPlayer::Play は、停止または一時停止後に再生を再開します。

次のコードは、Space キーが押されると再生を一時停止または再開します。

//-------------------------------------------------------------------
// 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 はコールバック インターフェイスを使って、アプリケーションにイベントを送信します。 このコールバックには 2 つの理由があります。

  • 再生は別のスレッドで行われます。 ファイルの最後に達したときなど、再生中に特定のイベントが発生する可能性があります。 MFPlay はコールバックを使って、イベントをアプリケーションに通知します。
  • IMFPMediaPlayer のメソッドの多くは非同期であり、操作が完了する前に戻ります。 非同期メソッドを使うと、UI をブロックすることなく、完了に時間がかかる可能性のある操作を UI スレッドから開始できます。 操作が完了すると、MFPlay はコールバックに通知します。

コールバック通知を受け取るには、IMFPMediaPlayerCallback インターフェイスを実装します。 IUnknown を継承するこのインターフェイスでは、1 つのメソッド OnMediaPlayerEvent が定義されています。 コールバックを設定するには、MFPCreateMediaPlayer 関数の pCallback パラメーターで IMFPMediaPlayerCallback の実装へのポインターを渡します。

次に示すのは、このチュートリアルの最初の例を、コールバックを含むように変更したものです。

// 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 構造体へのポインターである 1 つのパラメーターがあります。 この構造体の 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 を呼び出したのと同じスレッドからコールバックを呼び出します。 このスレッドにはメッセージ ループが必要です。 または、MFPCreateMediaPlayercreationOptions パラメーターに MFP_OPTION_FREE_THREADED_CALLBACK フラグを渡すことができます。 このフラグを渡すと、MFPlay は別のスレッドからコールバックを呼び出します。 どちらのオプションも、アプリケーションに影響があります。 既定のオプションは、ウィンドウ プロシージャがブロックされるため、UI アクションの待機など、メッセージ ループで待機する処理をコールバックが実行できないことを意味します。 フリースレッド オプションは、コールバック内でアクセスするすべてのデータを、クリティカル セクションを使って保護する必要があることを意味します。 ほとんどの場合は、既定のオプションが最も簡単です。

メディア ファイルに関する情報の取得

MFPlay でメディア ファイルを開くと、プレーヤーによって、メディア ファイルを表す "メディア項目" と呼ばれるオブジェクトが作成されます。 このオブジェクトによって公開される IMFPMediaItem インターフェイスを使って、メディア ファイルに関する情報を取得できます。 MFPlay イベント構造の多くには、現在のメディア項目へのポインターが含まれます。 現在のメディア項目は、プレーヤーで IMFPMediaPlayer::GetMediaItem を呼び出すことによって取得することもできます。

特に便利な 2 つのメソッドは、IMFPMediaItem::HasVideoIMFPMediaItem::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();
}

再生するように選ばれたビデオ ストリームがソース ファイルに含まれている場合、bHasVideobIsSelected の両方が TRUE に設定されます。

ビデオ再生の管理

MFPlay は、ビデオ ファイルを再生するとき、MFPCreateMediaPlayer 関数で指定されたウィンドウにビデオを描画します。 これは、Microsoft メディア ファンデーションの再生パイプラインによって所有される別のスレッドで行われます。 ほとんどの場合、アプリケーションでこのプロセスを管理する必要はありません。 ただし、アプリケーションでビデオを更新するよう MFPlay に通知する必要がある状況が 2 つあります。

  • 再生が一時停止または停止されている場合、アプリケーションのビデオ ウィンドウが WM_PAINT メッセージを受信するたびに、MFPlay に通知する必要があります。 これにより、MFPlay はウィンドウを再描画できます。
  • ウィンドウのサイズが変更された場合は、新しいウィンドウ サイズに合わせてビデオをスケーリングできるよう、MFPlay に通知する必要があります。

どちらのケースも、IMFPMediaPlayer::UpdateVideo メソッドによって処理されます。 ビデオ ウィンドウの WM_PAINT と WM_SIZE 両方のメッセージ ハンドラー内で、このメソッドを呼び出します。

重要

UpdateVideo を呼び出す前に、GDI の BeginPaint 関数を呼び出します。

 

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 は、必要に応じてレターボックス化を使って、ビデオを正しい縦横比で表示します。 縦横比を保つ必要がない場合は、MFVideoARMode_None フラグを指定して IMFPMediaPlayer::SetAspectRatioMode を呼び出します。 このようにすると、MFPlay はレターボックス化を行わず、ビデオをストレッチして四角形全体を埋めます。 通常は、既定の設定を使い、MFPlay でビデオがレターボックス化されるようにする必要があります。 既定のレターボックスの色は黒ですが、IMFPMediaPlayer::SetBorderColor を呼び出すことで変更できます。

MFPlay の制限事項

MFPlay の現在のバージョンには、次の制限があります。

  • MFPlay では、DRM で保護されたコンテンツはサポートされていません。
  • 既定では、MFPlay はネットワーク ストリーミング プロトコルをサポートしません。 詳しくは、IMFPMediaPlayer::CreateMediaItemFromURL に関する記事をご覧ください。
  • MFPlay では、複数のセグメントを再生するサーバー側プレイリスト (SSPL) または他の種類のソースはサポートされていません。 技術的には、MFPlay は最初のプレゼンテーションの後で再生を停止し、メディア ソースからの MENewPresentation イベントを無視します。
  • MFPlay では、メディア ソース間のシームレスな切り替えはサポートされていません。
  • MFPlay では、複数のビデオ ストリームの混在はサポートされていません。
  • MFPlay は、メディア ファンデーションでネイティブにサポートされているメディア形式のみをサポートします。 (これには、システムにインストールされる可能性があるサード パーティのメディア ファンデーション コンポーネントが含まれます)。

オーディオとビデオの再生に MFPlay を使用する