1 /*
2 * H.265 video codec.
3 * Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de>
4 *
5 * This file is part of libde265.
6 *
7 * libde265 is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * libde265 is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with libde265. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "intrapred.h"
22 #include "transform.h"
23 #include "util.h"
24 #include <assert.h>
25
26
27 #include <sys/types.h>
28 #include <string.h>
29
30
31 #ifdef DE265_LOG_TRACE
32 template <class pixel_t>
print_border(pixel_t * data,uint8_t * available,int nT)33 void print_border(pixel_t* data, uint8_t* available, int nT)
34 {
35 for (int i=-2*nT ; i<=2*nT ; i++) {
36 if (i==0 || i==1 || i==-nT || i==nT+1) {
37 logtrace(LogIntraPred,"|");
38 } else {
39 logtrace(LogIntraPred," ");
40 }
41
42 if (available==NULL || available[i]) {
43 logtrace(LogIntraPred,"%02x",data[i]);
44 }
45 else {
46 logtrace(LogIntraPred,"--");
47 }
48 }
49 }
50 #else
51 #define print_border(data, available, nT)
52 #endif
53
54
fillIntraPredModeCandidates(int candModeList[3],int x,int y,int PUidx,bool availableA,bool availableB,const de265_image * img)55 void fillIntraPredModeCandidates(int candModeList[3], int x,int y, int PUidx,
56 bool availableA, // left
57 bool availableB, // top
58 const de265_image* img)
59 {
60 const seq_parameter_set* sps = &img->sps;
61
62 // block on left side
63
64 enum IntraPredMode candIntraPredModeA, candIntraPredModeB;
65 if (availableA==false) {
66 candIntraPredModeA=INTRA_DC;
67 }
68 else if (img->get_pred_mode(x-1,y) != MODE_INTRA ||
69 img->get_pcm_flag (x-1,y)) {
70 candIntraPredModeA=INTRA_DC;
71 }
72 else {
73 candIntraPredModeA = img->get_IntraPredMode_atIndex(PUidx-1);
74 }
75
76 // block above
77
78 if (availableB==false) {
79 candIntraPredModeB=INTRA_DC;
80 }
81 else if (img->get_pred_mode(x,y-1) != MODE_INTRA ||
82 img->get_pcm_flag (x,y-1)) {
83 candIntraPredModeB=INTRA_DC;
84 }
85 else if (y-1 < ((y >> sps->Log2CtbSizeY) << sps->Log2CtbSizeY)) {
86 candIntraPredModeB=INTRA_DC;
87 }
88 else {
89 candIntraPredModeB = img->get_IntraPredMode_atIndex(PUidx-sps->PicWidthInMinPUs);
90 }
91
92
93 // build candidate list
94
95 logtrace(LogSlice,"%d;%d availableA:%d candA:%d & availableB:%d candB:%d\n", x,y,
96 availableA, candIntraPredModeA,
97 availableB, candIntraPredModeB);
98
99 if (candIntraPredModeA == candIntraPredModeB) {
100 if (candIntraPredModeA < 2) {
101 candModeList[0] = INTRA_PLANAR;
102 candModeList[1] = INTRA_DC;
103 candModeList[2] = INTRA_ANGULAR_26;
104 }
105 else {
106 candModeList[0] = candIntraPredModeA;
107 candModeList[1] = 2 + ((candIntraPredModeA-2 -1 +32) % 32);
108 candModeList[2] = 2 + ((candIntraPredModeA-2 +1 ) % 32);
109 }
110 }
111 else {
112 candModeList[0] = candIntraPredModeA;
113 candModeList[1] = candIntraPredModeB;
114
115 if (candIntraPredModeA != INTRA_PLANAR &&
116 candIntraPredModeB != INTRA_PLANAR) {
117 candModeList[2] = INTRA_PLANAR;
118 }
119 else if (candIntraPredModeA != INTRA_DC &&
120 candIntraPredModeB != INTRA_DC) {
121 candModeList[2] = INTRA_DC;
122 }
123 else {
124 candModeList[2] = INTRA_ANGULAR_26;
125 }
126 }
127
128 /*
129 printf("candModeList: %d %d %d\n",
130 candModeList[0],
131 candModeList[1],
132 candModeList[2]
133 );
134 */
135 }
136
137
find_intra_pred_mode(enum IntraPredMode mode,int candModeList[3])138 int find_intra_pred_mode(enum IntraPredMode mode,
139 int candModeList[3])
140 {
141 // check whether the mode is in the candidate list
142
143 for (int i=0;i<3;i++) {
144 if (candModeList[i] == mode) {
145 return i;
146 }
147 }
148
149 // sort candModeList
150
151 if (candModeList[0] > candModeList[1]) {
152 std::swap(candModeList[0],candModeList[1]);
153 }
154 if (candModeList[0] > candModeList[2]) {
155 std::swap(candModeList[0],candModeList[2]);
156 }
157 if (candModeList[1] > candModeList[2]) {
158 std::swap(candModeList[1],candModeList[2]);
159 }
160
161 // skip modes already in the candidate list
162
163 int intraMode = mode;
164
165 for (int i=2;i>=0;i--) {
166 if (intraMode >= candModeList[i]) { intraMode--; }
167 }
168
169 return -intraMode-1;
170 }
171
172
list_chroma_pred_candidates(enum IntraPredMode chroma_mode[5],enum IntraPredMode luma_mode)173 void list_chroma_pred_candidates(enum IntraPredMode chroma_mode[5],
174 enum IntraPredMode luma_mode)
175 {
176 enum IntraPredMode chroma_cand[5];
177 chroma_cand[0] = INTRA_PLANAR;
178 chroma_cand[1] = INTRA_ANGULAR_26;
179 chroma_cand[2] = INTRA_ANGULAR_10;
180 chroma_cand[3] = INTRA_DC;
181 chroma_cand[4] = luma_mode;
182
183 switch (luma_mode) {
184 case INTRA_PLANAR: chroma_cand[0] = INTRA_ANGULAR_34; break;
185 case INTRA_ANGULAR_26: chroma_cand[1] = INTRA_ANGULAR_34; break;
186 case INTRA_ANGULAR_10: chroma_cand[2] = INTRA_ANGULAR_34; break;
187 case INTRA_DC: chroma_cand[3] = INTRA_ANGULAR_34; break;
188 default:
189 // use defaults from above
190 break;
191 }
192 }
193
194
get_intra_scan_idx(int log2TrafoSize,enum IntraPredMode intraPredMode,int cIdx,const seq_parameter_set * sps)195 int get_intra_scan_idx(int log2TrafoSize, enum IntraPredMode intraPredMode, int cIdx,
196 const seq_parameter_set* sps)
197 {
198 if (log2TrafoSize==2 ||
199 (log2TrafoSize==3 && (cIdx==0 ||
200 sps->ChromaArrayType==CHROMA_444))) {
201 /**/ if (intraPredMode >= 6 && intraPredMode <= 14) return 2;
202 else if (intraPredMode >= 22 && intraPredMode <= 30) return 1;
203 else return 0;
204 }
205 else { return 0; }
206 }
207
208
get_intra_scan_idx_luma(int log2TrafoSize,enum IntraPredMode intraPredMode)209 int get_intra_scan_idx_luma(int log2TrafoSize, enum IntraPredMode intraPredMode)
210 {
211 if (log2TrafoSize==2 || log2TrafoSize==3) {
212 /**/ if (intraPredMode >= 6 && intraPredMode <= 14) return 2;
213 else if (intraPredMode >= 22 && intraPredMode <= 30) return 1;
214 else return 0;
215 }
216 else { return 0; }
217 }
218
get_intra_scan_idx_chroma(int log2TrafoSize,enum IntraPredMode intraPredMode)219 int get_intra_scan_idx_chroma(int log2TrafoSize, enum IntraPredMode intraPredMode)
220 {
221 if (log2TrafoSize==1 || log2TrafoSize==2) {
222 /**/ if (intraPredMode >= 6 && intraPredMode <= 14) return 2;
223 else if (intraPredMode >= 22 && intraPredMode <= 30) return 1;
224 else return 0;
225 }
226 else { return 0; }
227 }
228
229
lumaPredMode_to_chromaPredMode(enum IntraPredMode luma,enum IntraChromaPredMode chroma)230 enum IntraPredMode lumaPredMode_to_chromaPredMode(enum IntraPredMode luma,
231 enum IntraChromaPredMode chroma)
232 {
233 switch (chroma) {
234 case INTRA_CHROMA_LIKE_LUMA:
235 return luma;
236
237 case INTRA_CHROMA_PLANAR_OR_34:
238 if (luma==INTRA_PLANAR) return INTRA_ANGULAR_34;
239 else return INTRA_PLANAR;
240
241 case INTRA_CHROMA_ANGULAR_26_OR_34:
242 if (luma==INTRA_ANGULAR_26) return INTRA_ANGULAR_34;
243 else return INTRA_ANGULAR_26;
244
245 case INTRA_CHROMA_ANGULAR_10_OR_34:
246 if (luma==INTRA_ANGULAR_10) return INTRA_ANGULAR_34;
247 else return INTRA_ANGULAR_10;
248
249 case INTRA_CHROMA_DC_OR_34:
250 if (luma==INTRA_DC) return INTRA_ANGULAR_34;
251 else return INTRA_DC;
252 }
253
254
255 assert(false);
256 return INTRA_DC;
257 }
258
259
260 // (8.4.4.2.2)
261 template <class pixel_t>
fill_border_samples(de265_image * img,int xB,int yB,int nT,int cIdx,pixel_t * out_border)262 void fill_border_samples(de265_image* img,
263 int xB,int yB, // in component specific resolution
264 int nT, int cIdx,
265 pixel_t* out_border)
266 {
267 const seq_parameter_set* sps = &img->sps;
268 const pic_parameter_set* pps = &img->pps;
269
270 uint8_t available_data[2*64 + 1];
271 uint8_t* available = &available_data[64];
272
273 pixel_t* image;
274 int stride;
275 image = (pixel_t*)img->get_image_plane(cIdx);
276 stride = img->get_image_stride(cIdx);
277
278 const int SubWidth = (cIdx==0) ? 1 : sps->SubWidthC;
279 const int SubHeight = (cIdx==0) ? 1 : sps->SubHeightC;
280
281 const int bit_depth = img->get_bit_depth(cIdx);
282
283 // --- check for CTB boundaries ---
284
285 int xBLuma = xB * SubWidth;
286 int yBLuma = yB * SubHeight;
287
288 int log2CtbSize = sps->Log2CtbSizeY;
289 int picWidthInCtbs = sps->PicWidthInCtbsY;
290
291 bool availableLeft=true; // is CTB at left side available?
292 bool availableTop=true; // is CTB at top side available?
293 bool availableTopRight=true; // is CTB at top-right side available?
294 bool availableTopLeft=true; // if CTB at top-left pixel available?
295
296
297 //printf("xB/yB: %d %d\n",xB,yB);
298
299 // are we at left image border
300
301 if (xBLuma == 0) {
302 availableLeft = false;
303 availableTopLeft = false;
304 xBLuma = 0; // fake value, available flags are already set to false
305 }
306
307
308 // are we at top image border
309
310 if (yBLuma == 0) {
311 availableTop = false;
312 availableTopLeft = false;
313 availableTopRight = false;
314 yBLuma = 0; // fake value, available flags are already set to false
315 }
316
317 if (xBLuma+nT*SubWidth >= sps->pic_width_in_luma_samples) {
318 availableTopRight=false;
319 }
320
321 // check for tile and slice boundaries
322
323 int xCurrCtb = xBLuma >> log2CtbSize;
324 int yCurrCtb = yBLuma >> log2CtbSize;
325 int xLeftCtb = (xBLuma-1) >> log2CtbSize;
326 int xRightCtb = (xBLuma+nT*SubWidth) >> log2CtbSize;
327 int yTopCtb = (yBLuma-1) >> log2CtbSize;
328
329 int currCTBSlice = img->get_SliceAddrRS(xCurrCtb,yCurrCtb);
330 int leftCTBSlice = availableLeft ? img->get_SliceAddrRS(xLeftCtb, yCurrCtb) : -1;
331 int topCTBSlice = availableTop ? img->get_SliceAddrRS(xCurrCtb, yTopCtb) : -1;
332 int toprightCTBSlice = availableTopRight ? img->get_SliceAddrRS(xRightCtb, yTopCtb) : -1;
333 int topleftCTBSlice = availableTopLeft ? img->get_SliceAddrRS(xLeftCtb, yTopCtb) : -1;
334
335 /*
336 printf("size: %d\n",pps->TileIdRS.size());
337 printf("curr: %d left: %d top: %d\n",
338 xCurrCtb+yCurrCtb*picWidthInCtbs,
339 availableLeft ? xLeftCtb+yCurrCtb*picWidthInCtbs : 9999,
340 availableTop ? xCurrCtb+yTopCtb*picWidthInCtbs : 9999);
341 */
342 int currCTBTileID = pps->TileIdRS[xCurrCtb+yCurrCtb*picWidthInCtbs];
343 int leftCTBTileID = availableLeft ? pps->TileIdRS[xLeftCtb+yCurrCtb*picWidthInCtbs] : -1;
344 int topCTBTileID = availableTop ? pps->TileIdRS[xCurrCtb+yTopCtb*picWidthInCtbs] : -1;
345 int topleftCTBTileID = availableTopLeft ? pps->TileIdRS[xLeftCtb+yTopCtb*picWidthInCtbs] : -1;
346 int toprightCTBTileID= availableTopRight? pps->TileIdRS[xRightCtb+yTopCtb*picWidthInCtbs] : -1;
347
348 if (leftCTBSlice != currCTBSlice || leftCTBTileID != currCTBTileID ) availableLeft = false;
349 if (topCTBSlice != currCTBSlice || topCTBTileID != currCTBTileID ) availableTop = false;
350 if (topleftCTBSlice !=currCTBSlice||topleftCTBTileID!=currCTBTileID ) availableTopLeft = false;
351 if (toprightCTBSlice!=currCTBSlice||toprightCTBTileID!=currCTBTileID) availableTopRight= false;
352
353 int currBlockAddr = pps->MinTbAddrZS[ (xBLuma>>sps->Log2MinTrafoSize) +
354 (yBLuma>>sps->Log2MinTrafoSize) * sps->PicWidthInTbsY ];
355
356
357 // number of pixels that are in the valid image area to the right and to the bottom
358
359 int nBottom = sps->pic_height_in_luma_samples - yB*SubHeight;
360 nBottom=(nBottom+SubHeight-1)/SubHeight;
361 if (nBottom>2*nT) nBottom=2*nT;
362
363 int nRight = sps->pic_width_in_luma_samples - xB*SubWidth;
364 nRight =(nRight +SubWidth-1)/SubWidth;
365 if (nRight >2*nT) nRight=2*nT;
366
367 int nAvail=0;
368
369 pixel_t firstValue;
370
371 memset(available-2*nT, 0, 4*nT+1);
372
373 {
374 // copy pixels at left column
375
376 for (int y=nBottom-1 ; y>=0 ; y-=4)
377 if (availableLeft)
378 {
379 int NBlockAddr = pps->MinTbAddrZS[ (((xB-1)*SubWidth )>>sps->Log2MinTrafoSize) +
380 (((yB+y)*SubHeight)>>sps->Log2MinTrafoSize)
381 * sps->PicWidthInTbsY ];
382
383 bool availableN = NBlockAddr <= currBlockAddr;
384
385 if (pps->constrained_intra_pred_flag) {
386 if (img->get_pred_mode((xB-1)*SubWidth,(yB+y)*SubHeight)!=MODE_INTRA)
387 availableN = false;
388 }
389
390 if (availableN) {
391 if (!nAvail) firstValue = image[xB-1 + (yB+y)*stride];
392
393 for (int i=0;i<4;i++) {
394 available[-y+i-1] = availableN;
395 out_border[-y+i-1] = image[xB-1 + (yB+y-i)*stride];
396 }
397
398 nAvail+=4;
399 }
400 }
401
402 // copy pixel at top-left position
403
404 if (availableTopLeft)
405 {
406 int NBlockAddr = pps->MinTbAddrZS[ (((xB-1)*SubWidth )>>sps->Log2MinTrafoSize) +
407 (((yB-1)*SubHeight)>>sps->Log2MinTrafoSize)
408 * sps->PicWidthInTbsY ];
409
410 bool availableN = NBlockAddr <= currBlockAddr;
411
412 if (pps->constrained_intra_pred_flag) {
413 if (img->get_pred_mode((xB-1)*SubWidth,(yB-1)*SubHeight)!=MODE_INTRA) {
414 availableN = false;
415 }
416 }
417
418 if (availableN) {
419 if (!nAvail) firstValue = image[xB-1 + (yB-1)*stride];
420
421 out_border[0] = image[xB-1 + (yB-1)*stride];
422 available[0] = availableN;
423 nAvail++;
424 }
425 }
426
427 // copy pixels at top row
428
429 for (int x=0 ; x<nRight ; x+=4) {
430 bool borderAvailable;
431 if (x<nT) borderAvailable=availableTop;
432 else borderAvailable=availableTopRight;
433
434 if (borderAvailable)
435 {
436 int NBlockAddr = pps->MinTbAddrZS[ (((xB+x)*SubWidth )>>sps->Log2MinTrafoSize) +
437 (((yB-1)*SubHeight)>>sps->Log2MinTrafoSize)
438 * sps->PicWidthInTbsY ];
439
440 bool availableN = NBlockAddr <= currBlockAddr;
441
442 if (pps->constrained_intra_pred_flag) {
443 if (img->get_pred_mode((xB+x)*SubWidth,(yB-1)*SubHeight)!=MODE_INTRA) {
444 availableN = false;
445 }
446 }
447
448
449 if (availableN) {
450 if (!nAvail) firstValue = image[xB+x + (yB-1)*stride];
451
452 for (int i=0;i<4;i++) {
453 out_border[x+i+1] = image[xB+x+i + (yB-1)*stride];
454 available[x+i+1] = availableN;
455 }
456
457 nAvail+=4;
458 }
459 }
460 }
461
462
463 // reference sample substitution
464
465 if (nAvail!=4*nT+1) {
466 if (nAvail==0) {
467 if (sizeof(pixel_t)==1) {
468 memset(out_border-2*nT, 1<<(bit_depth-1), 4*nT+1);
469 }
470 else {
471 for (int i = -2*nT; i <= 2*nT ; i++) {
472 out_border[i] = 1<<(bit_depth-1);
473 }
474 }
475 }
476 else {
477 if (!available[-2*nT]) {
478 out_border[-2*nT] = firstValue;
479 }
480
481 for (int i=-2*nT+1; i<=2*nT; i++)
482 if (!available[i]) {
483 out_border[i]=out_border[i-1];
484 }
485 }
486 }
487
488 logtrace(LogIntraPred,"availableN: ");
489 print_border(available,NULL,nT);
490 logtrace(LogIntraPred,"\n");
491
492 logtrace(LogIntraPred,"output: ");
493 print_border(out_border,NULL,nT);
494 logtrace(LogIntraPred,"\n");
495 }
496 }
497
498
499 // (8.4.4.2.3)
500 template <class pixel_t>
intra_prediction_sample_filtering(de265_image * img,pixel_t * p,int nT,int cIdx,enum IntraPredMode intraPredMode)501 void intra_prediction_sample_filtering(de265_image* img,
502 pixel_t* p,
503 int nT, int cIdx,
504 enum IntraPredMode intraPredMode)
505 {
506 int filterFlag;
507
508 if (intraPredMode==INTRA_DC || nT==4) {
509 filterFlag = 0;
510 } else {
511 // int-cast below prevents a typing problem that leads to wrong results when abs_value is a macro
512 int minDistVerHor = libde265_min( abs_value((int)intraPredMode-26),
513 abs_value((int)intraPredMode-10) );
514 switch (nT) {
515 case 8: filterFlag = (minDistVerHor>7) ? 1 : 0; break;
516 case 16: filterFlag = (minDistVerHor>1) ? 1 : 0; break;
517 case 32: filterFlag = (minDistVerHor>0) ? 1 : 0; break;
518 default: filterFlag = -1; assert(false); break; // should never happen
519 }
520 }
521
522
523 if (filterFlag) {
524 int biIntFlag = (img->sps.strong_intra_smoothing_enable_flag &&
525 cIdx==0 &&
526 nT==32 &&
527 abs_value(p[0]+p[ 64]-2*p[ 32]) < (1<<(img->sps.bit_depth_luma-5)) &&
528 abs_value(p[0]+p[-64]-2*p[-32]) < (1<<(img->sps.bit_depth_luma-5)))
529 ? 1 : 0;
530
531 pixel_t pF_mem[2*64+1];
532 pixel_t* pF = &pF_mem[64];
533
534 if (biIntFlag) {
535 pF[-2*nT] = p[-2*nT];
536 pF[ 2*nT] = p[ 2*nT];
537 pF[ 0] = p[ 0];
538
539 for (int i=1;i<=63;i++) {
540 pF[-i] = p[0] + ((i*(p[-64]-p[0])+32)>>6);
541 pF[ i] = p[0] + ((i*(p[ 64]-p[0])+32)>>6);
542 }
543 } else {
544 pF[-2*nT] = p[-2*nT];
545 pF[ 2*nT] = p[ 2*nT];
546
547 for (int i=-(2*nT-1) ; i<=2*nT-1 ; i++)
548 {
549 pF[i] = (p[i+1] + 2*p[i] + p[i-1] + 2) >> 2;
550 }
551 }
552
553
554 // copy back to original array
555
556 memcpy(p-2*nT, pF-2*nT, (4*nT+1) * sizeof(pixel_t));
557 }
558 else {
559 // do nothing ?
560 }
561
562
563 logtrace(LogIntraPred,"post filtering: ");
564 print_border(p,NULL,nT);
565 logtrace(LogIntraPred,"\n");
566 }
567
568
569 const int intraPredAngle_table[1+34] =
570 { 0, 0,32,26,21,17,13, 9, 5, 2, 0,-2,-5,-9,-13,-17,-21,-26,
571 -32,-26,-21,-17,-13,-9,-5,-2,0,2,5,9,13,17,21,26,32 };
572
573 static const int invAngle_table[25-10] =
574 { -4096,-1638,-910,-630,-482,-390,-315,-256,
575 -315,-390,-482,-630,-910,-1638,-4096 };
576
577
578 // (8.4.4.2.6)
579 template <class pixel_t>
intra_prediction_angular(de265_image * img,int xB0,int yB0,enum IntraPredMode intraPredMode,int nT,int cIdx,pixel_t * border)580 void intra_prediction_angular(de265_image* img,
581 int xB0,int yB0,
582 enum IntraPredMode intraPredMode,
583 int nT,int cIdx,
584 pixel_t* border)
585 {
586 pixel_t ref_mem[2*64+1];
587 pixel_t* ref=&ref_mem[64];
588
589 pixel_t* pred;
590 int stride;
591 pred = img->get_image_plane_at_pos_NEW<pixel_t>(cIdx,xB0,yB0);
592 stride = img->get_image_stride(cIdx);
593
594 int bit_depth = img->get_bit_depth(cIdx);
595
596 assert(intraPredMode<35);
597 assert(intraPredMode>=2);
598
599 int intraPredAngle = intraPredAngle_table[intraPredMode];
600
601 bool disableIntraBoundaryFilter =
602 (img->sps.range_extension.implicit_rdpcm_enabled_flag &&
603 img->get_cu_transquant_bypass(xB0,yB0));
604
605 if (intraPredMode >= 18) {
606
607 for (int x=0;x<=nT;x++)
608 { ref[x] = border[x]; }
609
610 if (intraPredAngle<0) {
611 int invAngle = invAngle_table[intraPredMode-11];
612
613 if ((nT*intraPredAngle)>>5 < -1) {
614 for (int x=(nT*intraPredAngle)>>5; x<=-1; x++) {
615 ref[x] = border[0-((x*invAngle+128)>>8)];
616 }
617 }
618 } else {
619 for (int x=nT+1; x<=2*nT;x++) {
620 ref[x] = border[x];
621 }
622 }
623
624 for (int y=0;y<nT;y++)
625 for (int x=0;x<nT;x++)
626 {
627 int iIdx = ((y+1)*intraPredAngle)>>5;
628 int iFact= ((y+1)*intraPredAngle)&31;
629
630 if (iFact != 0) {
631 pred[x+y*stride] = ((32-iFact)*ref[x+iIdx+1] + iFact*ref[x+iIdx+2] + 16)>>5;
632 } else {
633 pred[x+y*stride] = ref[x+iIdx+1];
634 }
635 }
636
637 if (intraPredMode==26 && cIdx==0 && nT<32 && !disableIntraBoundaryFilter) {
638 for (int y=0;y<nT;y++) {
639 pred[0+y*stride] = Clip_BitDepth(border[1] + ((border[-1-y] - border[0])>>1), bit_depth);
640 }
641 }
642 }
643 else { // intraPredAngle < 18
644
645 for (int x=0;x<=nT;x++)
646 { ref[x] = border[-x]; } // DIFF (neg)
647
648 if (intraPredAngle<0) {
649 int invAngle = invAngle_table[intraPredMode-11];
650
651 if ((nT*intraPredAngle)>>5 < -1) {
652 for (int x=(nT*intraPredAngle)>>5; x<=-1; x++) {
653 ref[x] = border[((x*invAngle+128)>>8)]; // DIFF (neg)
654 }
655 }
656 } else {
657 for (int x=nT+1; x<=2*nT;x++) {
658 ref[x] = border[-x]; // DIFF (neg)
659 }
660 }
661
662 for (int y=0;y<nT;y++)
663 for (int x=0;x<nT;x++)
664 {
665 int iIdx = ((x+1)*intraPredAngle)>>5; // DIFF (x<->y)
666 int iFact= ((x+1)*intraPredAngle)&31; // DIFF (x<->y)
667
668 if (iFact != 0) {
669 pred[x+y*stride] = ((32-iFact)*ref[y+iIdx+1] + iFact*ref[y+iIdx+2] + 16)>>5; // DIFF (x<->y)
670 } else {
671 pred[x+y*stride] = ref[y+iIdx+1]; // DIFF (x<->y)
672 }
673 }
674
675 if (intraPredMode==10 && cIdx==0 && nT<32 && !disableIntraBoundaryFilter) { // DIFF 26->10
676 for (int x=0;x<nT;x++) { // DIFF (x<->y)
677 pred[x] = Clip_BitDepth(border[-1] + ((border[1+x] - border[0])>>1), bit_depth); // DIFF (x<->y && neg)
678 }
679 }
680 }
681
682
683 logtrace(LogIntraPred,"result of angular intra prediction (mode=%d):\n",intraPredMode);
684
685 for (int y=0;y<nT;y++)
686 {
687 for (int x=0;x<nT;x++)
688 logtrace(LogIntraPred,"%02x ", pred[x+y*stride]);
689
690 logtrace(LogIntraPred,"\n");
691 }
692 }
693
694
695 template <class pixel_t>
intra_prediction_planar(de265_image * img,int xB0,int yB0,int nT,int cIdx,pixel_t * border)696 void intra_prediction_planar(de265_image* img,int xB0,int yB0,int nT,int cIdx,
697 pixel_t* border)
698 {
699 pixel_t* pred;
700 int stride;
701 pred = img->get_image_plane_at_pos_NEW<pixel_t>(cIdx,xB0,yB0);
702 stride = img->get_image_stride(cIdx);
703
704 int Log2_nT = Log2(nT);
705
706 for (int y=0;y<nT;y++)
707 for (int x=0;x<nT;x++)
708 {
709 pred[x+y*stride] = ((nT-1-x)*border[-1-y] + (x+1)*border[ 1+nT] +
710 (nT-1-y)*border[ 1+x] + (y+1)*border[-1-nT] + nT) >> (Log2_nT+1);
711 }
712
713
714 logtrace(LogIntraPred,"result of planar prediction\n");
715
716 for (int y=0;y<nT;y++)
717 {
718 for (int x=0;x<nT;x++)
719 logtrace(LogIntraPred,"%02x ", pred[x+y*stride]);
720
721 logtrace(LogIntraPred,"\n");
722 }
723 }
724
725
726 template <class pixel_t>
intra_prediction_DC(de265_image * img,int xB0,int yB0,int nT,int cIdx,pixel_t * border)727 void intra_prediction_DC(de265_image* img,int xB0,int yB0,int nT,int cIdx,
728 pixel_t* border)
729 {
730 pixel_t* pred;
731 int stride;
732 pred = img->get_image_plane_at_pos_NEW<pixel_t>(cIdx,xB0,yB0);
733 stride = img->get_image_stride(cIdx);
734
735 int Log2_nT = Log2(nT);
736
737 int dcVal = 0;
738 for (int i=0;i<nT;i++)
739 {
740 dcVal += border[ i+1];
741 dcVal += border[-i-1];
742 }
743
744 dcVal += nT;
745 dcVal >>= Log2_nT+1;
746
747 if (cIdx==0 && nT<32) {
748 pred[0] = (border[-1] + 2*dcVal + border[1] +2) >> 2;
749
750 for (int x=1;x<nT;x++) { pred[x] = (border[ x+1] + 3*dcVal+2)>>2; }
751 for (int y=1;y<nT;y++) { pred[y*stride] = (border[-y-1] + 3*dcVal+2)>>2; }
752 for (int y=1;y<nT;y++)
753 for (int x=1;x<nT;x++)
754 {
755 pred[x+y*stride] = dcVal;
756 }
757 } else {
758 for (int y=0;y<nT;y++)
759 for (int x=0;x<nT;x++)
760 {
761 pred[x+y*stride] = dcVal;
762 }
763 }
764
765
766 logtrace(LogIntraPred,"INTRAPRED DC\n");
767 for (int y=0;y<nT;y++)
768 {
769 for (int x=0;x<nT;x++)
770 logtrace(LogIntraPred,"%02x ", pred[x+y*stride]);
771
772 logtrace(LogIntraPred,"\n");
773 }
774 }
775
776
777
778 template <class pixel_t>
decode_intra_prediction_internal(de265_image * img,int xB0,int yB0,enum IntraPredMode intraPredMode,int nT,int cIdx)779 void decode_intra_prediction_internal(de265_image* img,
780 int xB0,int yB0,
781 enum IntraPredMode intraPredMode,
782 int nT, int cIdx)
783 {
784 pixel_t border_pixels_mem[2*64+1];
785 pixel_t* border_pixels = &border_pixels_mem[64];
786
787 fill_border_samples(img, xB0,yB0, nT, cIdx, border_pixels);
788
789 if (img->sps.range_extension.intra_smoothing_disabled_flag == 0 &&
790 (cIdx==0 || img->sps.ChromaArrayType==CHROMA_444))
791 {
792 intra_prediction_sample_filtering(img, border_pixels, nT, cIdx, intraPredMode);
793 }
794
795
796 switch (intraPredMode) {
797 case INTRA_PLANAR:
798 intra_prediction_planar(img,xB0,yB0,nT,cIdx, border_pixels);
799 break;
800 case INTRA_DC:
801 intra_prediction_DC(img,xB0,yB0,nT,cIdx, border_pixels);
802 break;
803 default:
804 intra_prediction_angular(img,xB0,yB0,intraPredMode,nT,cIdx, border_pixels);
805 break;
806 }
807 }
808
809
810 // (8.4.4.2.1)
decode_intra_prediction(de265_image * img,int xB0,int yB0,enum IntraPredMode intraPredMode,int nT,int cIdx)811 void decode_intra_prediction(de265_image* img,
812 int xB0,int yB0,
813 enum IntraPredMode intraPredMode,
814 int nT, int cIdx)
815 {
816 logtrace(LogIntraPred,"decode_intra_prediction xy0:%d/%d mode=%d nT=%d, cIdx=%d\n",
817 xB0,yB0, intraPredMode, nT,cIdx);
818 /*
819 printf("decode_intra_prediction xy0:%d/%d mode=%d nT=%d, cIdx=%d\n",
820 xB0,yB0, intraPredMode, nT,cIdx);
821 */
822
823 if (img->high_bit_depth(cIdx)) {
824 decode_intra_prediction_internal<uint16_t>(img,xB0,yB0, intraPredMode,nT,cIdx);
825 }
826 else {
827 decode_intra_prediction_internal<uint8_t>(img,xB0,yB0, intraPredMode,nT,cIdx);
828 }
829 }
830