overlay_base.c

来自「betaplayer_0.096源码 tcpmp老版本」· C语言 代码 · 共 647 行 · 第 1/2 页

C
647
字号
/*****************************************************************************
 *
 * This program is free software ; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 * $Id: overlay_base.c 153 2004-12-20 16:46:49Z picard $
 *
 * BetaPlayer Overlay plugin
 * Copyright (c) 2004 Gabor Kovacs
 *
 ****************************************************************************/

#include "../stdafx.h"

#if defined(_WIN32)

#ifndef STRICT
#define STRICT
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

void OvlInvalidate( overlay_base* p, const rect* Rect, bool_t Local )
{
	POINT o;
	RECT r;

	if (Rect->Height>0 && Rect->Width>0)
	{
		DEBUG_MSG5(DEBUG_VIDEO,T("Invalidate %d,%d,%d,%d (%d)"),Rect->x,Rect->y,Rect->Width,Rect->Height,Local);

		if (Local)
		{
			// only local invalidate
			o.x = 0;
			o.y = 0;
			ClientToScreen(p->Wnd,&o);

			DEBUG_MSG2(DEBUG_VIDEO,T("Invalidate local offset %d,%d"),o.x,o.y);

			r.left = Rect->x - o.x;
			r.top = Rect->y - o.y;
			r.right = r.left + Rect->Width;
			r.bottom = r.top + Rect->Height;
			InvalidateRect(p->Wnd,&r,0);
		}
		else
			GlobalInvalidate(Rect);
	}
}

void OvlValidate( overlay_base* p, const rect* Rect )
{
	POINT o;
	RECT r;

	if (Rect->Height>0 && Rect->Width>0)
	{
		DEBUG_MSG4(DEBUG_VIDEO,T("Validate %d,%d,%d,%d"),Rect->x,Rect->y,Rect->Width,Rect->Height);

		o.x = 0;
		o.y = 0;
		ClientToScreen(p->Wnd,&o);

		DEBUG_MSG2(DEBUG_VIDEO,T("Validate offset %d,%d"),o.x,o.y);

		r.left = Rect->x - o.x;
		r.top = Rect->y - o.y;
		r.right = r.left+Rect->Width;
		r.bottom = r.top+Rect->Height;

		ValidateRect(p->Wnd,&r);
	}
} 

void OvlInit(overlay_base* p,int Id,int UseDLL,int Priority)
{
	if (UseDLL && !p->Module)
		return;

	if (!p->VMT.Enum) p->VMT.Enum = OvlEnum;
	if (!p->VMT.Get) p->VMT.Get = OvlGet;
	if (!p->VMT.Set) p->VMT.Set = OvlSet;
	if (!p->Blit) p->Blit = OvlBlitImage;
	if (!p->Update) p->Update = OvlUpdateAlign;

	p->Soft = NULL;
	p->Id = Id;
	p->Primary = 1;
	p->Overlay = 0;

	memset(&p->OrigFX,0,sizeof(blitfx));
	p->OrigFX.ScaleX = SCALE_ONE;
	p->OrigFX.ScaleY = SCALE_ONE;
	p->AutoPrerotate = 1;
	p->ColorKey = -1;
	p->Aspect.Num = p->Aspect.Den = 1;

	NodeRegister(&p->VMT,Priority);
}

void OvlDone(overlay_base* p)
{
	BlitRelease(p->Soft);
	NodeUnRegister(&p->VMT);

	if (p->Module)
	{
		FreeLibrary(p->Module);
		p->Module = NULL;
	}
}

int OvlEnum(overlay_base* p,int No,datadef* DataType)
{
	return NodeEnumType(&No,DataType,NodeParams,FlowParams,OutputParams,VOutputParams,p->Params,NULL);
}

void OvlClearBorder( overlay_base* p )
{
	planes Planes;
	if (p->Lock && p->Lock(p,Planes,0) == ERR_NONE)
	{
		uint32_t c = RGBToFormat(0,&p->Output.Pixel);
		rect Viewport;
		VirtToPhy(&p->Viewport,&Viewport,&p->Output);

		FillColor(Planes[0],p->Output.Pitch,Viewport.x,Viewport.y,
			Viewport.Width,p->DstAlignedRect.y-Viewport.y,
			p->Output.Pixel.BitCount,c);

		FillColor(Planes[0],p->Output.Pitch,Viewport.x,p->DstAlignedRect.y,
			p->DstAlignedRect.x-Viewport.x,p->DstAlignedRect.Height,
			p->Output.Pixel.BitCount,c);

		FillColor(Planes[0],p->Output.Pitch,p->DstAlignedRect.x+p->DstAlignedRect.Width,p->DstAlignedRect.y,
			(Viewport.x+Viewport.Width)-(p->DstAlignedRect.x+p->DstAlignedRect.Width),p->DstAlignedRect.Height,
			p->Output.Pixel.BitCount,c);

		FillColor(Planes[0],p->Output.Pitch,Viewport.x,p->DstAlignedRect.y+p->DstAlignedRect.Height,
			Viewport.Width,(Viewport.y+Viewport.Height)-(p->DstAlignedRect.y+p->DstAlignedRect.Height),
			p->Output.Pixel.BitCount,c);

		p->Unlock(p);
	}
}

int OvlUpdateAlign( overlay_base* p )
{
	rect OldGUI = p->GUIAlignedRect;
	rect Old = p->DstAlignedRect;
	rect FullScreen;

	DEBUG_MSG4(DEBUG_TEST,T("BLIT Viewport:%d %d %d %d"),p->Viewport.x,p->Viewport.y,p->Viewport.Width,p->Viewport.Height);

	PhyToVirt(NULL,&FullScreen,&p->Output);
	p->FullScreenViewport = EqRect(&FullScreen,&p->Viewport);

	VirtToPhy(&p->Viewport,&p->DstAlignedRect,&p->Output);
	VirtToPhy(NULL,&p->SrcAlignedRect,&p->Input);

	BlitRelease(p->Soft);
	p->Soft = BlitCreate(&p->Output,&p->Input,&p->FX,&p->Caps);
	p->InputHintDir = p->Input.Direction; // default
	if (p->FX.Flags & BLITFX_AVOIDTEARING) // only suggest input dir when avoid tearing is set
		p->InputHintDir ^= p->FX.Direction;

	BlitAlign(p->Soft,&p->DstAlignedRect, &p->SrcAlignedRect );
	PhyToVirt(&p->DstAlignedRect,&p->GUIAlignedRect,&p->Output);

	//DEBUG_MSG4(DEBUG_TEST,T("BLIT DstRect:%d %d %d %d"),p->DstAlignedRect.x,p->DstAlignedRect.y,p->DstAlignedRect.Width,p->DstAlignedRect.Height);
	//DEBUG_MSG4(DEBUG_TEST,T("BLIT SrcRect:%d %d %d %d"),p->SrcAlignedRect.x,p->SrcAlignedRect.y,p->SrcAlignedRect.Width,p->SrcAlignedRect.Height);

	if (!EqRect(&Old,&p->DstAlignedRect) && p->Show && p->Primary)
	{
		OvlInvalidate(p,&OldGUI,0);
		OvlInvalidate(p,&p->Viewport,1);
		OvlValidate(p,&p->GUIAlignedRect);
	}

	if (p->FullScreenViewport || !p->Primary)
		OvlClearBorder(p);

	return ERR_NONE;
}

int OvlGet(overlay_base* p,int No,void* Data,int Size)
{
	int Result = ERR_INVALID_PARAM;
	switch (No)
	{
	case NODE_ID: GETVALUE(p->Id,int); break;
	case VOUT_PRIMARY: GETVALUE(p->Primary,bool_t); break;
	case VOUT_OVERLAY: GETVALUE(p->Overlay,bool_t); break;
	case VOUT_INPUT|PACKET_FORMAT: GETVALUE(p->Input,video); break;
	case VOUT_INPUT|PACKET_PREF_FORMAT: GETVALUE(p->PrefInput,video); break;
	case VOUT_OUTPUT|PACKET_FORMAT: GETVALUE(p->Output,video); break;
	case VOUT_ACCEL_IDCT: GETVALUE(p->AccelIDCT,idct*); break;
	case VOUT_WND: GETVALUE(p->Wnd,void*); break;
	case VOUT_VISIBLE: GETVALUE(p->Visible,bool_t); break;
	case VOUT_CLIPPING: GETVALUE(p->Clipping,bool_t); break;
	case VOUT_FX: GETVALUE(p->OrigFX,blitfx); break;
	case VOUT_VIEWPORT: GETVALUE(p->Viewport,rect); break;
	case VOUT_OUTPUTRECT: GETVALUE(p->GUIAlignedRect,rect); break;
	case VOUT_AUTOPREROTATE: GETVALUE(p->AutoPrerotate,bool_t); break;
	case VOUT_UPDATING: GETVALUE(p->Updating,bool_t); break;
	case VOUT_PLAY: GETVALUE(p->Play,bool_t); break;
	case VOUT_DIRTY: GETVALUE(p->Dirty,bool_t); break;
	case VOUT_CAPS: GETVALUE(p->Caps,int); break;
	case VOUT_COLORKEY: GETVALUECOND(p->ColorKey,int32_t,!p->Disabled && p->ColorKey!=-1); break;
	case VOUT_ASPECT: GETVALUE(p->Aspect,fraction); break;
	case VOUT_INPUT_DIR: GETVALUE(p->InputHintDir,int); break;
	case VOUT_ORIENTATION:
		if (Size==sizeof(int) && p->QueryOrientation && !p->DisableOrientation)
		{
			*(int*)Data = p->QueryOrientation(p);
			Result = ERR_NONE;
		}
		break;
	}
	return Result;
}

int OvlUpdateFX(overlay_base* p, bool_t ForceUpdate)
{
	blitfx LastFX = p->FX;
	int Width,Height,ScaleX,ScaleY;

	if (!p->Inited) return ERR_INVALID_PARAM;
	if (p->Updating) return ERR_NONE;

	p->FX = p->OrigFX;
	p->FX.Flags |= p->SetFX;
	p->FX.Flags &= ~p->ClearFX;
	p->FX.Direction = CombineDir(p->InputDirection,p->OrigFX.Direction,p->Output.Direction);
	p->PrefInput.Direction = CombineDir(p->FX.Direction,0,p->Input.Direction);

	if (p->OrigFX.ScaleX<=0)
	{
		int v = p->OrigFX.ScaleX;

		Width = p->Viewport.Width;
		Height = p->Viewport.Height;

		if ((p->InputDirection ^ p->OrigFX.Direction) & DIR_SWAPXY)
			SwapInt(&Width,&Height);

		if (p->PreRotate)
		{
			ScaleX = Scale(Width,SCALE_ONE,p->Input.Width);
			ScaleY = Scale(Height,SCALE_ONE,Scale(p->Input.Height,p->Aspect.Num,p->Aspect.Den));
		}
		else
		{
			ScaleX = Scale(Width,SCALE_ONE,Scale(p->Input.Width,p->Aspect.Num,p->Aspect.Den));
			ScaleY = Scale(Height,SCALE_ONE,p->Input.Height);
		}

		if (p->PreRotate && (v == -1 || v == -2))
			v = -3-v;

		if ((v == -2) || (v != -1 && ScaleX>ScaleY))
			ScaleX = ScaleY;

		if (v<-2)
			ScaleX = Scale(ScaleX,-v,SCALE_ONE);

		p->FX.ScaleY = ScaleX;
		p->FX.ScaleX = Scale(ScaleX,p->Aspect.Num,p->Aspect.Den);

		if (p->PreRotate)
			SwapInt(&p->FX.ScaleX,&p->FX.ScaleY);
	}
	else
	{
		// prefer source horizontal scaling (because of smooth scale option)
		if (p->PreRotate)
			p->FX.ScaleY = Scale(p->FX.ScaleY,p->Aspect.Num,p->Aspect.Den);
		else
			p->FX.ScaleX = Scale(p->FX.ScaleX,p->Aspect.Num,p->Aspect.Den);
	}

	if (p->Output.Pixel.Flags & PF_PIXELDOUBLE)
	{
		p->FX.ScaleX >>= 1;
		p->FX.ScaleY >>= 1;
	}

	if ((p->FX.Flags & BLITFX_ONLYDIFF) && p->FX.ScaleX < (SCALE_ONE*2)/3)
		p->FX.Flags &= ~BLITFX_ONLYDIFF;

	if (ForceUpdate || !EqBlitFX(&p->FX,&LastFX))
	{
		p->Update(p);
		p->Dirty = 1;
		p->LastTime = -1;
	}

	return ERR_NONE;
}

static int UpdateInputDirection(overlay_base* p,bool_t Update)
{
	if (p->Inited && !p->Updating)
	{
		p->InputDirection = p->Input.Direction;
		p->PreRotate = 0;

		if (p->AutoPrerotate)
		{
			rect r;
			PhyToVirt(NULL,&r,&p->Input);

⌨️ 快捷键说明

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