I have a DirectShow app for generating silent videos, whose filter graph is
my video frame generator -> selectable video compressor -> AVI mux -> file writer
or just
my video frame generator -> AVI mux -> file writer
This mostly works as expected, unless the selected compressor is a DMO, in which case the pFilterGraph->Connect() call from source to compressor fails - typically with VFW_E_TYPE_NOT_ACCEPTED or VFW_E_CANNOT_CONNECT. I would like to make DMOs work too. I found a deprecated sample (AVIEncoderDShow) that I was able to tweak to compress an input AVI file with the WMV9 DMO, which seemed promising on this score. Its filter graph is
pFilterGraph->AddSourceFilter(AVI file) -> AVI splitter -> DMO wrapper for WMV -> AVI mux -> file writer
so I thought I could just swap out the source filter for my filter (or the bouncing ball DirectShow sample that it's based on). Trying that just gives the same connection failures though. The source I'm supplying is 32 bit RGB, which WMV9 should accept. What might it be stumbling on?
EDIT: The details of my preferred media type are:
majortype: MEDIATYPE_Video
subtype: MEDIASUBTYPE_RGB32
bFixedSizeSamples: 1
bTemporalCompression: 0
lSampleSize: 3145728
formattype: CLSID_KsDataTypeHandlerVideo
pUnk: NULL
cbFormat: 1128
pbFormat: 0x12ce4bf0
and the exact point of failure with VFW_E_TYPE_NOT_ACCEPTED is
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++
My media type's pbFormat is set up as a VIDEOINFO, which seems to have the same structure as a VIDEOINFOHEADER but with additional data tacked on the end of it. It looks like this:
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' ...}, ...} }
Some filters, especially multiplexers and sometimes encoders, require that you specify frame rate of the video stream. And otherwise the media types are rejected with generic error code, without a mention that frame rate is the cause.
WMV9 Encoder DMO does accept 32-bit RGB on the input, so you should try it out with a positive AvgTimePerFrame
value in VIDEOINFOHEADER
structure of the media type: