基本ストリームでの Demux の使用
[このページに関連付けられている機能 DirectShow は、従来の機能です。 MediaPlayer、IMFMediaEngine、Media Foundation のオーディオ/ビデオ キャプチャに置き換わりました。 これらの機能は、Windows 10とWindows 11用に最適化されています。 新しいコードでは、可能であれば、DirectShow ではなく Media Foundation で MediaPlayer、IMFMediaEngine、Audio/Video Capture を使用することを強くお勧めします。 Microsoft は、レガシ API を使用する既存のコードを、可能であれば新しい API を使用するように書き換えるよう提案しています。]
MPEG-2 demux が PES ペイロードを配信すると、メディア サンプルのバッチで ES バイト ストリームが送信されます。 既定のサンプル サイズは 8K です。 demux は、各 PES 境界で新しいメディア サンプルを開始しますが、1 つの PES ペイロードを複数のサンプルに分割できます。 たとえば、PES ペイロードが 20K の場合、2 つの 8K サンプルの後に 1 つの 4K サンプルが配信されます。 demux はバイト ストリームの内容を調べません。 シーケンス ヘッダーを解析し、形式の変更を探すのはデコーダー次第です。
demux フィルターの出力ピンがデコーダーに接続すると、ピンの作成時に指定されたメディアの種類が提供されます。 demux は ES バイト ストリームを調べないため、メディアの種類を検証しません。 理論的には、MPEG-2 デコーダーは、データの種類を示すために、入力された主要な型とサブタイプだけで接続できる必要があります。 その後、デコーダーは、メディア サンプルに到着するシーケンス ヘッダーを調べる必要があります。 ただし、実際には、メディアタイプに完全なフォーマットブロックが含まれていない限り、多くのデコーダーは接続しません。
たとえば、PID 0x31に MPEG-2 メイン プロファイル ビデオが含まれているとします。 少なくとも、次の手順を実行する必要があります。
まず、MPEG-2 ビデオのメディアの種類を作成します。 ここでは、フォーマット ブロックを脇に置いておきます。
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video ;
mt.subtype = MEDIASUBTYPE_MPEG2_VIDEO;
// Possibly create a format block (not shown here).
次に、demux に出力ピンを作成します。
// Query the demux filter for IMpeg2Demultiplexer.
IMpeg2Demultiplexer *pDemux;
hr = pFilter->QueryInterface(IID_IMpeg2Demultiplexer, (void**)&pDemux);
if (SUCCEEDED(hr))
{
// Create a new output pin.
IPin *pPin0;
hr = pDemux->CreateOutputPin(&mt, L"Video Pin", &pPin0);
if (SUCCEEDED(hr))
{
....
}
}
次に、 IMPEG2PIDMap インターフェイスの新しいピンに対してクエリを実行し、 MapPID を呼び出します。 PID 番号0x30を指定し、PES ペイロードにMEDIA_ELEMENTARY_STREAMします。
// Query the pin for IMPEG2PIDMap. This implicitly configures the
// demux to carry a transport stream.
IMPEG2PIDMap *pPidMap;
hr = pPin0->QueryInterface(IID_IMPEG2PIDMap, (void**)&pPidMap);
if (SUCCEEDED(hr))
{
// Assign PID 0x31 to pin 0. Set the type to "PES payload."
ULONG Pid = 0x031;
hr = pPidMap->MapPID(1, &Pid, MEDIA_ELEMENTARY_STREAM);
pPidMap->Release();
}
最後に、完了したら、すべてのインターフェイスを解放します。
pPin0->Release();
pDemux->Release();
フォーマット ブロックを含むメディアの種類を設定するより完全な例を次に示します。 この例では、MPEG-2 メイン プロファイル ビデオを引き続き想定しています。 詳細は、ストリームの内容によって異なります。
// Set up a byte array to hold the first sequence header.
// This may or may not be required, depending on the decoder.
BYTE SeqHdr[] = { ... }; // Contains the sequence header (not shown).
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video ;
mt.subtype = MEDIASUBTYPE_MPEG2_VIDEO;
mt.formattype = FORMAT_MPEG2Video;
// Allocate the format block, including space for the sequence header.
mt.cbFormat = sizeof(MPEG2VIDEOINFO) + sizeof(SeqHdr);
mt.pbFormat = (BYTE*)CoTaskMemAlloc(mt.cbFormat);
if (mt.pbFormat == NULL)
{
// Out of memory; return an error code.
}
ZeroMemory(mt.pbFormat, mt.cbFormat);
// Cast the buffer pointer to an MPEG2VIDEOINFO struct.
MPEG2VIDEOINFO *pMVIH = (MPEG2VIDEOINFO*)mt.pbFormat;
RECT rcSrc = {0, 480, 0, 720}; // Source rectangle.
pMVIH->hdr.rcSource = rcSrc;
pMVIH->hdr.dwBitRate = 4000000; // Bit rate.
pMVIH->hdr.AvgTimePerFrame = 333667; // 29.97 fps.
pMVIH->hdr.dwPictAspectRatioX = 4; // 4:3 aspect ratio.
pMVIH->hdr.dwPictAspectRatioY = 3;
// BITMAPINFOHEADER information.
pMVIH->hdr.bmiHeader.biSize = 40;
pMVIH->hdr.bmiHeader.biWidth = 720;
pMVIH->hdr.bmiHeader.biHeight = 480;
pMVIH->dwLevel = AM_MPEG2Profile_Main; // MPEG-2 profile.
pMVIH->dwProfile = AM_MPEG2Level_Main; // MPEG-2 level.
// Copy the sequence header into the format block.
pMVIH->cbSequenceHeader = sizeof(SeqHdr); // Size of sequence header.
memcpy(pMVIH->dwSequenceHeader, SeqHdr, sizeof(SeqHdr));
関連トピック