I have recently stuck in the place where I set outputs of the DMO encoding
to WMV3/WVC1 format. Decoding DMO proceeds OK, but when I call SetOutputType
on an encoder, I am receiving 0x800402005 error.
Input were set to RGB24 or YUY2. In both cases same error is returned for
output.
Can somebody help me in solving this problem?
PS. When I run EnumDMO sample app it lists wmvencod.dll as an not keyed
encoder capable to encode to WMV3 format. So what might be the problem?
Here is excerpt fo the code:
DMO_MEDIA_TYPE mtOut;
ZeroMemory(&mtOut, sizeof(DMO_MEDIA_TYPE));
FOURCCMap fccOut(pOut->bmiHeader.biCompression); // WMV
mtOut.majortype = MEDIATYPE_Video;
mtOut.formattype = FORMAT_VideoInfo;
mtOut.subtype = fccOut;
mtOut.bFixedSizeSamples = 0;
mtOut.bTemporalCompression = 1;
// Allocate memory for the format block.
int iSize = sizeof(VIDEOINFOHEADER) + pOut->bmiHeader.biSize -
sizeof(BITMAPINFOHEADER);
hr = MoInitMediaType(&mtOut, iSize);
memcpy(mtOut.pbFormat, pOut, iSize);
hr = pDMO->SetOutputType(0, &mtOut, 0);
hr is 0x80040205
> I have recently stuck in the place where I set outputs of
> the DMO encoding to WMV3/WVC1 format. Decoding DMO
> proceeds OK, but when I call SetOutputType on an encoder,
> I am receiving 0x800402005 error.
That's a 36 bit number, I sincerely doubt you are getting
that.
[...]
> hr = pDMO->SetOutputType(0, &mtOut, 0);
> hr is 0x80040205
Which means DMO_E_TYPE_NOT_ACCEPTED. What values are you
setting in each field of the media type, including the
format block?
BTW, can't you just enumerate the supported output types to
choose the one you like? That will correctly fill the media
type for you.
--
// Alessandro Angeli
// MVP :: DirectShow / MediaFoundation
// mvpnews at riseoftheants dot com
// http://www.riseoftheants.com/mmx/faq.htm
Here are more details to what you were asking about:
>
> Which means DMO_E_TYPE_NOT_ACCEPTED. What values are you
> setting in each field of the media type, including the
> format block?
format block is a VIDEOINFOHEADER structure:
rcSource = {0,0,0,0}
rcTarget = {0,0,0,0}
dwBitrate = 201000
dwBitErrorRate = 0
AvgTimePerFrame = 666666
bmiHeader.biSize = 44
bmiHeader.biWidth = 320
bmiHeader.biHeight = 240
bmiHeader.biPlanes = 1
bmiHeader.biBitCount = 24
bmiHeader.biCompression = '3VMW'
bmiHeader.biSizeImage = 0
bmiHeader.biXPelsPerMeter = 0
bmiHeader.biYPelsPerMeter = 0
bmiHeader.biClrUsed = 0
bmiHeader.biClrImportant = 0
// To remaind: other fields are
mtOut.majortype = MEDIATYPE_Video;
mtOut.formattype = FORMAT_VideoInfo;
mtOut.subtype = fccOut; // WMV3
mtOut.bFixedSizeSamples = 0;
mtOut.bTemporalCompression = 1;
> BTW, can't you just enumerate the supported output types to
> choose the one you like? That will correctly fill the media
> type for you.
DMO interface has no enumeration methods.
You probably meant, if I enumerate DMOs while selecting them?
Yes, of course. Below you can find an excerpt of code:
HRESULT hr = S_OK;
IEnumDMO * pEnum = NULL;
DMO_PARTIAL_MEDIATYPE dmoOutType;
dmoOutType.type = MEDIATYPE_Video;
FOURCCMap fccOut(m_pOutVIH->bmiHeader.biCompression); // here is WMV3 mapped
to GUID
dmoOutType.subtype = fccOut;
hr = DMOEnum(DMOCATEGORY_VIDEO_ENCODER, 0, 0, NULL, 1, &dmoOutType, &pEnum);
// hr is S_OK
CLSID clsidDMO;
WCHAR * wszName;
IMediaObject * pDMO = NULL;
do
{
hr = pEnum->Next(1, &clsidDMO, &wszName, NULL);
if(hr != S_OK)
break;
CoTaskMemFree(wszName);
hr = CoCreateInstance(clsidDMO, NULL, CLSCTX_INPROC, IID_IMediaObject,
(void **)&pDMO);
}
while(!pDMO);
if(FAILED(hr))
return NULL;
pEnum->Release();
return pDMO; // returns valid object
Name of a returned codec is :
wszName = "WMVideo9 Encoder DMO"
and what may help you, is that wmvencod.dll is loaded when calling
CoCreateInstance.
I do not know what else can be set improperly, so
I would really apreciate your hint in this matter.
With best regards, Radek Strugalski
> bmiHeader.biSize = 44
Isn't sizeof(bmiHeader) 40?
> DMO interface has no enumeration methods.
IMediaObject::GetOutputType(): <<<Call this method to
enumerate an output stream's preferred media types.>>>.
Still nothing, but thanks to you I could check enumerating outputs,
however still with the same error code 0x80040205.
Here is what I tried:
1. Enumerating inputs (before setting output) - GetInputType() always return
uninitialised DMO_MEDIA_TYPE.
2. Enumerating outputs (before setting input) - GetOutputType() always
returns
zeroed DMO_MEDIA_TYPE.
3. Enumerating outputs (after setting input) - returns different types nicely,
including 'WMV3' at the first place.
Here are more details:
DMO_MEDIA_TYPE set on input is:
== INPUT ===============================
majortype = MEDIATYPE_Video;
subtype = MEDIASUBTYPE_RGB24 // tried also YUY2
formattype = FORMAT_VideoInfo;
bFixedSizeSamples = 1
bTemporalCompression = 0
lSampleSize = 230400 //(320x240x3)
cbFormat = 88
VIDEOINFOHEADER members:
rcSource = {0,0,0,0}
rcTarget = {0,0,0,0}
dwBitrate = 201000
dwBitErrorRate = 0
AvgTimePerFrame = 666666
bmiHeader.biSize = 40 // !!!!!! Corrected already from 44
bmiHeader.biWidth = 320
bmiHeader.biHeight = 240
bmiHeader.biPlanes = 1
bmiHeader.biBitCount = 24
bmiHeader.biCompression = 0
bmiHeader.biSizeImage = 0
bmiHeader.biXPelsPerMeter = 0
bmiHeader.biYPelsPerMeter = 0
bmiHeader.biClrUsed = 0
bmiHeader.biClrImportant = 0
What returns GetOutputType for the first preffered type:
== OUTPUT ===============================
majortype = MEDIATYPE_Video;
subtype = '3VMW'
formattype = FORMAT_VideoInfo;
bFixedSizeSamples = 0
bTemporalCompression = 1
lSampleSize = 230400 (320x240) //!!!! not a zero! tried also zeroing
cbFormat = 88
VIDEOINFOHEADER members:
rcSource = {0,0,0,0}
rcTarget = {0,0,0,0}
dwBitrate = 0 // !!! - tried also 201000 (same as source WMV file)
dwBitErrorRate = 0
AvgTimePerFrame = 666666
bmiHeader.biSize = 40 // !!!!!! Corrected already from 44
bmiHeader.biWidth = 320
bmiHeader.biHeight = 240
bmiHeader.biPlanes = 1
bmiHeader.biBitCount = 24
bmiHeader.biCompression = '3VMW'
bmiHeader.biSizeImage = 0
bmiHeader.biXPelsPerMeter = 0
bmiHeader.biYPelsPerMeter = 0
bmiHeader.biClrUsed = 0
bmiHeader.biClrImportant = 0
So as you can see, although GetOutputType returns reasonable values
SetOutputType fails each time.
Isn't it because the encoder is somehow "locked" and may be only
used in some specific "environment"? Still EnumDMO reports this
encoder as unkeyed one.
Is there still some thing I could overlook?
PS. When calling SetInputType and SetOutputType I am always using 0 index
as StreamIndex.
Still hoping there is some solution,
best regards, Radek
> also zeroing cbFormat = 88
Aren't you missing the codec's private data?
http://msdn2.microsoft.com/en-us/library/aa391512(VS.85).aspx
> Isn't it because the encoder is somehow "locked" and may
> be only used in some specific "environment"?
It's not locked/
> One more question regarding IWMCodecPrivateData
> interface, as I was digging for information on what SDK
> should I use in order I could use this interface under XP
> and Visual Studio 2003. Is there a way I could use
> something smaller than WM Format SDK 11? Doesn't it
> interfere with DXSDK from October 2004
> and PlatformSDK Feb 2003 (this pair is the last pair
> compatible with VC6)?
Despite what is commonly believed, you don't need any SDK,
since the SDK does not contain code, which is part of the
runtime, but only docs, samples and headers. What you need
is simply the definition of the interface, its IID and
custom data types (if any). IIRC, You can use the WMF SDK
9.5 or the v9.0 "Sample Code for Using the Windows Media
Audio and Video Codec Interfaces":
http://msdn2.microsoft.com/en-us/windowsmedia/bb190309.aspx
Or you can just copy the definitions from any version of the
headers into your own source files.
Yes! Probably this has to be it!
Thanks for pointing this out.
One more question regarding IWMCodecPrivateData interface, as I was digging
for information on what SDK should I use in order I could use this interface
under XP and Visual Studio 2003. Is there a way I could use something smaller
than WM Format SDK 11? Doesn't it interfere with DXSDK from October 2004
and PlatformSDK Feb 2003 (this pair is the last pair compatible with VC6)?
Once more time thank you for you time.
Radek
I did as it was in the MSDN article. Also I looked for some codes on the net
regarding
codec private data (VLC sources for example) and made slight modifications,
I have made a lot of different tests (I will describe them below) and still
with unimaginable stubbornness I am getting 0x80040205 error.
:(
Everything went fine with getting private data. I got 1024 bytes on the
beginning
and after second call to GetPrivateData I got 5 bytes for WMV3 and 22 for
WVC1.
Tried setting VIDEOINFOHEADER cbFormat to sizeof(VIDEOINFOHEADER) + 5, + 4
and + 1024
prior to calling pDMO->SetOutputType(), tried to set VIDEOINFOHEADER
->bmiHeader.biSize
to 40 + 0, + 4, + 5, + 1024 (Why 4? Because 4 was in the VIH read from ASF
header),
tried to reset to 0 following VIH fields: bmiHeader.biSizeImage,
dwBitRate, AvgTimePerFrame.
I also tried to set rcSource and rcTarget RECTs to reflect input bitmap size.
Always with the same result.
I have double-checked majortype and formattype for some memory
differencies with MEDIATYPE_Video guid and FORMAT_VideoInfo guid respectively.
I don't know if the DMOs are to such extent fussy about DMO_MEDIA_TYPE
and I haven't tried some combination of possible values yet or...
the problem lies somewhere else ...? Maybe wrong input?
So I have checked the input DMO_MEDIA_TYPE structure. rcSource and rcTarget
was unset, so I have set it with proper values... and still nothing.
Input subtype is RGB24. So the input seems to be ok.
Do you have still some thoughts as to what it may be the reason that
those DMO's always fail to set output?
I am going to test it on an other computer. Maybe it is something in the
configuration?
[... after a couple of hours...] No, on Windows 2003 Server there is still
exactly
the same situation.
It has to work... or am I the first person who tries to do this? ;)
Looking forward to hearing from you soon,
Best regards, Radek Strugalski
> I did as it was in the MSDN article. Also I looked for
> some codes on the net regarding
> codec private data (VLC sources for example) and made
> slight modifications,
> I have made a lot of different tests (I will describe
> them below) and still with unimaginable stubbornness I am
> getting 0x80040205 error. :(
[...]
Are you sure you are following the instructions provided
here?
http://msdn2.microsoft.com/en-us/library/aa391512(VS.85).aspx
There is only one right way, no need to experiment. I
followed those instructions and the test code worked at
first try on my machine:
-------------------------------------------
#pragma warning(disable: 4996)
#include <windows.h>
#include <stdio.h>
#include <dshow.h>
#pragma comment(lib,"strmiids")
#include <wmsdk.h>
#include <wmcodecconst.h> /// line 171 is missing a ");" at
the end, causing a "fatal error C1057: unexpected end of
file in macro expansion"
#include <wmcodeciface.h> /// wmcodeciface.h (singular) and
not wmcodecifaces.h (plural)
int wmain(int argc, LPCWSTR argv[])
{
HRESULT hr = S_OK;
bool com = false;
IMediaObject* pEncObject = NULL;
IWMCodecPrivateData* pEncPrivate = NULL;
VIDEOINFOHEADER vihSource = {
{0,0,0,0}, {0,0,0,0}, 0,0, 666666,
{ sizeof(BITMAPINFOHEADER), 320,240, 1,24,BI_RGB,
320*240*3, 0,0, 0,0, }
};
DMO_MEDIA_TYPE mtSource = {
MEDIATYPE_Video,MEDIASUBTYPE_RGB24, TRUE,FALSE,
vihSource.bmiHeader.biSizeImage,
FORMAT_VideoInfo,NULL,
sizeof(vihSource),(LPBYTE)&vihSource
};
VIDEOINFOHEADER vihTarget = {
{0,0,0,0}, {0,0,0,0}, 201000,0, 666666,
{ sizeof(BITMAPINFOHEADER), 320,240, 1,24,*(DWORD*)"WMV3",
0, 0,0, 0,0, }
};
DMO_MEDIA_TYPE mtTarget = {
MEDIATYPE_Video,WMMEDIASUBTYPE_WMV3, FALSE,TRUE, 0,
FORMAT_VideoInfo,NULL,
sizeof(vihTarget),(LPBYTE)&vihTarget
};
VIDEOINFOHEADER* pbTarget = NULL;
DWORD cbTarget = 0;
if(FAILED(hr = CoInitialize(NULL))) goto exit; else com =
true;
if(S_OK != (hr =
CoCreateInstance(CLSID_CWMV9EncMediaObject,NULL,CLSCTX_INPROC_SERVER,__uuidof(IMediaObject),(void**)&pEncObject)))
goto exit;
if(S_OK != (hr = pEncObject->SetInputType(0,&mtSource,0)))
goto exit;
if(S_OK != (hr =
pEncObject->QueryInterface(__uuidof(IWMCodecPrivateData),(void**)&pEncPrivate)))
goto exit;
if(S_OK != (hr =
pEncPrivate->SetPartialOutputType(&mtTarget))) goto exit;
if(S_OK != (hr =
pEncPrivate->GetPrivateData(NULL,&cbTarget))) goto exit;
if(NULL == (pbTarget = (VIDEOINFOHEADER*)new
BYTE[sizeof(pbTarget[0]) + cbTarget])) { hr = E_OUTOFMEMORY;
goto exit; }
if(S_OK != (hr =
pEncPrivate->GetPrivateData((LPBYTE)&pbTarget[1],&cbTarget)))
goto exit;
pbTarget[0] = vihTarget;
mtTarget.cbFormat = sizeof(pbTarget[0]) + cbTarget;
mtTarget.pbFormat = (LPBYTE)pbTarget;
if(S_OK != (hr = pEncObject->SetOutputType(0,&mtTarget,0)))
goto exit;
exit:
if(pbTarget) delete [] (LPBYTE)pbTarget;
if(pEncPrivate ) pEncPrivate ->Release();
if(pEncObject ) pEncObject ->Release();
if(com) CoUninitialize();
return hr;
}
-------------------------------------------
I would like to thak you very much for the exceptional quality help and for
the time I have spend helping me in solving this problem.
I hope that many other users will find this case useful.
Yes, the sample code, you have provided works fine, as mine is working now.
And yes indeed as you told
> There is only one right way, ...
Exactly.
It was not easy to spot the difference in the code. The first difference I
have
noticed was a slight difference in bytes returned by GetPrivateData.
(2 bits on second byte). So I was wondering why. DMO_MEDIA_TYPE in
SetPartialOutputType() was the place I started to looking for. And although I
was experimenting earlier with Bitrate member, I did all experiments _after_
the call to SetPartialOutputType() and bitrate was always 0. That was the
only problem.
no need to experiment.
Yes I know, but this is not a standard use case. And when you see some
working code evering becomes muich more easier.
Anyway, great support!
Best regards, Radek Strugalski