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