Commit | Line | Data |
---|---|---|
72b9787e JB |
1 | /***************************************************************************** |
2 | * Copyright (C) 2013 x265 project | |
3 | * | |
4 | * Authors: Min Chen <chenm003@163.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. | |
19 | * | |
20 | * This program is also available under a commercial proprietary license. | |
21 | * For more information, contact us at license @ x265.com. | |
22 | *****************************************************************************/ | |
23 | ||
24 | #include "common.h" | |
25 | #include "primitives.h" | |
26 | ||
27 | using namespace x265; | |
28 | ||
29 | namespace { | |
30 | pixel dcPredValue(pixel* above, pixel* left, intptr_t width) | |
31 | { | |
32 | int w, sum = 0; | |
33 | pixel pDcVal; | |
34 | ||
35 | for (w = 0; w < width; w++) | |
36 | { | |
37 | sum += above[w]; | |
38 | } | |
39 | ||
40 | for (w = 0; w < width; w++) | |
41 | { | |
42 | sum += left[w]; | |
43 | } | |
44 | ||
45 | pDcVal = (pixel)((sum + width) / (width + width)); | |
46 | ||
47 | return pDcVal; | |
48 | } | |
49 | ||
50 | void dcPredFilter(pixel* above, pixel* left, pixel* dst, intptr_t dststride, int size) | |
51 | { | |
52 | // boundary pixels processing | |
53 | dst[0] = (pixel)((above[0] + left[0] + 2 * dst[0] + 2) >> 2); | |
54 | ||
55 | for (int x = 1; x < size; x++) | |
56 | { | |
57 | dst[x] = (pixel)((above[x] + 3 * dst[x] + 2) >> 2); | |
58 | } | |
59 | ||
60 | dst += dststride; | |
61 | for (int y = 1; y < size; y++) | |
62 | { | |
63 | *dst = (pixel)((left[y] + 3 * *dst + 2) >> 2); | |
64 | dst += dststride; | |
65 | } | |
66 | } | |
67 | ||
68 | template<int width> | |
69 | void intra_pred_dc_c(pixel* dst, intptr_t dstStride, pixel* left, pixel* above, int /*dirMode*/, int bFilter) | |
70 | { | |
71 | int k, l; | |
72 | ||
73 | pixel dcval = dcPredValue(above + 1, left + 1, width); | |
74 | ||
75 | for (k = 0; k < width; k++) | |
76 | { | |
77 | for (l = 0; l < width; l++) | |
78 | { | |
79 | dst[k * dstStride + l] = dcval; | |
80 | } | |
81 | } | |
82 | ||
83 | if (bFilter) | |
84 | { | |
85 | dcPredFilter(above + 1, left + 1, dst, dstStride, width); | |
86 | } | |
87 | } | |
88 | ||
89 | template<int log2Size> | |
90 | void planar_pred_c(pixel* dst, intptr_t dstStride, pixel* left, pixel* above, int /*dirMode*/, int /*bFilter*/) | |
91 | { | |
92 | above += 1; | |
93 | left += 1; | |
94 | int k, l; | |
95 | pixel bottomLeft, topRight; | |
96 | int horPred; | |
97 | int32_t leftColumn[MAX_CU_SIZE + 1], topRow[MAX_CU_SIZE + 1]; | |
98 | // CHECK_ME: dynamic range is 9 bits or 15 bits(I assume max input bit_depth is 14 bits) | |
99 | int16_t bottomRow[MAX_CU_SIZE], rightColumn[MAX_CU_SIZE]; | |
100 | const int blkSize = 1 << log2Size; | |
101 | const int offset2D = blkSize; | |
102 | const int shift1D = log2Size; | |
103 | const int shift2D = shift1D + 1; | |
104 | ||
105 | // Get left and above reference column and row | |
106 | for (k = 0; k < blkSize + 1; k++) | |
107 | { | |
108 | topRow[k] = above[k]; | |
109 | leftColumn[k] = left[k]; | |
110 | } | |
111 | ||
112 | // Prepare intermediate variables used in interpolation | |
113 | bottomLeft = (pixel)leftColumn[blkSize]; | |
114 | topRight = (pixel)topRow[blkSize]; | |
115 | for (k = 0; k < blkSize; k++) | |
116 | { | |
117 | bottomRow[k] = (int16_t)(bottomLeft - topRow[k]); | |
118 | rightColumn[k] = (int16_t)(topRight - leftColumn[k]); | |
119 | topRow[k] <<= shift1D; | |
120 | leftColumn[k] <<= shift1D; | |
121 | } | |
122 | ||
123 | // Generate prediction signal | |
124 | for (k = 0; k < blkSize; k++) | |
125 | { | |
126 | horPred = leftColumn[k] + offset2D; | |
127 | for (l = 0; l < blkSize; l++) | |
128 | { | |
129 | horPred += rightColumn[k]; | |
130 | topRow[l] += bottomRow[l]; | |
131 | dst[k * dstStride + l] = (pixel)((horPred + topRow[l]) >> shift2D); | |
132 | } | |
133 | } | |
134 | } | |
135 | ||
136 | template<int width> | |
137 | void intra_pred_ang_c(pixel* dst, intptr_t dstStride, pixel *refLeft, pixel *refAbove, int dirMode, int bFilter) | |
138 | { | |
139 | // Map the mode index to main prediction direction and angle | |
140 | int k, l; | |
141 | bool modeHor = (dirMode < 18); | |
142 | bool modeVer = !modeHor; | |
143 | int intraPredAngle = modeVer ? (int)dirMode - VER_IDX : modeHor ? -((int)dirMode - HOR_IDX) : 0; | |
144 | int absAng = abs(intraPredAngle); | |
145 | int signAng = intraPredAngle < 0 ? -1 : 1; | |
146 | ||
147 | // Set bitshifts and scale the angle parameter to block size | |
148 | static const int angTable[9] = { 0, 2, 5, 9, 13, 17, 21, 26, 32 }; | |
149 | static const int invAngTable[9] = { 0, 4096, 1638, 910, 630, 482, 390, 315, 256 }; // (256 * 32) / Angle | |
150 | int invAngle = invAngTable[absAng]; | |
151 | ||
152 | absAng = angTable[absAng]; | |
153 | intraPredAngle = signAng * absAng; | |
154 | ||
155 | // Do angular predictions | |
156 | { | |
157 | pixel* refMain; | |
158 | pixel* refSide; | |
159 | ||
160 | // Initialise the Main and Left reference array. | |
161 | if (intraPredAngle < 0) | |
162 | { | |
163 | refMain = (modeVer ? refAbove : refLeft); // + (width - 1); | |
164 | refSide = (modeVer ? refLeft : refAbove); // + (width - 1); | |
165 | ||
166 | // Extend the Main reference to the left. | |
167 | int invAngleSum = 128; // rounding for (shift by 8) | |
168 | for (k = -1; k > width * intraPredAngle >> 5; k--) | |
169 | { | |
170 | invAngleSum += invAngle; | |
171 | refMain[k] = refSide[invAngleSum >> 8]; | |
172 | } | |
173 | } | |
174 | else | |
175 | { | |
176 | refMain = modeVer ? refAbove : refLeft; | |
177 | refSide = modeVer ? refLeft : refAbove; | |
178 | } | |
179 | ||
180 | if (intraPredAngle == 0) | |
181 | { | |
182 | for (k = 0; k < width; k++) | |
183 | { | |
184 | for (l = 0; l < width; l++) | |
185 | { | |
186 | dst[k * dstStride + l] = refMain[l + 1]; | |
187 | } | |
188 | } | |
189 | ||
190 | if (bFilter) | |
191 | { | |
192 | for (k = 0; k < width; k++) | |
193 | { | |
194 | dst[k * dstStride] = (pixel)Clip3((int16_t)0, (int16_t)((1 << X265_DEPTH) - 1), static_cast<int16_t>((dst[k * dstStride]) + ((refSide[k + 1] - refSide[0]) >> 1))); | |
195 | } | |
196 | } | |
197 | } | |
198 | else | |
199 | { | |
200 | int deltaPos = 0; | |
201 | int deltaInt; | |
202 | int deltaFract; | |
203 | int refMainIndex; | |
204 | ||
205 | for (k = 0; k < width; k++) | |
206 | { | |
207 | deltaPos += intraPredAngle; | |
208 | deltaInt = deltaPos >> 5; | |
209 | deltaFract = deltaPos & (32 - 1); | |
210 | ||
211 | if (deltaFract) | |
212 | { | |
213 | // Do linear filtering | |
214 | for (l = 0; l < width; l++) | |
215 | { | |
216 | refMainIndex = l + deltaInt + 1; | |
217 | dst[k * dstStride + l] = (pixel)(((32 - deltaFract) * refMain[refMainIndex] + deltaFract * refMain[refMainIndex + 1] + 16) >> 5); | |
218 | } | |
219 | } | |
220 | else | |
221 | { | |
222 | // Just copy the integer samples | |
223 | for (l = 0; l < width; l++) | |
224 | { | |
225 | dst[k * dstStride + l] = refMain[l + deltaInt + 1]; | |
226 | } | |
227 | } | |
228 | } | |
229 | } | |
230 | ||
231 | // Flip the block if this is the horizontal mode | |
232 | if (modeHor) | |
233 | { | |
234 | for (k = 0; k < width - 1; k++) | |
235 | { | |
236 | for (l = k + 1; l < width; l++) | |
237 | { | |
238 | pixel tmp = dst[k * dstStride + l]; | |
239 | dst[k * dstStride + l] = dst[l * dstStride + k]; | |
240 | dst[l * dstStride + k] = tmp; | |
241 | } | |
242 | } | |
243 | } | |
244 | } | |
245 | } | |
246 | ||
247 | template<int log2Size> | |
248 | void all_angs_pred_c(pixel *dest, pixel *above0, pixel *left0, pixel *above1, pixel *left1, int bLuma) | |
249 | { | |
250 | const int size = 1 << log2Size; | |
251 | for (int mode = 2; mode <= 34; mode++) | |
252 | { | |
253 | pixel *left = (g_intraFilterFlags[mode] & size ? left1 : left0); | |
254 | pixel *above = (g_intraFilterFlags[mode] & size ? above1 : above0); | |
255 | pixel *out = dest + ((mode - 2) << (log2Size * 2)); | |
256 | ||
257 | intra_pred_ang_c<size>(out, size, left, above, mode, bLuma); | |
258 | ||
259 | // Optimize code don't flip buffer | |
260 | bool modeHor = (mode < 18); | |
261 | ||
262 | // transpose the block if this is a horizontal mode | |
263 | if (modeHor) | |
264 | { | |
265 | for (int k = 0; k < size - 1; k++) | |
266 | { | |
267 | for (int l = k + 1; l < size; l++) | |
268 | { | |
269 | pixel tmp = out[k * size + l]; | |
270 | out[k * size + l] = out[l * size + k]; | |
271 | out[l * size + k] = tmp; | |
272 | } | |
273 | } | |
274 | } | |
275 | } | |
276 | } | |
277 | } | |
278 | ||
279 | namespace x265 { | |
280 | // x265 private namespace | |
281 | ||
282 | void Setup_C_IPredPrimitives(EncoderPrimitives& p) | |
283 | { | |
284 | p.intra_pred[0][BLOCK_4x4] = planar_pred_c<2>; | |
285 | p.intra_pred[0][BLOCK_8x8] = planar_pred_c<3>; | |
286 | p.intra_pred[0][BLOCK_16x16] = planar_pred_c<4>; | |
287 | p.intra_pred[0][BLOCK_32x32] = planar_pred_c<5>; | |
288 | ||
289 | // Intra Prediction DC | |
290 | p.intra_pred[1][BLOCK_4x4] = intra_pred_dc_c<4>; | |
291 | p.intra_pred[1][BLOCK_8x8] = intra_pred_dc_c<8>; | |
292 | p.intra_pred[1][BLOCK_16x16] = intra_pred_dc_c<16>; | |
293 | p.intra_pred[1][BLOCK_32x32] = intra_pred_dc_c<32>; | |
294 | for (int i = 2; i < NUM_INTRA_MODE; i++) | |
295 | { | |
296 | p.intra_pred[i][BLOCK_4x4] = intra_pred_ang_c<4>; | |
297 | p.intra_pred[i][BLOCK_8x8] = intra_pred_ang_c<8>; | |
298 | p.intra_pred[i][BLOCK_16x16] = intra_pred_ang_c<16>; | |
299 | p.intra_pred[i][BLOCK_32x32] = intra_pred_ang_c<32>; | |
300 | } | |
301 | ||
302 | p.intra_pred_allangs[BLOCK_4x4] = all_angs_pred_c<2>; | |
303 | p.intra_pred_allangs[BLOCK_8x8] = all_angs_pred_c<3>; | |
304 | p.intra_pred_allangs[BLOCK_16x16] = all_angs_pred_c<4>; | |
305 | p.intra_pred_allangs[BLOCK_32x32] = all_angs_pred_c<5>; | |
306 | } | |
307 | } |