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