IMFMediaSource
COM公式ドキュメント
メディアソースオブジェクトによって実装されます。
解説(Remarks)
Windows 8 では、このインターフェイスは IMFMediaSourceEx によって拡張されています。
カメラやマイクなどの一部のデバイスソースでは、IMFMediaSource は IKsControl も実装しています。これはユーザーモードアプリケーションが基盤となるデバイスドライバーに対して KSPROPERTY、KSEVENT、KSMETHOD の各操作を発行するために使用できます。
このインターフェイスは省略可能であり、利用できない場合があります。このインターフェイスが利用できない場合、QueryInterface は E_NOINTERFACE を返します。
IMFMediaSource のインスタンスを取得するには、IMFSourceResolver::CreateObjectFromByteStream、IMFSourceResolver::CreateObjectFromURL、またはこれらのメソッドの非同期バージョンを呼び出します。
次の例は、IMFSourceResolver を使用して IMFByteStream から IMFMediaSource のインスタンスを取得する方法を示しています。
#include <wil.h>
#include <mfplat.h>
#include <mfidl.h>
HRESULT CreateMediaSourceFromStream(_In_ IMFByteStream* stream, _COM_Outptr_ IMFMediaSource** source)
{
*source = nullptr;
wil::com_ptr_nothrow<IMFSourceResolver> sourceResolver;
RETURN_IF_FAILED(MFCreateSourceResolver(&sourceResolver));
MF_OBJECT_TYPE objectType;
wil::com_ptr_nothrow<IUnknown> sourceUnknown;
RETURN_IF_FAILED(sourceResolver->CreateObjectFromByteStream(stream, nullptr, MF_RESOLUTION_MEDIASOURCE, nullptr, &objectType, &sourceUnknown));
RETURN_IF_FAILED(sourceUnknown.copy_to(IID_PPV_ARGS(source)));
return S_OK;
}
メソッド 6
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
メディアソースの特性を取得します。
| pdwCharacteristics | DWORD* | out | MFMEDIASOURCE_CHARACTERISTICS 列挙体の 0 個以上のフラグをビットごとの OR で組み合わせた値を受け取ります。 |
戻り値
このメソッドは HRESULT を返します。取り得る値には次の表に示すものが含まれますが、これらに限定されません。
| 戻り値 | 説明 |
|---|---|
| メソッドは成功しました。 | |
| メディアソースの Shutdown メソッドが呼び出されています。 |
解説(Remarks)
メディアソースの特性はいつでも変化する可能性があります。この変化が起きた場合、ソースは MESourceCharacteristicsChanged イベントを送信します。
メディアソースのプレゼンテーション記述子のコピーを取得します。アプリケーションはプレゼンテーション記述子を使用して、ストリームの選択やソースコンテンツに関する情報の取得を行います。
| ppPresentationDescriptor | IMFPresentationDescriptor** | out | プレゼンテーション記述子の IMFPresentationDescriptor インターフェイスへのポインターを受け取ります。呼び出し元はこのインターフェイスを解放する必要があります。 |
戻り値
このメソッドは HRESULT を返します。取り得る値には次の表に示すものが含まれますが、これらに限定されません。
| 戻り値 | 説明 |
|---|---|
| メソッドは成功しました。 | |
| メディアソースの Shutdown メソッドが呼び出されています。 |
解説(Remarks)
プレゼンテーション記述子には、プレゼンテーションに対するメディアソースの既定の設定が含まれています。アプリケーションは、ストリームの選択や選択解除、またはストリームのメディアタイプの変更によってこれらの設定を変更できます。ソースが停止していない限り、プレゼンテーション記述子を変更しないでください。変更内容は、ソースの IMFMediaSource::Start メソッドが呼び出されたときに有効になります。
再生の開始位置を指定して、メディアソースの開始、シーク、または再開を行います。
| pPresentationDescriptor | IMFPresentationDescriptor* | in | メディアソースのプレゼンテーション記述子の IMFPresentationDescriptor インターフェイスへのポインター。プレゼンテーション記述子を取得するには、IMFMediaSource::CreatePresentationDescriptor を呼び出します。Start を呼び出す前にプレゼンテーション記述子を変更して、ストリームの選択や選択解除、またはメディアタイプの変更を行うことができます。 |
| pguidTimeFormat | GUID* | in | 時間フォーマットを指定する GUID へのポインター。時間フォーマットは pvarStartPosition パラメーターの単位を定義します。値 が GUID_NULL の場合、時間フォーマットは 100 ナノ秒単位になります。一部のメディアソースは追加の時間フォーマット GUID をサポートする場合があります。このパラメーターは NULL でもかまいません。値が NULL の場合、GUID_NULL と同等です。 |
| pvarStartPosition | PROPVARIANT* | in | 再生の開始位置を指定します。このパラメーターの単位は、pguidTimeFormat で指定された時間フォーマットによって示されます。時間フォーマットが GUID_NULL の場合、バリアント型は VT_I8 または VT_EMPTY でなければなりません。新しい開始位置を 100 ナノ秒単位で指定するには VT_I8 を使用します。現在の位置から開始するには VT_EMPTY を使用します。他の時間フォーマットでは、別の PROPVARIANT 型を使用する場合があります。 |
戻り値
このメソッドは HRESULT を返します。取り得る値には次の表に示すものが含まれますが、これらに限定されません。
| 戻り値 | 説明 |
|---|---|
| メソッドは成功しました。 | |
| 開始位置がプレゼンテーションの終端を超えています (ASF メディアソース)。 | |
| ハードウェアデバイスがストリーミングを開始できませんでした。このエラーコードは、カメラなどのハードウェアデバイスを表すメディアソースから返されることがあります。たとえば、カメラが既に別のアプリケーションによって使用されている場合、このメソッドはこのエラーコードを返すことがあります。 | |
| 開始要求が有効ではありません。たとえば、開始位置がプレゼンテーションの終端を超えている場合などです。 | |
| メディアソースの Shutdown メソッドが呼び出されています。 | |
| メディアソースは、pguidTimeFormat で指定された時間フォーマットをサポートしていません。 |
解説(Remarks)
このメソッドは非同期です。操作が成功すると、メディアソースは次のイベントを送信します。
- 新しいストリームごとに、ソースは MENewStream イベントを送信します。このイベントは、そのストリームが出現した最初の Start 呼び出しに対して送信されます。イベントデータはストリームの IMFMediaStream インターフェイスへのポインターです。
- 更新されたストリームごとに、ソースは MEUpdatedStream イベントを送信します。Start が呼び出されたときにストリームが既に存在していた場合 (たとえば、再生中にアプリケーションがシークした場合)、そのストリームは更新されたものとみなされます。イベントデータはストリームの IMFMediaStream インターフェイスへのポインターです。
- 直前の状態が停止であった場合、ソースは MESourceStarted イベントを送信します。
- 直前の状態が開始または一時停止であり、開始位置が現在の位置 (VT_EMPTY) である場合、ソースは MESourceStarted イベントを送信します。
- 直前の状態が開始または一時停止であり、新しい開始位置が指定された場合、ソースは MESourceSeeked イベントを送信します。
- ソースが MESourceStarted イベントを送信する場合、各メディアストリームは MEStreamStarted イベントを送信します。ソースが MESourceSeeked イベントを送信する場合、各ストリームは MEStreamSeeked イベントを送信します。
直前の状態が開始または一時停止であり、新しい開始位置が VT_EMPTY でない場合、Start の呼び出しはシークとなります。すべてのメディアソースがシークできるわけではありません。メディアソースがシークできる場合、IMFMediaSource::GetCharacteristics メソッドは MFMEDIASOURCE_CAN_SEEK フラグを返します。
メディアソースからのイベントは、メディアストリームからのイベントと同期していません。したがって、メディアソースをシークした場合でも、MESourceSeeked イベントを受け取った後に、以前の位置からのサンプルを受け取ることがあります。これらの操作を同期する必要がある場合は、ストリームイベント MEStreamSeeked を待機してください。このイベントは、シークが発生するストリーム内の正確なポイントを示します。
ストリームの終端
ストリームが終端まで再生されると、そのストリームは MEEndOfStream イベントを送信します。選択されたすべてのストリームが終端に達すると、メディアソースは MEEndOfPresentation イベントを送信します。開始位置が選択されたストリームの終端を超えている (ただしプレゼンテーションの終端より前である) 場合、そのストリームは MEStreamStarted/MEStreamSeeked の直後に MEEndOfStream を送信する必要があります。再生がプレゼンテーションの終端に達した後、現在の位置から Start が再度呼び出された場合、ストリームは MEEndOfStream イベントを再送信し、メディアソースは MEEndOfPresentation イベントを再送信します。これらのイベントは、これ以上データを要求しないようパイプラインに通知します。
逆方向再生の間は、ファイルの先頭がストリームの終端とみなされます。詳細については、Implementing Rate Control を参照してください。
Start の実装
メディアソースがシークを実行する際は、デコーダーがターゲットの開始時刻のサンプルをデコードできるように、シーク時刻より前の最初のキーフレームから開始する必要があります。パイプラインは、早すぎるデコード済みサンプルをすべて破棄します。開始時刻が VT_EMPTY であり、直前の状態が開始または一時停止であった場合、ソースは現在の位置から再開する必要があります。この場合、デコーダーは以前に送信されたデータを依然として保持しているため、直前のキーフレームを再送信する必要はありません。
pPresentationDescriptor パラメーターを検証する際、メディアソースは正しく機能するために必要な情報のみをチェックする必要があります。特に、クライアントはプレゼンテーション記述子にプライベート属性を追加できます。追加の属性が存在しても、Start メソッドが失敗する原因になってはなりません。
Start が呼び出された後、メディアソース上の各ストリームは次のいずれかを行う必要があります。
- IMFMediaStream::RequestSample の呼び出しに応じてメディアデータを配信する。
- ストリーム内のギャップを示すために MEStreamTick イベントを送信する。
- ストリームの終端を示すために MEEndOfStream イベントを送信する。
例
次の例では、プレゼンテーションの 1 秒後の位置から再生を開始します。
PROPVARIANT var;
PropVariantInit(&var);
var.vt = VT_I8;
var.hVal.QuadPart = 10000000; // 10^7 = 1 second.
hr = pSource->Start(pPresentationDescriptor, NULL, &var);
メディアソース内のすべてのアクティブなストリームを停止します。
戻り値
このメソッドは HRESULT を返します。取り得る値には次の表に示すものが含まれますが、これらに限定されません。
| 戻り値 | 説明 |
|---|---|
| メソッドは成功しました。 | |
| メディアソースの Shutdown メソッドが呼び出されています。 |
解説(Remarks)
このメソッドは非同期です。操作が完了すると、メディアソースは MESourceStopped イベントを送信し、すべてのアクティブなストリームは MEStreamStopped イベントを送信します。メソッドが失敗コードを返した場合、イベントは発生しません。
メディアソースが停止すると、その現在の位置は 0 に戻ります。その後、開始位置に VT_EMPTY を指定して Start メソッドが呼び出された場合、再生はプレゼンテーションの先頭から開始されます。
ソースが停止している間、どのストリームもデータを生成しません。
メディアソース内のすべてのアクティブなストリームを一時停止します。
戻り値
このメソッドは HRESULT を返します。取り得る値には次の表に示すものが含まれますが、これらに限定されません。
| 戻り値 | 説明 |
|---|---|
| メソッドは成功しました。 | |
| 無効な状態遷移です。メディアソースは開始状態でなければなりません。 | |
| メディアソースの Shutdown メソッドが呼び出されています。 |
解説(Remarks)
このメソッドは非同期です。操作が完了すると、メディアソースは MESourcePaused イベントを送信し、すべてのアクティブなストリームは MEStreamPaused イベントを送信します。メソッドが失敗コードを返した場合、イベントは発生しません。
メディアソースは開始状態でなければなりません。メディアソースが一時停止または停止している場合、このメソッドは失敗します。
ソースが一時停止している間、IMFMediaStream::RequestSample の呼び出しは成功しますが、ソースが再度開始されるまでストリームはサンプルを配信しません。ソースのイベントキューはストリームのイベントキューとシリアル化されていないため、マルチスレッドの問題により、クライアントは MESourcePaused イベントの後にいくつかのサンプルを受け取る場合があることに注意してください。ただし、クライアントは MEStreamPaused イベントの後にストリームからサンプルを受け取ることはありません。
すべてのメディアソースが一時停止できるわけではありません。メディアソースが一時停止できる場合、IMFMediaSource::GetCharacteristics メソッドは MFMEDIASOURCE_CAN_PAUSE フラグを返します。
メディアソースをシャットダウンし、使用しているリソースを解放します。
戻り値
このメソッドは HRESULT を返します。取り得る値には次の表に示すものが含まれますが、これらに限定されません。
| 戻り値 | 説明 |
|---|---|
| メソッドは成功しました。 |
解説(Remarks)
アプリケーションが直接またはソースリゾルバーを介してメディアソースを作成した場合、メモリリークやリソースリークを避けるために、アプリケーションは Shutdown を呼び出す責任を負います。
このメソッドが呼び出された後、メディアソースおよびそのすべてのメディアストリームのメソッドは (IUnknown のメソッドを除いて) MF_E_SHUTDOWN を返します。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IMFMediaSource "{279A808D-AEC7-40C8-9C6B-A6B492C78A66}" #usecom global IMFMediaSource IID_IMFMediaSource "{}" #comfunc global IMFMediaSource_GetCharacteristics 7 var #comfunc global IMFMediaSource_CreatePresentationDescriptor 8 sptr #comfunc global IMFMediaSource_Start 9 sptr,var,var #comfunc global IMFMediaSource_Stop 10 #comfunc global IMFMediaSource_Pause 11 #comfunc global IMFMediaSource_Shutdown 12 ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。#define global IID_IMFMediaSource "{279A808D-AEC7-40C8-9C6B-A6B492C78A66}" #usecom global IMFMediaSource IID_IMFMediaSource "{}" #comfunc global IMFMediaSource_GetCharacteristics 7 sptr #comfunc global IMFMediaSource_CreatePresentationDescriptor 8 sptr #comfunc global IMFMediaSource_Start 9 sptr,sptr,sptr #comfunc global IMFMediaSource_Stop 10 #comfunc global IMFMediaSource_Pause 11 #comfunc global IMFMediaSource_Shutdown 12 ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。