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

📄 dmo_win32.c

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