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

📄 softidct.c

📁 betaplayer的源码 tcpmp的老版本
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
 *
 * 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: softidct.c 202 2005-01-25 01:27:33Z picard $
 *
 * BetaPlayer SoftIDCT 
 * Copyright (c) 2004 Gabor Kovacs
 *
 ****************************************************************************/
 
#include "../stdafx.h"
#include "softidct.h"

#ifdef MIPS64

// 8 byte steps
static void edge_copy(uint8_t *p_border_top,uint8_t *p_border_top_ref,int width){
	__asm (	"srl	$8,$6,4;"
			"bucle: ldr	$10,0($5);"
			"ldr	$11,8($5);"
#ifdef MIPSVR41XX
			".set noreorder;"
			"cache	13,0($4);" //cache without loading
			".set reorder;"
#endif
			"addi	$5,$5,16;"
			"sdr	$10,0($4);"
			"sdr	$11,8($4);"
			"addi	$8,$8,-1;"
			"addi	$4,$4,16;"
			"bgtz	$8,bucle;"
			"andi	$6,$6,0x08;"
			"beq	$6,$0,final;"
			"ldr	$10,0($5);"
			"sdr	$10,0($4);"
			"final:"
			);
}

// 16 byte steps
static void edge_set(uint8_t *p_border_top,int p_border_top_ref,int width) {
	__asm (	"srl	$8,$6,4;"
			"dsll	$10,$5,56;"
			"dsrl	$11,$10,8;"
			"or		$10,$10,$11;"
			"dsrl	$11,$10,16;"
			"or		$10,$10,$11;"
			"dsrl	$11,$10,32;"
			"or		$10,$10,$11;"
			"bucle2:"
#ifdef MIPSVR41XX
			".set noreorder;"
			"cache	13,0($4);" //cache without loading
			".set reorder;"
#endif
			"sdr	$10,0($4);"
			"sdr	$10,8($4);"
			"addi	$8,$8,-1;"
			"addi	$4,$4,16;"
			"bgtz	$8,bucle2;"
			);
}
#else
#define edge_copy memcpy
#define edge_set memset
#endif

static void FillEdge(uint8_t *Ptr, int Width, int Height, int EdgeX, int EdgeY)
{
	int n;
	uint8_t *p;
	int InnerWidth = Width - EdgeX*2;
	int InnerHeight = Height - EdgeY*2;
		
	// left and right
	p = Ptr + EdgeX + EdgeY * Width;
	for (n=0;n<InnerHeight;++n)
	{
		edge_set(p-EdgeX, p[0], EdgeX);
		edge_set(p+InnerWidth,p[InnerWidth-1], EdgeX);
		p += Width;
	}

	// top
	p = Ptr;
	for (n=0;n<EdgeY;++n)
	{
		edge_copy(p, Ptr+EdgeY * Width, Width);
		p += Width;
	}

	// bottom
	p = Ptr + (Height-EdgeY)*Width;
	for (n=0;n<EdgeY;++n)
	{
		edge_copy(p, Ptr+(Height-EdgeY-1)*Width, Width);
		p += Width;
	}
}

static void FillEdgeYUV(softidct* p,uint8_t *Ptr)
{
	FillEdge(Ptr, p->BufWidth, p->BufHeight, EDGE, EDGE );
	Ptr += p->YToU;
	FillEdge(Ptr, p->BufWidth>>p->UVX2, p->BufHeight>>p->UVY2, EDGE>>p->UVX2, EDGE>>p->UVY2);
	Ptr += p->YToU >> (p->UVX2+p->UVY2);
	FillEdge(Ptr, p->BufWidth>>p->UVX2, p->BufHeight>>p->UVY2, EDGE>>p->UVX2, EDGE>>p->UVY2);
}

#if defined( MIPS64_WIN32 ) 
static int TouchPages(softidct* p)
{
	uint8_t* i;
	int Sum = 0;
	for (i=p->CodeBegin;i<p->CodeEnd;i+=p->CodePage)
		Sum += *i;
	return Sum;
}
#endif

static int Lock(softidct* p,int No,planes Planes,int* Brightness,video* Format)
{
	if (Brightness)
		*Brightness = 0;
	if (Format)
	{
		*Format = p->OutputFormat;
		Format->Pitch = p->BufWidth;
		Format->Width = p->BufWidth - 2*EDGE;
		Format->Height = p->BufHeight - 2*EDGE;
	}

	if (No<0 || No>=p->BufCount)
	{
		Planes[0] = NULL;
		Planes[1] = NULL;
		Planes[2] = NULL;
		return ERR_INVALID_PARAM;
	}

	Planes[0] = p->Buffer[No] + EDGE + EDGE*p->BufWidth;
	Planes[1] = p->Buffer[No] + p->YToU + (EDGE >> p->UVX2) + (EDGE >> p->UVY2)*(p->BufWidth >> p->UVX2);
	Planes[2] = (uint8_t*)Planes[1] + (p->YToU >> (p->UVX2+p->UVY2));
	return ERR_NONE;
}

static void Unlock(softidct* p,int No)
{
}

static int SetRounding(softidct* p,int Rounding)
{
	p->CopyBlock = p->AllCopyBlock[0][Rounding];
	p->CopyMBlock = p->AllCopyBlock[1][Rounding];
	p->Rounding = Rounding;
	return ERR_NONE;
}

static int SetBufferCount(softidct* p, int n, int Temp)
{
	int i;
	n += Temp;
	if (n>p->MaxCount) return ERR_NOT_SUPPORTED;

	for (i=n;i<p->BufCount;++i)
	{
		Free(p->_Buffer[i]);
		p->_Buffer[i] = NULL;
		p->Buffer[i] = NULL;
	}
	if (p->BufCount > n)
		p->BufCount = n;

	for (i=p->BufCount;i<n;++i)
	{
#ifndef MIPS
		int Align = 32;
		int Offset = 0;
#else
		int Align = 8192;
		int Offset = ((i>>1)+(i&1)*2)*2048;
#endif
		p->_Buffer[i] = (uint8_t*) Alloc(p->BufSize+Align+Offset);
		if (!p->_Buffer[i]) 
		{
			p->MaxCount = p->BufCount;
			break;
		}
		p->Buffer[i] = (uint8_t*)(((int)p->_Buffer[i] + Align-1) & ~(Align-1));
		p->Buffer[i] += Offset;
		p->BufBorder[i] = 0;
		p->BufFrameNo[i] = -1;
		p->BufCount = i+1;
	}

	if (p->ShowNext >= p->BufCount)
		p->ShowNext = -1;
	if (p->ShowCurr >= p->BufCount)
		p->ShowCurr = -1;
	p->LastTemp = Temp && p->BufCount == n;

	if (p->BufCount != n)
		return ERR_OUT_OF_MEMORY;

	return ERR_NONE;
}

static int Init(softidct* p)
{
	int AlignX,AlignY,Mode;

	PlanarYUV(&p->OutputFormat.Pixel,&p->UVX2,&p->UVY2,NULL);

	AlignX = (8 << p->UVX2) - 1;
	AlignY = (8 << p->UVY2) - 1;

	p->BufWidth = ((p->BufferWidth+AlignX)&~AlignX)+2*EDGE;
	p->BufHeight = ((p->BufferHeight+AlignY)&~AlignY)+2*EDGE;
	if (p->OutputFormat.Direction & DIR_SWAPXY)
		SwapInt(&p->BufWidth,&p->BufHeight);

	p->YToU = p->BufHeight * p->BufWidth;
	p->BufSize = p->YToU + 2*(p->YToU >> (p->UVX2+p->UVY2));
	p->BufWidthUV = p->BufWidth >> p->UVX2;

	p->OutputFormat.Pitch = p->BufWidth;

	if (p->OutputFormat.Pixel.Flags & PF_YUV420)
	{
		Mode = 0;
		p->Tab[0] = 2*(8);					//Y[0;0] -> Y[0;1]
		p->Tab[1] = 2*(8*p->BufWidth-8);	//Y[0;1] -> Y[1;0]
		p->Tab[2] = 2*(8);					//Y[1;0] -> Y[1;1]
		p->Tab[4] = 2*(p->YToU >> 2);		//U->V
		p->Tab[5] = 2*(0);	
	}
	else 
	if (p->OutputFormat.Pixel.Flags & PF_YUV422)
	{
		Mode = 1;
		p->Tab[0] = 2*(8);					//Y[0;0] -> Y[0;1]
		p->Tab[2] = 2*(p->YToU >> 1);		//U->V
		p->Tab[3] = 2*(0);	
	}
	else
	if (p->OutputFormat.Pixel.Flags & PF_YUV444)
	{
		Mode = 2;
		p->Tab[0] = 2*(p->YToU);			//Y->U
		p->Tab[1] = 2*(p->YToU);			//U->V
		p->Tab[2] = 2*(0);					
	}
	else
		return ERR_NOT_SUPPORTED;

#ifdef IDCTSWAP
	if (p->OutputFormat.Direction & DIR_SWAPXY)
	{
		p->VMT.Process = p->ProcessSwap[Mode];
		p->VMT.Copy16x16 = p->Copy16x16Swap[Mode];
		p->VMT.Intra8x8 = p->Intra8x8Swap;
		p->VMT.MComp8x8 = (idctmcomp) SoftMComp8x8Swap;
		p->VMT.MComp16x16 = (idctmcomp) SoftMComp16x16Swap;

		if (Mode == 0)
		{
			p->Tab[0] = 2*(8*p->BufWidth);		//Y[0;0] -> Y[1;0]
			p->Tab[1] = 2*(8-8*p->BufWidth);	//Y[1;0] -> Y[0;1]
			p->Tab[2] = 2*(8*p->BufWidth);		//Y[0;1] -> Y[1;1]
		}
	}
	else
#endif
	{
		p->VMT.Process = p->Process[Mode];
		p->VMT.Copy16x16 = p->Copy16x16[Mode];
		p->VMT.Intra8x8 = p->Intra8x8;
		p->VMT.MComp8x8 = (idctmcomp) SoftMComp8x8;
		p->VMT.MComp16x16 = (idctmcomp) SoftMComp16x16;
	}

#ifdef MIPS64
	p->VMT.Inter8x8 = Inter8x8Add;
#endif

	if (p->Output.Node)
	{
		int Result = p->Output.Node->Set(p->Output.Node,p->Output.No | PACKET_FORMAT,&p->OutputFormat,sizeof(video));
		if (Result != ERR_NONE)
			return Result;
	}

	return ERR_NONE;
}

#ifdef IDCTSWAP
static void ChangeSwap(softidct* p)
{
	//DEBUG_MSG(-1,T("IDCTSoft SWAP"));

	if (p->BufCount > 0)
	{
		blitfx FX;
		int No;
		planes TmpPlanes;
		video TmpFormat;
		int Brightness;
		video Format[2];
		planes Planes[2];

		memset(&FX,0,sizeof(FX));
		FX.ScaleX = SCALE_ONE;
		FX.ScaleY = SCALE_ONE;

		TmpFormat = p->OutputFormat;
		TmpFormat.Width = p->BufWidth - 2*EDGE;
		TmpFormat.Height = p->BufHeight - 2*EDGE;

		if (SurfaceAlloc(TmpPlanes,&TmpFormat) == ERR_NONE)
		{
			if (Lock(p,0,Planes[0],&Brightness,&Format[0])==ERR_NONE)
			{
				SurfaceCopy(&Format[0],&TmpFormat,Planes[0],TmpPlanes,&FX);
				Unlock(p,0);
			}

			FX.Direction = DIR_SWAPXY;

			for (No=1;No<p->BufCount;++No)
				if (Lock(p,No,Planes[0],&Brightness,&Format[0])==ERR_NONE)
				{
					SwapInt(&p->BufWidth,&p->BufHeight);
					if (Lock(p,0,Planes[1],&Brightness,&Format[1])==ERR_NONE)
					{
						SurfaceCopy(&Format[0],&Format[1],Planes[0],Planes[1],&FX);
						Unlock(p,0);

						SwapPByte(&p->Buffer[No],&p->Buffer[0]);
						SwapPByte(&p->_Buffer[No],&p->_Buffer[0]);
						p->BufBorder[No] = 0;
					}
					SwapInt(&p->BufWidth,&p->BufHeight);
					Unlock(p,No);
				}

			SwapInt(&p->BufWidth,&p->BufHeight);
			if (Lock(p,0,Planes[0],&Brightness,&Format[0])==ERR_NONE)
			{
				SurfaceCopy(&TmpFormat,&Format[0],TmpPlanes,Planes[0],&FX);
				Unlock(p,0);
				p->BufBorder[0] = 0;
			}
			SwapInt(&p->BufWidth,&p->BufHeight);

			SurfaceFree(TmpPlanes);
		}
	}

	p->OutputFormat.Direction ^= DIR_SWAPXY;
	SwapInt(&p->OutputFormat.Width,&p->OutputFormat.Height);
	Init(p);
}
#endif

static void CheckSwap(softidct* p)
{
#ifdef IDCTSWAP
	if (QueryAdvPlatform(ADVPLATFORM_IDCTSWAP) && !(p->OutputFormat.Pixel.Flags & PF_YUV422))
	{
		if (p->Output.Node)
		{
			video Prefer;
			if (p->Output.Node->Get(p->Output.Node,p->Output.No | PACKET_PREF_FORMAT,&Prefer,sizeof(video))==ERR_NONE)
			{
				if ((p->OutputFormat.Direction ^ Prefer.Direction) & DIR_SWAPXY)
					ChangeSwap(p);
			}
		}
	}
	else
	if (p->OutputFormat.Direction & DIR_SWAPXY)
		ChangeSwap(p);
#endif
}

static int SetFormat(softidct* p, const video* Format )
{
	SetBufferCount(p,0,0);
	memset(&p->OutputFormat,0,sizeof(p->OutputFormat));

	if (Format)
	{
		if (!(Format->Pixel.Flags & (PF_YUV420|PF_YUV422|PF_YUV444)))
			return ERR_NOT_SUPPORTED;

		p->OutputFormat = *Format;
		if (p->OutputFormat.Direction & DIR_SWAPXY)
			SwapInt(&p->OutputFormat.Width,&p->OutputFormat.Height);

		p->OutputFormat.Direction = 0;
		p->OutputFormat.Pixel.Flags |= PF_16ALIGNED | PF_SAFEBORDER;

⌨️ 快捷键说明

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