IAsyncReader
COM公式ドキュメント
IAsyncReader インターフェースは、フィルター上で非同期のデータ要求を実行します。このインターフェースは、非同期の読み取り操作を行う出力ピンによって公開されます。
メソッド 8
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
RequestAllocator メソッドは、ピンの接続時にアロケーターを要求します。
| pPreferred | IMemAllocator* | in | 入力ピンが優先するアロケーターの IMemAllocator インターフェースへのポインター。優先するものがない場合は NULL を指定します。 |
| pProps | ALLOCATOR_PROPERTIES* | in | 呼び出し側が確保した ALLOCATOR_PROPERTIES 構造体のアドレスを指定します。呼び出し側は、入力ピンが必要とするアロケーターのプロパティを設定し、残りのメンバーはゼロに設定してください。 |
| ppActual | IMemAllocator** | out | IMemAllocator インターフェースポインターを受け取る変数のアドレス。 |
戻り値
HRESULT 値を返します。取り得る値には次のものが含まれます。
| Return code | Description |
|---|---|
| アロケーターの初期化に失敗しました。 | |
| 無効なアラインメントが指定されました。 | |
| アロケーターが返されました。 |
解説(Remarks)
下流の入力ピンは、接続処理の間にこのメソッドを呼び出してください。ピンに優先するアロケーターがある場合は、pPreferred パラメーターで指定します。バッファーサイズやアラインメントなどのバッファー要件は、pProps パラメーターで指定します。出力ピンがアロケーターを選択し、ppActual パラメーターでそのポインターを返します。
出力ピンは、入力ピンの要求に従う義務はありません。入力ピンに絶対的な要件がある場合は、返されたアロケーターに対して IMemAllocator::GetProperties メソッドを呼び出してください。アロケーターのプロパティが適切でない場合は、接続を失敗させることができます。接続が確立された後は、入力ピンは出力ピンが選択したアロケーターを使用しなければなりません。
入力ピンは、アロケーターのコミットおよびデコミットを行う責任があります。
Request メソッドは、データに対する非同期要求をキューに登録します。
| pSample | IMediaSample* | in | 呼び出し側が提供するメディアサンプルの IMediaSample インターフェースへのポインター。 |
| dwUser | UINT_PTR | in | 要求が完了したときに返される任意の値を指定します。 |
戻り値
HRESULT 値を返します。取り得る値には次のものが含まれます。
| Return code | Description |
|---|---|
| 成功しました。 | |
| バッファーが正しくアラインメントされていません。 | |
| サンプルにタイムスタンプが設定されていません。 | |
| ピンがフラッシュ中です。 | |
|
要求された開始位置がファイルの末尾を超えています。 |
| メモリが不足しています。 |
解説(Remarks)
このメソッドを呼び出す前に、ピンのアロケーターからメディアサンプルを取得してください。要求するバイトオフセット(最初と最後を含む)に 10,000,000 を掛けた値を、サンプルにタイムスタンプとして設定します。バイトオフセットはストリームの先頭を基準とします。
開始位置と終了位置は、ピンの接続時に決定されたアラインメントに一致させる必要があります。そうでない場合、このメソッドは VFW_E_BADALIGN を返すことがあります。合意されたアラインメントがストリームの実際のアラインメントより粗い場合、終了位置が実際の長さを超えることがあります。その場合、メソッドは終了位置を実際のアラインメントに切り下げます。
技術的には COM の規則違反ですが、呼び出し側はサンプルに未解放の参照カウントを残しておく必要があります。Request メソッドは AddRef や Release を呼び出さないため、サンプルを有効な状態に保つにはこの参照カウントが必要です。
このメソッドは要求が完了する前に戻ります。要求を待機するには IAsyncReader::WaitForNext メソッドを呼び出してください。要求が保留されている間は、元のメディアサンプルを再利用しないでください。WaitForNext メソッドは元のサンプルへのポインターを返します。要求が成功した場合、サンプルには要求されたデータが格納されています。WaitForNext メソッドは、dwUser パラメーターで指定された値も返します。呼び出し側はこの値を使ってサンプルを識別できます。
例
次の例は、要求をキューに登録するための入力ピン用ヘルパー関数の一例を示します。
| C++ |
|---|
|
WaitForNext メソッドは、次の保留中の読み取り要求が完了するのを待機します。
| dwTimeout | DWORD | in | タイムアウトをミリ秒単位で指定します。無期限に待機する場合は INFINITE を使用します。 |
| ppSample | IMediaSample** | outoptional | IMediaSample インターフェースポインターを受け取る変数のアドレス。 |
| pdwUser | UINT_PTR* | out | IAsyncReader::Request メソッドで指定された dwUser パラメーターの値を受け取る変数へのポインター。 |
戻り値
HRESULT 値を返します。取り得る値には次のものが含まれます。
| Return code | Description |
|---|---|
| タイムアウトが経過したか、ピンがフラッシュ中です。 | |
| ピンがフラッシュ中です。 | |
| 読み取りエラーが発生しました。 | |
| 成功しました。 | |
| ファイルの末尾に達しました。要求より少ないバイト数を取得しました。 |
解説(Remarks)
メソッドが成功した場合、ppSample パラメーターには、要求されたデータをバッファーに保持するメディアサンプルへのポインターが格納されます。IMediaSample::GetTime メソッドを呼び出し、その結果を 10,000,000 で割ることで、開始バイトと終了バイトを求めることができます。サンプルは順不同で返される場合があります。データの処理が完了したら、サンプルを解放してください。
ピンがフラッシュ中の場合、このメソッドは失敗します。ただし、ppSample に空のサンプルを返すことがあります。*ppSample が非 NULL の場合は、そのサンプルを解放して破棄してください。詳細については、IAsyncReader::BeginFlush を参照してください。
読み取りエラーが発生した場合、ソースフィルターはフィルターグラフマネージャーにエラーイベントを送信します。呼び出し側がエラーを通知する必要はありません。
SyncReadAligned メソッドは、同期読み取りを実行します。このメソッドは、要求が完了するまでブロックします。ファイル位置とバッファーアドレスはアラインメントされている必要があります。必要なアラインメントについてはアロケーターのプロパティを確認してください。
| pSample | IMediaSample* | in | 呼び出し側が提供するメディアサンプルの IMediaSample インターフェースへのポインター。 |
戻り値
HRESULT 値を返します。取り得る値には次のものが含まれます。
| Return code | Description |
|---|---|
| 無効なアラインメントです。 | |
| 要求より少ないバイト数を取得しました。(おそらくファイルの末尾に達しました。) | |
| 成功しました。 |
解説(Remarks)
このメソッドを呼び出す前に、ピンのアロケーターからメディアサンプルを取得してください。要求するバイトオフセット(最初と最後を含む)に 10,000,000 を掛けた値を、サンプルにタイムスタンプとして設定します。バイトオフセットはストリームの先頭を基準とします。
開始位置と終了位置は、ピンの接続時に決定されたアラインメントに一致させる必要があります。そうでない場合、このメソッドは VFW_E_BADALIGN を返します。合意されたアラインメントがストリームの実際のアラインメントより粗い場合、終了位置が実際の長さを超えることがあります。その場合、メソッドは終了位置を実際のアラインメントに切り下げます。
このメソッドはバッファリングなしの読み取りを行うため、IAsyncReader::SyncRead メソッドよりも高速な場合があります。
SyncRead メソッドは、同期読み取りを実行します。このメソッドは、要求が完了するまでブロックします。ファイル位置とバッファーアドレスはアラインメントされている必要はありません。要求がアラインメントされていない場合、このメソッドはバッファリングありの読み取り操作を行います。
| llPosition | LONGLONG | in | 読み取りを開始するバイトオフセットを指定します。この値がファイルの末尾を超えている場合、メソッドは失敗します。 |
| lLength | INT | in | 読み取るバイト数を指定します。 |
| pBuffer | BYTE* | out | データを受け取るバッファーへのポインター。 |
戻り値
HRESULT 値を返します。取り得る値には次のものが含まれます。
| Return code | Description |
|---|---|
| 要求より少ないバイト数を取得しました。(おそらくファイルの末尾に達しました。) | |
| 成功しました。 |
解説(Remarks)
このメソッドは、フィルターが停止している場合でも動作します。
Length メソッドは、ストリームの全長を取得します。
| pTotal | LONGLONG* | out | ストリームの長さ(バイト単位)を受け取る変数へのポインター。 |
| pAvailable | LONGLONG* | out | ストリームのうち現在利用可能な部分の長さ(バイト単位)を受け取る変数へのポインター。 |
戻り値
HRESULT 値を返します。取り得る値には次のものが含まれます。
| Return code | Description |
|---|---|
| 成功しました。 | |
| 返された値は推定値です。たとえば、ファイルがネットワーク経由で読み取られている場合などです。 | |
| ファイルが開かれていないか、既に存在しません。 |
解説(Remarks)
ネットワーク経由で取得されるストリームでは、最初はストリーム全体が利用可能でない場合があります。利用可能な長さを超えた読み取り操作は、その部分のストリームが利用可能になるまで、長時間ブロックすることがあります。
BeginFlush メソッドは、フラッシュ操作を開始します。(IAsyncReader.BeginFlush)
戻り値
解説(Remarks)
このメソッドは、保留中のすべての読み取り要求を中断します。ピンがフラッシュ中の間、IAsyncReader::Request メソッドは失敗し、IAsyncReader::WaitForNext メソッドはすぐに戻ります(戻り値が VFW_E_TIMEOUT になる場合があります)。
下流の入力ピンは、下流のフィルターがフィルターグラフをフラッシュするたびに、このメソッドを呼び出してください。このメソッドを呼び出した後、ppSample パラメーターに NULL が返されるまで WaitForNext メソッドを呼び出し続けて、保留中のサンプルのキューをクリアしてください。エラーコードは無視し、各サンプルを解放します。その後、IAsyncReader::EndFlush メソッドを呼び出して、フラッシュ操作を終了します。
詳細については、Flushing を参照してください。
例
次の例は、下流の入力ピンがこのメソッドをどのように呼び出すべきかを示します。
| C++ |
|---|
m_pReader->BeginFlush();
while (1) {
IMediaSample *pSample;
DWORD_PTR dwUnused;
m_pReader->WaitForNext(0, &pSample, &dwUnused);
if(pSample) {
pSample->Release();
}
else { // No more samples.
break;
}
}
m_pReader->EndFlush();
|
EndFlush メソッドは、フラッシュ操作を終了します。(IAsyncReader.EndFlush)
戻り値
解説(Remarks)
ピンがフラッシュ中の間、IAsyncReader::Request メソッドは失敗し、IAsyncReader::WaitForNext メソッドはすぐに戻ります。フラッシュ操作の終わりに EndFlush メソッドを呼び出して、Request メソッドを再び有効にします。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IAsyncReader "{56A868AA-0AD4-11CE-B03A-0020AF0BA770}" #usecom global IAsyncReader IID_IAsyncReader "{}" #comfunc global IAsyncReader_RequestAllocator 3 sptr,var,sptr #comfunc global IAsyncReader_Request 4 sptr,sptr #comfunc global IAsyncReader_WaitForNext 5 int,sptr,var #comfunc global IAsyncReader_SyncReadAligned 6 sptr #comfunc global IAsyncReader_SyncRead 7 int64,int,var #comfunc global IAsyncReader_Length 8 var,var #comfunc global IAsyncReader_BeginFlush 9 #comfunc global IAsyncReader_EndFlush 10 ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。#define global IID_IAsyncReader "{56A868AA-0AD4-11CE-B03A-0020AF0BA770}" #usecom global IAsyncReader IID_IAsyncReader "{}" #comfunc global IAsyncReader_RequestAllocator 3 sptr,sptr,sptr #comfunc global IAsyncReader_Request 4 sptr,sptr #comfunc global IAsyncReader_WaitForNext 5 int,sptr,sptr #comfunc global IAsyncReader_SyncReadAligned 6 sptr #comfunc global IAsyncReader_SyncRead 7 int64,int,sptr #comfunc global IAsyncReader_Length 8 sptr,sptr #comfunc global IAsyncReader_BeginFlush 9 #comfunc global IAsyncReader_EndFlush 10 ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。