Share via


Utilisation de Demux avec des flux élémentaires

[La fonctionnalité associée à cette page, DirectShow, est une fonctionnalité héritée. Il a été remplacé par MediaPlayer, IMFMediaEngine et Audio/Video Capture in Media Foundation. Ces fonctionnalités ont été optimisées pour Windows 10 et Windows 11. Microsoft recommande vivement que le nouveau code utilise MediaPlayer, IMFMediaEngine et Audio/Video Capture dans Media Foundation au lieu de DirectShow, si possible. Microsoft suggère que le code existant qui utilise les API héritées soit réécrit pour utiliser les nouvelles API si possible.]

Lorsque le demux MPEG-2 fournit des charges utiles PES, il envoie le flux d’octets ES par lots d’échantillons de média. La taille de l’échantillon par défaut est de 8 Ko. Le demux démarre un nouvel exemple de média sur chaque limite PES, mais peut décomposer une charge utile PES unique en plusieurs exemples. Par exemple, si une charge utile PES est de 20 Ko, elle est fournie dans deux échantillons de 8 Ko suivis d’un échantillon de 4 Ko. Le demux n’examine pas le contenu du flux d’octets. Il appartient au décodeur d’analyser les en-têtes de séquence et de rechercher les modifications de format.

Lorsque la broche de sortie du filtre demux se connecte au décodeur, il offre le type de média qui a été spécifié lors de la création de l’épingle. Étant donné que le demux n’examine pas le flux d’octets ES, il ne valide pas le type de média. En théorie, un décodeur MPEG-2 doit être en mesure de se connecter uniquement avec le type principal et le sous-type renseignés, pour indiquer le type de données. Le décodeur doit ensuite examiner les en-têtes de séquence qui arrivent dans les exemples multimédias. Toutefois, dans la pratique, de nombreux décodeurs ne se connectent pas, sauf si le type de média inclut un bloc de format complet.

Par exemple, supposons que PID 0x31 contienne une vidéo de profil main MPEG-2. Au minimum, vous devez effectuer les étapes suivantes.

Tout d’abord, créez un type de média pour la vidéo MPEG-2. En laissant de côté le bloc de format pour l’instant :

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

Ensuite, créez une broche de sortie sur le 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))
    {
        ....
    }
}

Ensuite, interrogez la nouvelle broche pour l’interface IMPEG2PIDMap et appelez MapPID. Spécifiez le numéro PID 0x30 et MEDIA_ELEMENTARY_STREAM pour les charges utiles 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();
}

Enfin, libérez toutes les interfaces lorsque vous avez terminé :

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

Voici un exemple plus complet de définition du type de média, y compris le bloc de format. Cet exemple suppose toujours une vidéo de profil mpeg-2 main. Les détails varient en fonction du contenu du flux :

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

Utilisation du démultiplexeur MPEG-2