Imported Upstream version 1.4
[deb_x265.git] / source / common / intrapred.cpp
CommitLineData
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
27using namespace x265;
28
29namespace {
30pixel 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
50void 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
68template<int width>
69void 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
89template<int log2Size>
90void 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
136template<int width>
137void 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
247template<int log2Size>
248void 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
279namespace x265 {
280// x265 private namespace
281
282void 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}