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

📄 dmo_win32.c

📁 betaplayer的源码 tcpmp的老版本
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 + -