📄 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 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 + -