📄 softidct.cpp
字号:
/*****************************************************************************
*
* 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
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "Rules.h"
#include "Util.h"
#include "SoftIdct.h"
#ifdef ARM
#include "DynamicArmCode.h"
#endif
#define USE_WMMX //use Wireless MMX, if available by platform and is supported by hardware
//----------------------------
#define MV_X(v) ((v<<16)>>17)
#define MV_Y(v) (v>>17)
#define MV_SUB(v) (v&1)+((v>>15)&2)
#define UVX2 1
#define UVY2 1
#define EDGE 32
//----------------------------
void IDCT_Const8x8(int v, byte * Dst,int DstStride, const byte *Src);
//ARM-optimized functions:
#ifndef _ARM
void CopyBlock(const byte * Src, byte * Dst, int SrcPitch, int DstPitch);
void CopyBlockHor(const byte * Src, byte * Dst, int SrcPitch, int DstPitch);
void CopyBlockVer(const byte * Src, byte * Dst, int SrcPitch, int DstPitch);
void CopyBlockHorVer(const byte * Src, byte * Dst, int SrcPitch, int DstPitch);
void CopyBlockHorRound(const byte * Src, byte * Dst, int SrcPitch, int DstPitch);
void CopyBlockVerRound(const byte * Src, byte * Dst, int SrcPitch, int DstPitch);
void CopyBlockHorVerRound(const byte * Src, byte * Dst, int SrcPitch, int DstPitch);
void IDCT_Block4x8(short *Block, byte *Dest, int DestStride, const byte *Src);
void IDCT_Block8x8(short *Block, byte *Dest, int DestStride, const byte *Src);
// AddBlock DstPitch=8
void AddBlock(const byte * Src, byte * Dst, int SrcPitch);
void AddBlockHor(const byte * Src, byte * Dst, int SrcPitch);
void AddBlockVer(const byte * Src, byte * Dst, int SrcPitch);
void AddBlockHorVer(const byte * Src, byte * Dst, int SrcPitch);
// Src must be aligned
void CopyBlock8x8(const byte * Src, byte * Dst, int SrcPitch,int DstPitch);
void CopyBlock16x16(const byte * Src, byte * Dst, int SrcPitch,int DstPitch);
#endif
//----------------------------
void C_softidct::Drop(){
for(int i=0; i<bufer_count; ++i)
buffers[i].frame_index = -1;
last_frame_index = -1;
}
//----------------------------
void C_softidct::IncPtr(bool inc_back, bool inc_forward){
int v = *pass_ptr++;
if(v & 0x80000000){
//transition from Y to UV
current_pitch >>= 1;
v &= 0x7fffffff;
}
curr_block_ptr += v;
if(inc_back)
curr_back_buf_ptr += v;
if(inc_forward)
curr_forward_buf_ptr += v;
}
//----------------------------
bool C_softidct::GetBuffer(const byte *&Y, const byte *&U, const byte *&V) const{
if(rendered_buffer_index < 0)
return false;
Y = buffers[rendered_buffer_index].ptr + EDGE + EDGE*buffer_sx;
U = buffers[rendered_buffer_index].ptr + Y_buffer_size + (EDGE >> UVX2) + (EDGE >> UVY2)*(buffer_sx >> UVX2);
V = U + (Y_buffer_size >> (UVX2+UVY2));
return true;
}
//----------------------------
void C_softidct::Inter8x8(short* Block, int Length){
if(!ptr_forward_buffer){
int MV = *mv_back++;
byte *ptr = curr_back_buf_ptr + MV_X(MV) + current_pitch * MV_Y(MV);
if(Length){
//mcomp and idct (using tmp buffer)
if(ptr >= ptr_backward_buffer && ptr < ptr_b_max)
CopyBlock[MV_SUB(MV)](ptr, temp_buffer_16, current_pitch, 8);
if(Length == 1){
int v = (Block[0]+4) >> 3;
if(v)
IDCT_Const8x8(v, curr_block_ptr, current_pitch, temp_buffer_16);
else
CopyBlock8x8(temp_buffer_16, curr_block_ptr, 8, current_pitch);
}else
if(Length < 15 || (Length<26 && ((dword*)Block)[2]==0 && ((dword*)Block)[6]==0)){
IDCT_Block4x8(Block, curr_block_ptr, current_pitch, temp_buffer_16);
}else{
IDCT_Block8x8(Block, curr_block_ptr, current_pitch, temp_buffer_16);
}
} else {
//only back mcomp
if(ptr >= ptr_backward_buffer && ptr < ptr_b_max)
CopyBlock[MV_SUB(MV)](ptr, curr_block_ptr, current_pitch, current_pitch);
}
IncPtr(true, false);
}else{
if(Length){
//mcomp and idct (using tmp buffer)
if(mv_back){
int MV = *mv_back++;
byte *ptr = curr_back_buf_ptr + MV_X(MV) + current_pitch * MV_Y(MV);
if(ptr >= ptr_backward_buffer && ptr < ptr_b_max)
CopyBlock[MV_SUB(MV)](ptr, temp_buffer_16, current_pitch, 8);
if(mv_forward){
MV = *mv_forward++;
ptr = curr_forward_buf_ptr + MV_X(MV) + current_pitch * MV_Y(MV);
if(ptr >= ptr_forward_buffer && ptr < ptr_f_max)
add_block[MV_SUB(MV)](ptr, temp_buffer_16, current_pitch);
}
}else
if(mv_forward){
int MV = *mv_forward++;
byte *ptr = curr_forward_buf_ptr + MV_X(MV) + current_pitch * MV_Y(MV);
if(ptr >= ptr_forward_buffer && ptr < ptr_f_max)
CopyBlock[MV_SUB(MV)](ptr,temp_buffer_16, current_pitch, 8);
}
if(Length == 1){
int v = (Block[0]+4) >> 3;
if(v)
IDCT_Const8x8(v, curr_block_ptr, current_pitch, temp_buffer_16);
else
CopyBlock8x8(temp_buffer_16, curr_block_ptr, 8, current_pitch);
}else
if(Length < 15){
IDCT_Block4x8(Block, curr_block_ptr, current_pitch, temp_buffer_16);
}else{
IDCT_Block8x8(Block, curr_block_ptr, current_pitch, temp_buffer_16);
}
}else{
//interpolate back and foward (using tmp buffer)
if(mv_back && mv_forward){
int MV = *mv_back++;
byte *ptr = curr_back_buf_ptr + MV_X(MV) + current_pitch * MV_Y(MV);
if(ptr >= ptr_backward_buffer && ptr < ptr_b_max)
CopyBlock[MV_SUB(MV)](ptr, temp_buffer_16, current_pitch, 8);
MV = *mv_forward++;
ptr = curr_forward_buf_ptr + MV_X(MV) + current_pitch * MV_Y(MV);
if(ptr >= ptr_forward_buffer && ptr < ptr_f_max){
add_block[MV_SUB(MV)](ptr, temp_buffer_16, current_pitch);
//copy temp_buffer_16 to Dst
all_copy_block[0][0](temp_buffer_16, curr_block_ptr, 8, current_pitch);
}
}else
if(mv_back){
int MV = *mv_back++;
byte *ptr = curr_back_buf_ptr + MV_X(MV) + current_pitch * MV_Y(MV);
if(ptr >= ptr_backward_buffer && ptr < ptr_b_max)
CopyBlock[MV_SUB(MV)](ptr, curr_block_ptr, current_pitch, current_pitch);
}else
if(mv_forward){
int MV = *mv_forward++;
byte *ptr = curr_forward_buf_ptr + MV_X(MV) + current_pitch * MV_Y(MV);
if(ptr >= ptr_forward_buffer && ptr < ptr_f_max)
CopyBlock[MV_SUB(MV)](ptr, curr_block_ptr, current_pitch, current_pitch);
}
}
IncPtr(true, true);
}
}
//----------------------------
void C_softidct::BeginBlock(int x, int y){
x = x*16 + EDGE;
y = (y*16 + EDGE) * buffer_sx;
current_pitch = buffer_sx;
curr_block_ptr = curr_frame_buffer_ptr + x + y;
curr_back_buf_ptr = ptr_backward_buffer + x + y;
curr_forward_buf_ptr = ptr_forward_buffer + x + y;
pass_ptr = pass_offset;
//Y[1;1] -> U
pass_offset[3] = (-y-x-8*buffer_sx-8 + Y_buffer_size + (x>>1) + (y>>2)) | 0x80000000;
}
//----------------------------
void C_softidct::Copy16x16(int x, int y, int Forward){
BeginBlock(x, y);
byte *&ref_ptr = Forward ? curr_forward_buf_ptr : curr_back_buf_ptr;
CopyBlock16x16(ref_ptr, curr_block_ptr, current_pitch, current_pitch);
{
//like 4x IncPtr
dword v = (pass_offset[0]+pass_offset[1]+pass_offset[2]+pass_offset[3]) & 0x7fffffff;
current_pitch >>= 1;
curr_block_ptr += v;
curr_back_buf_ptr += v;
curr_forward_buf_ptr += v;
pass_ptr = pass_offset+4;
}
//U
CopyBlock8x8(ref_ptr, curr_block_ptr, current_pitch, current_pitch);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -