Verwenden des Demux mit Elementary Streams
[Das dieser Seite zugeordnete Feature DirectShow ist ein Legacyfeature. Es wurde von MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation abgelöst. Diese Features wurden für Windows 10 und Windows 11 optimiert. Microsoft empfiehlt dringend, dass neuer Code mediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation anstelle von DirectShow verwendet, wenn möglich. Microsoft schlägt vor, dass vorhandener Code, der die Legacy-APIs verwendet, so umgeschrieben wird, dass nach Möglichkeit die neuen APIs verwendet werden.]
Wenn das MPEG-2-Demux PES-Nutzlasten übermittelt, sendet es den ES-Bytestream in Batches von Medienbeispielen. Die Standardbeispielgröße beträgt 8.000. Die Demux startet ein neues Medienbeispiel an jeder PES-Grenze, kann jedoch eine einzelne PES-Nutzlast in mehrere Beispiele unterteilen. Wenn eine PES-Nutzlast beispielsweise 20.000 beträgt, wird sie in zwei 8K-Beispielen gefolgt von einem 4K-Beispiel bereitgestellt. Der Demux untersucht nicht den Inhalt des Bytestreams. Es liegt am Decoder, die Sequenzheader zu analysieren und nach Formatänderungen zu suchen.
Wenn der Ausgabepin des Demux-Filters eine Verbindung mit dem Decoder herstellt, wird der Medientyp angezeigt, der beim Erstellen des Pins angegeben wurde. Da der Demux den ES-Bytestream nicht untersucht, wird der Medientyp nicht überprüft. Theoretisch sollte ein MPEG-2-Decoder nur mit dem ausgefüllten Haupttyp und Untertyp eine Verbindung herstellen können, um den Datentyp anzugeben. Der Decoder sollte dann die Sequenzheader untersuchen, die in den Medienbeispielen eingehen. In der Praxis stellen viele Decoder jedoch keine Verbindung her, es sei denn, der Medientyp enthält einen vollständigen Formatblock.
Angenommen, pid 0x31 enthält mpeg-2 Standard Profilvideo. Sie müssen mindestens die folgenden Schritte ausführen.
Erstellen Sie zunächst einen Medientyp für MPEG-2-Video. Lassen Sie den Formatblock vorerst außer Acht:
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).
Erstellen Sie als Nächstes einen Ausgabepin auf 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))
{
....
}
}
Fragen Sie dann die neue Pin für die IMPEG2PIDMap-Schnittstelle ab, und rufen Sie MapPID auf. Geben Sie die PID-Nummer 0x30 und MEDIA_ELEMENTARY_STREAM für PES-Nutzlasten an.
// 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();
}
Lassen Sie schließlich alle Schnittstellen frei, wenn Sie fertig sind:
pPin0->Release();
pDemux->Release();
Hier sehen Sie ein vollständiges Beispiel für das Festlegen des Medientyps, einschließlich des Formatblocks. In diesem Beispiel wird weiterhin von einem MPEG-2-Standard-Profilvideo ausgegangen. Die Details variieren je nach Streaminhalt:
// 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));
Zugehörige Themen