1 /*****************************************************************************
2 * Copyright (C) 2013 x265 project
4 * Authors: Min Chen <chenm003@163.com>
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.
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.
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.
20 * This program is also available under a commercial proprietary license.
21 * For more information, contact us at license @ x265.com.
22 *****************************************************************************/
25 #include "primitives.h"
30 pixel
dcPredValue(pixel
* above
, pixel
* left
, intptr_t width
)
35 for (w
= 0; w
< width
; w
++)
40 for (w
= 0; w
< width
; w
++)
45 pDcVal
= (pixel
)((sum
+ width
) / (width
+ width
));
50 void dcPredFilter(pixel
* above
, pixel
* left
, pixel
* dst
, intptr_t dststride
, int size
)
52 // boundary pixels processing
53 dst
[0] = (pixel
)((above
[0] + left
[0] + 2 * dst
[0] + 2) >> 2);
55 for (int x
= 1; x
< size
; x
++)
57 dst
[x
] = (pixel
)((above
[x
] + 3 * dst
[x
] + 2) >> 2);
61 for (int y
= 1; y
< size
; y
++)
63 *dst
= (pixel
)((left
[y
] + 3 * *dst
+ 2) >> 2);
69 void intra_pred_dc_c(pixel
* dst
, intptr_t dstStride
, pixel
* left
, pixel
* above
, int /*dirMode*/, int bFilter
)
73 pixel dcval
= dcPredValue(above
+ 1, left
+ 1, width
);
75 for (k
= 0; k
< width
; k
++)
77 for (l
= 0; l
< width
; l
++)
79 dst
[k
* dstStride
+ l
] = dcval
;
85 dcPredFilter(above
+ 1, left
+ 1, dst
, dstStride
, width
);
89 template<int log2Size
>
90 void planar_pred_c(pixel
* dst
, intptr_t dstStride
, pixel
* left
, pixel
* above
, int /*dirMode*/, int /*bFilter*/)
95 pixel bottomLeft
, topRight
;
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;
105 // Get left and above reference column and row
106 for (k
= 0; k
< blkSize
+ 1; k
++)
108 topRow
[k
] = above
[k
];
109 leftColumn
[k
] = left
[k
];
112 // Prepare intermediate variables used in interpolation
113 bottomLeft
= (pixel
)leftColumn
[blkSize
];
114 topRight
= (pixel
)topRow
[blkSize
];
115 for (k
= 0; k
< blkSize
; k
++)
117 bottomRow
[k
] = (int16_t)(bottomLeft
- topRow
[k
]);
118 rightColumn
[k
] = (int16_t)(topRight
- leftColumn
[k
]);
119 topRow
[k
] <<= shift1D
;
120 leftColumn
[k
] <<= shift1D
;
123 // Generate prediction signal
124 for (k
= 0; k
< blkSize
; k
++)
126 horPred
= leftColumn
[k
] + offset2D
;
127 for (l
= 0; l
< blkSize
; l
++)
129 horPred
+= rightColumn
[k
];
130 topRow
[l
] += bottomRow
[l
];
131 dst
[k
* dstStride
+ l
] = (pixel
)((horPred
+ topRow
[l
]) >> shift2D
);
137 void intra_pred_ang_c(pixel
* dst
, intptr_t dstStride
, pixel
*refLeft
, pixel
*refAbove
, int dirMode
, int bFilter
)
139 // Map the mode index to main prediction direction and angle
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;
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
];
152 absAng
= angTable
[absAng
];
153 intraPredAngle
= signAng
* absAng
;
155 // Do angular predictions
160 // Initialise the Main and Left reference array.
161 if (intraPredAngle
< 0)
163 refMain
= (modeVer
? refAbove
: refLeft
); // + (width - 1);
164 refSide
= (modeVer
? refLeft
: refAbove
); // + (width - 1);
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
--)
170 invAngleSum
+= invAngle
;
171 refMain
[k
] = refSide
[invAngleSum
>> 8];
176 refMain
= modeVer
? refAbove
: refLeft
;
177 refSide
= modeVer
? refLeft
: refAbove
;
180 if (intraPredAngle
== 0)
182 for (k
= 0; k
< width
; k
++)
184 for (l
= 0; l
< width
; l
++)
186 dst
[k
* dstStride
+ l
] = refMain
[l
+ 1];
192 for (k
= 0; k
< width
; k
++)
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)));
205 for (k
= 0; k
< width
; k
++)
207 deltaPos
+= intraPredAngle
;
208 deltaInt
= deltaPos
>> 5;
209 deltaFract
= deltaPos
& (32 - 1);
213 // Do linear filtering
214 for (l
= 0; l
< width
; l
++)
216 refMainIndex
= l
+ deltaInt
+ 1;
217 dst
[k
* dstStride
+ l
] = (pixel
)(((32 - deltaFract
) * refMain
[refMainIndex
] + deltaFract
* refMain
[refMainIndex
+ 1] + 16) >> 5);
222 // Just copy the integer samples
223 for (l
= 0; l
< width
; l
++)
225 dst
[k
* dstStride
+ l
] = refMain
[l
+ deltaInt
+ 1];
231 // Flip the block if this is the horizontal mode
234 for (k
= 0; k
< width
- 1; k
++)
236 for (l
= k
+ 1; l
< width
; l
++)
238 pixel tmp
= dst
[k
* dstStride
+ l
];
239 dst
[k
* dstStride
+ l
] = dst
[l
* dstStride
+ k
];
240 dst
[l
* dstStride
+ k
] = tmp
;
247 template<int log2Size
>
248 void all_angs_pred_c(pixel
*dest
, pixel
*above0
, pixel
*left0
, pixel
*above1
, pixel
*left1
, int bLuma
)
250 const int size
= 1 << log2Size
;
251 for (int mode
= 2; mode
<= 34; mode
++)
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));
257 intra_pred_ang_c
<size
>(out
, size
, left
, above
, mode
, bLuma
);
259 // Optimize code don't flip buffer
260 bool modeHor
= (mode
< 18);
262 // transpose the block if this is a horizontal mode
265 for (int k
= 0; k
< size
- 1; k
++)
267 for (int l
= k
+ 1; l
< size
; l
++)
269 pixel tmp
= out
[k
* size
+ l
];
270 out
[k
* size
+ l
] = out
[l
* size
+ k
];
271 out
[l
* size
+ k
] = tmp
;
280 // x265 private namespace
282 void Setup_C_IPredPrimitives(EncoderPrimitives
& p
)
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>;
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
++)
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>;
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>;