Как подключить исходный фильтр к кодировщику DMO?

У меня есть приложение DirectShow для создания беззвучных видео, граф фильтра которого

my video frame generator -> selectable video compressor -> AVI mux -> file writer

или просто

my video frame generator -> AVI mux -> file writer

Это в основном работает так, как ожидалось, если только выбранный компрессор не является DMO, и в этом случае вызов pFilterGraph->Connect() от источника к компрессору завершается ошибкой - обычно с VFW_E_TYPE_NOT_ACCEPTED или VFW_E_CANNOT_CONNECT. Я хотел бы, чтобы DMO тоже работали. Я нашел устаревший образец (AVIEncoderDShow), который мне удалось настроить для сжатия входного AVI-файла с помощью DMO WMV9, который показался многообещающим в этом отношении. Его граф фильтра

pFilterGraph->AddSourceFilter(AVI file) -> AVI splitter -> DMO wrapper for WMV -> AVI mux -> file writer

поэтому я подумал, что могу просто заменить исходный фильтр на мой фильтр (или образец DirectShow с прыгающим мячом, на котором он основан). Однако попытка сделать это дает те же сбои соединения. Источник, который я предоставляю, - это 32-битный RGB, который должен принимать WMV9. На что он может наткнуться?

РЕДАКТИРОВАТЬ: Детали моего предпочтительного типа носителя:

majortype: MEDIATYPE_Video
subtype: MEDIASUBTYPE_RGB32
bFixedSizeSamples: 1
bTemporalCompression: 0
lSampleSize: 3145728
formattype: CLSID_KsDataTypeHandlerVideo
pUnk: NULL
cbFormat: 1128
pbFormat: 0x12ce4bf0

и точная точка отказа с VFW_E_TYPE_NOT_ACCEPTED

hr = pReceivePin->ReceiveConnection((IPin *)this, pmt);
CBasePin::AttemptConnection(IPin * pReceivePin, const CMediaType * pmt) Line 1796   C++
CBasePin::AgreeMediaType(IPin * pReceivePin, const CMediaType * pmt) Line 1939  C++
CBasePin::Connect(IPin * pReceivePin, const _AMMediaType * pmt) Line 1728   C++
CFilterGraph::ConnectDirectInternal(struct IPin *,struct IPin *,struct _AMMediaType const *)    Unknown
CFilterGraph::ConnectDirect(struct IPin *,struct IPin *,struct _AMMediaType const *)    Unknown
ConnectFilters(IBaseFilter * pUpstream, IBaseFilter * pDownstream, IGraphBuilder * pGraph, _AMMediaType * pmt) Line 332 C++

pbFormat моего медиа-типа настроен как VIDEOINFO, который, кажется, имеет ту же структуру, что и VIDEOINFOHEADER, но с дополнительными данными, прикрепленными к нему в конце. Это выглядит так:

rcSource    {LT(0, 0) RB(0, 0)  [0 x 0]}    tagRECT
rcTarget    {LT(0, 0) RB(0, 0)  [0 x 0]}    tagRECT
dwBitRate   0   unsigned long
dwBitErrorRate  0   unsigned long
AvgTimePerFrame 0   __int64
bmiHeader   {biSize=40 biWidth=1024 biHeight=768 ...}   tagBITMAPINFOHEADER
    biSize  40  unsigned long
    biWidth 1024    long
    biHeight    768 long
    biPlanes    1   unsigned short
    biBitCount  32  unsigned short
    biCompression   0   unsigned long
    biSizeImage 3145728 unsigned long
    biXPelsPerMeter 0   long
    biYPelsPerMeter 0   long
    biClrUsed   0   unsigned long
    biClrImportant  0   unsigned long
bmiColors   0x0d381c60 {{rgbBlue=0 '\0' rgbGreen=0 '\0' rgbRed=0 '\0' ...}, {rgbBlue=0 '\0' rgbGreen=0 '\0' rgbRed=...}, ...}   tagRGBQUAD[256]
dwBitMasks  0x0d381c60 {0, 0, 0}    unsigned long[3]
    [0] 0   unsigned long
    [1] 0   unsigned long
    [2] 0   unsigned long
TrueColorInfo   {dwBitMasks=0x0d381c60 {0, 0, 0} bmiColors=0x0d381c6c {{rgbBlue=0 '\0' rgbGreen=0 '\0' rgbRed=0 '\0' ...}, ...} }

person tombola    schedule 22.10.2015    source источник
comment
VFW_E_TYPE_NOT_ACCEPTED означает, что этот тип несовместим. DMO будет принимать только некоторые типы носителей, и ваш источник также может предоставлять данные определенного типа носителей. Вам удастся подключиться, если есть совпадение... Возможно, вам следует опубликовать более подробную информацию о том, что именно у вас есть (тип носителя в источнике).   -  person Roman R.    schedule 22.10.2015
comment
CLSID_KsDataTypeHandlerVideo это FORMAT_VideoInfo? Что находится в файле VIDEOINFOHEADER. Я бы предположил, что кодировщик WMV принимает 32-битный RGB.   -  person Roman R.    schedule 23.10.2015
comment
@RomanR.: Да, это то же значение, что и FORMAT_VideoInfo. Я добавил информацию к основному вопросу.   -  person tombola    schedule 23.10.2015
comment
Я не думаю, что вам нужны дополнительные данные для VIDEOINFOHEADER (что делает cbFormat размером до 1128), но вряд ли это будет проблемой. Что действительно может привести к сбою соединения, так это ноль AvgTimePerFrame, я бы попробовал там ненулевое значение. Я только что быстро проверил - да, я могу подключить свой 32-битный источник RGB к Wrapped WMV9 DMO.   -  person Roman R.    schedule 23.10.2015
comment
@РоманР. : Установка AvgTimePerFrame действительно решает проблему! Большое спасибо! Если вы хотите добавить это в качестве ответа, я приму это.   -  person tombola    schedule 23.10.2015


Ответы (1)


Некоторые фильтры, особенно мультиплексоры и иногда кодировщики, требуют указания частоты кадров видеопотока. В противном случае типы мультимедиа отклоняются с общим кодом ошибки без упоминания того, что причиной является частота кадров.

WMV9 Encoder DMO принимает 32-битный RGB на входе, поэтому вы должны попробовать его с положительным значением AvgTimePerFrame в структуре VIDEOINFOHEADER типа носителя:

введите здесь описание изображения

person Roman R.    schedule 23.10.2015