📄 intra.c
字号:
/*****************************************************************************
*
* T264 AVC CODEC
*
* Copyright(C) 2004-2005 llcc <lcgate1@yahoo.com.cn>
* 2004-2005 visionany <visionany@yahoo.com.cn>
*
* 2004.11.18 Cloud Wu < sywu@sohu.com> Add 4x4 Intrmode 3 and 7
* 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
*
****************************************************************************/
#include "portab.h"
#include "stdio.h"
#ifndef CHIP_DM642
#include "memory.h"
#endif
#include "T264.h"
#include "intra.h"
#include "utility.h"
#include "cavlc.h"
#include "bitstream.h"
//
// NOTE: (t->flags & (INTRA_16x16 | INTRA_4x4)) != 0
//
uint32_t
T264_mode_decision_intra_y(_RW T264_t* t)
{
uint32_t sad16x16 = -1;
uint32_t sad4x4 = -1;
if (t->flags & USE_INTRA16x16)
sad16x16 = T264_mode_decision_intra_16x16(t);
if (t->flags & USE_INTRA4x4)
sad4x4 = T264_mode_decision_intra_4x4(t);
if (sad16x16 < sad4x4)
{
t->mb.mb_mode = I_16x16;
t->mb.sad = sad16x16;
}
else
{
t->mb.mb_mode = I_4x4;
t->mb.sad = sad4x4;
}
return t->mb.sad;
}
uint32_t
T264_mode_decision_intra_16x16(_RW T264_t* t)
{
DECLARE_ALIGNED_MATRIX(pred16x16, 16, 16, uint8_t, CACHE_SIZE);
DECLARE_ALIGNED_MATRIX(topcache, 1, 16 + CACHE_SIZE, uint8_t, CACHE_SIZE);
DECLARE_ALIGNED_MATRIX(leftcache, 1, 16 + CACHE_SIZE, uint8_t, CACHE_SIZE);
uint32_t sad16x16 = -1;
uint8_t* pred16x16free0 = pred16x16;
uint8_t* pred16x16free1 = t->mb.pred_i16x16;
int32_t modes;
int32_t bestmode;
int32_t preds[9];
int32_t i;
uint8_t* top, *left;
static const uint8_t fixmode[] =
{
Intra_16x16_TOP,
Intra_16x16_LEFT,
Intra_16x16_DC,
Intra_16x16_PLANE,
Intra_16x16_DC,
Intra_16x16_DC,
Intra_16x16_DC
};
top = &topcache[CACHE_SIZE];
left = &leftcache[CACHE_SIZE];
T264_intra_16x16_available(t, preds, &modes, top, left);
for(i = 0 ; i < modes ; i ++)
{
int32_t mode = preds[i];
uint32_t sad;
//
// pred
//
t->pred16x16[mode](
pred16x16free1,
16,
top,
left);
// Now use satd for 16x16 Intra
// Thomascatlee@163.com
sad = t->T264_satd_16x16_u(t->mb.src_y, t->stride, pred16x16free1, 16) +
t->mb.lambda * eg_size_ue(t->bs, fixmode[mode]);
if (sad < sad16x16)
{
SWAP(uint8_t, pred16x16free0, pred16x16free1);
sad16x16 = sad;
bestmode = mode;
}
}
if (pred16x16free0 != t->mb.pred_i16x16)
{
memcpy(t->mb.pred_i16x16, pred16x16free0, sizeof(uint8_t) * 16 * 16);
}
//fixed prediction mode DCLEFT DCTOP DC128 = DC
t->mb.mode_i16x16 = fixmode[bestmode];
return sad16x16;
}
uint32_t
T264_mode_decision_intra_4x4(T264_t* t)
{
DECLARE_ALIGNED_MATRIX(pred4x40, 4, 5, uint8_t, CACHE_SIZE);
DECLARE_ALIGNED_MATRIX(pred4x41, 4, 5, uint8_t, CACHE_SIZE);
DECLARE_ALIGNED_MATRIX(topcache, 8 + CACHE_SIZE, 1, uint8_t, CACHE_SIZE);
DECLARE_ALIGNED_MATRIX(leftcache, 4 + CACHE_SIZE, 1, uint8_t, CACHE_SIZE);
uint32_t sad_all = 0;
uint32_t sad4x4;
int32_t i, j;
uint8_t* src;
uint8_t* dst;
uint8_t* p0, *p1;
uint8_t* left;
uint8_t* top;
int32_t preds[9];
int32_t modes;
int32_t bestmode;
static const uint8_t fixmode[] =
{
Intra_4x4_TOP,
Intra_4x4_LEFT,
Intra_4x4_DC,
Intra_4x4_DIAGONAL_DOWNLEFT,
Intra_4x4_DIAGONAL_DOWNRIGHT,
Intra_4x4_VERTICAL_RIGHT,
Intra_4x4_HORIZONTAL_DOWN,
Intra_4x4_VERTICAL_LEFT,
Intra_4x4_HORIZONTAL_UP,
Intra_4x4_DC,
Intra_4x4_DC,
Intra_4x4_DC
};
p0 = pred4x40;
p1 = pred4x41;
left = &leftcache[CACHE_SIZE];
top = &topcache[CACHE_SIZE];
for(i = 0 ; i < 16 ; i ++)
{
int32_t row = i / 4;
int32_t col = i % 4;
int32_t pred_mode;
src = t->mb.src_y + (row * t->stride << 2) + (col << 2);
dst = t->mb.dst_y + (row * t->edged_stride << 2) + (col << 2);
pred_mode = T264_mb_predict_intra4x4_mode(t, luma_index[i]);
T264_intra_4x4_available(t, i, preds, &modes, dst, left, top);
sad4x4 = -1;
for(j = 0 ; j < modes ; j ++)
{
uint32_t sad;
int32_t mode = preds[j];
t->pred4x4[mode](p1, 4, top, left);
sad = t->cmp[MB_4x4](src, t->stride, p1, 4) +
(pred_mode == fixmode[mode] ? 0 : 4 * t->mb.lambda);
//t->mb.lambda * (pred_mode == fixmode[mode] ? 1 : 4);
if (sad < sad4x4)
{
SWAP(uint8_t, p0, p1);
sad4x4 = sad;
bestmode = mode;
}
}
//fixed prediction mode DCLEFT DCTOP DC128 = DC
t->mb.i4x4_pred_mode_ref[IPM_LUMA + col + row * 8] =
t->mb.mode_i4x4[luma_index[i]] = fixmode[bestmode];
sad_all += sad4x4;
T264_encode_intra_4x4(t, p0, i);
}
sad_all += t->mb.lambda * 24;
return sad_all;
}
void
T264_intra_16x16_available(T264_t* t, int32_t preds[], int32_t* modes, uint8_t* top, uint8_t* left)
{
uint8_t* p;
int32_t i;
if ((t->mb.mb_neighbour & (MB_LEFT | MB_TOP)) == (MB_LEFT | MB_TOP))
{
preds[0] = Intra_16x16_TOP;
preds[1] = Intra_16x16_LEFT;
preds[2] = Intra_16x16_DC;
preds[3] = Intra_16x16_PLANE;
*modes = 4;
p = t->mb.dst_y - t->edged_stride;
for(i = -1 ; i < 16 ; i ++)
{
top[i] = p[i];
}
p --;
for(i = -1 ; i < 16 ; i ++)
{
left[i] = p[0];
p += t->edged_stride;
}
}
else if(t->mb.mb_neighbour & MB_LEFT)
{
preds[0] = Intra_16x16_LEFT;
preds[1] = Intra_16x16_DCLEFT;
*modes = 2;
p = t->mb.dst_y - 1;
for(i = 0 ; i < 16 ; i ++)
{
left[i] = p[0];
p += t->edged_stride;
}
}
else if(t->mb.mb_neighbour & MB_TOP)
{
preds[0] = Intra_16x16_TOP;
preds[1] = Intra_16x16_DCTOP;
*modes = 2;
p = t->mb.dst_y - t->edged_stride;
for(i = 0 ; i < 16 ; i ++)
{
top[i] = p[i];
}
}
else
{
preds[0] = Intra_16x16_DC128;
*modes = 1;
}
}
void
T264_intra_4x4_available(T264_t* t, int32_t idx, int32_t preds[], int32_t* modes, uint8_t* dst, uint8_t* left, uint8_t* top)
{
static const int32_t neighbour[] =
{
0, MB_LEFT, MB_LEFT, MB_LEFT,
MB_TOP| MB_TOPRIGHT, MB_LEFT| MB_TOP, MB_LEFT |MB_TOP| MB_TOPRIGHT, MB_LEFT| MB_TOP,
MB_TOP| MB_TOPRIGHT, MB_LEFT| MB_TOP| MB_TOPRIGHT, MB_LEFT |MB_TOP| MB_TOPRIGHT, MB_LEFT| MB_TOP,
MB_TOP| MB_TOPRIGHT, MB_LEFT| MB_TOP, MB_LEFT |MB_TOP| MB_TOPRIGHT, MB_LEFT| MB_TOP
};
static const int32_t fix[] =
{
~0, ~0, ~0, ~0,
~0, ~MB_TOPRIGHT, ~0, ~MB_TOPRIGHT,
~0, ~0, ~0, ~MB_TOPRIGHT,
~0, ~MB_TOPRIGHT, ~0, ~MB_TOPRIGHT
};
uint8_t* p;
int32_t i;
int32_t mb_neighbour = (t->mb.mb_neighbour| neighbour[idx]) & fix[idx];
if((idx & 3) == 3) //if is the right-most sub-block
if(t->mb.mb_x == t->mb_width - 1) //if is th last MB in horizontal
mb_neighbour &= ~MB_TOPRIGHT; //no top-right exist
if ((mb_neighbour & (MB_LEFT | MB_TOP)) == (MB_LEFT | MB_TOP))
{
preds[0] = Intra_4x4_TOP;
preds[1] = Intra_4x4_LEFT;
preds[2] = Intra_4x4_DC;
preds[3] = Intra_4x4_DIAGONAL_DOWNLEFT;
preds[4] = Intra_4x4_DIAGONAL_DOWNRIGHT;
preds[5] = Intra_4x4_VERTICAL_RIGHT;
preds[6] = Intra_4x4_HORIZONTAL_DOWN;
preds[7] = Intra_4x4_VERTICAL_LEFT;
preds[8] = Intra_4x4_HORIZONTAL_UP;
*modes = 9;
p = dst - t->edged_stride;
if (mb_neighbour & MB_TOPRIGHT)
{
for(i = -1 ; i < 8 ; i ++)
{
top[i] = p[i];
}
}
else
{
for(i = -1 ; i < 4 ; i ++)
{
top[i] = p[i];
}
//to fill padded 4 positions
for( ; i < 8 ; ++ i)
top[i] = p[3];
}
p --;
for(i = -1 ; i < 4 ; i ++)
{
left[i] = p[0];
p += t->edged_stride;
}
}
else if(mb_neighbour & MB_LEFT)
{
preds[0] = Intra_4x4_LEFT;
preds[1] = Intra_4x4_DCLEFT;
preds[2] = Intra_4x4_HORIZONTAL_UP;
*modes = 3;
p = dst - 1;
for(i = 0 ; i < 4 ; i ++)
{
left[i] = p[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -