1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci/** 20cabdff1aSopenharmony_ci * @file 21cabdff1aSopenharmony_ci *@brief IntraX8 frame subdecoder image manipulation routines 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "intrax8dsp.h" 25cabdff1aSopenharmony_ci#include "libavutil/common.h" 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci/* 28cabdff1aSopenharmony_ci * area positions, #3 is 1 pixel only, other are 8 pixels 29cabdff1aSopenharmony_ci * |66666666| 30cabdff1aSopenharmony_ci * 3|44444444|55555555| 31cabdff1aSopenharmony_ci * - -+--------+--------+ 32cabdff1aSopenharmony_ci * 1 2|XXXXXXXX| 33cabdff1aSopenharmony_ci * 1 2|XXXXXXXX| 34cabdff1aSopenharmony_ci * 1 2|XXXXXXXX| 35cabdff1aSopenharmony_ci * 1 2|XXXXXXXX| 36cabdff1aSopenharmony_ci * 1 2|XXXXXXXX| 37cabdff1aSopenharmony_ci * 1 2|XXXXXXXX| 38cabdff1aSopenharmony_ci * 1 2|XXXXXXXX| 39cabdff1aSopenharmony_ci * 1 2|XXXXXXXX| 40cabdff1aSopenharmony_ci * ^-start 41cabdff1aSopenharmony_ci */ 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_ci#define area1 (0) 44cabdff1aSopenharmony_ci#define area2 (8) 45cabdff1aSopenharmony_ci#define area3 (8 + 8) 46cabdff1aSopenharmony_ci#define area4 (8 + 8 + 1) 47cabdff1aSopenharmony_ci#define area5 (8 + 8 + 1 + 8) 48cabdff1aSopenharmony_ci#define area6 (8 + 8 + 1 + 16) 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci/** 51cabdff1aSopenharmony_ci Collect statistics and prepare the edge pixels required by the other spatial compensation functions. 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci * @param src pointer to the beginning of the processed block 54cabdff1aSopenharmony_ci * @param dst pointer to emu_edge, edge pixels are stored the way other compensation routines do. 55cabdff1aSopenharmony_ci * @param linesize byte offset between 2 vertical pixels in the source image 56cabdff1aSopenharmony_ci * @param range pointer to the variable where the edge pixel range is to be stored (max-min values) 57cabdff1aSopenharmony_ci * @param psum pointer to the variable where the edge pixel sum is to be stored 58cabdff1aSopenharmony_ci * @param edges Informs this routine that the block is on an image border, so it has to interpolate the missing edge pixels. 59cabdff1aSopenharmony_ci and some of the edge pixels should be interpolated, the flag has the following meaning: 60cabdff1aSopenharmony_ci 1 - mb_x==0 - first block in the row, interpolate area #1,#2,#3; 61cabdff1aSopenharmony_ci 2 - mb_y==0 - first row, interpolate area #3,#4,#5,#6; 62cabdff1aSopenharmony_ci note: 1|2 - mb_x==mb_y==0 - first block, use 0x80 value for all areas; 63cabdff1aSopenharmony_ci 4 - mb_x>= (mb_width-1) last block in the row, interpolate area #5; 64cabdff1aSopenharmony_ci-*/ 65cabdff1aSopenharmony_cistatic void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, 66cabdff1aSopenharmony_ci ptrdiff_t stride, int *range, 67cabdff1aSopenharmony_ci int *psum, int edges) 68cabdff1aSopenharmony_ci{ 69cabdff1aSopenharmony_ci uint8_t *ptr; 70cabdff1aSopenharmony_ci int sum; 71cabdff1aSopenharmony_ci int i; 72cabdff1aSopenharmony_ci int min_pix, max_pix; 73cabdff1aSopenharmony_ci uint8_t c; 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci if ((edges & 3) == 3) { 76cabdff1aSopenharmony_ci *psum = 0x80 * (8 + 1 + 8 + 2); 77cabdff1aSopenharmony_ci *range = 0; 78cabdff1aSopenharmony_ci memset(dst, 0x80, 16 + 1 + 16 + 8); 79cabdff1aSopenharmony_ci /* this triggers flat_dc for sure. flat_dc avoids all (other) 80cabdff1aSopenharmony_ci * prediction modes, but requires dc_level decoding. */ 81cabdff1aSopenharmony_ci return; 82cabdff1aSopenharmony_ci } 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci min_pix = 256; 85cabdff1aSopenharmony_ci max_pix = -1; 86cabdff1aSopenharmony_ci 87cabdff1aSopenharmony_ci sum = 0; 88cabdff1aSopenharmony_ci 89cabdff1aSopenharmony_ci if (!(edges & 1)) { // (mb_x != 0) // there is previous block on this row 90cabdff1aSopenharmony_ci ptr = src - 1; // left column, area 2 91cabdff1aSopenharmony_ci for (i = 7; i >= 0; i--) { 92cabdff1aSopenharmony_ci c = *(ptr - 1); // area1, same mb as area2, no need to check 93cabdff1aSopenharmony_ci dst[area1 + i] = c; 94cabdff1aSopenharmony_ci c = *ptr; 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ci sum += c; 97cabdff1aSopenharmony_ci min_pix = FFMIN(min_pix, c); 98cabdff1aSopenharmony_ci max_pix = FFMAX(max_pix, c); 99cabdff1aSopenharmony_ci dst[area2 + i] = c; 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci ptr += stride; 102cabdff1aSopenharmony_ci } 103cabdff1aSopenharmony_ci } 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci if (!(edges & 2)) { // (mb_y != 0) // there is row above 106cabdff1aSopenharmony_ci ptr = src - stride; // top line 107cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) { 108cabdff1aSopenharmony_ci c = *(ptr + i); 109cabdff1aSopenharmony_ci sum += c; 110cabdff1aSopenharmony_ci min_pix = FFMIN(min_pix, c); 111cabdff1aSopenharmony_ci max_pix = FFMAX(max_pix, c); 112cabdff1aSopenharmony_ci } 113cabdff1aSopenharmony_ci if (edges & 4) { // last block on the row? 114cabdff1aSopenharmony_ci memset(dst + area5, c, 8); // set with last pixel fr 115cabdff1aSopenharmony_ci memcpy(dst + area4, ptr, 8); 116cabdff1aSopenharmony_ci } else { 117cabdff1aSopenharmony_ci memcpy(dst + area4, ptr, 16); // both area4 and 5 118cabdff1aSopenharmony_ci } 119cabdff1aSopenharmony_ci // area6 always present in the above block 120cabdff1aSopenharmony_ci memcpy(dst + area6, ptr - stride, 8); 121cabdff1aSopenharmony_ci } 122cabdff1aSopenharmony_ci // now calculate the stuff we need 123cabdff1aSopenharmony_ci if (edges & 3) { // mb_x ==0 || mb_y == 0) { 124cabdff1aSopenharmony_ci int avg = (sum + 4) >> 3; 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_ci if (edges & 1) // (mb_x == 0) { // implies mb_y !=0 127cabdff1aSopenharmony_ci memset(dst + area1, avg, 8 + 8 + 1); // areas 1, 2, 3 are averaged 128cabdff1aSopenharmony_ci else // implies y == 0 x != 0 129cabdff1aSopenharmony_ci memset(dst + area3, avg, 1 + 16 + 8); // areas 3, 4, 5, 6 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci sum += avg * 9; 132cabdff1aSopenharmony_ci } else { 133cabdff1aSopenharmony_ci // the edge pixel, in the top line and left column 134cabdff1aSopenharmony_ci uint8_t c = *(src - 1 - stride); 135cabdff1aSopenharmony_ci dst[area3] = c; 136cabdff1aSopenharmony_ci sum += c; 137cabdff1aSopenharmony_ci // edge pixel is not part of min/max 138cabdff1aSopenharmony_ci } 139cabdff1aSopenharmony_ci *range = max_pix - min_pix; 140cabdff1aSopenharmony_ci sum += *(dst + area5) + *(dst + area5 + 1); 141cabdff1aSopenharmony_ci *psum = sum; 142cabdff1aSopenharmony_ci} 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_cistatic const uint16_t zero_prediction_weights[64 * 2] = { 145cabdff1aSopenharmony_ci 640, 640, 669, 480, 708, 354, 748, 257, 146cabdff1aSopenharmony_ci 792, 198, 760, 143, 808, 101, 772, 72, 147cabdff1aSopenharmony_ci 480, 669, 537, 537, 598, 416, 661, 316, 148cabdff1aSopenharmony_ci 719, 250, 707, 185, 768, 134, 745, 97, 149cabdff1aSopenharmony_ci 354, 708, 416, 598, 488, 488, 564, 388, 150cabdff1aSopenharmony_ci 634, 317, 642, 241, 716, 179, 706, 132, 151cabdff1aSopenharmony_ci 257, 748, 316, 661, 388, 564, 469, 469, 152cabdff1aSopenharmony_ci 543, 395, 571, 311, 655, 238, 660, 180, 153cabdff1aSopenharmony_ci 198, 792, 250, 719, 317, 634, 395, 543, 154cabdff1aSopenharmony_ci 469, 469, 507, 380, 597, 299, 616, 231, 155cabdff1aSopenharmony_ci 161, 855, 206, 788, 266, 710, 340, 623, 156cabdff1aSopenharmony_ci 411, 548, 455, 455, 548, 366, 576, 288, 157cabdff1aSopenharmony_ci 122, 972, 159, 914, 211, 842, 276, 758, 158cabdff1aSopenharmony_ci 341, 682, 389, 584, 483, 483, 520, 390, 159cabdff1aSopenharmony_ci 110, 1172, 144, 1107, 193, 1028, 254, 932, 160cabdff1aSopenharmony_ci 317, 846, 366, 731, 458, 611, 499, 499, 161cabdff1aSopenharmony_ci}; 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_cistatic void spatial_compensation_0(uint8_t *src, uint8_t *dst, ptrdiff_t stride) 164cabdff1aSopenharmony_ci{ 165cabdff1aSopenharmony_ci int i, j; 166cabdff1aSopenharmony_ci int x, y; 167cabdff1aSopenharmony_ci unsigned int p; // power divided by 2 168cabdff1aSopenharmony_ci int a; 169cabdff1aSopenharmony_ci uint16_t left_sum[2][8] = { { 0 } }; 170cabdff1aSopenharmony_ci uint16_t top_sum[2][8] = { { 0 } }; 171cabdff1aSopenharmony_ci 172cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) { 173cabdff1aSopenharmony_ci a = src[area2 + 7 - i] << 4; 174cabdff1aSopenharmony_ci for (j = 0; j < 8; j++) { 175cabdff1aSopenharmony_ci p = abs(i - j); 176cabdff1aSopenharmony_ci left_sum[p & 1][j] += a >> (p >> 1); 177cabdff1aSopenharmony_ci } 178cabdff1aSopenharmony_ci } 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) { 181cabdff1aSopenharmony_ci a = src[area4 + i] << 4; 182cabdff1aSopenharmony_ci for (j = 0; j < 8; j++) { 183cabdff1aSopenharmony_ci p = abs(i - j); 184cabdff1aSopenharmony_ci top_sum[p & 1][j] += a >> (p >> 1); 185cabdff1aSopenharmony_ci } 186cabdff1aSopenharmony_ci } 187cabdff1aSopenharmony_ci for (; i < 10; i++) { 188cabdff1aSopenharmony_ci a = src[area4 + i] << 4; 189cabdff1aSopenharmony_ci for (j = 5; j < 8; j++) { 190cabdff1aSopenharmony_ci p = abs(i - j); 191cabdff1aSopenharmony_ci top_sum[p & 1][j] += a >> (p >> 1); 192cabdff1aSopenharmony_ci } 193cabdff1aSopenharmony_ci } 194cabdff1aSopenharmony_ci for (; i < 12; i++) { 195cabdff1aSopenharmony_ci a = src[area4 + i] << 4; 196cabdff1aSopenharmony_ci for (j = 7; j < 8; j++) { 197cabdff1aSopenharmony_ci p = abs(i - j); 198cabdff1aSopenharmony_ci top_sum[p & 1][j] += a >> (p >> 1); 199cabdff1aSopenharmony_ci } 200cabdff1aSopenharmony_ci } 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) { 203cabdff1aSopenharmony_ci top_sum[0][i] += (top_sum[1][i] * 181 + 128) >> 8; // 181 is sqrt(2)/2 204cabdff1aSopenharmony_ci left_sum[0][i] += (left_sum[1][i] * 181 + 128) >> 8; 205cabdff1aSopenharmony_ci } 206cabdff1aSopenharmony_ci for (y = 0; y < 8; y++) { 207cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) 208cabdff1aSopenharmony_ci dst[x] = ((uint32_t) top_sum[0][x] * zero_prediction_weights[y * 16 + x * 2 + 0] + 209cabdff1aSopenharmony_ci (uint32_t) left_sum[0][y] * zero_prediction_weights[y * 16 + x * 2 + 1] + 210cabdff1aSopenharmony_ci 0x8000) >> 16; 211cabdff1aSopenharmony_ci dst += stride; 212cabdff1aSopenharmony_ci } 213cabdff1aSopenharmony_ci} 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_cistatic void spatial_compensation_1(uint8_t *src, uint8_t *dst, ptrdiff_t stride) 216cabdff1aSopenharmony_ci{ 217cabdff1aSopenharmony_ci int x, y; 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci for (y = 0; y < 8; y++) { 220cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) 221cabdff1aSopenharmony_ci dst[x] = src[area4 + FFMIN(2 * y + x + 2, 15)]; 222cabdff1aSopenharmony_ci dst += stride; 223cabdff1aSopenharmony_ci } 224cabdff1aSopenharmony_ci} 225cabdff1aSopenharmony_ci 226cabdff1aSopenharmony_cistatic void spatial_compensation_2(uint8_t *src, uint8_t *dst, ptrdiff_t stride) 227cabdff1aSopenharmony_ci{ 228cabdff1aSopenharmony_ci int x, y; 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci for (y = 0; y < 8; y++) { 231cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) 232cabdff1aSopenharmony_ci dst[x] = src[area4 + 1 + y + x]; 233cabdff1aSopenharmony_ci dst += stride; 234cabdff1aSopenharmony_ci } 235cabdff1aSopenharmony_ci} 236cabdff1aSopenharmony_ci 237cabdff1aSopenharmony_cistatic void spatial_compensation_3(uint8_t *src, uint8_t *dst, ptrdiff_t stride) 238cabdff1aSopenharmony_ci{ 239cabdff1aSopenharmony_ci int x, y; 240cabdff1aSopenharmony_ci 241cabdff1aSopenharmony_ci for (y = 0; y < 8; y++) { 242cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) 243cabdff1aSopenharmony_ci dst[x] = src[area4 + ((y + 1) >> 1) + x]; 244cabdff1aSopenharmony_ci dst += stride; 245cabdff1aSopenharmony_ci } 246cabdff1aSopenharmony_ci} 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_cistatic void spatial_compensation_4(uint8_t *src, uint8_t *dst, ptrdiff_t stride) 249cabdff1aSopenharmony_ci{ 250cabdff1aSopenharmony_ci int x, y; 251cabdff1aSopenharmony_ci 252cabdff1aSopenharmony_ci for (y = 0; y < 8; y++) { 253cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) 254cabdff1aSopenharmony_ci dst[x] = (src[area4 + x] + src[area6 + x] + 1) >> 1; 255cabdff1aSopenharmony_ci dst += stride; 256cabdff1aSopenharmony_ci } 257cabdff1aSopenharmony_ci} 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_cistatic void spatial_compensation_5(uint8_t *src, uint8_t *dst, ptrdiff_t stride) 260cabdff1aSopenharmony_ci{ 261cabdff1aSopenharmony_ci int x, y; 262cabdff1aSopenharmony_ci 263cabdff1aSopenharmony_ci for (y = 0; y < 8; y++) { 264cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) { 265cabdff1aSopenharmony_ci if (2 * x - y < 0) 266cabdff1aSopenharmony_ci dst[x] = src[area2 + 9 + 2 * x - y]; 267cabdff1aSopenharmony_ci else 268cabdff1aSopenharmony_ci dst[x] = src[area4 + x - ((y + 1) >> 1)]; 269cabdff1aSopenharmony_ci } 270cabdff1aSopenharmony_ci dst += stride; 271cabdff1aSopenharmony_ci } 272cabdff1aSopenharmony_ci} 273cabdff1aSopenharmony_ci 274cabdff1aSopenharmony_cistatic void spatial_compensation_6(uint8_t *src, uint8_t *dst, ptrdiff_t stride) 275cabdff1aSopenharmony_ci{ 276cabdff1aSopenharmony_ci int x, y; 277cabdff1aSopenharmony_ci 278cabdff1aSopenharmony_ci for (y = 0; y < 8; y++) { 279cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) 280cabdff1aSopenharmony_ci dst[x] = src[area3 + x - y]; 281cabdff1aSopenharmony_ci dst += stride; 282cabdff1aSopenharmony_ci } 283cabdff1aSopenharmony_ci} 284cabdff1aSopenharmony_ci 285cabdff1aSopenharmony_cistatic void spatial_compensation_7(uint8_t *src, uint8_t *dst, ptrdiff_t stride) 286cabdff1aSopenharmony_ci{ 287cabdff1aSopenharmony_ci int x, y; 288cabdff1aSopenharmony_ci 289cabdff1aSopenharmony_ci for (y = 0; y < 8; y++) { 290cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) { 291cabdff1aSopenharmony_ci if (x - 2 * y > 0) 292cabdff1aSopenharmony_ci dst[x] = (src[area3 - 1 + x - 2 * y] + src[area3 + x - 2 * y] + 1) >> 1; 293cabdff1aSopenharmony_ci else 294cabdff1aSopenharmony_ci dst[x] = src[area2 + 8 - y + (x >> 1)]; 295cabdff1aSopenharmony_ci } 296cabdff1aSopenharmony_ci dst += stride; 297cabdff1aSopenharmony_ci } 298cabdff1aSopenharmony_ci} 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_cistatic void spatial_compensation_8(uint8_t *src, uint8_t *dst, ptrdiff_t stride) 301cabdff1aSopenharmony_ci{ 302cabdff1aSopenharmony_ci int x, y; 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci for (y = 0; y < 8; y++) { 305cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) 306cabdff1aSopenharmony_ci dst[x] = (src[area1 + 7 - y] + src[area2 + 7 - y] + 1) >> 1; 307cabdff1aSopenharmony_ci dst += stride; 308cabdff1aSopenharmony_ci } 309cabdff1aSopenharmony_ci} 310cabdff1aSopenharmony_ci 311cabdff1aSopenharmony_cistatic void spatial_compensation_9(uint8_t *src, uint8_t *dst, ptrdiff_t stride) 312cabdff1aSopenharmony_ci{ 313cabdff1aSopenharmony_ci int x, y; 314cabdff1aSopenharmony_ci 315cabdff1aSopenharmony_ci for (y = 0; y < 8; y++) { 316cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) 317cabdff1aSopenharmony_ci dst[x] = src[area2 + 6 - FFMIN(x + y, 6)]; 318cabdff1aSopenharmony_ci dst += stride; 319cabdff1aSopenharmony_ci } 320cabdff1aSopenharmony_ci} 321cabdff1aSopenharmony_ci 322cabdff1aSopenharmony_cistatic void spatial_compensation_10(uint8_t *src, uint8_t *dst, ptrdiff_t stride) 323cabdff1aSopenharmony_ci{ 324cabdff1aSopenharmony_ci int x, y; 325cabdff1aSopenharmony_ci 326cabdff1aSopenharmony_ci for (y = 0; y < 8; y++) { 327cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) 328cabdff1aSopenharmony_ci dst[x] = (src[area2 + 7 - y] * (8 - x) + src[area4 + x] * x + 4) >> 3; 329cabdff1aSopenharmony_ci dst += stride; 330cabdff1aSopenharmony_ci } 331cabdff1aSopenharmony_ci} 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_cistatic void spatial_compensation_11(uint8_t *src, uint8_t *dst, ptrdiff_t stride) 334cabdff1aSopenharmony_ci{ 335cabdff1aSopenharmony_ci int x, y; 336cabdff1aSopenharmony_ci 337cabdff1aSopenharmony_ci for (y = 0; y < 8; y++) { 338cabdff1aSopenharmony_ci for (x = 0; x < 8; x++) 339cabdff1aSopenharmony_ci dst[x] = (src[area2 + 7 - y] * y + src[area4 + x] * (8 - y) + 4) >> 3; 340cabdff1aSopenharmony_ci dst += stride; 341cabdff1aSopenharmony_ci } 342cabdff1aSopenharmony_ci} 343cabdff1aSopenharmony_ci 344cabdff1aSopenharmony_cistatic void x8_loop_filter(uint8_t *ptr, const ptrdiff_t a_stride, 345cabdff1aSopenharmony_ci const ptrdiff_t b_stride, int quant) 346cabdff1aSopenharmony_ci{ 347cabdff1aSopenharmony_ci int i, t; 348cabdff1aSopenharmony_ci int p0, p1, p2, p3, p4, p5, p6, p7, p8, p9; 349cabdff1aSopenharmony_ci int ql = (quant + 10) >> 3; 350cabdff1aSopenharmony_ci 351cabdff1aSopenharmony_ci for (i = 0; i < 8; i++, ptr += b_stride) { 352cabdff1aSopenharmony_ci p0 = ptr[-5 * a_stride]; 353cabdff1aSopenharmony_ci p1 = ptr[-4 * a_stride]; 354cabdff1aSopenharmony_ci p2 = ptr[-3 * a_stride]; 355cabdff1aSopenharmony_ci p3 = ptr[-2 * a_stride]; 356cabdff1aSopenharmony_ci p4 = ptr[-1 * a_stride]; 357cabdff1aSopenharmony_ci p5 = ptr[0]; 358cabdff1aSopenharmony_ci p6 = ptr[1 * a_stride]; 359cabdff1aSopenharmony_ci p7 = ptr[2 * a_stride]; 360cabdff1aSopenharmony_ci p8 = ptr[3 * a_stride]; 361cabdff1aSopenharmony_ci p9 = ptr[4 * a_stride]; 362cabdff1aSopenharmony_ci 363cabdff1aSopenharmony_ci t = (FFABS(p1 - p2) <= ql) + 364cabdff1aSopenharmony_ci (FFABS(p2 - p3) <= ql) + 365cabdff1aSopenharmony_ci (FFABS(p3 - p4) <= ql) + 366cabdff1aSopenharmony_ci (FFABS(p4 - p5) <= ql); 367cabdff1aSopenharmony_ci 368cabdff1aSopenharmony_ci // You need at least 1 to be able to reach a total score of 6. 369cabdff1aSopenharmony_ci if (t > 0) { 370cabdff1aSopenharmony_ci t += (FFABS(p5 - p6) <= ql) + 371cabdff1aSopenharmony_ci (FFABS(p6 - p7) <= ql) + 372cabdff1aSopenharmony_ci (FFABS(p7 - p8) <= ql) + 373cabdff1aSopenharmony_ci (FFABS(p8 - p9) <= ql) + 374cabdff1aSopenharmony_ci (FFABS(p0 - p1) <= ql); 375cabdff1aSopenharmony_ci if (t >= 6) { 376cabdff1aSopenharmony_ci int min, max; 377cabdff1aSopenharmony_ci 378cabdff1aSopenharmony_ci min = max = p1; 379cabdff1aSopenharmony_ci min = FFMIN(min, p3); 380cabdff1aSopenharmony_ci max = FFMAX(max, p3); 381cabdff1aSopenharmony_ci min = FFMIN(min, p5); 382cabdff1aSopenharmony_ci max = FFMAX(max, p5); 383cabdff1aSopenharmony_ci min = FFMIN(min, p8); 384cabdff1aSopenharmony_ci max = FFMAX(max, p8); 385cabdff1aSopenharmony_ci if (max - min < 2 * quant) { // early stop 386cabdff1aSopenharmony_ci min = FFMIN(min, p2); 387cabdff1aSopenharmony_ci max = FFMAX(max, p2); 388cabdff1aSopenharmony_ci min = FFMIN(min, p4); 389cabdff1aSopenharmony_ci max = FFMAX(max, p4); 390cabdff1aSopenharmony_ci min = FFMIN(min, p6); 391cabdff1aSopenharmony_ci max = FFMAX(max, p6); 392cabdff1aSopenharmony_ci min = FFMIN(min, p7); 393cabdff1aSopenharmony_ci max = FFMAX(max, p7); 394cabdff1aSopenharmony_ci if (max - min < 2 * quant) { 395cabdff1aSopenharmony_ci ptr[-2 * a_stride] = (4 * p2 + 3 * p3 + 1 * p7 + 4) >> 3; 396cabdff1aSopenharmony_ci ptr[-1 * a_stride] = (3 * p2 + 3 * p4 + 2 * p7 + 4) >> 3; 397cabdff1aSopenharmony_ci ptr[0] = (2 * p2 + 3 * p5 + 3 * p7 + 4) >> 3; 398cabdff1aSopenharmony_ci ptr[1 * a_stride] = (1 * p2 + 3 * p6 + 4 * p7 + 4) >> 3; 399cabdff1aSopenharmony_ci continue; 400cabdff1aSopenharmony_ci } 401cabdff1aSopenharmony_ci } 402cabdff1aSopenharmony_ci } 403cabdff1aSopenharmony_ci } 404cabdff1aSopenharmony_ci { 405cabdff1aSopenharmony_ci int x, x0, x1, x2; 406cabdff1aSopenharmony_ci int m; 407cabdff1aSopenharmony_ci 408cabdff1aSopenharmony_ci x0 = (2 * p3 - 5 * p4 + 5 * p5 - 2 * p6 + 4) >> 3; 409cabdff1aSopenharmony_ci if (FFABS(x0) < quant) { 410cabdff1aSopenharmony_ci x1 = (2 * p1 - 5 * p2 + 5 * p3 - 2 * p4 + 4) >> 3; 411cabdff1aSopenharmony_ci x2 = (2 * p5 - 5 * p6 + 5 * p7 - 2 * p8 + 4) >> 3; 412cabdff1aSopenharmony_ci 413cabdff1aSopenharmony_ci x = FFABS(x0) - FFMIN(FFABS(x1), FFABS(x2)); 414cabdff1aSopenharmony_ci m = p4 - p5; 415cabdff1aSopenharmony_ci 416cabdff1aSopenharmony_ci if (x > 0 && (m ^ x0) < 0) { 417cabdff1aSopenharmony_ci int32_t sign; 418cabdff1aSopenharmony_ci 419cabdff1aSopenharmony_ci sign = m >> 31; 420cabdff1aSopenharmony_ci m = (m ^ sign) - sign; // abs(m) 421cabdff1aSopenharmony_ci m >>= 1; 422cabdff1aSopenharmony_ci 423cabdff1aSopenharmony_ci x = 5 * x >> 3; 424cabdff1aSopenharmony_ci 425cabdff1aSopenharmony_ci if (x > m) 426cabdff1aSopenharmony_ci x = m; 427cabdff1aSopenharmony_ci 428cabdff1aSopenharmony_ci x = (x ^ sign) - sign; 429cabdff1aSopenharmony_ci 430cabdff1aSopenharmony_ci ptr[-1 * a_stride] -= x; 431cabdff1aSopenharmony_ci ptr[0] += x; 432cabdff1aSopenharmony_ci } 433cabdff1aSopenharmony_ci } 434cabdff1aSopenharmony_ci } 435cabdff1aSopenharmony_ci } 436cabdff1aSopenharmony_ci} 437cabdff1aSopenharmony_ci 438cabdff1aSopenharmony_cistatic void x8_h_loop_filter(uint8_t *src, ptrdiff_t stride, int qscale) 439cabdff1aSopenharmony_ci{ 440cabdff1aSopenharmony_ci x8_loop_filter(src, stride, 1, qscale); 441cabdff1aSopenharmony_ci} 442cabdff1aSopenharmony_ci 443cabdff1aSopenharmony_cistatic void x8_v_loop_filter(uint8_t *src, ptrdiff_t stride, int qscale) 444cabdff1aSopenharmony_ci{ 445cabdff1aSopenharmony_ci x8_loop_filter(src, 1, stride, qscale); 446cabdff1aSopenharmony_ci} 447cabdff1aSopenharmony_ci 448cabdff1aSopenharmony_ciav_cold void ff_intrax8dsp_init(IntraX8DSPContext *dsp) 449cabdff1aSopenharmony_ci{ 450cabdff1aSopenharmony_ci dsp->h_loop_filter = x8_h_loop_filter; 451cabdff1aSopenharmony_ci dsp->v_loop_filter = x8_v_loop_filter; 452cabdff1aSopenharmony_ci dsp->setup_spatial_compensation = x8_setup_spatial_compensation; 453cabdff1aSopenharmony_ci dsp->spatial_compensation[0] = spatial_compensation_0; 454cabdff1aSopenharmony_ci dsp->spatial_compensation[1] = spatial_compensation_1; 455cabdff1aSopenharmony_ci dsp->spatial_compensation[2] = spatial_compensation_2; 456cabdff1aSopenharmony_ci dsp->spatial_compensation[3] = spatial_compensation_3; 457cabdff1aSopenharmony_ci dsp->spatial_compensation[4] = spatial_compensation_4; 458cabdff1aSopenharmony_ci dsp->spatial_compensation[5] = spatial_compensation_5; 459cabdff1aSopenharmony_ci dsp->spatial_compensation[6] = spatial_compensation_6; 460cabdff1aSopenharmony_ci dsp->spatial_compensation[7] = spatial_compensation_7; 461cabdff1aSopenharmony_ci dsp->spatial_compensation[8] = spatial_compensation_8; 462cabdff1aSopenharmony_ci dsp->spatial_compensation[9] = spatial_compensation_9; 463cabdff1aSopenharmony_ci dsp->spatial_compensation[10] = spatial_compensation_10; 464cabdff1aSopenharmony_ci dsp->spatial_compensation[11] = spatial_compensation_11; 465cabdff1aSopenharmony_ci} 466