Compartir a través de


Uso de Demux con flujos elementales

[La característica asociada a esta página, DirectShow, es una característica heredada. Se ha reemplazado por MediaPlayer, IMFMediaEngine y Captura de audio/vídeo en Media Foundation. Esas características se han optimizado para Windows 10 y Windows 11. Microsoft recomienda encarecidamente que el nuevo código use MediaPlayer, IMFMediaEngine y Audio/Video Capture en Media Foundation en lugar de DirectShow, siempre que sea posible. Microsoft sugiere que el código existente que usa las API heredadas se reescriba para usar las nuevas API si es posible.

Cuando el demux MPEG-2 entrega cargas PES, envía la secuencia de bytes de ES en lotes de muestras multimedia. El tamaño de muestra predeterminado es 8K. El demux inicia una nueva muestra de medios en cada límite de PES, pero puede dividir una sola carga peS en varias muestras. Por ejemplo, si una carga PES es de 20 000, se entregará en dos muestras de 8K seguidas de una muestra de 4K. El demux no examina el contenido de la secuencia de bytes. Es hasta el descodificador para analizar los encabezados de secuencia y buscar cambios de formato.

Cuando el pin de salida del filtro demux se conecta al descodificador, ofrece el tipo de medio que se especificó cuando se creó el pin. Dado que el demux no examina la secuencia de bytes de ES, no valida el tipo de medio. En teoría, un descodificador MPEG-2 debe poder conectarse con solo el tipo principal y el subtipo rellenados, para indicar el tipo de datos. A continuación, el descodificador debe examinar los encabezados de secuencia que llegan a los ejemplos multimedia. Sin embargo, en la práctica, muchos descodificadores no se conectarán a menos que el tipo de medio incluya un bloque de formato completo.

Por ejemplo, supongamos que PID 0x31 contiene vídeo de perfil principal MPEG-2. Como mínimo, tendría que realizar los pasos siguientes.

En primer lugar, cree un tipo de medio para el vídeo MPEG-2. Dejando aparte el bloque de formato por ahora:

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

A continuación, cree un pin de salida en 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))
    {
        ....
    }
}

A continuación, consulte el nuevo pin para la interfaz IMPEG2PIDMap y llame a MapPID. Especifique el número piD 0x30 y MEDIA_ELEMENTARY_STREAM para las cargas 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();
}

Por último, publique todas las interfaces cuando haya terminado:

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

Este es un ejemplo más completo de cómo establecer el tipo de medio, incluido el bloque de formato. En este ejemplo se sigue presuponiendo un vídeo de perfil principal MPEG-2. Los detalles variarán en función del contenido de la secuencia:

// 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 del Demultiplexer MPEG-2