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

📄 softidct.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
 *
 * 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 543 2006-01-07 22:06:24Z picard $
 *
 * The Core Pocket Media Player
 * Copyright (c) 2004-2005 Gabor Kovacs
 *
 ****************************************************************************/
 
#include "../common.h"
#include "softidct.h"

#ifndef MIPS64
#define MemCpy8 memcpy
#define MemSet8 memset
#else

static void MemCpy8(void* dst,void* src,int len)
{
	__asm(	"addi	$6,$6,-16;"
			"bltz	$6,cpyskip16;"

			"cpyloop16:"
			"ldr	$10,0($5);"
			"addi	$6,$6,-16;"
			"ldr	$11,8($5);"

#ifdef MIPSVR41XX
			".set noreorder;"
			"cache	13,0($4);" //cache without loading
			".set reorder;"
#endif
			"sdr	$10,0($4);"
			"addi	$5,$5,16;"
			"sdr	$11,8($4);"
			"addi	$4,$4,16;"
			"bgez	$6,cpyloop16;"
			"cpyskip16:"

			"andi	$6,$6,8;"
			"beq	$6,$0,cpyskip8;"
			"ldr	$10,0($5);"
			"sdr	$10,0($4);"
			"cpyskip8:");
}

static void MemSet8(void* dst,int v,int len) 
{
	__asm(	"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;"

			"addi	$6,$6,-16;"
			"bltz	$6,setskip16;"

			"setloop16:"

#ifdef MIPSVR41XX
			".set noreorder;"
			"cache	13,0($4);" //cache without loading
			".set reorder;"
#endif
			"sdr	$10,0($4);"
			"addi	$6,$6,-16;"
			"sdr	$10,8($4);"
			"addi	$4,$4,16;"
			"bgez	$6,setloop16;"
			"setskip16:"

			"andi	$6,$6,8;"
			"beq	$6,$0,setskip8;"
			"sdr	$10,0($4);"
			"setskip8:");
}
#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)
	{
		MemSet8(p-EdgeX, p[0], EdgeX);
		MemSet8(p+InnerWidth,p[InnerWidth-1], EdgeX);
		p += Width;
	}

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

	// bottom
	p = Ptr + (Height-EdgeY)*Width;
	for (n=0;n<EdgeY;++n)
	{
		MemCpy8(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->Out.Format.Format.Video;
		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)
{
}

#if defined(CONFIG_IDCT_LOWRES)

static const copyblock AllCopyBlock4x4[2][16] = //[Rounding][x][y]
{
   { CopyBlock4x4_00, CopyBlock4x4_01, CopyBlock4x4_02, CopyBlock4x4_03,
	 CopyBlock4x4_10, CopyBlock4x4_11, CopyBlock4x4_12, CopyBlock4x4_13,
	 CopyBlock4x4_20, CopyBlock4x4_21, CopyBlock4x4_22, CopyBlock4x4_23,
	 CopyBlock4x4_30, CopyBlock4x4_31, CopyBlock4x4_32, CopyBlock4x4_33 },

   { CopyBlock4x4_00, CopyBlock4x4_01R, CopyBlock4x4_02R, CopyBlock4x4_03R,
     CopyBlock4x4_10R, CopyBlock4x4_11R, CopyBlock4x4_12R, CopyBlock4x4_13R,
     CopyBlock4x4_20R, CopyBlock4x4_21R, CopyBlock4x4_22R, CopyBlock4x4_23R,
     CopyBlock4x4_30R, CopyBlock4x4_31R, CopyBlock4x4_32R, CopyBlock4x4_33R },
};

#ifndef MIPS32
const addblock TableAddBlock4x4[16] = 
{
	AddBlock4x4_00,AddBlock4x4_01,AddBlock4x4_02,AddBlock4x4_03,
	AddBlock4x4_10,AddBlock4x4_11,AddBlock4x4_12,AddBlock4x4_13,
	AddBlock4x4_20,AddBlock4x4_21,AddBlock4x4_22,AddBlock4x4_23,
	AddBlock4x4_30,AddBlock4x4_31,AddBlock4x4_32,AddBlock4x4_33,
};
#endif
#endif

static const copyblock AllCopyBlock[2][4] = //[Rounding][x][y]
{
	{ CopyBlock, CopyBlockHor, CopyBlockVer, CopyBlockHorVer },
	{ CopyBlock, CopyBlockHorRound, CopyBlockVerRound, CopyBlockHorVerRound }
};

#ifdef MIPS64
static const copyblock AllCopyBlockM[2][4] = //[Rounding][x][y]
{
	{ CopyMBlock, CopyMBlockHor, CopyMBlockVer, CopyMBlockHorVer },
	{ CopyMBlock, CopyMBlockHorRound, CopyMBlockVerRound, CopyMBlockHorVerRound }
};
#endif

static int UpdateRounding(softidct* p)
{
#if defined(CONFIG_IDCT_LOWRES)
	if (p->Shift)
		p->CopyBlock4x4 = AllCopyBlock4x4[p->Rounding];
	else
#endif
		memcpy(p->CopyBlock,p->AllCopyBlock[p->Rounding],sizeof(copyblock)*4);
#ifdef MIPS64
	p->CopyMBlock = AllCopyBlockM[p->Rounding]; // no shift, instead 16x16
#endif
	return ERR_NONE;
}

static const idctprocess Process[3] =   // pixelformat
{
	(idctprocess)Process420,
	(idctprocess)Process422,
	(idctprocess)Process444,
};

static const idctcopy Copy16x16[3] =  // pixelformat
{
	(idctcopy)Copy420,
	NULL,
	NULL,
};

#ifdef CONFIG_IDCT_SWAP
static const idctprocess ProcessSwap[3] =   // pixelformat
{
	(idctprocess)Process420Swap,
	(idctprocess)Process422Swap,
	(idctprocess)Process444Swap
};

static const idctcopy Copy16x16Swap[3] =  // pixelformat
{
	(idctcopy)Copy420Swap,
	NULL,
	NULL,
};
#endif

#if defined(CONFIG_IDCT_LOWRES)
static const idctprocess ProcessHalf[3] =   // pixelformat
{
	(idctprocess)Process420Half,
	(idctprocess)Process422Half,
	(idctprocess)Process444Half
};

static const idctprocess ProcessQuarter[3] =   // pixelformat
{
	(idctprocess)Process420Quarter,
	(idctprocess)Process422Quarter,
	(idctprocess)Process444Quarter,
};

static const idctcopy Copy16x16Half[3] =  // pixelformat
{
	(idctcopy)Copy420Half,
	NULL,
	NULL,
};
#endif

static bool_t AllocBuffer(softidct* p,int i,block* Block,uint8_t** Ptr)
{
#ifndef MIPS
	int Align = 32;
	int Offset = 0;
#else
	int Align = 8192;
	int Offset = ((i>>1)+(i&1)*2)*2048;
#endif

	if (!AllocBlock(p->BufSize+Align+Offset,Block,0,HEAP_ANYWR))
		return 0;

	if (i>=2 && AvailMemory()<64*1024)
	{
		FreeBlock(Block);
		ShowOutOfMemory();
		return 0;
	}

	*Ptr = (uint8_t*)(((uintptr_t)Block->Ptr + Align-1) & ~(Align-1)) + Offset;
	return 1;
}

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)
	{
		FreeBlock(&p->_Buffer[i]);
		p->Buffer[i] = NULL;
		p->BufAlloc[i] = 0;
	}
	if (p->BufCount > n)
		p->BufCount = n;

	for (i=p->BufCount;i<n;++i)
	{
		if (!p->BufSize)
			p->Buffer[i] = NULL;
		else
		if (!AllocBuffer(p,i,&p->_Buffer[i],&p->Buffer[i]))
		{
			p->MaxCount = p->BufCount;
			break;
		}
		p->BufAlloc[i] = p->BufSize;
		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 UpdateFormat(softidct* p)
{
	if (p->Out.Format.Type == PACKET_VIDEO)
	{
		int AlignX,AlignY,Mode;
		int BlockSize;

		PlanarYUV(&p->Out.Format.Format.Video.Pixel,&p->UVX2,&p->UVY2,NULL);

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

		if (!p->BufferWidth || !p->BufferHeight)
			p->BufWidth = p->BufHeight = 0;
		else
		{
			p->BufWidth = (((p->BufferWidth+AlignX)&~AlignX) >> p->Shift)+2*EDGE;
			p->BufHeight = (((p->BufferHeight+AlignY)&~AlignY) >> p->Shift)+2*EDGE;
		}
		if (p->Out.Format.Format.Video.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->Out.Format.Format.Video.Pitch = p->BufWidth;

		BlockSize = 8 >> p->Shift;
		if (p->Out.Format.Format.Video.Pixel.Flags & PF_YUV420)
		{
			Mode = 0;
			p->Tab[0] = 2*(BlockSize);							//Y[0;0] -> Y[0;1]
			p->Tab[1] = 2*(BlockSize*p->BufWidth-BlockSize);	//Y[0;1] -> Y[1;0]
			p->Tab[2] = 2*(BlockSize);							//Y[1;0] -> Y[1;1]
			p->Tab[4] = 2*(p->YToU >> 2);						//U->V
			p->Tab[5] = 2*(0);	
		}
		else 
		if (p->Out.Format.Format.Video.Pixel.Flags & PF_YUV422)
		{
			Mode = 1;
			p->Tab[0] = 2*(BlockSize);			//Y[0;0] -> Y[0;1]
			p->Tab[2] = 2*(p->YToU >> 1);		//U->V
			p->Tab[3] = 2*(0);	
		}
		else
		if (p->Out.Format.Format.Video.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

⌨️ 快捷键说明

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