📄 dmo_win32.c
字号:
{
AutoBufferSize += VideoInfo->bmiHeader.biSize;
p->ConstSize = VideoInfo->bmiHeader.biSize;
p->Const = &VideoInfo->bmiHeader;
}
p->Codec.ReSend = Resend;
p->OutputNoMask = 1;
p->UseDropping = 1;
break;
case PACKET_AUDIO:
if (MoInitMediaType(&p->InType,sizeof(WAVEFORMATEX)+p->Codec.In.Format.ExtraLength) != S_OK)
return ERR_OUT_OF_MEMORY;
WaveFormat = (WAVEFORMATEX*)p->InType.pbFormat;
memset(WaveFormat,0,sizeof(WAVEFORMATEX));
WaveFormat->wFormatTag = (WORD)p->Codec.In.Format.Format.Audio.Format;
WaveFormat->nChannels = (WORD)p->Codec.In.Format.Format.Audio.Channels;
WaveFormat->nSamplesPerSec = p->Codec.In.Format.Format.Audio.SampleRate;
WaveFormat->nAvgBytesPerSec = p->Codec.In.Format.ByteRate;
WaveFormat->nBlockAlign = (WORD)p->Codec.In.Format.Format.Audio.BlockAlign;
WaveFormat->wBitsPerSample = (WORD)p->Codec.In.Format.Format.Audio.Bits;
WaveFormat->cbSize = (WORD)p->Codec.In.Format.ExtraLength;
if (p->Codec.In.Format.ExtraLength)
{
// PocketPC WMP9
if (p->CreateCodecDMO && p->WMPVersion==9 && WaveFormat->wFormatTag == AUDIOFMT_WMA9 && p->Codec.In.Format.ExtraLength==10)
{
char* e = (char*)(WaveFormat+1);
e[0] = e[1] = 0;
e[8] = e[9] = 0;
memcpy(e+2,p->Codec.In.Format.Extra,6);
}
else
memcpy(WaveFormat+1,p->Codec.In.Format.Extra,p->Codec.In.Format.ExtraLength);
}
p->InType.majortype = WMCMEDIATYPE_Audio;
p->InType.formattype = WMCFORMAT_WaveFormatEx;
p->InType.subtype = WMCMEDIASUBTYPE;
p->InType.subtype.v1 = p->Codec.In.Format.Format.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;
Found = 0;
TRY_BEGIN
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;
// it seems pocketpc can't split output data
if (WaveFormat->nBlockAlign && WaveFormat->nAvgBytesPerSec)
{
AutoBufferSize = Scale(p->Codec.Out.Format.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 || (MinBufferSize && BufferSize < AutoBufferSize))
BufferSize = AutoBufferSize;
else
if (p->WMPVersion>9)
BufferSize += 4096;
for (No=0;No<=p->OutputNoMask;++No)
{
p->OutputBuffer[No].pBuffer = (IMediaBuffer*) 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 Process(dmo* p, const packet* Packet, const flowstate* State)
{
REFERENCE_TIME TimeStamp;
DWORD Status;
IOwnMediaBuffer* Buffer;
IOwnMediaBuffer* LastBuffer;
if (Packet)
{
if (State->DropLevel > 1)
{
p->Media->VMT->Discontinuity(p->Media,0);
p->First = p->UseDropping;
return ERR_NONE;
}
if (p->Media->VMT->GetInputStatus(p->Media, 0, &Status)==0 &&
!(Status & DMO_INPUT_STATUSF_ACCEPT_DATA)) // this shouldn't happen
p->Media->VMT->Discontinuity(p->Media,0);
Status = 0;
if (Packet->Key)
Status |= DMO_INPUT_DATA_BUFFERF_SYNCPOINT;
else
if (p->First)
return ERR_NEED_MORE_DATA;
TimeStamp = 0;
if (Packet->RefTime >= 0)
{
Status |= DMO_INPUT_DATA_BUFFERF_TIME;
TimeStamp = ((REFERENCE_TIME)Packet->RefTime * 10000000 + (TICKSPERSEC/2)) / TICKSPERSEC;
}
Buffer = AllocBuffer(Packet->Length+p->ConstSize,&p->InputBuffers);
if (Buffer)
{
if (p->Const)
{
if (p->WMPVersion>9) p->Const->biSizeImage = Packet->Length;
AppendBuffer((IOwnMediaBuffer*)Buffer,p->ConstSize,p->Const);
}
if (Packet->Data[0])
AppendBuffer((IOwnMediaBuffer*)Buffer,Packet->Length,Packet->Data[0]);
p->Media->VMT->ProcessInput(p->Media,0,(IMediaBuffer*)Buffer,Status,TimeStamp,0);
Buffer->VMT->Release(Buffer);
}
}
LastBuffer = NULL;
if (p->OutputPrev >= 0 && p->OutputPrev != p->OutputNext)
LastBuffer = (IOwnMediaBuffer*) p->OutputBuffer[p->OutputPrev].pBuffer;
if (State && State->DropLevel > 0)
{
DMO_OUTPUT_DATA_BUFFER Discard;
Discard.dwStatus = 0;
Discard.pBuffer = NULL;
p->Media->VMT->ProcessOutput(p->Media, DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER, 1, &Discard, &Status);
}
for (;;)
{
Buffer = (IOwnMediaBuffer*) p->OutputBuffer[p->OutputNext].pBuffer;
Buffer->Length = 0;
p->OutputBuffer[p->OutputNext].dwStatus = 0;
if (p->Media->VMT->ProcessOutput(p->Media, 0, 1, &p->OutputBuffer[p->OutputNext], &Status) != S_OK || Buffer->Length==0)
break;
if (State && State->DropLevel > 0)
{
p->Codec.Out.Process(p->Codec.Out.Pin.Node,NULL,State);
continue;
}
if (p->OutputBuffer[p->OutputNext].dwStatus & DMO_OUTPUT_DATA_BUFFERF_TIME)
p->Codec.Packet.RefTime = (tick_t)((p->OutputBuffer[p->OutputNext].rtTimestamp * TICKSPERSEC + 5000000) / 10000000);
else
p->Codec.Packet.RefTime = -1;
if (p->ConstSize)
{
BITMAPINFOHEADER* Info = Buffer->Data;
p->Codec.Packet.Length = Buffer->Length - Info->biSize;
p->Codec.Packet.Data[0] = (char*)Buffer->Data + Info->biSize;
p->Codec.Packet.LastData[0] = NULL;
if (LastBuffer)
p->Codec.Packet.LastData[0] = (char*)LastBuffer->Data + Info->biSize;
if (p->Codec.Packet.Length <= 0)
p->Codec.Packet.Data[0] = NULL;
}
else
{
p->Codec.Packet.Length = Buffer->Length;
p->Codec.Packet.Data[0] = Buffer->Data;
p->Codec.Packet.LastData[0] = NULL;
if (LastBuffer)
p->Codec.Packet.LastData[0] = LastBuffer->Data;
}
p->OutputPrev = p->OutputNext;
p->OutputNext = (p->OutputNext+1) & p->OutputNoMask;
p->First = 0;
return ERR_NONE;
}
return ERR_NEED_MORE_DATA;
}
static int Flush(dmo* p)
{
if (p->Media)
{
p->Media->VMT->Discontinuity(p->Media,0);
p->Media->VMT->Flush(p->Media);
}
p->OutputPrev = -1;
p->First = p->UseDropping;
return ERR_NONE;
}
static int Create(dmo* p)
{
p->Module = LoadLibrary(LangStr(p->Codec.Node.Class,DMO_MODULEPPC));
GetProc(&p->Module,&p->CreateCodecDMO,T("CreateCodecDMO"),0);
GetProc(&p->Module,&p->CreateCodecDMOEx,T("CreateCodecDMOEx"),1);
GetProc(&p->Module,&p->QueryUnloadCodecDMO,T("QueryUnloadCodecDMO"),1);
if (!p->Module && StringToGUID(LangStr(p->Codec.Node.Class,DMO_CLASSID),&p->ClassId))
{
p->Module = LoadLibrary(LangStr(p->Codec.Node.Class,DMO_MODULE));
GetProc(&p->Module,&p->DllGetClassObject,T("DllGetClassObject"),0);
GetProc(&p->Module,&p->DllCanUnloadNow,T("DllCanUnloadNow"),1);
}
if (!p->Module)
return ERR_NOT_SUPPORTED;
p->Codec.Flush = Flush;
p->Codec.Process = Process;
p->Codec.UpdateInput = UpdateInput;
return ERR_NONE;
}
static void Delete(dmo* p)
{
if ((p->QueryUnloadCodecDMO==NULL || p->QueryUnloadCodecDMO()) &&
(p->DllCanUnloadNow==NULL || p->DllCanUnloadNow()==S_OK))
FreeLibrary(p->Module);
}
static const nodedef DMO =
{
sizeof(dmo)|CF_ABSTRACT,
DMO_CLASS,
CODEC_CLASS,
PRI_DEFAULT-100,
(nodecreate)Create,
(nodedelete)Delete,
};
static const nodedef WMV =
{
0, // parent size
WMV_ID,
DMO_CLASS,
PRI_DEFAULT-100,
};
static const nodedef WMS =
{
0, // parent size
WMS_ID,
DMO_CLASS,
PRI_DEFAULT-100,
};
static const nodedef WMVA =
{
0, // parent size
WMVA_ID,
DMO_CLASS,
PRI_DEFAULT-95,
};
static const nodedef WMA =
{
0, // parent size
WMA_ID,
DMO_CLASS,
PRI_DEFAULT-100,
};
static const nodedef WMAV =
{
0, // parent size
WMAV_ID,
DMO_CLASS,
PRI_DEFAULT-100,
};
//todo: auto find supported content-types
static int Find(int Class)
{
if (CheckModule(LangStr(Class,DMO_MODULEPPC)))
return 2;
if (CheckModule(LangStr(Class,DMO_MODULE)))
return 1;
return 0;
}
void DMO_Init()
{
int WMPVersion = QueryPlatform(PLATFORM_WMPVERSION);
#ifndef TARGET_WIN32
// shellexecute won't work under win32
CoInitializeEx(NULL,COINIT_MULTITHREADED);
#endif
NodeRegisterClass(&DMO);
if (Find(WMV_ID))
{
NodeRegisterClass(&WMV);
NodeRegisterClass(&WMVF);
}
if (Find(WMVA_ID))
{
NodeRegisterClass(&WMVA);
NodeRegisterClass(&WMVF);
}
if (Find(WMS_ID))
{
NodeRegisterClass(&WMS);
NodeRegisterClass(&WMVF);
}
if (Find(WMA_ID))
{
NodeRegisterClass(&WMA);
NodeRegisterClass(&WMAF);
}
if (Find(WMAV_ID))
{
NodeRegisterClass(&WMAV);
NodeRegisterClass(&WMAF);
if (WMPVersion==9 && QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_XSCALE)
{
DWORD Disp=0;
HKEY Key;
tchar_t* Base = T("SOFTWARE\\Microsoft\\Windows Media Player\\Codecs\\WMAVoice");
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, Base, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &Key, &Disp) == ERROR_SUCCESS)
{
DWORD Value = 1;
RegSetValueEx(Key, T("CPUPerformance"), 0, REG_DWORD, (LPBYTE)&Value, sizeof(Value));
RegCloseKey(Key);
}
}
}
}
void DMO_Done()
{
NodeUnRegisterClass(DMO_CLASS);
NodeUnRegisterClass(WMAF_ID);
NodeUnRegisterClass(WMVF_ID);
#ifndef TARGET_WIN32
CoUninitialize();
#endif
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -