Menggunakan Demux dengan Aliran Dasar

[Fitur yang terkait dengan halaman ini, DirectShow, adalah fitur warisan. Ini telah digantikan oleh MediaPlayer, IMFMediaEngine, dan Tangkapan Audio/Video di Media Foundation. Fitur-fitur tersebut telah dioptimalkan untuk Windows 10 dan Windows 11. Microsoft sangat menyarankan agar kode baru menggunakan MediaPlayer, IMFMediaEngine dan Audio/Video Capture di Media Foundation alih-alih DirectShow, jika memungkinkan. Microsoft menyarankan agar kode yang ada yang menggunakan API warisan ditulis ulang untuk menggunakan API baru jika memungkinkan.]

Ketika demux MPEG-2 mengirimkan payload PES, ia mengirim aliran byte ES dalam batch sampel media. Ukuran sampel default adalah 8K. Demux memulai sampel media baru pada setiap batas PES, tetapi dapat memecah satu payload PES menjadi beberapa sampel. Misalnya, jika payload PES adalah 20K, itu akan dikirimkan dalam dua sampel 8K diikuti oleh satu sampel 4K. Demux tidak memeriksa konten aliran byte. Terserah dekoder untuk mengurai header urutan dan mencari perubahan format.

Ketika pin output filter demux tersambung ke dekoder, ia menawarkan jenis media yang ditentukan saat pin dibuat. Karena demux tidak memeriksa aliran byte ES, demux tidak memvalidasi jenis media. Secara teori, dekoder MPEG-2 harus dapat terhubung hanya dengan jenis utama dan subjenis yang diisi, untuk menunjukkan jenis data. Dekoder kemudian harus memeriksa header urutan yang tiba di sampel media. Namun, dalam praktiknya, banyak dekode tidak akan terhubung kecuali jenis media menyertakan blok format lengkap.

Misalnya, pid 0x31 berisi video profil utama MPEG-2. Minimal, Anda harus melakukan langkah-langkah berikut.

Pertama, buat jenis media untuk video MPEG-2. Menyisihkan blok format untuk saat ini:

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).

Selanjutnya, buat pin output pada 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))
    {
        ....
    }
}

Kemudian, kueri pin baru untuk antarmuka IMPEG2PIDMap dan panggil MapPID. Tentukan 0x30 nomor PID, dan MEDIA_ELEMENTARY_STREAM untuk payload PES.

// 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();
}

Terakhir, rilis semua antarmuka setelah Anda selesai:

pPin0->Release();
pDemux->Release();

Berikut adalah contoh pengaturan jenis media yang lebih lengkap, termasuk blok format. Contoh ini masih mengasumsikan video profil utama MPEG-2. Detailnya akan bervariasi tergantung pada konten streaming:

// 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));

Menggunakan MPEG-2 Demultiplexer