新しい ASF データ パケットの生成
ASF マルチプレクサ は、 ASF データ オブジェクト で動作し、ContentInfo オブジェクトで定義されている要件に一致するストリームの ASF データ パケットを生成する機能をアプリケーションに提供する WMContainer レイヤー コンポーネントです。
マルチプレクサには、1 つの入力と 1 つの出力があります。 デジタル メディア データを含むストリーム サンプルを受け取り、ASF コンテナーに書き込むことができる 1 つ以上のデータ パケットを生成します。
次の一覧は、ASF データ パケットを生成するプロセスをまとめたものです。
- IMFASFMultiplexer::P rocessSample のマルチプレクサーに入力データを渡します。
- すべての完全なパケットが取得されるまで、ループ内で IMFASFMultiplexer::GetNextPacket を呼び出してデータ パケットを収集します。
- 入力データが完全なパケットに変換された後、マルチプレクサーに保留中のデータが存在する可能性があります。これは 、GetNextPacket によって取得されませんでした。 IMFASFMultiplexer::Flush を呼び出して保留中のサンプルをパケット化し、GetNextPacket をもう一度呼び出してマルチプレクサーから収集します。
- データ パケットの生成中にマルチプレクサーによって行われた変更を反映するために 、IMFASFMultiplexer::End を呼び出して、関連付けられている ASF ヘッダー オブジェクトを更新します。
次の図は、マルチプレクサーを介した ASF ファイルのデータ パケット生成を示しています。
ASF データ パケットの作成
「マルチプレクサー オブジェクトの作成」の説明に従ってマルチプレクサーを作成して初期化した後、IMFASFMultiplexer::P rocessSample を呼び出して、入力データをデータ パケットに処理するためにマルチプレクサーに渡します。 指定された入力は、ストリームのデータを含む 1 つ以上のメディア バッファー (IMFMediaBuffer インターフェイス) を含むことができるメディア サンプル (IMFSample インターフェイス) に含まれている必要があります。 ASF から ASF へのトランスコーディングの場合は、パケット化されたストリーム サンプルを作成するスプリッターから入力メディア サンプルを生成できます。 詳細については、「 ASF スプリッター」を参照してください。
ProcessSample を呼び出す前に、入力メディア サンプルのタイム スタンプが有効なプレゼンテーション時間であることを確認します。それ以外の場合、ProcessSample は失敗し、MF_E_NO_SAMPLE_TIMESTAMPコードを返します。
マルチプレクサは、 ProcessSample を介して圧縮または圧縮されていないメディア サンプルとして入力を受け入れます。 マルチプレクサは、ストリームの帯域幅の使用状況に応じて、これらのサンプルに送信時間を割り当てます。 このプロセス中に、マルチプレクサーはリークバケットパラメータ(ビットレートとバッファウィンドウ使用率)をチェックし、それらの値に準拠していないサンプルを拒否することができます。 入力メディア のサンプルでは、次のいずれかの理由で帯域幅チェックが失敗する可能性があります。
- 最後に割り当てられた送信時間がこのメディア サンプルのタイム スタンプより大きいため、入力メディア サンプルが遅れて到着した場合。 ProcessSample が失敗し、 MF_E_LATE_SAMPLE エラー コードが返されます。
- 入力メディア サンプルのタイム スタンプが割り当てられた送信時刻より前の場合 (これはバッファー オーバーフローを示します)。 マルチプレクサーの初期化中に MFASF_MULTIPLEXER_AUTOADJUST_BITRATE フラグを設定してビット レートを調整するように構成されている場合、マルチプレクサはこの状況を無視できます。 詳細については、「マルチプレクサー オブジェクトの作成」の「 マルチプレクサーの初期化とリーク バケット設定」を参照してください。 このフラグが設定されておらず、マルチプレクサーで帯域幅オーバーランが発生した場合、 ProcessSample は失敗し、 MF_E_BANDWIDTH_OVERRUN エラー コードを返します。
マルチプレクサが送信時間を割り当てると、入力メディア サンプルが 送信ウィンドウに追加されます。これは、送信時間別に並べ替えられた入力メディア サンプルの一覧であり、データ パケットに処理される準備が整います。 データ パケットの構築中に、入力メディア サンプルが解析され、関連するデータがペイロードとしてデータ パケットに書き込まれます。 完全なデータ パケットには、1 つ以上の入力メディア サンプルからのデータを含めることができます。
新しい入力メディア サンプルが送信ウィンドウに到着すると、1 つの完全なパケットを形成するのに十分なメディア サンプルが存在するまでキューに追加されます。 入力メディア サンプルに含まれるメディア バッファー内のデータは、生成されたデータ パケットにコピーされません。 データ パケットは、入力メディア サンプルが完全にパケット化され、完全なパケットがマルチプレクサから収集されるまで、入力メディア バッファーへの参照を保持します。
完全なデータ パケットが使用可能な場合は、 IMFASFMultiplexer::GetNextPacket を呼び出すことによって取得できます。 取得する準備ができている完全なパケットがある間 に ProcessSample を呼び出すと、失敗し、 MF_E_NOTACCEPTING エラー コードが返されます。 これは、マルチプレクサーがより多くの入力を受け入れることができないことを示し、待機中のパケットを取得するには GetNextPacket を呼び出す必要があります。 すべての ProcessSample 呼び出しの後に 1 つ以上の GetNextPacket 呼び出しを実行して、完全なデータ パケットを取得するのが理想的です。 完全なデータ パケットを作成するには、複数の入力メディア サンプルが必要になる場合があります。 逆に、1 つの入力メディア サンプルのデータが複数のパケットにまたがる場合があります。 したがって、 ProcessSample のすべての呼び出しで出力メディア サンプルが生成されるわけではありません。
入力メディア サンプルに MFSampleExtension_CleanPoint 属性で示されるキー フレームが含まれている場合、マルチプレクサーは属性をパケットにコピーします。
ASF データ パケットの取得
マルチプレクサーによって生成された完全なデータ パケットの出力メディア サンプルを収集するには、パケットの出力メディア サンプルが残らなくなるまで、ループで IMFASFMultiplexer::GetNextPacket を呼び出します。 成功事例の一覧を次に示します。
- 使用可能な完全なデータ パケットがある場合、GetNextPacket は pdwStatusFlags パラメーターでASF_STATUS_FLAGS_INCOMPLETE フラグを受け取ります。ppIPacket パラメーターは、最初のデータ パケットへのポインターを受け取ります。 このフラグを受け取る限り、このメソッドを呼び出す必要があります。 反復するたびに、 ppIPacket はキュー内の次のパケットを指します。
- データ パケットが 1 つしかない場合、 ppIPacket はそのパケットを指し示し、 ASF_STATUS_FLAGS_INCOMPLETE フラグは pdwStatusFlags で受信されません。
- マルチプレクサーがまだデータ パケットのパケット化と追加の処理中である場合、GetNextPacket はデータ パケットを生成せずに成功します。 この場合、 ppIPacket はNULL を指します。 続行するには、 ProcessSample を呼び出して、マルチプレクサーにより多くの入力メディア サンプルを提供する必要があります。
次のコード例は、マルチプレクサーを使用してデータ パケットを生成する関数を示しています。 生成されたデータ パケットの内容は、呼び出し元によって割り当てられたデータ バイト ストリームに書き込まれます。
//-------------------------------------------------------------------
// GenerateASFDataPackets
//
// Gets data packets from the mux. This function is called after
// calling IMFASFMultiplexer::ProcessSample.
//-------------------------------------------------------------------
HRESULT GenerateASFDataPackets(
IMFASFMultiplexer *pMux,
IMFByteStream *pDataStream
)
{
HRESULT hr = S_OK;
IMFSample *pOutputSample = NULL;
IMFMediaBuffer *pDataPacketBuffer = NULL;
DWORD dwMuxStatus = ASF_STATUSFLAGS_INCOMPLETE;
while (dwMuxStatus & ASF_STATUSFLAGS_INCOMPLETE)
{
hr = pMux->GetNextPacket(&dwMuxStatus, &pOutputSample);
if (FAILED(hr))
{
break;
}
if (pOutputSample)
{
//Convert to contiguous buffer
hr = pOutputSample->ConvertToContiguousBuffer(&pDataPacketBuffer);
if (FAILED(hr))
{
break;
}
//Write buffer to byte stream
hr = WriteBufferToByteStream(pDataStream, pDataPacketBuffer, NULL);
if (FAILED(hr))
{
break;
}
}
SafeRelease(&pDataPacketBuffer);
SafeRelease(&pOutputSample);
}
SafeRelease(&pOutputSample);
SafeRelease(&pDataPacketBuffer);
return hr;
}
関数は WriteBufferToByteStream
、 トピック「IMFByteStream::Write」に示されています。
このコード例を使用する完全なアプリケーションについては、「 チュートリアル: ASF ストリームを 1 つのファイルから別のファイルにコピーする」を参照してください。
Packet-Generation呼び出しの投稿
マルチプレクサーで完全なデータ パケットが待機していないことを確認するには、 IMFASFMultiplexer::Flush を呼び出します。 これにより、マルチプレクサーは進行中のすべてのメディア サンプルをパケット化します。 アプリケーションは、取得するパケットが残らなくなるまで、 GetNextPacket を使用してループ内のメディア サンプルの形式でこれらのパケットを収集できます。
すべてのメディア サンプルが生成されたら、 IMFASFMultiplexer::End を呼び出して、これらのデータ パケットに関連付けられている ASF ヘッダー オブジェクトを更新します。 Header オブジェクトは、マルチプレクサーの初期化に使用された ContentInfo オブジェクトを渡すことによって指定されます。 この呼び出しは、データ パケットの生成中にマルチプレクサーによって行われた変更を反映するように、さまざまなヘッダー オブジェクトを更新します。 この情報には、すべてのストリームのパケット数、送信期間、再生時間、ストリーム番号が含まれます。 ヘッダー全体のサイズも更新されます。
すべてのデータ パケットが取得された後に End が呼び出されるようにする必要があります。 マルチプレクサーで待機しているパケットがある場合、 End は失敗し、 MF_E_FLUSH_NEEDED エラー コードを返します。 この場合は、ループ内で Flush と GetNextPacket を呼び出して待機中のパケットを取得します。
注意
VBR エンコードの場合は、 End を呼び出した後、ContentInfo オブジェクトのエンコード プロパティでエンコード統計を設定する必要があります。 このプロセスの詳細については、「ContentInfo オブジェクトのプロパティの設定」の「エンコーダー設定を使用した ContentInfo オブジェクトの構成」を参照してください。 次の一覧は、設定する特定のプロパティを示しています。
- MFPKEY_RAVG は、VBR コンテンツの平均ビット レートです。
- MFPKEY_BAVG は、平均ビット レートのバッファー ウィンドウです。
- MFPKEY_RMAX は、VBR コンテンツのピーク ビット レートです。
- MFPKEY_BMAX は、ピーク バッファー ウィンドウです。
関連トピック