📄 dmo_win32.c
字号:
VideoInfo->bmiHeader.biSize = sizeof(VideoInfo->bmiHeader);
VideoInfo->bmiHeader.biWidth = Video->Width;
VideoInfo->bmiHeader.biHeight = Video->Height;
VideoInfo->bmiHeader.biCompression = 3;
VideoInfo->bmiHeader.biBitCount = 16;
VideoInfo->bmiHeader.biPlanes = 1;
VideoInfo->bmiHeader.biSizeImage = (Video->Width * Video->Height * Video->Pixel.BitCount)/8;
VideoInfo->rcSource.left = 0;
VideoInfo->rcSource.top = 0;
VideoInfo->rcSource.right = Video->Width;
VideoInfo->rcSource.bottom = 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 = 1;
p->OutType.lSampleSize = 0;
*/
return 1;
}
bool_t MatchOutVideo( dmo* p )
{
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;
video* Video = (video*) p->OutputFormat;
Video->Pixel.FourCC = Info->bmiHeader.biCompression;
Video->Pixel.BitCount = Info->bmiHeader.biBitCount;
Video->Width = Info->bmiHeader.biWidth;
Video->Height = Info->bmiHeader.biHeight;
Video->Aspect = ASPECT_ONE;
Format_DefaultVideo(Video);
/* if (((Video->Pixel.Flags & PF_RGB) || Video->Pixel.FourCC==3) && Video->Pixel.BitCount==16)
{
Video->Pixel.Flags = PF_FOURCC;
Video->Pixel.FourCC = FOURCC_I420;
Video->Pitch = Video->Width;
}
else
Video->Pixel.FourCC = 0;
*/
if (PlanarYUV420(&Video->Pixel))
return 1;
}
if (p->OutType.pbFormat)
FuncMoFreeMediaType(&p->OutType);
memset(&p->OutType,0,sizeof(p->OutType));
}
return 0;
}
/* on WM2003 doesn't work this way...
bool_t MatchOutAudio( dmo* p )
{
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_WaveFormatEx,sizeof(GUID))==0 &&
p->OutType.cbFormat >= sizeof(WAVEFORMATEX) &&
p->OutType.pbFormat)
{
WAVEFORMATEX *Info = (WAVEFORMATEX*) p->OutType.pbFormat;
audio* Audio = (audio*) p->OutputFormat;
Audio->Format = Info->wFormatTag;
Audio->Channels = Info->nChannels;
Audio->SampleRate = Info->nSamplesPerSec;
Audio->ByteRate = Info->nAvgBytesPerSec;
Audio->BlockAlign = Info->nBlockAlign;
Audio->Bits = Info->wBitsPerSample;
if (Audio->Format == AUDIOFMT_PCM)
{
Audio->FracBits = Audio->Bits - 1;
if (Audio->Bits <= 8)
Audio->Flags = PCM_UNSIGNED;
Audio->Bits = (Audio->Bits + 7) & ~7;
Audio->BlockAlign = (Audio->Channels * Audio->Bits) >> 3;
}
// accept PCM audio
//if (Audio->Format == AUDIOFMT_PCM && Audio->Channels <= 2)
// return 1;
}
if (p->OutType.pbFormat)
FuncMoFreeMediaType(&p->OutType);
memset(&p->OutType,0,sizeof(p->OutType));
}
return 0;
}
*/
bool_t BuildPCM( dmo* p )
{
// manual audio format guessing
WAVEFORMATEX *WaveFormat;
audio* Audio = (audio*) p->OutputFormat;
memcpy(p->OutputFormat,p->InputFormat,sizeof(audio));
if (FuncMoInitMediaType(&p->OutType,sizeof(WAVEFORMATEX)) != S_OK)
return 0;
WaveFormat = (WAVEFORMATEX*) p->OutType.pbFormat;
Audio->Format = AUDIOFMT_PCM;
if (Audio->Channels > 2)
Audio->Channels = 2;
if (Audio->Bits > 16)
Audio->Bits = 16;
if (Audio->Bits <= 8)
Audio->Flags = PCM_UNSIGNED;
Audio->Bits = (Audio->Bits + 7) & ~7;
Audio->FracBits = Audio->Bits - 1;
Audio->BlockAlign = (Audio->Channels * Audio->Bits) >> 3;
Audio->ByteRate = Audio->BlockAlign * Audio->SampleRate;
Audio->Extra = NULL;
Audio->ExtraLength = 0;
WaveFormat->wFormatTag = (WORD)Audio->Format;
WaveFormat->nChannels = (WORD)Audio->Channels;
WaveFormat->nSamplesPerSec = Audio->SampleRate;
WaveFormat->nAvgBytesPerSec = Audio->ByteRate;
WaveFormat->nBlockAlign = (WORD)Audio->BlockAlign;
WaveFormat->wBitsPerSample = (WORD)Audio->Bits;
WaveFormat->cbSize = 0;
p->OutType.majortype = WMCMEDIATYPE_Audio;
p->OutType.formattype = WMCFORMAT_WaveFormatEx;
p->OutType.subtype = WMCMEDIASUBTYPE;
p->OutType.subtype.Data1 = AUDIOFMT_PCM;
p->OutType.bTemporalCompression = 0;
p->OutType.bFixedSizeSamples = 1;
p->OutType.lSampleSize = 0;
return 1;
}
static int SetFormat( dmo* p, const void* Format, int Size )
{
VIDEOINFOHEADER* VideoInfo;
WAVEFORMATEX* WaveFormat;
video* Video;
audio* Audio;
int Dummy;
int BufferSize;
int AutoBufferSize;
int No,Extra;
p->Pending = 0;
p->TotalPackets = 0;
p->TotalBytes = 0;
p->DroppedPackets = 0;
for (No=0;No<p->OutputNoMask+1;++No)
if (p->OutputBuffer[No].pBuffer)
{
p->OutputBuffer[No].pBuffer->VMT->Release(p->OutputBuffer[No].pBuffer);
p->OutputBuffer[No].pBuffer = NULL;
}
p->ConstSize = 0;
p->Const = NULL;
Free(p->InputFormat);
p->InputFormat = NULL;
Free(p->OutputFormat);
p->OutputFormat = NULL;
if (p->InType.pbFormat) FuncMoFreeMediaType(&p->InType);
memset(&p->InType,0,sizeof(p->InType));
if (p->OutType.pbFormat) FuncMoFreeMediaType(&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 (Format)
{
switch (p->FormatType)
{
case PACKET_VIDEO:
if (Size != sizeof(video)) return ERR_INVALID_PARAM;
Video = (video*)Format;
if (!(Video->Pixel.Flags & PF_FOURCC))
return ERR_INVALID_PARAM;
for (No=0;No<p->FourCCCount;++No)
if (p->FourCC[No] == Video->Pixel.FourCC)
break;
if (No==p->FourCCCount)
return ERR_INVALID_PARAM;
break;
case PACKET_AUDIO:
if (Size != sizeof(audio)) return ERR_INVALID_PARAM;
Audio = (audio*)Format;
for (No=0;No<p->FourCCCount;++No)
if (p->FourCC[No] == Audio->Format)
break;
if (No==p->FourCCCount)
return ERR_INVALID_PARAM;
break;
}
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,&IID_IMediaObject,&p->Media);
Class->lpVtbl->Release(Class);
}
}
if (!p->Media)
return ERR_INVALID_PARAM;
switch (p->FormatType)
{
case PACKET_VIDEO:
Video = (video*)Format;
p->FormatSize = sizeof(video);
p->InputFormat = CAlloc(sizeof(video),1);
p->OutputFormat = CAlloc(sizeof(video),1);
Extra = Video->ExtraLength;
if ((Video->Pixel.FourCC == FOURCC('W','M','V','3') ||
Video->Pixel.FourCC == FOURCC('W','M','V','2')) && Extra>4)
Extra = 4; //hope this is right...
if (!p->InputFormat || !p->OutputFormat)
return ERR_OUT_OF_MEMORY;
if (FuncMoInitMediaType(&p->InType,sizeof(VIDEOINFOHEADER)+Extra) != S_OK)
return ERR_OUT_OF_MEMORY;
memcpy(p->InputFormat,Format,sizeof(video));
VideoInfo = (VIDEOINFOHEADER*)p->InType.pbFormat;
memset(VideoInfo,0,sizeof(VIDEOINFOHEADER));
VideoInfo->bmiHeader.biSize = sizeof(VideoInfo->bmiHeader)+Extra;
VideoInfo->bmiHeader.biWidth = Video->Width;
VideoInfo->bmiHeader.biHeight = Video->Height;
VideoInfo->bmiHeader.biCompression = Video->Pixel.FourCC;
VideoInfo->bmiHeader.biBitCount = (WORD)Video->Pixel.BitCount;
VideoInfo->bmiHeader.biPlanes = 1;
VideoInfo->bmiHeader.biSizeImage = (Video->Width * Video->Height * Video->Pixel.BitCount)/8;
if (p->WMPVersion > 9)
VideoInfo->bmiHeader.biSizeImage = 0;
if (Extra)
memcpy(VideoInfo+1,Video->Extra,Extra);
VideoInfo->rcSource.left = 0;
VideoInfo->rcSource.top = 0;
VideoInfo->rcSource.right = Video->Width;
VideoInfo->rcSource.bottom = Video->Height;
VideoInfo->rcTarget = VideoInfo->rcSource;
if (Video->FrameRate.Num)
{
VideoInfo->AvgTimePerFrame = (REFERENCE_TIME)Video->FrameRate.Den * 10000000 / Video->FrameRate.Num;
VideoInfo->dwBitRate = Scale(VideoInfo->bmiHeader.biSizeImage*8,Video->FrameRate.Num,Video->FrameRate.Den);
}
p->InType.majortype = WMCMEDIATYPE_Video;
p->InType.formattype = WMCFORMAT_VideoInfo;
p->InType.subtype = WMCMEDIASUBTYPE;
p->InType.subtype.Data1 = Video->Pixel.FourCC;
if (p->Media->VMT->SetInputType(p->Media, 0, &p->InType, 0) != S_OK)
return ERR_INVALID_DATA;
// first try I420 (sometimes it's not enumarated as support format, but it's supported)
if (!BuildI420(p) || p->Media->VMT->SetOutputType(p->Media,0, &p->OutType, 0) != S_OK)
{
if (p->OutType.pbFormat)
FuncMoFreeMediaType(&p->OutType);
memset(&p->OutType,0,sizeof(p->OutType));
if (!MatchOutVideo(p))
return ERR_INVALID_DATA;
if (p->Media->VMT->SetOutputType(p->Media,0, &p->OutType, 0) != S_OK)
return ERR_INVALID_DATA;
}
AutoBufferSize = GetImageSize((video*)p->OutputFormat);
if (p->CreateCodecDMO)
{
AutoBufferSize += VideoInfo->bmiHeader.biSize;
p->ConstSize = VideoInfo->bmiHeader.biSize;
p->Const = &VideoInfo->bmiHeader;
}
p->OutputNoMask = 1;
p->UseDropping = 1;
break;
case PACKET_AUDIO:
Audio = (audio*)Format;
p->FormatSize = sizeof(audio);
p->InputFormat = CAlloc(sizeof(audio),1);
p->OutputFormat = CAlloc(sizeof(audio),1);
if (!p->InputFormat || !p->OutputFormat)
return ERR_OUT_OF_MEMORY;
if (FuncMoInitMediaType(&p->InType,sizeof(WAVEFORMATEX)+Audio->ExtraLength) != S_OK)
return ERR_OUT_OF_MEMORY;
memcpy(p->InputFormat,Format,sizeof(audio));
WaveFormat = (WAVEFORMATEX*)p->InType.pbFormat;
memset(WaveFormat,0,sizeof(WAVEFORMATEX));
WaveFormat->wFormatTag = (WORD)Audio->Format;
WaveFormat->nChannels = (WORD)Audio->Channels;
WaveFormat->nSamplesPerSec = Audio->SampleRate;
WaveFormat->nAvgBytesPerSec = Audio->ByteRate;
WaveFormat->nBlockAlign = (WORD)Audio->BlockAlign;
WaveFormat->wBitsPerSample = (WORD)Audio->Bits;
WaveFormat->cbSize = (WORD)Audio->ExtraLength;
if (Audio->ExtraLength)
{
// PocketPC WMP9
if (p->CreateCodecDMO && p->WMPVersion == 9 && WaveFormat->wFormatTag == AUDIOFMT_WMA9 && Audio->ExtraLength==10)
{
char* p = (char*)(WaveFormat+1);
p[0] = p[1] = 0;
p[8] = p[9] = 0;
memcpy(p+2,Audio->Extra,6);
}
else
memcpy(WaveFormat+1,Audio->Extra,Audio->ExtraLength);
}
p->InType.majortype = WMCMEDIATYPE_Audio;
p->InType.formattype = WMCFORMAT_WaveFormatEx;
p->InType.subtype = WMCMEDIASUBTYPE;
p->InType.subtype.Data1 = Audio->Format;
p->InType.bTemporalCompression = 0;
p->InType.bFixedSizeSamples = 1;
p->InType.lSampleSize = 0;
if (p->Media->VMT->SetInputType(p->Media, 0, &p->InType, 0) != S_OK)
return ERR_INVALID_DATA;
if (!BuildPCM(p))
return ERR_INVALID_DATA;
if (p->Media->VMT->SetOutputType(p->Media,0, &p->OutType, 0) != S_OK)
return ERR_INVALID_DATA;
// it seems pocketpc can't split output data
if (WaveFormat->nBlockAlign && WaveFormat->nAvgBytesPerSec)
{
AutoBufferSize = Scale(((audio*)p->OutputFormat)->ByteRate,WaveFormat->nBlockAlign,WaveFormat->nAvgBytesPerSec);
AutoBufferSize *= 4; // just to be safe
if (AutoBufferSize < 128*1024)
AutoBufferSize = 128*1024;
}
else
AutoBufferSize = 128*1024;
p->OutputNoMask = 0;
p->UseDropping = 0;
break;
default:
return ERR_INVALID_DATA;
}
BufferSize = 0;
if (p->Media->VMT->GetOutputSizeInfo(p->Media, 0, (DWORD*)&BufferSize, (DWORD*)&Dummy) != S_OK)
return ERR_INVALID_DATA;
if (BufferSize<=0)
BufferSize = AutoBufferSize;
else
if (p->WMPVersion>9)
BufferSize += 4096;
for (No=0;No<p->OutputNoMask+1;++No)
{
p->OutputBuffer[No].pBuffer = AllocBuffer(BufferSize,NULL);
if (!p->OutputBuffer[No].pBuffer)
return ERR_OUT_OF_MEMORY;
}
p->First = p->UseDropping;
p->OutputNext = 0;
p->OutputPrev = -1;
p->Media->VMT->AllocateStreamingResources(p->Media);
}
FreeBuffers(&p->InputBuffers);
return ERR_NONE;
}
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;
memset(&Packet,0,sizeof(Packet));
Packet.RefTime = -1;
Packet.CurrTime = -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -