Condividi tramite


Uso del Demux con i flussi elementari

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation invece di DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

Quando MPEG-2 demux fornisce payload PES, invia il flusso di byte ES in batch di campioni multimediali. La dimensione del campione predefinita è 8K. Il demux avvia un nuovo campione multimediale su ogni limite di PES, ma può suddividere un singolo payload PES in diversi campioni. Ad esempio, se un payload di PES è 20K, verrà distribuito in due campioni di 8K seguiti da un campione di 4K. Il demux non esamina il contenuto del flusso di byte. Spetta al decodificatore analizzare le intestazioni della sequenza e cercare le modifiche al formato.

Quando il pin di output del filtro demux si connette al decodificatore, offre il tipo di supporto specificato al momento della creazione del pin. Poiché il demux non esamina il flusso di byte ES, non convalida il tipo di supporto. In teoria, un decodificatore MPEG-2 dovrebbe essere in grado di connettersi solo con il tipo principale e il sottotipo compilato, per indicare il tipo di dati. Il decodificatore deve quindi esaminare le intestazioni di sequenza che arrivano negli esempi multimediali. Tuttavia, in pratica, molti decodificatori non si connettono a meno che il tipo di supporto non includa un blocco di formato completo.

Si supponga, ad esempio, che PID 0x31 contenga video di profilo principale MPEG-2. Come minimo, è necessario eseguire i passaggi seguenti.

Creare prima di tutto un tipo di supporto per il video MPEG-2. Lasciare da parte il blocco di formato per il momento:

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

Creare quindi un pin di output in 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))
    {
        ....
    }
}

Eseguire quindi una query sul nuovo pin per l'interfaccia IMPEG2PIDMap e chiamare MapPID. Specificare il numero PID 0x30 e MEDIA_ELEMENTARY_STREAM per i payload di 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();
}

Infine, rilasciare tutte le interfacce al termine:

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

Di seguito è riportato un esempio più completo dell'impostazione del tipo di supporto, incluso il blocco di formato. Questo esempio presuppone ancora un video di profilo principale MPEG-2. I dettagli variano a seconda del contenuto del flusso:

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

Uso di MPEG-2 Demultiplexer