⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dmo_win32.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
📖 第 1 页 / 共 3 页
字号:
			{
				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 + -