📄 dmo_win32.c
字号:
return NULL;
if (p)
*Chain = p->Next;
else
{
p = (IOwnMediaBuffer*)malloc(sizeof(IOwnMediaBuffer));
if (!p)
return NULL;
memset(p,0,sizeof(IOwnMediaBuffer));
p->VMT = &MediaBufferVMT;
}
p->Chain = Chain;
p->Length = 0;
MBSetMaxLength(p,MaxLength);
p->VMT->AddRef(p);
return p;
}
static bool_t BuildI420(dmo* p)
{
// manual video format guessing (for wince4 non pocketpc)
VIDEOINFOHEADER* VideoInfo;
PacketFormatClear(&p->Codec.Out.Format);
p->Codec.Out.Format.Type = PACKET_VIDEO;
memcpy(&p->Codec.Out.Format.Format.Video,&p->Codec.In.Format.Format.Video,sizeof(video));
p->Codec.Out.Format.Format.Video.Pixel.Flags = PF_FOURCC;
p->Codec.Out.Format.Format.Video.Pixel.FourCC = FOURCC_I420;
p->Codec.Out.Format.Format.Video.Pixel.BitCount = 16;
p->Codec.Out.Format.Format.Video.Pitch = p->Codec.Out.Format.Format.Video.Width;
if (MoInitMediaType(&p->OutType,sizeof(VIDEOINFOHEADER)) != S_OK)
return 0;
VideoInfo = (VIDEOINFOHEADER*)p->OutType.pbFormat;
memset(VideoInfo,0,sizeof(VIDEOINFOHEADER));
VideoInfo->bmiHeader.biSize = sizeof(VideoInfo->bmiHeader);
VideoInfo->bmiHeader.biWidth = p->Codec.Out.Format.Format.Video.Width;
VideoInfo->bmiHeader.biHeight = p->Codec.Out.Format.Format.Video.Height;
VideoInfo->bmiHeader.biCompression = p->Codec.Out.Format.Format.Video.Pixel.FourCC;
VideoInfo->bmiHeader.biBitCount = (WORD)p->Codec.Out.Format.Format.Video.Pixel.BitCount;
VideoInfo->bmiHeader.biPlanes = 1;
VideoInfo->bmiHeader.biSizeImage = (p->Codec.Out.Format.Format.Video.Width *
p->Codec.Out.Format.Format.Video.Height * p->Codec.Out.Format.Format.Video.Pixel.BitCount)/8;
VideoInfo->rcSource.left = 0;
VideoInfo->rcSource.top = 0;
VideoInfo->rcSource.right = p->Codec.Out.Format.Format.Video.Width;
VideoInfo->rcSource.bottom = p->Codec.Out.Format.Format.Video.Height;
VideoInfo->rcTarget = VideoInfo->rcSource;
p->OutType.majortype = WMCMEDIATYPE_Video;
p->OutType.formattype = WMCFORMAT_VideoInfo;
p->OutType.subtype = WMCMEDIASUBTYPE;
p->OutType.subtype.v1 = FOURCC_YUY2; // tricky
p->OutType.bTemporalCompression = 0;
p->OutType.bFixedSizeSamples = 1;
p->OutType.lSampleSize = 0;
return 1;
}
static bool_t BuildRGB16(dmo* p)
{
// wmp10 enumerates falsely the input extra info for rgb16 output (wmv9 advanced profile)
// we have to build our own version
VIDEOINFOHEADER* VideoInfo;
PacketFormatClear(&p->Codec.Out.Format);
p->Codec.Out.Format.Type = PACKET_VIDEO;
memcpy(&p->Codec.Out.Format.Format.Video,&p->Codec.In.Format.Format.Video,sizeof(video));
DefaultRGB(&p->Codec.Out.Format.Format.Video.Pixel,16,5,6,5,0,0,0);
p->Codec.Out.Format.Format.Video.Pitch = p->Codec.Out.Format.Format.Video.Width*2;
p->Codec.Out.Format.Format.Video.Direction = DIR_MIRRORUPDOWN;
if (MoInitMediaType(&p->OutType,sizeof(VIDEOINFOHEADER)+3*4) != S_OK)
return 0;
VideoInfo = (VIDEOINFOHEADER*)p->OutType.pbFormat;
memset(VideoInfo,0,sizeof(VIDEOINFOHEADER));
VideoInfo->bmiHeader.biSize = sizeof(VideoInfo->bmiHeader)+3*4;
VideoInfo->bmiHeader.biWidth = p->Codec.Out.Format.Format.Video.Width;
VideoInfo->bmiHeader.biHeight = p->Codec.Out.Format.Format.Video.Height;
VideoInfo->bmiHeader.biCompression = 3;
VideoInfo->bmiHeader.biBitCount = (WORD)p->Codec.Out.Format.Format.Video.Pixel.BitCount;
VideoInfo->bmiHeader.biPlanes = 1;
VideoInfo->bmiHeader.biSizeImage = (p->Codec.Out.Format.Format.Video.Width *
p->Codec.Out.Format.Format.Video.Height * p->Codec.Out.Format.Format.Video.Pixel.BitCount)/8;
((int32_t*)(VideoInfo+1))[0] = p->Codec.Out.Format.Format.Video.Pixel.BitMask[0];
((int32_t*)(VideoInfo+1))[1] = p->Codec.Out.Format.Format.Video.Pixel.BitMask[1];
((int32_t*)(VideoInfo+1))[2] = p->Codec.Out.Format.Format.Video.Pixel.BitMask[2];
VideoInfo->rcSource.left = 0;
VideoInfo->rcSource.top = 0;
VideoInfo->rcSource.right = p->Codec.Out.Format.Format.Video.Width;
VideoInfo->rcSource.bottom = p->Codec.Out.Format.Format.Video.Height;
VideoInfo->rcTarget = VideoInfo->rcSource;
p->OutType.majortype = WMCMEDIATYPE_Video;
p->OutType.formattype = WMCFORMAT_VideoInfo;
p->OutType.subtype = WMCMEDIASUBTYPE_RGB565;
p->OutType.bTemporalCompression = 0;
p->OutType.bFixedSizeSamples = 0;
p->OutType.lSampleSize = 0;
return 1;
}
// mode0 yuv420
// mode1 rgb16
// mode2 rgb32
static bool_t MatchOutVideo(dmo* p,int Mode)
{
int No;
for (No=0;;++No)
{
if (p->Media->VMT->GetOutputType(p->Media, 0, No, &p->OutType) != S_OK)
break;
if (memcmp(&p->OutType.formattype,&WMCFORMAT_VideoInfo,sizeof(GUID))==0 &&
p->OutType.cbFormat >= sizeof(VIDEOINFOHEADER) &&
p->OutType.pbFormat)
{
VIDEOINFOHEADER *Info = (VIDEOINFOHEADER*) p->OutType.pbFormat;
PacketFormatClear(&p->Codec.Out.Format);
p->Codec.Out.Format.Type = PACKET_VIDEO;
p->Codec.Out.Format.Format.Video.Pixel.FourCC = Info->bmiHeader.biCompression;
p->Codec.Out.Format.Format.Video.Pixel.BitCount = Info->bmiHeader.biBitCount;
p->Codec.Out.Format.Format.Video.Width = Info->bmiHeader.biWidth;
p->Codec.Out.Format.Format.Video.Height = Info->bmiHeader.biHeight;
p->Codec.Out.Format.Format.Video.Aspect = ASPECT_ONE; //todo: fix
if (Info->bmiHeader.biCompression == 3)
{
p->Codec.Out.Format.Format.Video.Pixel.BitMask[0] = 0xF800;
p->Codec.Out.Format.Format.Video.Pixel.BitMask[1] = 0x07E0;
p->Codec.Out.Format.Format.Video.Pixel.BitMask[2] = 0x001F;
}
PacketFormatDefault(&p->Codec.Out.Format);
switch (Mode)
{
case 0:
if (PlanarYUV420(&p->Codec.Out.Format.Format.Video.Pixel))
return 1;
break;
case 1:
if (p->Codec.Out.Format.Format.Video.Pixel.BitCount==16 &&
Info->bmiHeader.biCompression==3)
return 1;
break;
case 2:
if (p->Codec.Out.Format.Format.Video.Pixel.BitCount==32 &&
Info->bmiHeader.biCompression==0)
return 1;
break;
}
}
MoFreeMediaType(&p->OutType);
memset(&p->OutType,0,sizeof(p->OutType));
}
return 0;
}
static bool_t BuildPCM(dmo* p)
{
// manual audio format guessing
WAVEFORMATEX *WaveFormat;
if (MoInitMediaType(&p->OutType,sizeof(WAVEFORMATEX)) != S_OK)
return 0;
PacketFormatPCM(&p->Codec.Out.Format,&p->Codec.In.Format,16);
WaveFormat = (WAVEFORMATEX*) p->OutType.pbFormat;
WaveFormat->wFormatTag = (WORD)p->Codec.Out.Format.Format.Audio.Format;
WaveFormat->nChannels = (WORD)p->Codec.Out.Format.Format.Audio.Channels;
WaveFormat->nSamplesPerSec = p->Codec.Out.Format.Format.Audio.SampleRate;
WaveFormat->nAvgBytesPerSec = p->Codec.Out.Format.ByteRate;
WaveFormat->nBlockAlign = (WORD)p->Codec.Out.Format.Format.Audio.BlockAlign;
WaveFormat->wBitsPerSample = (WORD)p->Codec.Out.Format.Format.Audio.Bits;
WaveFormat->cbSize = 0;
p->OutType.majortype = WMCMEDIATYPE_Audio;
p->OutType.formattype = WMCFORMAT_WaveFormatEx;
p->OutType.subtype = WMCMEDIASUBTYPE;
p->OutType.subtype.v1 = AUDIOFMT_PCM;
p->OutType.bTemporalCompression = 0;
p->OutType.bFixedSizeSamples = 1;
p->OutType.lSampleSize = 0;
return 1;
}
static int Resend(dmo* p)
{
int Result = ERR_INVALID_DATA;
if (p->OutputPrev >= 0 && p->OutputPrev != p->OutputNext)
{
IOwnMediaBuffer* Buffer = (IOwnMediaBuffer*) p->OutputBuffer[p->OutputPrev].pBuffer;
packet Packet;
flowstate State;
State.CurrTime = TIME_RESEND;
State.DropLevel = 0;
memset(&Packet,0,sizeof(Packet));
Packet.RefTime = TIME_UNKNOWN;
if (p->ConstSize)
{
BITMAPINFOHEADER* Info = Buffer->Data;
Packet.Length = Buffer->Length - Info->biSize;
Packet.Data[0] = (char*)Buffer->Data + Info->biSize;
}
else
{
Packet.Length = Buffer->Length;
Packet.Data[0] = Buffer->Data;
}
if (Packet.Length > 0)
Result = p->Codec.Out.Process(p->Codec.Out.Pin.Node,&Packet,&State);
}
return Result;
}
static int UpdateInput(dmo* p)
{
VIDEOINFOHEADER* VideoInfo;
WAVEFORMATEX* WaveFormat;
int Dummy;
int BufferSize;
int AutoBufferSize;
int No,Extra;
bool_t ForceRGB;
bool_t Found;
bool_t MinBufferSize = 0;
for (No=0;No<=p->OutputNoMask;++No)
if (p->OutputBuffer[No].pBuffer)
{
p->OutputBuffer[No].pBuffer->VMT->Release(p->OutputBuffer[No].pBuffer);
p->OutputBuffer[No].pBuffer = NULL;
}
p->Codec.ReSend = NULL;
p->ConstSize = 0;
p->Const = NULL;
p->WMPVersion = QueryPlatform(PLATFORM_WMPVERSION);
MoFreeMediaType(&p->InType);
memset(&p->InType,0,sizeof(p->InType));
MoFreeMediaType(&p->OutType);
memset(&p->OutType,0,sizeof(p->OutType));
if (p->Media)
{
p->Media->VMT->FreeStreamingResources(p->Media);
p->Media->VMT->Release(p->Media);
p->Media = NULL;
}
if (p->Codec.In.Format.Type != PACKET_NONE)
{
uint32_t FourCC;
switch (p->Codec.In.Format.Type)
{
case PACKET_VIDEO:
FourCC = p->Codec.In.Format.Format.Video.Pixel.FourCC;
break;
case PACKET_AUDIO:
FourCC = p->Codec.In.Format.Format.Audio.Format;
break;
default:
FourCC = 0;
break;
}
if (FourCC && p->CreateCodecDMOEx)
p->CreateCodecDMOEx(FourCC,&p->Media);
else
if (p->CreateCodecDMO)
p->CreateCodecDMO(&p->Media);
else
if (p->DllGetClassObject)
{
IClassFactory* Class = NULL;
if (p->DllGetClassObject(&p->ClassId,&ID_ICLASSFACTORY,&Class) == S_OK)
{
Class->lpVtbl->CreateInstance(Class,NULL,(REFIID)&IID_IMediaObject,&p->Media);
Class->lpVtbl->Release(Class);
}
}
if (!p->Media)
return ERR_INVALID_PARAM;
switch (p->Codec.In.Format.Type)
{
case PACKET_VIDEO:
Extra = p->Codec.In.Format.ExtraLength;
if ((p->Codec.In.Format.Format.Video.Pixel.FourCC == FOURCC('W','M','V','3') ||
p->Codec.In.Format.Format.Video.Pixel.FourCC == FOURCC('W','M','V','2')) && Extra>4)
Extra = 4; //hope this is right...
if (MoInitMediaType(&p->InType,sizeof(VIDEOINFOHEADER)+Extra) != S_OK)
return ERR_OUT_OF_MEMORY;
VideoInfo = (VIDEOINFOHEADER*)p->InType.pbFormat;
memset(VideoInfo,0,sizeof(VIDEOINFOHEADER));
VideoInfo->bmiHeader.biSize = sizeof(VideoInfo->bmiHeader)+Extra;
VideoInfo->bmiHeader.biWidth = p->Codec.In.Format.Format.Video.Width;
VideoInfo->bmiHeader.biHeight = p->Codec.In.Format.Format.Video.Height;
VideoInfo->bmiHeader.biCompression = p->Codec.In.Format.Format.Video.Pixel.FourCC;
VideoInfo->bmiHeader.biBitCount = (WORD)p->Codec.In.Format.Format.Video.Pixel.BitCount;
VideoInfo->bmiHeader.biPlanes = 1;
VideoInfo->bmiHeader.biSizeImage = (p->Codec.In.Format.Format.Video.Width *
p->Codec.In.Format.Format.Video.Height * p->Codec.In.Format.Format.Video.Pixel.BitCount)/8;
if (p->WMPVersion > 9)
VideoInfo->bmiHeader.biSizeImage = 0;
if (Extra)
memcpy(VideoInfo+1,p->Codec.In.Format.Extra,Extra);
VideoInfo->rcSource.left = 0;
VideoInfo->rcSource.top = 0;
VideoInfo->rcSource.right = p->Codec.In.Format.Format.Video.Width;
VideoInfo->rcSource.bottom = p->Codec.In.Format.Format.Video.Height;
VideoInfo->rcTarget = VideoInfo->rcSource;
if (p->Codec.In.Format.PacketRate.Num)
{
VideoInfo->AvgTimePerFrame = (REFERENCE_TIME)p->Codec.In.Format.PacketRate.Den * 10000000 / p->Codec.In.Format.PacketRate.Num;
VideoInfo->dwBitRate = Scale(VideoInfo->bmiHeader.biSizeImage*8,p->Codec.In.Format.PacketRate.Num,p->Codec.In.Format.PacketRate.Den);
}
p->InType.majortype = WMCMEDIATYPE_Video;
p->InType.formattype = WMCFORMAT_VideoInfo;
p->InType.subtype = WMCMEDIASUBTYPE;
p->InType.subtype.v1 = p->Codec.In.Format.Format.Video.Pixel.FourCC;
if (p->Media->VMT->SetInputType(p->Media, 0, &p->InType, 0) != S_OK)
return ERR_INVALID_DATA;
// for some reason using planar yuv fails with Window Mobile WMP10 :(
ForceRGB = p->CreateCodecDMO && p->WMPVersion==10;
// some version of C550 ROM uses low level stuff which raises exception in non Kernel mode (default on smartphone)
Found = 0;
TRY_BEGIN
// first try I420 (sometimes it's not enumarated as supported format, even if it is)
if (!(ForceRGB?BuildRGB16(p):BuildI420(p)) || p->Media->VMT->SetOutputType(p->Media,0, &p->OutType, 0) != S_OK)
{
MoFreeMediaType(&p->OutType);
memset(&p->OutType,0,sizeof(p->OutType));
if (ForceRGB || !MatchOutVideo(p,0))
{
video Desktop;
QueryDesktop(&Desktop);
if (Desktop.Pixel.BitCount!=16 || !MatchOutVideo(p,1))
{
if (!MatchOutVideo(p,2))
return ERR_INVALID_DATA;
}
}
if (p->Media->VMT->SetOutputType(p->Media,0, &p->OutType, 0) != S_OK)
return ERR_INVALID_DATA;
}
Found = 1;
TRY_END
if (!Found)
return ERR_INVALID_DATA;
if (p->WMPVersion==9 && PlanarYUV420(&p->Codec.Out.Format.Format.Video.Pixel))
{
// override default pitch, it has to be dword aligned
p->Codec.Out.Format.Format.Video.Pitch = (p->Codec.Out.Format.Format.Video.Pitch+3) & ~3;
MinBufferSize = 1;
}
AutoBufferSize = GetImageSize(&p->Codec.Out.Format.Format.Video);
if (p->CreateCodecDMO)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -