OLD | NEW |
1 // Copyright 2011 Google Inc. All Rights Reserved. | 1 // Copyright 2011 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Use of this source code is governed by a BSD-style license | 3 // Use of this source code is governed by a BSD-style license |
4 // that can be found in the COPYING file in the root of the source | 4 // that can be found in the COPYING file in the root of the source |
5 // tree. An additional intellectual property rights grant can be found | 5 // tree. An additional intellectual property rights grant can be found |
6 // in the file PATENTS. All contributing project authors may | 6 // in the file PATENTS. All contributing project authors may |
7 // be found in the AUTHORS file in the root of the source tree. | 7 // be found in the AUTHORS file in the root of the source tree. |
8 // ----------------------------------------------------------------------------- | 8 // ----------------------------------------------------------------------------- |
9 // | 9 // |
10 // YUV to RGB upsampling functions. | 10 // YUV to RGB upsampling functions. |
11 // | 11 // |
12 // Author: somnath@google.com (Somnath Banerjee) | 12 // Author: somnath@google.com (Somnath Banerjee) |
13 | 13 |
14 #include "./dsp.h" | 14 #include "./dsp.h" |
15 #include "./yuv.h" | 15 #include "./yuv.h" |
16 | 16 |
17 #if defined(__cplusplus) || defined(c_plusplus) | 17 #include <assert.h> |
18 extern "C" { | |
19 #endif | |
20 | 18 |
21 //------------------------------------------------------------------------------ | 19 //------------------------------------------------------------------------------ |
22 // Fancy upsampler | 20 // Fancy upsampler |
23 | 21 |
24 #ifdef FANCY_UPSAMPLING | 22 #ifdef FANCY_UPSAMPLING |
25 | 23 |
26 // Fancy upsampling functions to convert YUV to RGB | 24 // Fancy upsampling functions to convert YUV to RGB |
27 WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST]; | 25 WebPUpsampleLinePairFunc WebPUpsamplers[MODE_LAST]; |
28 | 26 |
29 // Given samples laid out in a square as: | 27 // Given samples laid out in a square as: |
30 // [a b] | 28 // [a b] |
31 // [c d] | 29 // [c d] |
32 // we interpolate u/v as: | 30 // we interpolate u/v as: |
33 // ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 | 31 // ([9*a + 3*b + 3*c + d 3*a + 9*b + 3*c + d] + [8 8]) / 16 |
34 // ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 | 32 // ([3*a + b + 9*c + 3*d a + 3*b + 3*c + 9*d] [8 8]) / 16 |
35 | 33 |
36 // We process u and v together stashed into 32bit (16bit each). | 34 // We process u and v together stashed into 32bit (16bit each). |
37 #define LOAD_UV(u, v) ((u) | ((v) << 16)) | 35 #define LOAD_UV(u, v) ((u) | ((v) << 16)) |
38 | 36 |
39 #define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ | 37 #define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \ |
40 static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ | 38 static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ |
41 const uint8_t* top_u, const uint8_t* top_v, \ | 39 const uint8_t* top_u, const uint8_t* top_v, \ |
42 const uint8_t* cur_u, const uint8_t* cur_v, \ | 40 const uint8_t* cur_u, const uint8_t* cur_v, \ |
43 uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ | 41 uint8_t* top_dst, uint8_t* bottom_dst, int len) { \ |
44 int x; \ | 42 int x; \ |
45 const int last_pixel_pair = (len - 1) >> 1; \ | 43 const int last_pixel_pair = (len - 1) >> 1; \ |
46 uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \ | 44 uint32_t tl_uv = LOAD_UV(top_u[0], top_v[0]); /* top-left sample */ \ |
47 uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \ | 45 uint32_t l_uv = LOAD_UV(cur_u[0], cur_v[0]); /* left-sample */ \ |
48 if (top_y) { \ | 46 assert(top_y != NULL); \ |
| 47 { \ |
49 const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ | 48 const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ |
50 FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ | 49 FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ |
51 } \ | 50 } \ |
52 if (bottom_y) { \ | 51 if (bottom_y != NULL) { \ |
53 const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ | 52 const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ |
54 FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \ | 53 FUNC(bottom_y[0], uv0 & 0xff, (uv0 >> 16), bottom_dst); \ |
55 } \ | 54 } \ |
56 for (x = 1; x <= last_pixel_pair; ++x) { \ | 55 for (x = 1; x <= last_pixel_pair; ++x) { \ |
57 const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \ | 56 const uint32_t t_uv = LOAD_UV(top_u[x], top_v[x]); /* top sample */ \ |
58 const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \ | 57 const uint32_t uv = LOAD_UV(cur_u[x], cur_v[x]); /* sample */ \ |
59 /* precompute invariant values associated with first and second diagonals*/\ | 58 /* precompute invariant values associated with first and second diagonals*/\ |
60 const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \ | 59 const uint32_t avg = tl_uv + t_uv + l_uv + uv + 0x00080008u; \ |
61 const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \ | 60 const uint32_t diag_12 = (avg + 2 * (t_uv + l_uv)) >> 3; \ |
62 const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \ | 61 const uint32_t diag_03 = (avg + 2 * (tl_uv + uv)) >> 3; \ |
63 if (top_y) { \ | 62 { \ |
64 const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ | 63 const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ |
65 const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ | 64 const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ |
66 FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ | 65 FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ |
67 top_dst + (2 * x - 1) * XSTEP); \ | 66 top_dst + (2 * x - 1) * XSTEP); \ |
68 FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ | 67 FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ |
69 top_dst + (2 * x - 0) * XSTEP); \ | 68 top_dst + (2 * x - 0) * XSTEP); \ |
70 } \ | 69 } \ |
71 if (bottom_y) { \ | 70 if (bottom_y != NULL) { \ |
72 const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ | 71 const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ |
73 const uint32_t uv1 = (diag_12 + uv) >> 1; \ | 72 const uint32_t uv1 = (diag_12 + uv) >> 1; \ |
74 FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ | 73 FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ |
75 bottom_dst + (2 * x - 1) * XSTEP); \ | 74 bottom_dst + (2 * x - 1) * XSTEP); \ |
76 FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \ | 75 FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \ |
77 bottom_dst + (2 * x + 0) * XSTEP); \ | 76 bottom_dst + (2 * x + 0) * XSTEP); \ |
78 } \ | 77 } \ |
79 tl_uv = t_uv; \ | 78 tl_uv = t_uv; \ |
80 l_uv = uv; \ | 79 l_uv = uv; \ |
81 } \ | 80 } \ |
82 if (!(len & 1)) { \ | 81 if (!(len & 1)) { \ |
83 if (top_y) { \ | 82 { \ |
84 const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ | 83 const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ |
85 FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ | 84 FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ |
86 top_dst + (len - 1) * XSTEP); \ | 85 top_dst + (len - 1) * XSTEP); \ |
87 } \ | 86 } \ |
88 if (bottom_y) { \ | 87 if (bottom_y != NULL) { \ |
89 const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ | 88 const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ |
90 FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ | 89 FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ |
91 bottom_dst + (len - 1) * XSTEP); \ | 90 bottom_dst + (len - 1) * XSTEP); \ |
92 } \ | 91 } \ |
93 } \ | 92 } \ |
94 } | 93 } |
95 | 94 |
96 // All variants implemented. | 95 // All variants implemented. |
97 UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3) | 96 UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3) |
98 UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3) | 97 UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3) |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 //------------------------------------------------------------------------------ | 160 //------------------------------------------------------------------------------ |
162 | 161 |
163 #if !defined(FANCY_UPSAMPLING) | 162 #if !defined(FANCY_UPSAMPLING) |
164 #define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \ | 163 #define DUAL_SAMPLE_FUNC(FUNC_NAME, FUNC) \ |
165 static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \ | 164 static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \ |
166 const uint8_t* top_u, const uint8_t* top_v, \ | 165 const uint8_t* top_u, const uint8_t* top_v, \ |
167 const uint8_t* bot_u, const uint8_t* bot_v, \ | 166 const uint8_t* bot_u, const uint8_t* bot_v, \ |
168 uint8_t* top_dst, uint8_t* bot_dst, int len) { \ | 167 uint8_t* top_dst, uint8_t* bot_dst, int len) { \ |
169 const int half_len = len >> 1; \ | 168 const int half_len = len >> 1; \ |
170 int x; \ | 169 int x; \ |
171 if (top_dst != NULL) { \ | 170 assert(top_dst != NULL); \ |
| 171 { \ |
172 for (x = 0; x < half_len; ++x) { \ | 172 for (x = 0; x < half_len; ++x) { \ |
173 FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \ | 173 FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x + 0); \ |
174 FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \ | 174 FUNC(top_y[2 * x + 1], top_u[x], top_v[x], top_dst + 8 * x + 4); \ |
175 } \ | 175 } \ |
176 if (len & 1) FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x); \ | 176 if (len & 1) FUNC(top_y[2 * x + 0], top_u[x], top_v[x], top_dst + 8 * x); \ |
177 } \ | 177 } \ |
178 if (bot_dst != NULL) { \ | 178 if (bot_dst != NULL) { \ |
179 for (x = 0; x < half_len; ++x) { \ | 179 for (x = 0; x < half_len; ++x) { \ |
180 FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x + 0); \ | 180 FUNC(bot_y[2 * x + 0], bot_u[x], bot_v[x], bot_dst + 8 * x + 0); \ |
181 FUNC(bot_y[2 * x + 1], bot_u[x], bot_v[x], bot_dst + 8 * x + 4); \ | 181 FUNC(bot_y[2 * x + 1], bot_u[x], bot_v[x], bot_dst + 8 * x + 4); \ |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 #endif | 357 #endif |
358 #if defined(WEBP_USE_NEON) | 358 #if defined(WEBP_USE_NEON) |
359 if (VP8GetCPUInfo(kNEON)) { | 359 if (VP8GetCPUInfo(kNEON)) { |
360 WebPInitPremultiplyNEON(); | 360 WebPInitPremultiplyNEON(); |
361 } | 361 } |
362 #endif | 362 #endif |
363 } | 363 } |
364 #endif // FANCY_UPSAMPLING | 364 #endif // FANCY_UPSAMPLING |
365 } | 365 } |
366 | 366 |
367 #if defined(__cplusplus) || defined(c_plusplus) | |
368 } // extern "C" | |
369 #endif | |
OLD | NEW |