📄 softidct.c
字号:
/*****************************************************************************
*
* 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 + -