Source code
Revision control
Copy as Markdown
Other Tools
/*
* H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder
* Copyright (c) 2003-2011 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* H.264 / AVC / MPEG-4 part10 prediction functions.
* @author Michael Niedermayer <michaelni@gmx.at>
*/
#include "libavutil/intreadwrite.h"
#include "mathops.h"
#include "bit_depth_template.c"
static void FUNCC(pred4x4_vertical)(uint8_t *_src, const uint8_t *topright,
ptrdiff_t _stride)
{
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const pixel4 a= AV_RN4PA(src-stride);
AV_WN4PA(src+0*stride, a);
AV_WN4PA(src+1*stride, a);
AV_WN4PA(src+2*stride, a);
AV_WN4PA(src+3*stride, a);
}
static void FUNCC(pred4x4_horizontal)(uint8_t *_src, const uint8_t *topright,
ptrdiff_t _stride)
{
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
AV_WN4PA(src+0*stride, PIXEL_SPLAT_X4(src[-1+0*stride]));
AV_WN4PA(src+1*stride, PIXEL_SPLAT_X4(src[-1+1*stride]));
AV_WN4PA(src+2*stride, PIXEL_SPLAT_X4(src[-1+2*stride]));
AV_WN4PA(src+3*stride, PIXEL_SPLAT_X4(src[-1+3*stride]));
}
static void FUNCC(pred4x4_dc)(uint8_t *_src, const uint8_t *topright,
ptrdiff_t _stride)
{
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const int dc= ( src[-stride] + src[1-stride] + src[2-stride] + src[3-stride]
+ src[-1+0*stride] + src[-1+1*stride] + src[-1+2*stride] + src[-1+3*stride] + 4) >>3;
const pixel4 a = PIXEL_SPLAT_X4(dc);
AV_WN4PA(src+0*stride, a);
AV_WN4PA(src+1*stride, a);
AV_WN4PA(src+2*stride, a);
AV_WN4PA(src+3*stride, a);
}
static void FUNCC(pred4x4_left_dc)(uint8_t *_src, const uint8_t *topright,
ptrdiff_t _stride)
{
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const int dc= ( src[-1+0*stride] + src[-1+1*stride] + src[-1+2*stride] + src[-1+3*stride] + 2) >>2;
const pixel4 a = PIXEL_SPLAT_X4(dc);
AV_WN4PA(src+0*stride, a);
AV_WN4PA(src+1*stride, a);
AV_WN4PA(src+2*stride, a);
AV_WN4PA(src+3*stride, a);
}
static void FUNCC(pred4x4_top_dc)(uint8_t *_src, const uint8_t *topright,
ptrdiff_t _stride)
{
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const int dc= ( src[-stride] + src[1-stride] + src[2-stride] + src[3-stride] + 2) >>2;
const pixel4 a = PIXEL_SPLAT_X4(dc);
AV_WN4PA(src+0*stride, a);
AV_WN4PA(src+1*stride, a);
AV_WN4PA(src+2*stride, a);
AV_WN4PA(src+3*stride, a);
}
static void FUNCC(pred4x4_128_dc)(uint8_t *_src, const uint8_t *topright,
ptrdiff_t _stride)
{
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const pixel4 a = PIXEL_SPLAT_X4(1<<(BIT_DEPTH-1));
AV_WN4PA(src+0*stride, a);
AV_WN4PA(src+1*stride, a);
AV_WN4PA(src+2*stride, a);
AV_WN4PA(src+3*stride, a);
}
#define LOAD_TOP_RIGHT_EDGE\
const unsigned av_unused t4 = topright[0];\
const unsigned av_unused t5 = topright[1];\
const unsigned av_unused t6 = topright[2];\
const unsigned av_unused t7 = topright[3];\
#define LOAD_DOWN_LEFT_EDGE\
const unsigned av_unused l4 = src[-1+4*stride];\
const unsigned av_unused l5 = src[-1+5*stride];\
const unsigned av_unused l6 = src[-1+6*stride];\
const unsigned av_unused l7 = src[-1+7*stride];\
#define LOAD_LEFT_EDGE\
const unsigned av_unused l0 = src[-1+0*stride];\
const unsigned av_unused l1 = src[-1+1*stride];\
const unsigned av_unused l2 = src[-1+2*stride];\
const unsigned av_unused l3 = src[-1+3*stride];\
#define LOAD_TOP_EDGE\
const unsigned av_unused t0 = src[ 0-1*stride];\
const unsigned av_unused t1 = src[ 1-1*stride];\
const unsigned av_unused t2 = src[ 2-1*stride];\
const unsigned av_unused t3 = src[ 3-1*stride];\
static void FUNCC(pred4x4_down_right)(uint8_t *_src, const uint8_t *topright,
ptrdiff_t _stride)
{
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const int lt= src[-1-1*stride];
LOAD_TOP_EDGE
LOAD_LEFT_EDGE
src[0+3*stride]=(l3 + 2*l2 + l1 + 2)>>2;
src[0+2*stride]=
src[1+3*stride]=(l2 + 2*l1 + l0 + 2)>>2;
src[0+1*stride]=
src[1+2*stride]=
src[2+3*stride]=(l1 + 2*l0 + lt + 2)>>2;
src[0+0*stride]=
src[1+1*stride]=
src[2+2*stride]=
src[3+3*stride]=(l0 + 2*lt + t0 + 2)>>2;
src[1+0*stride]=
src[2+1*stride]=
src[3+2*stride]=(lt + 2*t0 + t1 + 2)>>2;
src[2+0*stride]=
src[3+1*stride]=(t0 + 2*t1 + t2 + 2)>>2;
src[3+0*stride]=(t1 + 2*t2 + t3 + 2)>>2;
}
static void FUNCC(pred4x4_down_left)(uint8_t *_src, const uint8_t *_topright,
ptrdiff_t _stride)
{
pixel *src = (pixel*)_src;
const pixel *topright = (const pixel*)_topright;
int stride = _stride>>(sizeof(pixel)-1);
LOAD_TOP_EDGE
LOAD_TOP_RIGHT_EDGE
// LOAD_LEFT_EDGE
src[0+0*stride]=(t0 + t2 + 2*t1 + 2)>>2;
src[1+0*stride]=
src[0+1*stride]=(t1 + t3 + 2*t2 + 2)>>2;
src[2+0*stride]=
src[1+1*stride]=
src[0+2*stride]=(t2 + t4 + 2*t3 + 2)>>2;
src[3+0*stride]=
src[2+1*stride]=
src[1+2*stride]=
src[0+3*stride]=(t3 + t5 + 2*t4 + 2)>>2;
src[3+1*stride]=
src[2+2*stride]=
src[1+3*stride]=(t4 + t6 + 2*t5 + 2)>>2;
src[3+2*stride]=
src[2+3*stride]=(t5 + t7 + 2*t6 + 2)>>2;
src[3+3*stride]=(t6 + 3*t7 + 2)>>2;
}
static void FUNCC(pred4x4_vertical_right)(uint8_t *_src,
const uint8_t *topright,
ptrdiff_t _stride)
{
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const int lt= src[-1-1*stride];
LOAD_TOP_EDGE
LOAD_LEFT_EDGE
src[0+0*stride]=
src[1+2*stride]=(lt + t0 + 1)>>1;
src[1+0*stride]=
src[2+2*stride]=(t0 + t1 + 1)>>1;
src[2+0*stride]=
src[3+2*stride]=(t1 + t2 + 1)>>1;
src[3+0*stride]=(t2 + t3 + 1)>>1;
src[0+1*stride]=
src[1+3*stride]=(l0 + 2*lt + t0 + 2)>>2;
src[1+1*stride]=
src[2+3*stride]=(lt + 2*t0 + t1 + 2)>>2;
src[2+1*stride]=
src[3+3*stride]=(t0 + 2*t1 + t2 + 2)>>2;
src[3+1*stride]=(t1 + 2*t2 + t3 + 2)>>2;
src[0+2*stride]=(lt + 2*l0 + l1 + 2)>>2;
src[0+3*stride]=(l0 + 2*l1 + l2 + 2)>>2;
}
static void FUNCC(pred4x4_vertical_left)(uint8_t *_src,
const uint8_t *_topright,
ptrdiff_t _stride)
{
pixel *src = (pixel*)_src;
const pixel *topright = (const pixel*)_topright;
int stride = _stride>>(sizeof(pixel)-1);
LOAD_TOP_EDGE
LOAD_TOP_RIGHT_EDGE
src[0+0*stride]=(t0 + t1 + 1)>>1;
src[1+0*stride]=
src[0+2*stride]=(t1 + t2 + 1)>>1;
src[2+0*stride]=
src[1+2*stride]=(t2 + t3 + 1)>>1;
src[3+0*stride]=
src[2+2*stride]=(t3 + t4+ 1)>>1;
src[3+2*stride]=(t4 + t5+ 1)>>1;
src[0+1*stride]=(t0 + 2*t1 + t2 + 2)>>2;
src[1+1*stride]=
src[0+3*stride]=(t1 + 2*t2 + t3 + 2)>>2;
src[2+1*stride]=
src[1+3*stride]=(t2 + 2*t3 + t4 + 2)>>2;
src[3+1*stride]=
src[2+3*stride]=(t3 + 2*t4 + t5 + 2)>>2;
src[3+3*stride]=(t4 + 2*t5 + t6 + 2)>>2;
}
static void FUNCC(pred4x4_horizontal_up)(uint8_t *_src, const uint8_t *topright,
ptrdiff_t _stride)
{
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
LOAD_LEFT_EDGE
src[0+0*stride]=(l0 + l1 + 1)>>1;
src[1+0*stride]=(l0 + 2*l1 + l2 + 2)>>2;
src[2+0*stride]=
src[0+1*stride]=(l1 + l2 + 1)>>1;
src[3+0*stride]=
src[1+1*stride]=(l1 + 2*l2 + l3 + 2)>>2;
src[2+1*stride]=
src[0+2*stride]=(l2 + l3 + 1)>>1;
src[3+1*stride]=
src[1+2*stride]=(l2 + 2*l3 + l3 + 2)>>2;
src[3+2*stride]=
src[1+3*stride]=
src[0+3*stride]=
src[2+2*stride]=
src[2+3*stride]=
src[3+3*stride]=l3;
}
static void FUNCC(pred4x4_horizontal_down)(uint8_t *_src,
const uint8_t *topright,
ptrdiff_t _stride)
{
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const int lt= src[-1-1*stride];
LOAD_TOP_EDGE
LOAD_LEFT_EDGE
src[0+0*stride]=
src[2+1*stride]=(lt + l0 + 1)>>1;
src[1+0*stride]=
src[3+1*stride]=(l0 + 2*lt + t0 + 2)>>2;
src[2+0*stride]=(lt + 2*t0 + t1 + 2)>>2;
src[3+0*stride]=(t0 + 2*t1 + t2 + 2)>>2;
src[0+1*stride]=
src[2+2*stride]=(l0 + l1 + 1)>>1;
src[1+1*stride]=
src[3+2*stride]=(lt + 2*l0 + l1 + 2)>>2;
src[0+2*stride]=
src[2+3*stride]=(l1 + l2+ 1)>>1;
src[1+2*stride]=
src[3+3*stride]=(l0 + 2*l1 + l2 + 2)>>2;
src[0+3*stride]=(l2 + l3 + 1)>>1;
src[1+3*stride]=(l1 + 2*l2 + l3 + 2)>>2;
}
static void FUNCC(pred16x16_vertical)(uint8_t *_src, ptrdiff_t _stride)
{
int i;
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const pixel4 a = AV_RN4PA(((pixel4*)(src-stride))+0);
const pixel4 b = AV_RN4PA(((pixel4*)(src-stride))+1);
const pixel4 c = AV_RN4PA(((pixel4*)(src-stride))+2);
const pixel4 d = AV_RN4PA(((pixel4*)(src-stride))+3);
for(i=0; i<16; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, a);
AV_WN4PA(((pixel4*)(src+i*stride))+1, b);
AV_WN4PA(((pixel4*)(src+i*stride))+2, c);
AV_WN4PA(((pixel4*)(src+i*stride))+3, d);
}
}
static void FUNCC(pred16x16_horizontal)(uint8_t *_src, ptrdiff_t stride)
{
int i;
pixel *src = (pixel*)_src;
stride >>= sizeof(pixel)-1;
for(i=0; i<16; i++){
const pixel4 a = PIXEL_SPLAT_X4(src[-1+i*stride]);
AV_WN4PA(((pixel4*)(src+i*stride))+0, a);
AV_WN4PA(((pixel4*)(src+i*stride))+1, a);
AV_WN4PA(((pixel4*)(src+i*stride))+2, a);
AV_WN4PA(((pixel4*)(src+i*stride))+3, a);
}
}
#define PREDICT_16x16_DC(v)\
for(i=0; i<16; i++){\
AV_WN4PA(src+ 0, v);\
AV_WN4PA(src+ 4, v);\
AV_WN4PA(src+ 8, v);\
AV_WN4PA(src+12, v);\
src += stride;\
}
static void FUNCC(pred16x16_dc)(uint8_t *_src, ptrdiff_t stride)
{
int i, dc=0;
pixel *src = (pixel*)_src;
pixel4 dcsplat;
stride >>= sizeof(pixel)-1;
for(i=0;i<16; i++){
dc+= src[-1+i*stride];
}
for(i=0;i<16; i++){
dc+= src[i-stride];
}
dcsplat = PIXEL_SPLAT_X4((dc+16)>>5);
PREDICT_16x16_DC(dcsplat);
}
static void FUNCC(pred16x16_left_dc)(uint8_t *_src, ptrdiff_t stride)
{
int i, dc=0;
pixel *src = (pixel*)_src;
pixel4 dcsplat;
stride >>= sizeof(pixel)-1;
for(i=0;i<16; i++){
dc+= src[-1+i*stride];
}
dcsplat = PIXEL_SPLAT_X4((dc+8)>>4);
PREDICT_16x16_DC(dcsplat);
}
static void FUNCC(pred16x16_top_dc)(uint8_t *_src, ptrdiff_t stride)
{
int i, dc=0;
pixel *src = (pixel*)_src;
pixel4 dcsplat;
stride >>= sizeof(pixel)-1;
for(i=0;i<16; i++){
dc+= src[i-stride];
}
dcsplat = PIXEL_SPLAT_X4((dc+8)>>4);
PREDICT_16x16_DC(dcsplat);
}
#define PRED16x16_X(n, v) \
static void FUNCC(pred16x16_##n##_dc)(uint8_t *_src, ptrdiff_t stride)\
{\
int i;\
pixel *src = (pixel*)_src;\
stride >>= sizeof(pixel)-1;\
PREDICT_16x16_DC(PIXEL_SPLAT_X4(v));\
}
PRED16x16_X(128, (1<<(BIT_DEPTH-1))+0)
#if BIT_DEPTH == 8
PRED16x16_X(127, (1<<(BIT_DEPTH-1))-1)
PRED16x16_X(129, (1<<(BIT_DEPTH-1))+1)
#endif
static inline void FUNCC(pred16x16_plane_compat)(uint8_t *_src,
ptrdiff_t _stride,
const int svq3,
const int rv40)
{
int i, j, k;
int a;
INIT_CLIP
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const pixel * const src0 = src +7-stride;
const pixel * src1 = src +8*stride-1;
const pixel * src2 = src1-2*stride; // == src+6*stride-1;
int H = src0[1] - src0[-1];
int V = src1[0] - src2[ 0];
for(k=2; k<=8; ++k) {
src1 += stride; src2 -= stride;
H += k*(src0[k] - src0[-k]);
V += k*(src1[0] - src2[ 0]);
}
if(svq3){
H = ( 5*(H/4) ) / 16;
V = ( 5*(V/4) ) / 16;
/* required for 100% accuracy */
i = H; H = V; V = i;
}else if(rv40){
H = ( H + (H>>2) ) >> 4;
V = ( V + (V>>2) ) >> 4;
}else{
H = ( 5*H+32 ) >> 6;
V = ( 5*V+32 ) >> 6;
}
a = 16*(src1[0] + src2[16] + 1) - 7*(V+H);
for(j=16; j>0; --j) {
int b = a;
a += V;
for(i=-16; i<0; i+=4) {
src[16+i] = CLIP((b ) >> 5);
src[17+i] = CLIP((b+ H) >> 5);
src[18+i] = CLIP((b+2*H) >> 5);
src[19+i] = CLIP((b+3*H) >> 5);
b += 4*H;
}
src += stride;
}
}
static void FUNCC(pred16x16_plane)(uint8_t *src, ptrdiff_t stride)
{
FUNCC(pred16x16_plane_compat)(src, stride, 0, 0);
}
static void FUNCC(pred8x8_vertical)(uint8_t *_src, ptrdiff_t _stride)
{
int i;
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const pixel4 a= AV_RN4PA(((pixel4*)(src-stride))+0);
const pixel4 b= AV_RN4PA(((pixel4*)(src-stride))+1);
for(i=0; i<8; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, a);
AV_WN4PA(((pixel4*)(src+i*stride))+1, b);
}
}
static void FUNCC(pred8x16_vertical)(uint8_t *_src, ptrdiff_t _stride)
{
int i;
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const pixel4 a= AV_RN4PA(((pixel4*)(src-stride))+0);
const pixel4 b= AV_RN4PA(((pixel4*)(src-stride))+1);
for(i=0; i<16; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, a);
AV_WN4PA(((pixel4*)(src+i*stride))+1, b);
}
}
static void FUNCC(pred8x8_horizontal)(uint8_t *_src, ptrdiff_t stride)
{
int i;
pixel *src = (pixel*)_src;
stride >>= sizeof(pixel)-1;
for(i=0; i<8; i++){
const pixel4 a = PIXEL_SPLAT_X4(src[-1+i*stride]);
AV_WN4PA(((pixel4*)(src+i*stride))+0, a);
AV_WN4PA(((pixel4*)(src+i*stride))+1, a);
}
}
static void FUNCC(pred8x16_horizontal)(uint8_t *_src, ptrdiff_t stride)
{
int i;
pixel *src = (pixel*)_src;
stride >>= sizeof(pixel)-1;
for(i=0; i<16; i++){
const pixel4 a = PIXEL_SPLAT_X4(src[-1+i*stride]);
AV_WN4PA(((pixel4*)(src+i*stride))+0, a);
AV_WN4PA(((pixel4*)(src+i*stride))+1, a);
}
}
#define PRED8x8_X(n, v)\
static void FUNCC(pred8x8_##n##_dc)(uint8_t *_src, ptrdiff_t stride)\
{\
int i;\
const pixel4 a = PIXEL_SPLAT_X4(v);\
pixel *src = (pixel*)_src;\
stride >>= sizeof(pixel)-1;\
for(i=0; i<8; i++){\
AV_WN4PA(((pixel4*)(src+i*stride))+0, a);\
AV_WN4PA(((pixel4*)(src+i*stride))+1, a);\
}\
}
PRED8x8_X(128, (1<<(BIT_DEPTH-1))+0)
#if BIT_DEPTH == 8
PRED8x8_X(127, (1<<(BIT_DEPTH-1))-1)
PRED8x8_X(129, (1<<(BIT_DEPTH-1))+1)
#endif
static void FUNCC(pred8x16_128_dc)(uint8_t *_src, ptrdiff_t stride)
{
FUNCC(pred8x8_128_dc)(_src, stride);
FUNCC(pred8x8_128_dc)(_src+8*stride, stride);
}
static void FUNCC(pred8x8_left_dc)(uint8_t *_src, ptrdiff_t stride)
{
int i;
int dc0, dc2;
pixel4 dc0splat, dc2splat;
pixel *src = (pixel*)_src;
stride >>= sizeof(pixel)-1;
dc0=dc2=0;
for(i=0;i<4; i++){
dc0+= src[-1+i*stride];
dc2+= src[-1+(i+4)*stride];
}
dc0splat = PIXEL_SPLAT_X4((dc0 + 2)>>2);
dc2splat = PIXEL_SPLAT_X4((dc2 + 2)>>2);
for(i=0; i<4; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, dc0splat);
AV_WN4PA(((pixel4*)(src+i*stride))+1, dc0splat);
}
for(i=4; i<8; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, dc2splat);
AV_WN4PA(((pixel4*)(src+i*stride))+1, dc2splat);
}
}
static void FUNCC(pred8x16_left_dc)(uint8_t *_src, ptrdiff_t stride)
{
FUNCC(pred8x8_left_dc)(_src, stride);
FUNCC(pred8x8_left_dc)(_src+8*stride, stride);
}
static void FUNCC(pred8x8_top_dc)(uint8_t *_src, ptrdiff_t stride)
{
int i;
int dc0, dc1;
pixel4 dc0splat, dc1splat;
pixel *src = (pixel*)_src;
stride >>= sizeof(pixel)-1;
dc0=dc1=0;
for(i=0;i<4; i++){
dc0+= src[i-stride];
dc1+= src[4+i-stride];
}
dc0splat = PIXEL_SPLAT_X4((dc0 + 2)>>2);
dc1splat = PIXEL_SPLAT_X4((dc1 + 2)>>2);
for(i=0; i<4; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, dc0splat);
AV_WN4PA(((pixel4*)(src+i*stride))+1, dc1splat);
}
for(i=4; i<8; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, dc0splat);
AV_WN4PA(((pixel4*)(src+i*stride))+1, dc1splat);
}
}
static void FUNCC(pred8x16_top_dc)(uint8_t *_src, ptrdiff_t stride)
{
int i;
int dc0, dc1;
pixel4 dc0splat, dc1splat;
pixel *src = (pixel*)_src;
stride >>= sizeof(pixel)-1;
dc0=dc1=0;
for(i=0;i<4; i++){
dc0+= src[i-stride];
dc1+= src[4+i-stride];
}
dc0splat = PIXEL_SPLAT_X4((dc0 + 2)>>2);
dc1splat = PIXEL_SPLAT_X4((dc1 + 2)>>2);
for(i=0; i<16; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, dc0splat);
AV_WN4PA(((pixel4*)(src+i*stride))+1, dc1splat);
}
}
static void FUNCC(pred8x8_dc)(uint8_t *_src, ptrdiff_t stride)
{
int i;
int dc0, dc1, dc2;
pixel4 dc0splat, dc1splat, dc2splat, dc3splat;
pixel *src = (pixel*)_src;
stride >>= sizeof(pixel)-1;
dc0=dc1=dc2=0;
for(i=0;i<4; i++){
dc0+= src[-1+i*stride] + src[i-stride];
dc1+= src[4+i-stride];
dc2+= src[-1+(i+4)*stride];
}
dc0splat = PIXEL_SPLAT_X4((dc0 + 4)>>3);
dc1splat = PIXEL_SPLAT_X4((dc1 + 2)>>2);
dc2splat = PIXEL_SPLAT_X4((dc2 + 2)>>2);
dc3splat = PIXEL_SPLAT_X4((dc1 + dc2 + 4)>>3);
for(i=0; i<4; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, dc0splat);
AV_WN4PA(((pixel4*)(src+i*stride))+1, dc1splat);
}
for(i=4; i<8; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, dc2splat);
AV_WN4PA(((pixel4*)(src+i*stride))+1, dc3splat);
}
}
static void FUNCC(pred8x16_dc)(uint8_t *_src, ptrdiff_t stride)
{
int i;
int dc0, dc1, dc2, dc3, dc4;
pixel4 dc0splat, dc1splat, dc2splat, dc3splat, dc4splat, dc5splat, dc6splat, dc7splat;
pixel *src = (pixel*)_src;
stride >>= sizeof(pixel)-1;
dc0=dc1=dc2=dc3=dc4=0;
for(i=0;i<4; i++){
dc0+= src[-1+i*stride] + src[i-stride];
dc1+= src[4+i-stride];
dc2+= src[-1+(i+4)*stride];
dc3+= src[-1+(i+8)*stride];
dc4+= src[-1+(i+12)*stride];
}
dc0splat = PIXEL_SPLAT_X4((dc0 + 4)>>3);
dc1splat = PIXEL_SPLAT_X4((dc1 + 2)>>2);
dc2splat = PIXEL_SPLAT_X4((dc2 + 2)>>2);
dc3splat = PIXEL_SPLAT_X4((dc1 + dc2 + 4)>>3);
dc4splat = PIXEL_SPLAT_X4((dc3 + 2)>>2);
dc5splat = PIXEL_SPLAT_X4((dc1 + dc3 + 4)>>3);
dc6splat = PIXEL_SPLAT_X4((dc4 + 2)>>2);
dc7splat = PIXEL_SPLAT_X4((dc1 + dc4 + 4)>>3);
for(i=0; i<4; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, dc0splat);
AV_WN4PA(((pixel4*)(src+i*stride))+1, dc1splat);
}
for(i=4; i<8; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, dc2splat);
AV_WN4PA(((pixel4*)(src+i*stride))+1, dc3splat);
}
for(i=8; i<12; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, dc4splat);
AV_WN4PA(((pixel4*)(src+i*stride))+1, dc5splat);
}
for(i=12; i<16; i++){
AV_WN4PA(((pixel4*)(src+i*stride))+0, dc6splat);
AV_WN4PA(((pixel4*)(src+i*stride))+1, dc7splat);
}
}
//the following 4 function should not be optimized!
static void FUNC(pred8x8_mad_cow_dc_l0t)(uint8_t *src, ptrdiff_t stride)
{
FUNCC(pred8x8_top_dc)(src, stride);
FUNCC(pred4x4_dc)(src, NULL, stride);
}
static void FUNC(pred8x16_mad_cow_dc_l0t)(uint8_t *src, ptrdiff_t stride)
{
FUNCC(pred8x16_top_dc)(src, stride);
FUNCC(pred4x4_dc)(src, NULL, stride);
}
static void FUNC(pred8x8_mad_cow_dc_0lt)(uint8_t *src, ptrdiff_t stride)
{
FUNCC(pred8x8_dc)(src, stride);
FUNCC(pred4x4_top_dc)(src, NULL, stride);
}
static void FUNC(pred8x16_mad_cow_dc_0lt)(uint8_t *src, ptrdiff_t stride)
{
FUNCC(pred8x16_dc)(src, stride);
FUNCC(pred4x4_top_dc)(src, NULL, stride);
}
static void FUNC(pred8x8_mad_cow_dc_l00)(uint8_t *src, ptrdiff_t stride)
{
FUNCC(pred8x8_left_dc)(src, stride);
FUNCC(pred4x4_128_dc)(src + 4*stride , NULL, stride);
FUNCC(pred4x4_128_dc)(src + 4*stride + 4*sizeof(pixel), NULL, stride);
}
static void FUNC(pred8x16_mad_cow_dc_l00)(uint8_t *src, ptrdiff_t stride)
{
FUNCC(pred8x16_left_dc)(src, stride);
FUNCC(pred4x4_128_dc)(src + 4*stride , NULL, stride);
FUNCC(pred4x4_128_dc)(src + 4*stride + 4*sizeof(pixel), NULL, stride);
}
static void FUNC(pred8x8_mad_cow_dc_0l0)(uint8_t *src, ptrdiff_t stride)
{
FUNCC(pred8x8_left_dc)(src, stride);
FUNCC(pred4x4_128_dc)(src , NULL, stride);
FUNCC(pred4x4_128_dc)(src + 4*sizeof(pixel), NULL, stride);
}
static void FUNC(pred8x16_mad_cow_dc_0l0)(uint8_t *src, ptrdiff_t stride)
{
FUNCC(pred8x16_left_dc)(src, stride);
FUNCC(pred4x4_128_dc)(src , NULL, stride);
FUNCC(pred4x4_128_dc)(src + 4*sizeof(pixel), NULL, stride);
}
static void FUNCC(pred8x8_plane)(uint8_t *_src, ptrdiff_t _stride)
{
int j, k;
int a;
INIT_CLIP
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const pixel * const src0 = src +3-stride;
const pixel * src1 = src +4*stride-1;
const pixel * src2 = src1-2*stride; // == src+2*stride-1;
int H = src0[1] - src0[-1];
int V = src1[0] - src2[ 0];
for(k=2; k<=4; ++k) {
src1 += stride; src2 -= stride;
H += k*(src0[k] - src0[-k]);
V += k*(src1[0] - src2[ 0]);
}
H = ( 17*H+16 ) >> 5;
V = ( 17*V+16 ) >> 5;
a = 16*(src1[0] + src2[8]+1) - 3*(V+H);
for(j=8; j>0; --j) {
int b = a;
a += V;
src[0] = CLIP((b ) >> 5);
src[1] = CLIP((b+ H) >> 5);
src[2] = CLIP((b+2*H) >> 5);
src[3] = CLIP((b+3*H) >> 5);
src[4] = CLIP((b+4*H) >> 5);
src[5] = CLIP((b+5*H) >> 5);
src[6] = CLIP((b+6*H) >> 5);
src[7] = CLIP((b+7*H) >> 5);
src += stride;
}
}
static void FUNCC(pred8x16_plane)(uint8_t *_src, ptrdiff_t _stride)
{
int j, k;
int a;
INIT_CLIP
pixel *src = (pixel*)_src;
int stride = _stride>>(sizeof(pixel)-1);
const pixel * const src0 = src +3-stride;
const pixel * src1 = src +8*stride-1;
const pixel * src2 = src1-2*stride; // == src+6*stride-1;
int H = src0[1] - src0[-1];
int V = src1[0] - src2[ 0];
for (k = 2; k <= 4; ++k) {
src1 += stride; src2 -= stride;
H += k*(src0[k] - src0[-k]);
V += k*(src1[0] - src2[ 0]);
}
for (; k <= 8; ++k) {
src1 += stride; src2 -= stride;
V += k*(src1[0] - src2[0]);
}
H = (17*H+16) >> 5;
V = (5*V+32) >> 6;
a = 16*(src1[0] + src2[8] + 1) - 7*V - 3*H;
for(j=16; j>0; --j) {
int b = a;
a += V;
src[0] = CLIP((b ) >> 5);
src[1] = CLIP((b+ H) >> 5);
src[2] = CLIP((b+2*H) >> 5);
src[3] = CLIP((b+3*H) >> 5);
src[4] = CLIP((b+4*H) >> 5);
src[5] =