Поделиться через


Использование Demux с элементарными потоками

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать в новом коде MediaPlayer, IMFMediaEngine и аудио/видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, в котором используются устаревшие API, чтобы по возможности использовать новые API.]

Когда demux MPEG-2 доставляет полезные данные PES, он отправляет поток байтов ES в пакетах примеров мультимедиа. Размер выборки по умолчанию — 8 КБ. Demux запускает новый пример носителя на каждой границе PES, но может разбить одну полезную нагрузку PES на несколько примеров. Например, если полезные данные PES равен 20K, они будут доставлены в двух примерах 8K, за которыми следует один пример 4K. Demux не проверяет содержимое потока байтов. Декодер выполняет синтаксический анализ заголовков последовательности и поиск изменений формата.

Когда выходной контакт фильтра demux подключается к декодеру, он предлагает тип носителя, указанный при создании контакта. Так как demux не проверяет поток байтов ES, он не проверяет тип носителя. Теоретически декодер MPEG-2 должен иметь возможность соединяться только с заполненным основным типом и подтипом, чтобы указать тип данных. Затем декодер должен проверить заголовки последовательности, поступающие в образцы мультимедиа. Однако на практике многие декодеры не будут подключаться, если тип носителя не содержит полный блок формата.

Например, предположим, что 0x31 PID содержит видео профиля MPEG-2 main. Как минимум необходимо выполнить следующие действия.

Сначала создайте тип мультимедиа для видео MPEG-2. Оставим в стороне блок формата на данный момент:

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

Затем создайте выходной контакт на 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))
    {
        ....
    }
}

Затем запросите новый контакт для интерфейса IMPEG2PIDMap и вызовите MapPID. Укажите номер PID 0x30 и MEDIA_ELEMENTARY_STREAM для полезных данных 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();
}

Наконец, отпустите все интерфейсы после завершения:

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

Ниже приведен более полный пример настройки типа мультимедиа, включая блок форматирования. В этом примере предполагается, что видео профиля MPEG-2 main. Сведения зависят от содержимого потока.

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

Использование демультиплексера MPEG-2