作業キューとスレッド処理の機能強化

このトピックでは、Microsoft Media Foundation プラットフォームでの作業キューとスレッド処理のWindows 8の機能強化について説明します。

Windows 7 の動作

このセクションでは、Windows 7 での Media Foundation 作業キューの動作について説明します。

作業キュー

Media Foundation プラットフォームでは、いくつかの標準作業キューが作成されます。 一般的なアプリケーション用として文書化されているのは、次の 2 つだけです。

  • MFASYNC_CALLBACK_QUEUE_STANDARD
  • MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION

アプリケーションまたはコンポーネントは、 MFAllocateWorkQueue または MFAllocateWorkQueueEx を呼び出すことによって、新しい作業キュー 割り当てることができます。 MFAllocateWorkQueueEx 関数は、次の 2 種類の作業キューを定義します。

  • MF_STANDARD_WORKQUEUE は、メッセージ ループなしで作業キューを作成します。
  • MF_WINDOW_WORKQUEUE は、メッセージ ループを含む作業キューを作成します。

作業項目をキューに登録するには、 MFPutWorkItem または MFPutWorkItemEx を呼び出します。 プラットフォームは、呼び出し元が提供する IMFAsyncCallback の実装を呼び出すことによって、作業項目を実行します。 Windows 7 以前では、プラットフォームは作業キューごとに 1 つのスレッドを作成します。

MMCSS のサポート

マルチメディア クラス スケジューラ サービス (MMCSS) は、優先度の低いアプリケーションに対する CPU リソースを拒否することなく、マルチメディア アプリケーションが定期的に CPU 時間のスライスを取得できるように、スレッドの優先順位を管理します。 MMCSS では、CPU 使用率プロファイルが異なる一連の タスク を定義します。 スレッドが MMCSS タスクに参加すると、MMCSS は次のいくつかの要因に基づいてスレッドの優先度を設定します。

  • レジストリで設定されるタスクの基本優先度。
  • AvSetMmThreadPriority を呼び出すことによって実行時に設定される相対スレッド優先度。
  • アプリケーションがフォアグラウンドにあるかどうか、各 MMCSS クラスのスレッドによって消費される CPU 時間など、さまざまな実行時特性。

アプリケーションは、 MFBeginRegisterWorkQueueWithMMCSS を呼び出すことによって、MMCSS に作業キューを登録できます。 この関数は、作業キュー ID、MMCSS クラス (タスク名)、MMCSS タスク識別子を受け取ります。 内部的には、タスク名とタスク ID を使用して AvSetMmThreadCharacteristics を呼び出します。 作業キューが MMCSS に登録されたら、 MFGetWorkQueueMMCSSClass と MFGetWorkQueueMMCSSTaskId を呼び出すことで、クラスとタスク ID 取得できます。

メディア セッションでは、IMFWorkQueueServices インターフェイスを使用して、これらの API に対するより高いレベルのアクセスを提供します。 このインターフェイスには、次の 2 つの主要なメソッドが用意されています。

メソッド 説明
BeginRegisterPlatformWorkQueueWithMMCSS 作業キューを MMCSS タスクに登録します。 このメソッドは基本的に MFBeginRegisterWorkQueueWithMMCSS に関するシン ラッパーですが、 MFASYNC_CALLBACK_QUEUE_ALL 値を渡して、すべてのプラットフォーム作業キューを一度に登録できます。
BeginRegisterTopologyWorkQueuesWithMMCSS トポロジのブランチを作業キューに登録します。

 

トポロジ ブランチを登録するには、次の操作を行います。

  1. ブランチのソース ノードに MF_TOPONODE_WORKQUEUE_ID 属性を設定します。 任意のアプリケーション定義値を使用します。
  2. 必要に応じて、作業キューを MMCSS タスクに参加させる MF_TOPONODE_WORKQUEUE_MMCSS_CLASS を設定します。
  3. 解決されたトポロジで BeginRegisterTopologyWorkQueuesWithMMCSS を呼び出します。

メディア セッションは、MF_TOPONODE_WORKQUEUE_IDの一意の値ごとに新しい作業キュー 割り当てます。 トポロジ ブランチごとに、非同期パイプライン操作は、ブランチに割り当てられている作業キューで実行されます。

IMFRealTimeClient

IMFRealTimeClient インターフェイスは、独自のスレッドを作成するか、非同期操作に作業キューを使用するパイプライン コンポーネントを対象としています。 メディア セッションでは、次のように、このインターフェイスを使用してパイプライン コンポーネントに正しい動作を通知します。

  • パイプライン コンポーネントがワーカー スレッドを作成する場合、 IMFRealTimeClient::RegisterThreads メソッドは、参加する MMCSS クラスをコンポーネントに通知します。
  • パイプライン コンポーネントが作業キューを使用する場合、 IMFRealTimeClient::SetWorkQueue メソッドは、使用する作業キューをコンポーネントに指示します。

通常、パイプライン コンポーネントはスレッドまたは作業キューを使用して非同期タスクを実行しますが、両方は実行しません。

Windows 8の機能強化

マルチスレッド作業キュー

Windows 8では、Media Foundation はマルチスレッド キューと呼ばれる新しい種類の作業キューをサポートしています。 マルチスレッド キューは、システム スレッド プールを使用して作業項目をディスパッチします。 マルチスレッド キューは、以前のシングルスレッド キューよりもスケーリングが優れています。 たとえば、次のように入力します。

  • 複数のコンポーネントで、相互にブロックすることなくマルチスレッド キューを共有できるため、スレッドの作成が少なくて済みます。

  • 作業項目は、イベントが既に設定されている場合にコンテキストの切り替えを回避するように最適化されています。 これは、イベントを待機する独自のスレッドを作成するよりも効率的です。

IMFRealTimeClientEx を使用する場合、アプリケーションはスレッドの起動を避け、代わりに作業キューを使用する必要があります。 これを実現するには、アプリケーションで RegisterThreads と UnregisterThreads を使用せず、SetWorkQueueEx を実装する必要があります。

Media Foundation プラットフォームが初期化されると、識別子 がMFASYNC_CALLBACK_QUEUE_MULTITHREADEDされたマルチスレッド キューが作成されます。

マルチスレッド キューは、作業項目をシリアル化しません。 スレッド プールのスレッドが使用可能になると、キューの次の作業項目がディスパッチされます。 呼び出し元は、作業が正しくシリアル化されていることを確認する必要があります。 これを簡単にするために、Media Foundation は シリアル作業キューを定義します。 シリアル キューは別の作業キューをラップしますが、完全にシリアル化された実行が保証されます。 キューの次の項目は、前の項目が完了するまでディスパッチされません。

次のコードでは、プラットフォーム のマルチスレッド キューを介してシリアライザー キューを作成します。

DWORD workQueueID;
hr = MFAllocateSerialWorkQueue(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, &workQueueID); 

複数のシリアル キューで、同じマルチスレッド キューをラップできます。 シリアル キューは同じスレッド プールを共有し、シリアル化された実行は各キュー内に適用されます。

Windows 8より前に存在していた標準の作業キューは、プラットフォームのマルチスレッド キューをラップするシリアル作業キューとして実装されるようになりました。 この変更により、下位互換性が維持されます。

共有タスク作業キュー

カーネル スケジューラを正しく操作するには、使用する MMCSS タスクごとに 1 つのマルチスレッド作業キューが必要です。 Media Foundation プラットフォームでは、必要に応じて、プロセスごとに MMCSS タスクごとに 1 つまでこれらを割り当てます。 特定の MMCSS タスクの共有作業キューを取得するには、 MFLockSharedWorkQueue を呼び出し、タスク名を指定します。 関数は、テーブル内のタスク名を検索します。 このタスクに対して作業キューがまだ存在しない場合、関数は新しい MT 作業キューを割り当てて、すぐに MMCSS タスクに参加させます。 そのタスクの作業キューが既に存在する場合、関数は既存の作業キューの識別子を返します。

待機キュー

待機キューは、通知されるイベントを待機する特別なプラットフォーム作業キューです。 コンポーネントがイベントの通知を待機する必要がある場合は、イベントを待機するワーカー スレッドを作成する代わりに待機キューを使用できます。

待機キューを使用するには、 MFPutWaitingWorkItem を呼び出します。 パラメーターには、イベント ハンドルと IMFAsyncResult ポインターが含まれます。 イベントが通知されると、待機キューによってコールバックが呼び出されます。 1 つのプラットフォーム待機キューがあります。アプリケーションは独自の待機キューを作成できません。

MMCSS サポートの機能強化

次の新しい Media Foundation プラットフォーム機能は MMCSS に関連しています。

機能 Description
MFBeginRegisterWorkQueueWithMMCSSEx 作業キューを MMCSS に登録します。 この関数には、相対スレッド優先度を指定するパラメーターが含まれています。 内部的には、この値は AvSetMmThreadPriority の呼び出しに変換されます。
MFGetWorkQueueMMCSSPriority 作業キューの優先度を照会します。
MFRegisterPlatformWithMMCSS プラットフォームのすべての作業キューを MMCSS タスクに登録します。 この関数は IMFWorkQueueServices::BeginRegisterPlatformWorkQueueWithMMCSS メソッドに似ていますが、メディア セッションのインスタンスを作成せずに使用できます。 さらに、 関数には、基本スレッドの優先度を指定するパラメーターが含まれています。

 

メディア セッションを使用するアプリケーションでは、オーディオ レンダリング ブランチの MF_TOPONODE_WORKQUEUE_MMCSS_CLASS 属性を "Audio" に設定する必要があります。 ビデオ レンダリング ブランチの属性を "Playback" に設定します。

IMFRealTimeClientEx

非同期操作を実行するパイプライン コンポーネントの IMFRealTimeClient を置き換える IMFRealTimeClientEx インターフェイス。

メソッド 説明
RegisterThreadsEx コンポーネントに MMCSS にスレッドを登録するよう通知します。 このメソッドは IMFRealTimeClient::RegisterThreads と同じですが、基本スレッド優先度のパラメーターを追加します。
SetWorkQueueEx 特定の作業キューを使用するようにコンポーネントに通知します。 このメソッドは IMFReadTimeClient::SetWorkQueue と同じですが、作業項目の優先度のパラメーターを追加します。
UnregisterThreads MMCSS からスレッドの登録を解除するようにコンポーネントに通知します。 このメソッドは、 IMFRealTimeClient::UnregisterThreads メソッドと同じです。

 

パイプライン コンポーネントでは、次の理由により、作業キューを使用し、ワーカー スレッドを作成しないでください。

  • 作業キューは OS スレッド プールを使用するため、スケーリングが向上します。
  • プラットフォームは、MMCSS に作業キューを登録する詳細を処理します。
  • ワーカー スレッドは、デバッグが困難なデッドロックを簡単に引き起こす可能性があります。

また、非同期操作をシリアル化する必要がある場合は、シリアライザー作業キューの使用を検討してください。

トポロジ ブランチ

MF_TOPONODE_WORKQUEUE_MMCSS_CLASS属性が MMCSS にトポロジ ブランチを登録する場合、Windows 8メディア セッションでは共有 MT 作業キューが使用されます。 以前のバージョンの Windows では、メディア セッションによって新しい作業キューが割り当てられます。

トポロジ ブランチを MMCSS に登録するために、2 つの新しい属性が定義されています。

属性 説明
MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY 基本スレッドの優先度を指定します。
MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY 作業項目の優先度を指定します。

 

推奨事項

  • メディア セッションを使用するアプリケーションでは、オーディオ レンダリング ブランチ の場合は MF_TOPONODE_WORKQUEUE_MMCSS_CLASS を "Audio" に、ビデオ レンダリング ブランチの場合は "Playback" に設定する必要があります。
  • メディア セッションを使用するアプリケーションでは、トポロジで IMFWorkQueueServices::BeginRegisterTopologyWorkQueuesWithMMCSS を呼び出す必要があります。
  • パイプライン コンポーネントの場合は、ワーカー スレッドの代わりに作業キューが推奨されます。 コンポーネントで作業キューまたはワーカー スレッドを使用する場合は、 IMFRealTimeClientEx を実装します
  • これはプラットフォーム作業キューの目的を打ち負かすので、プライベート作業キューを作成しないでください。 プラットフォーム マルチスレッド キューまたはプラットフォーム マルチスレッド キューをラップするシリアル キューを使用します。
  • 非同期操作をシリアル化する必要がある場合は、シリアル キューを使用します。

まとめ

スレッドと作業キューに関連する次の Media Foundation プラットフォーム API は、Windows 8の新機能です。

作業キュー