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 #ifndef DE265_INTRAPRED_H
22 #define DE265_INTRAPRED_H
23
24 #include "libde265/decctx.h"
25
26 extern const int intraPredAngle_table[1+34];
27
28
29 /* Fill the three intra-pred-mode candidates into candModeList.
30 Block position is (x,y) and you also have to give the PUidx for this
31 block (which is (x>>Log2MinPUSize) + (y>>Log2MinPUSize)*PicWidthInMinPUs).
32 availableA/B is the output of check_CTB_available().
33 */
34 void fillIntraPredModeCandidates(enum IntraPredMode candModeList[3],
35 int x,int y, int PUidx,
36 bool availableA, // left
37 bool availableB, // top
38 const de265_image* img);
39
40
fillIntraPredModeCandidates(enum IntraPredMode candModeList[3],int x,int y,bool availableA,bool availableB,const de265_image * img)41 inline void fillIntraPredModeCandidates(enum IntraPredMode candModeList[3], int x,int y,
42 bool availableA, // left
43 bool availableB, // top
44 const de265_image* img)
45 {
46 int PUidx = img->get_sps().getPUIndexRS(x,y);
47 fillIntraPredModeCandidates(candModeList, x,y, PUidx, availableA,availableB, img);
48 }
49
50 void fillIntraPredModeCandidates(enum IntraPredMode candModeList[3],
51 enum IntraPredMode candIntraPredModeA,
52 enum IntraPredMode candIntraPredModeB);
53
54
55 /* Return value >= 0 -> use mpm_idx(return value)
56 else -> use rem_intra(-return value-1)
57
58 This function may modify the candModeList !
59 */
60 int find_intra_pred_mode(enum IntraPredMode mode,
61 enum IntraPredMode candModeList[3]);
62
63 void list_chroma_pred_candidates(enum IntraPredMode chroma_mode[5],
64 enum IntraPredMode luma_mode);
65
66 int get_intra_scan_idx(int log2TrafoSize, enum IntraPredMode intraPredMode, int cIdx,
67 const seq_parameter_set* sps);
68
69 int get_intra_scan_idx_luma (int log2TrafoSize, enum IntraPredMode intraPredMode); // DEPRECATED
70 int get_intra_scan_idx_chroma(int log2TrafoSize, enum IntraPredMode intraPredMode); // DEPRECATED
71
72 enum IntraPredMode lumaPredMode_to_chromaPredMode(enum IntraPredMode luma,
73 enum IntraChromaPredMode chroma);
74
75 /*
76 void decode_intra_block(decoder_context* ctx,
77 thread_context* tctx,
78 int cIdx,
79 int xB0,int yB0, // position of TU in frame (chroma adapted)
80 int x0,int y0, // position of CU in frame (chroma adapted)
81 int log2TrafoSize, int trafoDepth,
82 enum IntraPredMode intraPredMode,
83 bool transform_skip_flag);
84 */
85
86 //void fill_border_samples(decoder_context* ctx, int xB,int yB,
87 // int nT, int cIdx, uint8_t* out_border);
88
89 void decode_intra_prediction(de265_image* img,
90 int xB0,int yB0,
91 enum IntraPredMode intraPredMode,
92 int nT, int cIdx);
93
94 // TODO: remove this
95 template <class pixel_t> void decode_intra_prediction(de265_image* img,
96 int xB0,int yB0,
97 enum IntraPredMode intraPredMode,
98 pixel_t* dst, int nT, int cIdx);
99
100
101
102
103 // --- internal use only ---
104
105 // Actually, the largest TB block can only be 32, but in some intra-pred-mode algorithms
106 // (e.g. min-residual), we may call intra prediction on the maximum CTB size (64).
107 static const int MAX_INTRA_PRED_BLOCK_SIZE = 64;
108
109
110 template <class pixel_t>
111 class intra_border_computer
112 {
113 public:
114 pixel_t* out_border;
115
116 const de265_image* img;
117 int nT;
118 int cIdx;
119
120 int xB,yB;
121
122 const seq_parameter_set* sps;
123 const pic_parameter_set* pps;
124
125 uint8_t available_data[4*MAX_INTRA_PRED_BLOCK_SIZE + 1];
126 uint8_t* available;
127
128 int SubWidth;
129 int SubHeight;
130
131 bool availableLeft; // is CTB at left side available?
132 bool availableTop; // is CTB at top side available?
133 bool availableTopRight; // is CTB at top-right side available?
134 bool availableTopLeft; // if CTB at top-left pixel available?
135
136 int nBottom;
137 int nRight;
138 int nAvail;
139 pixel_t firstValue;
140
init(pixel_t * _out_border,const de265_image * _img,int _nT,int _cIdx,int _xB,int _yB)141 void init(pixel_t* _out_border,
142 const de265_image* _img, int _nT, int _cIdx, int _xB, int _yB) {
143 img=_img; nT=_nT; cIdx=_cIdx;
144 out_border=_out_border; xB=_xB; yB=_yB;
145
146 assert(nT <= MAX_INTRA_PRED_BLOCK_SIZE);
147
148 availableLeft=true;
149 availableTop=true;
150 availableTopRight=true;
151 availableTopLeft=true;
152 }
153 void preproc();
154 void fill_from_image();
155
156 void reference_sample_substitution();
157 };
158
159
160 #ifdef DE265_LOG_TRACE
161 template <class pixel_t>
print_border(pixel_t * data,uint8_t * available,int nT)162 void print_border(pixel_t* data, uint8_t* available, int nT)
163 {
164 for (int i=-2*nT ; i<=2*nT ; i++) {
165 if (i==0 || i==1 || i==-nT || i==nT+1) {
166 logtrace(LogIntraPred,"|");
167 } else {
168 logtrace(LogIntraPred," ");
169 }
170
171 if (available==NULL || available[i]) {
172 logtrace(LogIntraPred,"%02x",data[i]);
173 }
174 else {
175 logtrace(LogIntraPred,"--");
176 }
177 }
178 }
179 #else
180 #define print_border(data, available, nT)
181 #endif
182
183
184 // (8.4.4.2.3)
185 template <class pixel_t>
intra_prediction_sample_filtering(const seq_parameter_set & sps,pixel_t * p,int nT,int cIdx,enum IntraPredMode intraPredMode)186 void intra_prediction_sample_filtering(const seq_parameter_set& sps,
187 pixel_t* p,
188 int nT, int cIdx,
189 enum IntraPredMode intraPredMode)
190 {
191 int filterFlag;
192
193 //printf("filtering, mode: %d\n",intraPredMode);
194
195 if (intraPredMode==INTRA_DC || nT==4) {
196 filterFlag = 0;
197 } else {
198 // int-cast below prevents a typing problem that leads to wrong results when abs_value is a macro
199 int minDistVerHor = libde265_min( abs_value((int)intraPredMode-26),
200 abs_value((int)intraPredMode-10) );
201
202 //printf("mindist: %d\n",minDistVerHor);
203
204 switch (nT) {
205 case 8: filterFlag = (minDistVerHor>7) ? 1 : 0; break;
206 case 16: filterFlag = (minDistVerHor>1) ? 1 : 0; break;
207 case 32: filterFlag = (minDistVerHor>0) ? 1 : 0; break;
208 // there is no official 64x64 TB block, but we call this for some intra-pred mode algorithms
209 // on the whole CB (2Nx2N mode for the whole CTB)
210 case 64: filterFlag = 0; break;
211 default: filterFlag = -1; assert(false); break; // should never happen
212 }
213 }
214
215
216 if (filterFlag) {
217 int biIntFlag = (sps.strong_intra_smoothing_enable_flag &&
218 cIdx==0 &&
219 nT==32 &&
220 abs_value(p[0]+p[ 64]-2*p[ 32]) < (1<<(sps.bit_depth_luma-5)) &&
221 abs_value(p[0]+p[-64]-2*p[-32]) < (1<<(sps.bit_depth_luma-5)))
222 ? 1 : 0;
223
224 pixel_t pF_mem[4*32+1];
225 pixel_t* pF = &pF_mem[2*32];
226
227 if (biIntFlag) {
228 pF[-2*nT] = p[-2*nT];
229 pF[ 2*nT] = p[ 2*nT];
230 pF[ 0] = p[ 0];
231
232 for (int i=1;i<=63;i++) {
233 pF[-i] = p[0] + ((i*(p[-64]-p[0])+32)>>6);
234 pF[ i] = p[0] + ((i*(p[ 64]-p[0])+32)>>6);
235 }
236 } else {
237 pF[-2*nT] = p[-2*nT];
238 pF[ 2*nT] = p[ 2*nT];
239
240 for (int i=-(2*nT-1) ; i<=2*nT-1 ; i++)
241 {
242 pF[i] = (p[i+1] + 2*p[i] + p[i-1] + 2) >> 2;
243 }
244 }
245
246
247 // copy back to original array
248
249 memcpy(p-2*nT, pF-2*nT, (4*nT+1) * sizeof(pixel_t));
250 }
251 else {
252 // do nothing ?
253 }
254
255
256 logtrace(LogIntraPred,"post filtering: ");
257 print_border(p,NULL,nT);
258 logtrace(LogIntraPred,"\n");
259 }
260
261
262 template <class pixel_t>
intra_prediction_planar(pixel_t * dst,int dstStride,int nT,int cIdx,pixel_t * border)263 void intra_prediction_planar(pixel_t* dst, int dstStride,
264 int nT,int cIdx,
265 pixel_t* border)
266 {
267 int Log2_nT = Log2(nT);
268
269 for (int y=0;y<nT;y++)
270 for (int x=0;x<nT;x++)
271 {
272 dst[x+y*dstStride] = ((nT-1-x)*border[-1-y] + (x+1)*border[ 1+nT] +
273 (nT-1-y)*border[ 1+x] + (y+1)*border[-1-nT] + nT) >> (Log2_nT+1);
274 }
275
276
277 logtrace(LogIntraPred,"result of planar prediction\n");
278
279 for (int y=0;y<nT;y++)
280 {
281 for (int x=0;x<nT;x++)
282 logtrace(LogIntraPred,"%02x ", dst[x+y*dstStride]);
283
284 logtrace(LogIntraPred,"\n");
285 }
286 }
287
288
289 template <class pixel_t>
intra_prediction_DC(pixel_t * dst,int dstStride,int nT,int cIdx,pixel_t * border)290 void intra_prediction_DC(pixel_t* dst, int dstStride,
291 int nT,int cIdx,
292 pixel_t* border)
293 {
294 int Log2_nT = Log2(nT);
295
296 int dcVal = 0;
297 for (int i=0;i<nT;i++)
298 {
299 dcVal += border[ i+1];
300 dcVal += border[-i-1];
301 }
302
303 dcVal += nT;
304 dcVal >>= Log2_nT+1;
305
306 if (cIdx==0 && nT<32) {
307 dst[0] = (border[-1] + 2*dcVal + border[1] +2) >> 2;
308
309 for (int x=1;x<nT;x++) { dst[x] = (border[ x+1] + 3*dcVal+2)>>2; }
310 for (int y=1;y<nT;y++) { dst[y*dstStride] = (border[-y-1] + 3*dcVal+2)>>2; }
311 for (int y=1;y<nT;y++)
312 for (int x=1;x<nT;x++)
313 {
314 dst[x+y*dstStride] = dcVal;
315 }
316 } else {
317 for (int y=0;y<nT;y++)
318 for (int x=0;x<nT;x++)
319 {
320 dst[x+y*dstStride] = dcVal;
321 }
322 }
323 }
324
325
326 extern const int intraPredAngle_table[1+34];
327 extern const int invAngle_table[25-10];
328
329
330 // (8.4.4.2.6)
331 template <class pixel_t>
intra_prediction_angular(pixel_t * dst,int dstStride,int bit_depth,bool disableIntraBoundaryFilter,int xB0,int yB0,enum IntraPredMode intraPredMode,int nT,int cIdx,pixel_t * border)332 void intra_prediction_angular(pixel_t* dst, int dstStride,
333 int bit_depth, bool disableIntraBoundaryFilter,
334 int xB0,int yB0,
335 enum IntraPredMode intraPredMode,
336 int nT,int cIdx,
337 pixel_t* border)
338 {
339 pixel_t ref_mem[4*MAX_INTRA_PRED_BLOCK_SIZE+1]; // TODO: what is the required range here ?
340 pixel_t* ref=&ref_mem[2*MAX_INTRA_PRED_BLOCK_SIZE];
341
342 assert(intraPredMode<35);
343 assert(intraPredMode>=2);
344
345 int intraPredAngle = intraPredAngle_table[intraPredMode];
346
347 if (intraPredMode >= 18) {
348
349 for (int x=0;x<=nT;x++)
350 { ref[x] = border[x]; }
351
352 if (intraPredAngle<0) {
353 int invAngle = invAngle_table[intraPredMode-11];
354
355 if ((nT*intraPredAngle)>>5 < -1) {
356 for (int x=(nT*intraPredAngle)>>5; x<=-1; x++) {
357 ref[x] = border[0-((x*invAngle+128)>>8)];
358 }
359 }
360 } else {
361 for (int x=nT+1; x<=2*nT;x++) {
362 ref[x] = border[x];
363 }
364 }
365
366 for (int y=0;y<nT;y++)
367 for (int x=0;x<nT;x++)
368 {
369 int iIdx = ((y+1)*intraPredAngle)>>5;
370 int iFact= ((y+1)*intraPredAngle)&31;
371
372 if (iFact != 0) {
373 dst[x+y*dstStride] = ((32-iFact)*ref[x+iIdx+1] + iFact*ref[x+iIdx+2] + 16)>>5;
374 } else {
375 dst[x+y*dstStride] = ref[x+iIdx+1];
376 }
377 }
378
379 if (intraPredMode==26 && cIdx==0 && nT<32 && !disableIntraBoundaryFilter) {
380 for (int y=0;y<nT;y++) {
381 dst[0+y*dstStride] = Clip_BitDepth(border[1] + ((border[-1-y] - border[0])>>1), bit_depth);
382 }
383 }
384 }
385 else { // intraPredAngle < 18
386
387 for (int x=0;x<=nT;x++)
388 { ref[x] = border[-x]; } // DIFF (neg)
389
390 if (intraPredAngle<0) {
391 int invAngle = invAngle_table[intraPredMode-11];
392
393 if ((nT*intraPredAngle)>>5 < -1) {
394 for (int x=(nT*intraPredAngle)>>5; x<=-1; x++) {
395 ref[x] = border[((x*invAngle+128)>>8)]; // DIFF (neg)
396 }
397 }
398 } else {
399 for (int x=nT+1; x<=2*nT;x++) {
400 ref[x] = border[-x]; // DIFF (neg)
401 }
402 }
403
404 for (int y=0;y<nT;y++)
405 for (int x=0;x<nT;x++)
406 {
407 int iIdx = ((x+1)*intraPredAngle)>>5; // DIFF (x<->y)
408 int iFact= ((x+1)*intraPredAngle)&31; // DIFF (x<->y)
409
410 if (iFact != 0) {
411 dst[x+y*dstStride] = ((32-iFact)*ref[y+iIdx+1] + iFact*ref[y+iIdx+2] + 16)>>5; // DIFF (x<->y)
412 } else {
413 dst[x+y*dstStride] = ref[y+iIdx+1]; // DIFF (x<->y)
414 }
415 }
416
417 if (intraPredMode==10 && cIdx==0 && nT<32 && !disableIntraBoundaryFilter) { // DIFF 26->10
418 for (int x=0;x<nT;x++) { // DIFF (x<->y)
419 dst[x] = Clip_BitDepth(border[-1] + ((border[1+x] - border[0])>>1), bit_depth); // DIFF (x<->y && neg)
420 }
421 }
422 }
423
424
425 logtrace(LogIntraPred,"result of angular intra prediction (mode=%d):\n",intraPredMode);
426
427 for (int y=0;y<nT;y++)
428 {
429 for (int x=0;x<nT;x++)
430 logtrace(LogIntraPred,"%02x ", dst[x+y*dstStride]);
431
432 logtrace(LogIntraPred,"\n");
433 }
434 }
435
436
437 template <class pixel_t>
preproc()438 void intra_border_computer<pixel_t>::preproc()
439 {
440 sps = &img->get_sps();
441 pps = &img->get_pps();
442
443 SubWidth = (cIdx==0) ? 1 : sps->SubWidthC;
444 SubHeight = (cIdx==0) ? 1 : sps->SubHeightC;
445
446 // --- check for CTB boundaries ---
447
448 int xBLuma = xB * SubWidth;
449 int yBLuma = yB * SubHeight;
450
451 int log2CtbSize = sps->Log2CtbSizeY;
452 int picWidthInCtbs = sps->PicWidthInCtbsY;
453
454
455 //printf("xB/yB: %d %d\n",xB,yB);
456
457 // are we at left image border
458
459 if (xBLuma == 0) {
460 availableLeft = false;
461 availableTopLeft = false;
462 xBLuma = 0; // fake value, available flags are already set to false
463 }
464
465
466 // are we at top image border
467
468 if (yBLuma == 0) {
469 availableTop = false;
470 availableTopLeft = false;
471 availableTopRight = false;
472 yBLuma = 0; // fake value, available flags are already set to false
473 }
474
475 if (xBLuma+nT*SubWidth >= sps->pic_width_in_luma_samples) {
476 availableTopRight=false;
477 }
478
479 // check for tile and slice boundaries
480
481 int xCurrCtb = xBLuma >> log2CtbSize;
482 int yCurrCtb = yBLuma >> log2CtbSize;
483 int xLeftCtb = (xBLuma-1) >> log2CtbSize;
484 int xRightCtb = (xBLuma+nT*SubWidth) >> log2CtbSize;
485 int yTopCtb = (yBLuma-1) >> log2CtbSize;
486
487 int currCTBSlice = img->get_SliceAddrRS(xCurrCtb,yCurrCtb);
488 int leftCTBSlice = availableLeft ? img->get_SliceAddrRS(xLeftCtb, yCurrCtb) : -1;
489 int topCTBSlice = availableTop ? img->get_SliceAddrRS(xCurrCtb, yTopCtb) : -1;
490 int toprightCTBSlice = availableTopRight ? img->get_SliceAddrRS(xRightCtb, yTopCtb) : -1;
491 int topleftCTBSlice = availableTopLeft ? img->get_SliceAddrRS(xLeftCtb, yTopCtb) : -1;
492
493 /*
494 printf("size: %d\n",pps->TileIdRS.size());
495 printf("curr: %d left: %d top: %d\n",
496 xCurrCtb+yCurrCtb*picWidthInCtbs,
497 availableLeft ? xLeftCtb+yCurrCtb*picWidthInCtbs : 9999,
498 availableTop ? xCurrCtb+yTopCtb*picWidthInCtbs : 9999);
499 */
500 int currCTBTileID = pps->TileIdRS[xCurrCtb+yCurrCtb*picWidthInCtbs];
501 int leftCTBTileID = availableLeft ? pps->TileIdRS[xLeftCtb+yCurrCtb*picWidthInCtbs] : -1;
502 int topCTBTileID = availableTop ? pps->TileIdRS[xCurrCtb+yTopCtb*picWidthInCtbs] : -1;
503 int topleftCTBTileID = availableTopLeft ? pps->TileIdRS[xLeftCtb+yTopCtb*picWidthInCtbs] : -1;
504 int toprightCTBTileID= availableTopRight? pps->TileIdRS[xRightCtb+yTopCtb*picWidthInCtbs] : -1;
505
506 if (leftCTBSlice != currCTBSlice || leftCTBTileID != currCTBTileID ) availableLeft = false;
507 if (topCTBSlice != currCTBSlice || topCTBTileID != currCTBTileID ) availableTop = false;
508 if (topleftCTBSlice !=currCTBSlice||topleftCTBTileID!=currCTBTileID ) availableTopLeft = false;
509 if (toprightCTBSlice!=currCTBSlice||toprightCTBTileID!=currCTBTileID) availableTopRight= false;
510
511
512 // number of pixels that are in the valid image area to the right and to the bottom
513
514 nBottom = sps->pic_height_in_luma_samples - yB*SubHeight;
515 nBottom=(nBottom+SubHeight-1)/SubHeight;
516 if (nBottom>2*nT) nBottom=2*nT;
517
518 nRight = sps->pic_width_in_luma_samples - xB*SubWidth;
519 nRight =(nRight +SubWidth-1)/SubWidth;
520 if (nRight >2*nT) nRight=2*nT;
521
522 nAvail=0;
523
524 available = &available_data[2*MAX_INTRA_PRED_BLOCK_SIZE];
525
526 memset(available-2*nT, 0, 4*nT+1);
527 }
528
529
530 template <class pixel_t>
fill_from_image()531 void intra_border_computer<pixel_t>::fill_from_image()
532 {
533 assert(nT<=32);
534
535 pixel_t* image;
536 int stride;
537 image = (pixel_t*)img->get_image_plane(cIdx);
538 stride = img->get_image_stride(cIdx);
539
540 int xBLuma = xB * SubWidth;
541 int yBLuma = yB * SubHeight;
542
543 int currBlockAddr = pps->MinTbAddrZS[ (xBLuma>>sps->Log2MinTrafoSize) +
544 (yBLuma>>sps->Log2MinTrafoSize) * sps->PicWidthInTbsY ];
545
546
547 // copy pixels at left column
548
549 for (int y=nBottom-1 ; y>=0 ; y-=4)
550 if (availableLeft)
551 {
552 int NBlockAddr = pps->MinTbAddrZS[ (((xB-1)*SubWidth )>>sps->Log2MinTrafoSize) +
553 (((yB+y)*SubHeight)>>sps->Log2MinTrafoSize)
554 * sps->PicWidthInTbsY ];
555
556 bool availableN = NBlockAddr <= currBlockAddr;
557
558 if (pps->constrained_intra_pred_flag) {
559 if (img->get_pred_mode((xB-1)*SubWidth,(yB+y)*SubHeight)!=MODE_INTRA)
560 availableN = false;
561 }
562
563 if (availableN) {
564 if (!nAvail) firstValue = image[xB-1 + (yB+y)*stride];
565
566 for (int i=0;i<4;i++) {
567 available[-y+i-1] = availableN;
568 out_border[-y+i-1] = image[xB-1 + (yB+y-i)*stride];
569 }
570
571 nAvail+=4;
572 }
573 }
574
575 // copy pixel at top-left position
576
577 if (availableTopLeft)
578 {
579 int NBlockAddr = pps->MinTbAddrZS[ (((xB-1)*SubWidth )>>sps->Log2MinTrafoSize) +
580 (((yB-1)*SubHeight)>>sps->Log2MinTrafoSize)
581 * sps->PicWidthInTbsY ];
582
583 bool availableN = NBlockAddr <= currBlockAddr;
584
585 if (pps->constrained_intra_pred_flag) {
586 if (img->get_pred_mode((xB-1)*SubWidth,(yB-1)*SubHeight)!=MODE_INTRA) {
587 availableN = false;
588 }
589 }
590
591 if (availableN) {
592 if (!nAvail) firstValue = image[xB-1 + (yB-1)*stride];
593
594 out_border[0] = image[xB-1 + (yB-1)*stride];
595 available[0] = availableN;
596 nAvail++;
597 }
598 }
599
600 // copy pixels at top row
601
602 for (int x=0 ; x<nRight ; x+=4) {
603 bool borderAvailable;
604 if (x<nT) borderAvailable=availableTop;
605 else borderAvailable=availableTopRight;
606
607 if (borderAvailable)
608 {
609 int NBlockAddr = pps->MinTbAddrZS[ (((xB+x)*SubWidth )>>sps->Log2MinTrafoSize) +
610 (((yB-1)*SubHeight)>>sps->Log2MinTrafoSize)
611 * sps->PicWidthInTbsY ];
612
613 bool availableN = NBlockAddr <= currBlockAddr;
614
615 if (pps->constrained_intra_pred_flag) {
616 if (img->get_pred_mode((xB+x)*SubWidth,(yB-1)*SubHeight)!=MODE_INTRA) {
617 availableN = false;
618 }
619 }
620
621
622 if (availableN) {
623 if (!nAvail) firstValue = image[xB+x + (yB-1)*stride];
624
625 for (int i=0;i<4;i++) {
626 out_border[x+i+1] = image[xB+x+i + (yB-1)*stride];
627 available[x+i+1] = availableN;
628 }
629
630 nAvail+=4;
631 }
632 }
633 }
634 }
635
636
637
638 template <class pixel_t>
reference_sample_substitution()639 void intra_border_computer<pixel_t>::reference_sample_substitution()
640 {
641 // reference sample substitution
642
643 const int bit_depth = img->get_bit_depth(cIdx);
644
645 if (nAvail!=4*nT+1) {
646 if (nAvail==0) {
647 if (sizeof(pixel_t)==1) {
648 memset(out_border-2*nT, 1<<(bit_depth-1), 4*nT+1);
649 }
650 else {
651 for (int i = -2*nT; i <= 2*nT ; i++) {
652 out_border[i] = 1<<(bit_depth-1);
653 }
654 }
655 }
656 else {
657 if (!available[-2*nT]) {
658 out_border[-2*nT] = firstValue;
659 }
660
661 for (int i=-2*nT+1; i<=2*nT; i++)
662 if (!available[i]) {
663 out_border[i]=out_border[i-1];
664 }
665 }
666 }
667
668 logtrace(LogIntraPred,"availableN: ");
669 print_border(available,NULL,nT);
670 logtrace(LogIntraPred,"\n");
671
672 logtrace(LogIntraPred,"output: ");
673 print_border(out_border,NULL,nT);
674 logtrace(LogIntraPred,"\n");
675 }
676
677
678 #endif
679