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

📄 dmo_win32.c

📁 betaplayer的源码 tcpmp的老版本
💻 C
📖 第 1 页 / 共 3 页
字号:

		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->Output.Node->Set(p->Output.Node,p->Output.No,&Packet,sizeof(packet));
	}
	return Result;
}

static bool_t DecodePacket( dmo* p )
{
	DWORD Status;
	IOwnMediaBuffer* Buffer;
	IOwnMediaBuffer* LastBuffer;

	LastBuffer = NULL;
	if (p->OutputPrev >= 0 && p->OutputPrev != p->OutputNext)
		LastBuffer = (IOwnMediaBuffer*) p->OutputBuffer[p->OutputPrev].pBuffer;

	if (p->Packet.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);

		//DebugMessage(T("DMO%d CurrTime:%d Drop"),p->FormatType,p->Packet.CurrTime);
	}

	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 (p->Packet.DropLevel > 0)
			continue;

		if (p->OutputBuffer[p->OutputNext].dwStatus & DMO_OUTPUT_DATA_BUFFERF_TIME)
			p->Packet.RefTime = (tick_t)(p->OutputBuffer[p->OutputNext].rtTimestamp * TICKSPERSEC / 10000000);
		else
			p->Packet.RefTime = -1;

		if (p->ConstSize)
		{
			BITMAPINFOHEADER* Info = Buffer->Data;
			p->Packet.Length = Buffer->Length - Info->biSize;
			p->Packet.Data[0] = (char*)Buffer->Data + Info->biSize;
			p->Packet.LastData[0] = NULL;
			if (LastBuffer)
				p->Packet.LastData[0] = (char*)LastBuffer->Data + Info->biSize;
			if (p->Packet.Length <= 0)
				continue; // empty frame (i guess)
		}
		else
		{
			p->Packet.Length = Buffer->Length;
			p->Packet.Data[0] = Buffer->Data;
			p->Packet.LastData[0] = NULL;
			if (LastBuffer)
				p->Packet.LastData[0] = LastBuffer->Data;
		}

		//DebugMessage(T("DMO%d CurrTime:%d RefTime:%d Diff:%d"),p->FormatType,p->Packet.CurrTime,p->Packet.RefTime,p->Packet.CurrTime-p->Packet.RefTime); 

		//DEBUG_MSG4(-1,T("DMO%d Output Time:%d Length:%d LastData:%d"),p->FormatType,p->Packet.RefTime,p->Packet.Length,p->Packet.LastData[0] != NULL);

		p->First = 0;
		p->TotalBytes += p->Packet.Length;
		return 1;
	}
	return 0;
}

static int Decode( dmo* p, const packet* Packet )
{
	IMediaBuffer* Buffer;
	REFERENCE_TIME TimeStamp;
	DWORD Status;
	int Result = ERR_NONE;

	p->Packet.CurrTime = Packet->CurrTime;
	p->Packet.DropLevel = p->First ? 0:Packet->DropLevel;

	if (p->Pending)
	{
		do
		{
			if (p->Output.Node->Set(p->Output.Node,p->Output.No,
					&p->Packet,sizeof(packet)) == ERR_BUFFER_FULL)
				return ERR_BUFFER_FULL;

			p->OutputPrev = p->OutputNext;
			p->OutputNext = (p->OutputNext+1) & p->OutputNoMask;
		}
		while (DecodePacket(p));

		p->Pending = 0;
	}

	if (!Packet->Length)
		return ERR_NEED_MORE_DATA;

	p->TotalPackets++;

	if (Packet->DropLevel > 0)
	{
		++p->DroppedPackets;

		if (Packet->DropLevel > 1)
		{
			DEBUG_MSG3(DEBUG_VIDEO,T("DMO%d DropLevel2 Curr:%d Time:%d"),p->FormatType,Packet->CurrTime,Packet->RefTime);
			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;
	}

	//DEBUG_MSG3(-1,T("DMO%d Input Time:%d Size:%d"),p->FormatType,Packet->RefTime,Packet->Length);

	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,Buffer,Status,TimeStamp,0);
		Buffer->VMT->Release(Buffer);
	}

	if (DecodePacket(p))
	{
		Result = ERR_NONE;
		do
		{
			int i = p->Output.Node->Set(p->Output.Node,p->Output.No,
						 				 &p->Packet,sizeof(packet));
			if (i == ERR_BUFFER_FULL)
			{
				p->Pending = 1;
				//return last result
				break;
			}

			p->OutputPrev = p->OutputNext;
			p->OutputNext = (p->OutputNext+1) & p->OutputNoMask;
			Result = i;
		}
		while (DecodePacket(p));
	}
	else
		Result = ERR_NEED_MORE_DATA; // if no frame decoded: need more packet

	return Result;
}

static bool_t IsEmpty( dmo* p )
{
	packet Zero;

  	if (!p->InputFormat) 
		return 1;

    p->Media->VMT->Discontinuity(p->Media,0);

	Zero.CurrTime = -1;
	Zero.DropLevel = p->Packet.DropLevel;
	Zero.Length = 0;
	Zero.Data[0] = NULL;
	Zero.RefTime = -1;

	return Decode(p,&Zero) == ERR_NEED_MORE_DATA;
}

const datadef DMOParams[] = 
{
	{ DMO_CLASS,	TYPE_CLASS },
	{ DMO_INPUT,	TYPE_PACKET, DF_INPUT, -1 },
	{ DMO_OUTPUT,	TYPE_PIN, DF_OUTPUT, -1 },

	DATADEF_END
};

static int Enum( dmo* p, int No, datadef* Param )
{
	int Result = NodeEnumType(&No,Param,NodeParams,FlowParams,DMOParams,NULL);

	if (Result != ERR_NONE && p->FormatType == PACKET_VIDEO)
		Result = NodeEnumType(&No,Param,FlowBufferParams,NULL);

	if (Result == ERR_NONE && Param->Class == DMO_CLASS && 
		(Param->No == DMO_INPUT || Param->No == DMO_OUTPUT))
		Param->Format1 = p->FormatType;

	return Result;
}

static int GetTotal( dmo* p )
{
	if (p->FormatType == PACKET_VIDEO)
		return p->TotalPackets;

	if (p->FormatType == PACKET_AUDIO && p->OutputFormat)
	{
		int BlockAlign = ((audio*)p->OutputFormat)->BlockAlign;
		if (BlockAlign)
			return p->TotalBytes / BlockAlign;
	}
	return 0;
}

static int GetDropped( dmo* p )
{
	if (p->FormatType == PACKET_VIDEO)
		return p->DroppedPackets;
	return 0;
}

static int Get( dmo* p, int No, void* Data, int Size )
{
	int Result = ERR_INVALID_PARAM;
	switch (No)
	{
	case NODE_ID: GETVALUE(p->Id,int); break;
	case DMO_INPUT | PACKET_FORMAT: 
		if (Size == p->FormatSize)
		{
			if (p->InputFormat)
				memcpy(Data,p->InputFormat,p->FormatSize);
			else
				memset(Data,0,p->FormatSize);
			Result = ERR_NONE;
		}
		break;
	case DMO_OUTPUT | PACKET_FORMAT:
		if (Size == p->FormatSize)
		{
			if (p->OutputFormat)
				memcpy(Data,p->OutputFormat,p->FormatSize);
			else
				memset(Data,0,p->FormatSize);
			Result = ERR_NONE;
		}
		break;
	case DMO_OUTPUT: GETVALUE(p->Output,pin); break;
	case FLOW_TOTAL:GETVALUE(GetTotal(p),int); break;
	case FLOW_DROPPED:GETVALUE(GetDropped(p),int); break;
	case FLOW_EMPTY:GETVALUE(IsEmpty(p),bool_t); break;
	}
	return Result;
}

static int Set( dmo* p, int No, const void* Data, int Size )
{
	int Result = ERR_INVALID_PARAM;
	switch (No)
	{
	case DMO_INPUT | PACKET_FORMAT:
		if (!Size) Data = NULL;
		Result = SetFormat(p,(const audio*)Data,Size);
		break;

	case DMO_INPUT:
		if (Size == sizeof(packet))
			Result = Decode(p,(const packet*)Data);
		break;

	case DMO_OUTPUT:
		if (Size == sizeof(pin))
			Result = NodeSetPin(&p->Output,(pin*)Data,p->OutputFormat,p->FormatSize);
		break;

	case FLOWBUFFER_RESEND:
		Result = Resend(p);
		break;

	case FLOW_TOTAL: 
		p->TotalPackets = 0;
		p->TotalBytes = 0;
		break;

	case FLOW_DROPPED: 
		p->DroppedPackets = 0;
		break;

	case FLOW_EMPTY:
		p->OutputPrev = -1;
		p->Media->VMT->Discontinuity(p->Media,0);
		p->Media->VMT->Flush(p->Media);
		p->Pending = 0;
		p->First = p->UseDropping;
		break;
	}
	return Result;
}

static dmo* Chain = NULL;

bool_t DMO_Load( const CLSID* ClassId,const tchar_t* FileNamePPC,const tchar_t* FileNameCOM, 
			     int Id,int FormatType, ... )
{
	dmo* p;
	const int* List = (const int*)&FormatType+1;

	if (!FuncMoInitMediaType || !FuncMoFreeMediaType)
		return 0;

	p = (dmo*) CAlloc(sizeof(dmo),1);
	p->Id = Id;
	p->ClassId = ClassId;
	p->FormatType = FormatType;
	for (;*List;++List)
		p->FourCC[p->FourCCCount++] = *List;

	if (FileNamePPC)
		p->Module = LoadLibrary(FileNamePPC);
	if (!p->Module && FileNameCOM)
		p->Module = LoadLibrary(FileNameCOM);

	if (p->Module)
	{
		*(FARPROC*)&p->CreateCodecDMO = GetProcAddress(p->Module,TWIN("CreateCodecDMO"));
		*(FARPROC*)&p->QueryUnloadCodecDMO = GetProcAddress(p->Module,TWIN("QueryUnloadCodecDMO"));
		*(FARPROC*)&p->DllGetClassObject = GetProcAddress(p->Module,TWIN("DllGetClassObject"));
		*(FARPROC*)&p->DllCanUnloadNow = GetProcAddress(p->Module,TWIN("DllCanUnloadNow"));
	}

	if (!p->CreateCodecDMO && !p->DllGetClassObject)
	{
		if (p->Module)
			FreeLibrary(p->Module);
		Free(p);
		return 0;
	}

#if defined(_WIN32_WCE)
	p->WMPVersion = 9;
	{
		HKEY Key;
		if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, T("SOFTWARE\\Microsoft\\MediaPlayer\\ASFCodecs"), 0, ACCESS_LOAD, &Key ) == ERROR_SUCCESS)
		{
			p->WMPVersion = 10;
			RegCloseKey( Key );

			// wmp10 wm video only works with rgb16 
			// which is currently not supported by BetaPlayer

			if (TcsICmp(FileNamePPC,T("wmvdecoder.dll"))==0 && p->CreateCodecDMO) 
			{
				if (p->Module)
					FreeLibrary(p->Module);
				Free(p);
				return 0; 
			}
		}
	}
#else
	p->WMPVersion = 0;
#endif


	p->VMT.Enum = Enum;
	p->VMT.Get = Get;
	p->VMT.Set = Set;
	p->Chain = Chain;
	Chain = p;

	NodeRegister(&p->VMT,PRI_DEFAULT-100); // we prefer native codecs
	return 1;
}

static HMODULE MSDMODLL = NULL;

void DMO_Init()
{
	CoInitializeEx(NULL,COINIT_MULTITHREADED);

	MSDMODLL = LoadLibrary(T("msdmo.dll"));
	if (!MSDMODLL)
		return;

	*(FARPROC*)&FuncMoInitMediaType = GetProcAddress(MSDMODLL,TWIN("MoInitMediaType"));
	*(FARPROC*)&FuncMoFreeMediaType = GetProcAddress(MSDMODLL,TWIN("MoFreeMediaType"));
}

void DMO_Done()
{
	dmo* i = Chain;
	while (i)
	{
		dmo* j=i->Chain;
		NodeUnRegister(&i->VMT);
		SetFormat(i,NULL,0);

		if (i->Module && 
			(!i->QueryUnloadCodecDMO || i->QueryUnloadCodecDMO()) &&
			(!i->DllCanUnloadNow || i->DllCanUnloadNow()==S_OK))
			FreeLibrary(i->Module);

		Free(i);
		i=j;
	}
	Chain = NULL;

	if (MSDMODLL)
	{
		FreeLibrary(MSDMODLL);
		MSDMODLL = NULL;
	}
	CoUninitialize();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -