📄 inter.c
字号:
/*****************************************************************************
*
* T264 AVC CODEC
*
* Copyright(C) 2004-2005 llcc <lcgate1@yahoo.com.cn>
* 2004-2005 visionany <visionany@yahoo.com.cn>
*
* 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 "inter.h"
#include "intra.h"
#include "estimation.h"
#include "utility.h"
#include "interpolate.h"
#include "bitstream.h"
//#define USE_PREV_DETECT
uint32_t
T264_predict_sad(T264_t* t, int32_t list)
{
return T264_median(t->mb.sad_ref[0], t->mb.sad_ref[1], t->mb.sad_ref[2]);
}
void
T264_predict_mv(T264_t* t, int32_t list, int32_t i, int32_t width, T264_vector_t* vec)
{
int32_t n;
int32_t count = 0;
int32_t idx;
int32_t row;
int32_t col;
int32_t org;
T264_vector_t vec_n[3];
n = vec->refno;
org = i;
i = luma_index[i];
col = org % 4;
row = org / 4;
vec_n[0] = t->mb.vec_ref[VEC_LUMA - 1 + row * 8 + col].vec[list];
vec_n[1] = t->mb.vec_ref[VEC_LUMA - 8 + row * 8 + col].vec[list];
vec_n[2] = t->mb.vec_ref[VEC_LUMA - 8 + row * 8 + col + width].vec[list];
if (vec_n[2].refno == -2)
{
vec_n[2] = t->mb.vec_ref[VEC_LUMA - 8 + row * 8 + col - 1].vec[list];
}
if (((i & 3) == 3) || ((i & 3) == 2 && width == 2))
{
vec_n[2] = t->mb.vec_ref[VEC_LUMA - 8 + row * 8 + col - 1].vec[list];
}
if (t->mb.mb_part == MB_16x8)
{
if (i == 0 && n == vec_n[1].refno)
{
vec[0].x = vec_n[1].x;
vec[0].y = vec_n[1].y;
return;
}
else if (i != 0 && n == vec_n[0].refno)
{
vec[0].x = vec_n[0].x;
vec[0].y = vec_n[0].y;
return;
}
}
else if (t->mb.mb_part == MB_8x16)
{
if (i == 0 && n == vec_n[0].refno)
{
vec[0].x = vec_n[0].x;
vec[0].y = vec_n[0].y;
return;
}
else if (i != 0 && n == vec_n[2].refno)
{
vec[0].x = vec_n[2].x;
vec[0].y = vec_n[2].y;
return;
}
}
if (vec_n[0].refno == n)
{
count ++;
idx = 0;
}
if (vec_n[1].refno == n)
{
count ++;
idx = 1;
}
if (vec_n[2].refno == n)
{
count ++;
idx = 2;
}
if (count > 1)
{
vec[0].x = T264_median(vec_n[0].x, vec_n[1].x, vec_n[2].x);
vec[0].y = T264_median(vec_n[0].y, vec_n[1].y, vec_n[2].y);
return;
}
else if (count == 1)
{
vec[0].x = vec_n[idx].x;
vec[0].y = vec_n[idx].y;
return;
}
else if (vec_n[1].refno == -2 && vec_n[2].refno == -2 && vec_n[0].refno != -2)
{
vec[0].x = vec_n[0].x;
vec[0].y = vec_n[0].y;
}
else
{
vec[0].x = T264_median(vec_n[0].x, vec_n[1].x, vec_n[2].x);
vec[0].y = T264_median(vec_n[0].y, vec_n[1].y, vec_n[2].y);
return;
}
}
void
T264_predict_mv_skip(T264_t* t, int32_t list, T264_vector_t* vec)
{
T264_vector_t vec_n[2];
int32_t zero_left, zero_top;
vec_n[0] = t->mb.vec_ref[VEC_LUMA - 1].vec[0];
vec_n[1] = t->mb.vec_ref[VEC_LUMA - 8].vec[0];
vec[0].refno = 0;
zero_left = vec_n[0].refno == -2 ? 1 : vec_n[0].refno == 0 && vec_n[0].x == 0 && vec_n[0].y == 0 ? 1 : 0;
zero_top = vec_n[1].refno == -2 ? 1 : vec_n[1].refno == 0 && vec_n[1].x == 0 && vec_n[1].y == 0 ? 1 : 0;
if (zero_left || zero_top)
{
vec[0].x = vec[0].y = 0;
}
else
{
T264_predict_mv(t, 0, 0, 4, vec);
}
}
int32_t
T264_median(int32_t x, int32_t y, int32_t z)
{
int32_t min, max;
if (x < y)
{
min = x;
max = y;
}
else
{
min = y;
max = x;
}
if (z < min)
{
min = z;
}
else if (z > max)
{
max = z;
}
return x + y + z - min - max;
}
void
copy_nvec(T264_vector_t* src, T264_vector_t* dst, int32_t width, int32_t height, int32_t stride)
{
int32_t i, j;
for(i = 0 ; i < height ; i ++)
{
for(j = 0 ; j < width ; j ++)
{
dst[j] = src[0];
}
dst += stride;
}
}
void
T264_inter_p16x16_mode_available(T264_t* t, int32_t preds[], int32_t* modes)
{
if (t->flags & USE_FORCEBLOCKSIZE)
{
*modes = 0;
preds[(*modes) ++] = MB_16x16;
if (t->param.block_size & SEARCH_16x8P)
preds[(*modes) ++] = MB_16x8;
if (t->param.block_size & SEARCH_8x16P)
preds[(*modes) ++] = MB_8x16;
return ;
}
if ((t->mb.mb_neighbour & (MB_LEFT | MB_TOP)) == (MB_LEFT | MB_TOP))
{
*modes = 0;
preds[(*modes) ++] = MB_16x16;
if (t->mb.vec_ref[VEC_LUMA - 1].part == MB_16x8)
{
preds[(*modes) ++] = MB_16x8;
}
if (t->mb.vec_ref[VEC_LUMA - 8].part == MB_8x16)
{
preds[(*modes) ++] = MB_8x16;
}
}
else
{
// try all
preds[0] = MB_16x16;
preds[1] = MB_16x8;
preds[2] = MB_8x16;
*modes = 3;
}
}
void
T264_inter_p8x8_mode_available(T264_t* t, int32_t preds[], int32_t* modes, int32_t sub_no)
{
static const int32_t neighbour[] =
{
0, MB_LEFT, MB_TOP, MB_LEFT| MB_TOP
};
int32_t mb_neighbour = t->mb.mb_neighbour| neighbour[sub_no];
if (t->flags & USE_FORCEBLOCKSIZE)
{
*modes = 0;
if (t->param.block_size & SEARCH_8x8P)
preds[(*modes) ++] = MB_8x8;
if (t->param.block_size & SEARCH_8x4P)
preds[(*modes) ++] = MB_8x4;
if (t->param.block_size & SEARCH_4x8P)
preds[(*modes) ++] = MB_4x8;
if (t->param.block_size & SEARCH_4x4P)
preds[(*modes) ++] = MB_4x4;
return ;
}
if ((mb_neighbour & (MB_LEFT | MB_TOP)) == (MB_LEFT | MB_TOP))
{
*modes = 0;
preds[*modes ++] = MB_8x8;
if (t->mb.vec_ref[VEC_LUMA - 8 + sub_no / 2 * 16 + sub_no % 2 * 4].part == MB_8x4)
{
preds[*modes ++] = MB_8x4;
}
if (t->mb.vec_ref[VEC_LUMA - 1 + sub_no / 2 * 16 + sub_no % 2 * 4].part == MB_4x8)
{
preds[*modes ++] = MB_4x8;
}
if (t->mb.vec_ref[VEC_LUMA - 8 + sub_no / 2 * 16 + sub_no % 2 * 4].part == MB_4x4 ||
t->mb.vec_ref[VEC_LUMA - 1 + sub_no / 2 * 16 + sub_no % 2 * 4].part == MB_4x4)
{
preds[*modes ++] = MB_4x4;
}
}
else
{
// try all
preds[0] = MB_8x8;
preds[1] = MB_8x4;
preds[2] = MB_4x8;
preds[3] = MB_4x4;
*modes = 4;
}
}
int32_t
T264_get_pos_sad(T264_t* t, uint8_t* ref, T264_vector_t* vec)
{
uint8_t* tmp;
int32_t x, y;
int32_t list_index = 0;
uint32_t sad;
static const int8_t index[4][4][6] =
{
{{0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 0, 0}, {1, 0, 0, 0, 1, 0}},
{{0, 2, 0, 0, 0, 0}, {1, 2, 0, 0, 0, 0}, {1, 3, 0, 0, 0, 0}, {1, 2, 0, 0, 1, 0}},
{{2, 2, 0, 0, 0, 0}, {2, 3, 0, 0, 0, 0}, {3, 3, 0, 0, 0, 0}, {3, 2, 0, 0, 1, 0}},
{{2, 0, 0, 0, 0, 1}, {2, 1, 0, 0, 0, 1}, {3, 1, 0, 0, 0, 1}, {1, 2, 0, 1, 1, 0}}
};
// need subpel
if ((t->flags & (USE_QUARTPEL)) == (USE_QUARTPEL))
{
x = (vec->x & 3);
y = (vec->y & 3);
if (index[y][x][0] == index[y][x][1])
{
tmp = t->ref[list_index][vec->refno]->Y[index[y][x][0]] + ((t->mb.mb_y << 4) + (vec->y >> 2)) * t->edged_stride +
((t->mb.mb_x << 4) + (vec->x >> 2));
t->memcpy_stride_u(tmp, 16, 16, t->edged_stride, ref, 16);
}
else
{
t->pia[MB_16x16](t->ref[list_index][vec->refno]->Y[index[y][x][0]] + ((t->mb.mb_y << 4) + (vec->y >> 2) + index[y][x][3]) * t->edged_stride + (t->mb.mb_x << 4) + (vec->x >> 2) + index[y][x][2],
t->ref[list_index][vec->refno]->Y[index[y][x][1]] + ((t->mb.mb_y << 4) + (vec->y >> 2) + index[y][x][5]) * t->edged_stride + (t->mb.mb_x << 4) + (vec->x >> 2) + index[y][x][4],
t->edged_stride, t->edged_stride, ref, 16);
}
// rc will use sad value
sad = t->cmp[MB_16x16](t->mb.src_y, t->stride, ref, 16);
return sad;
}
return -1;
}
int32_t
T264_detect_pskip(T264_t* t, uint32_t sad_t)
{
// detect p skip has a two-step process. here try to find suitable skip mv
// and encode post will decide if use skip mode or not
DECLARE_ALIGNED_MATRIX(ref, 16, 16, uint8_t, CACHE_SIZE);
T264_vector_t vec;
uint8_t* tmp;
int32_t x, y;
int32_t i, j;
int32_t list_index = 0;
static const int8_t index[4][4][6] =
{
{{0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0}, {1, 1, 0, 0, 0, 0}, {1, 0, 0, 0, 1, 0}},
{{0, 2, 0, 0, 0, 0}, {1, 2, 0, 0, 0, 0}, {1, 3, 0, 0, 0, 0}, {1, 2, 0, 0, 1, 0}},
{{2, 2, 0, 0, 0, 0}, {2, 3, 0, 0, 0, 0}, {3, 3, 0, 0, 0, 0}, {3, 2, 0, 0, 1, 0}},
{{2, 0, 0, 0, 0, 1}, {2, 1, 0, 0, 0, 1}, {3, 1, 0, 0, 0, 1}, {1, 2, 0, 1, 1, 0}}
};
T264_predict_mv_skip(t, 0, &vec);
// need subpel
if ((t->flags & (USE_QUARTPEL)) == (USE_QUARTPEL))
{
x = (vec.x & 3);
y = (vec.y & 3);
if (index[y][x][0] == index[y][x][1])
{
tmp = t->ref[list_index][vec.refno]->Y[index[y][x][0]] + ((t->mb.mb_y << 4) + (vec.y >> 2)) * t->edged_stride +
((t->mb.mb_x << 4) + (vec.x >> 2));
t->memcpy_stride_u(tmp, 16, 16, t->edged_stride, ref, 16);
}
else
{
t->pia[MB_16x16](t->ref[list_index][vec.refno]->Y[index[y][x][0]] + ((t->mb.mb_y << 4) + (vec.y >> 2) + index[y][x][3]) * t->edged_stride + (t->mb.mb_x << 4) + (vec.x >> 2) + index[y][x][2],
t->ref[list_index][vec.refno]->Y[index[y][x][1]] + ((t->mb.mb_y << 4) + (vec.y >> 2) + index[y][x][5]) * t->edged_stride + (t->mb.mb_x << 4) + (vec.x >> 2) + index[y][x][4],
t->edged_stride, t->edged_stride, ref, 16);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -