/work/libde265/libde265/intrapred.h
Line | Count | Source |
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 | | |
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 | 0 | { |
46 | 0 | int PUidx = img->get_sps().getPUIndexRS(x,y); |
47 | 0 | fillIntraPredModeCandidates(candModeList, x,y, PUidx, availableA,availableB, img); |
48 | 0 | } |
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 | | |
141 | | void init(pixel_t* _out_border, |
142 | 0 | const de265_image* _img, int _nT, int _cIdx, int _xB, int _yB) { |
143 | 0 | img=_img; nT=_nT; cIdx=_cIdx; |
144 | 0 | out_border=_out_border; xB=_xB; yB=_yB; |
145 | |
|
146 | 0 | assert(nT <= MAX_INTRA_PRED_BLOCK_SIZE); |
147 | | |
148 | 0 | availableLeft=true; |
149 | 0 | availableTop=true; |
150 | 0 | availableTopRight=true; |
151 | 0 | availableTopLeft=true; |
152 | 0 | } Unexecuted instantiation: intra_border_computer<unsigned short>::init(unsigned short*, de265_image const*, int, int, int, int) Unexecuted instantiation: intra_border_computer<unsigned char>::init(unsigned char*, de265_image const*, int, int, int, int) |
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> |
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==nullptr || 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> |
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 | 0 | { |
191 | 0 | int filterFlag; |
192 | | |
193 | | //printf("filtering, mode: %d\n",intraPredMode); |
194 | |
|
195 | 0 | if (intraPredMode==INTRA_DC || nT==4) { |
196 | 0 | filterFlag = 0; |
197 | 0 | } else { |
198 | 0 | int minDistVerHor = std::min( std::abs((int)intraPredMode-26), |
199 | 0 | std::abs((int)intraPredMode-10) ); |
200 | | |
201 | | //printf("mindist: %d\n",minDistVerHor); |
202 | |
|
203 | 0 | switch (nT) { |
204 | 0 | case 8: filterFlag = (minDistVerHor>7) ? 1 : 0; break; |
205 | 0 | case 16: filterFlag = (minDistVerHor>1) ? 1 : 0; break; |
206 | 0 | case 32: filterFlag = (minDistVerHor>0) ? 1 : 0; break; |
207 | | // there is no official 64x64 TB block, but we call this for some intra-pred mode algorithms |
208 | | // on the whole CB (2Nx2N mode for the whole CTB) |
209 | 0 | case 64: filterFlag = 0; break; |
210 | 0 | default: filterFlag = -1; assert(false); break; // should never happen |
211 | 0 | } |
212 | 0 | } |
213 | | |
214 | | |
215 | 0 | if (filterFlag) { |
216 | 0 | int biIntFlag = (sps.strong_intra_smoothing_enable_flag && |
217 | 0 | cIdx==0 && |
218 | 0 | nT==32 && |
219 | 0 | std::abs(p[0]+p[ 64]-2*p[ 32]) < (1<<(sps.bit_depth_luma-5)) && |
220 | 0 | std::abs(p[0]+p[-64]-2*p[-32]) < (1<<(sps.bit_depth_luma-5))) |
221 | 0 | ? 1 : 0; |
222 | |
|
223 | 0 | pixel_t pF_mem[4*32+1]; |
224 | 0 | pixel_t* pF = &pF_mem[2*32]; |
225 | |
|
226 | 0 | if (biIntFlag) { |
227 | 0 | pF[-2*nT] = p[-2*nT]; |
228 | 0 | pF[ 2*nT] = p[ 2*nT]; |
229 | 0 | pF[ 0] = p[ 0]; |
230 | |
|
231 | 0 | for (int i=1;i<=63;i++) { |
232 | 0 | pF[-i] = p[0] + ((i*(p[-64]-p[0])+32)>>6); |
233 | 0 | pF[ i] = p[0] + ((i*(p[ 64]-p[0])+32)>>6); |
234 | 0 | } |
235 | 0 | } else { |
236 | 0 | pF[-2*nT] = p[-2*nT]; |
237 | 0 | pF[ 2*nT] = p[ 2*nT]; |
238 | |
|
239 | 0 | for (int i=-(2*nT-1) ; i<=2*nT-1 ; i++) |
240 | 0 | { |
241 | 0 | pF[i] = (p[i+1] + 2*p[i] + p[i-1] + 2) >> 2; |
242 | 0 | } |
243 | 0 | } |
244 | | |
245 | | |
246 | | // copy back to original array |
247 | |
|
248 | 0 | memcpy(p-2*nT, pF-2*nT, (4*nT+1) * sizeof(pixel_t)); |
249 | 0 | } |
250 | 0 | else { |
251 | | // do nothing ? |
252 | 0 | } |
253 | | |
254 | |
|
255 | 0 | logtrace(LogIntraPred,"post filtering: "); |
256 | 0 | print_border(p,nullptr,nT); |
257 | 0 | logtrace(LogIntraPred,"\n"); |
258 | 0 | } Unexecuted instantiation: void intra_prediction_sample_filtering<unsigned short>(seq_parameter_set const&, unsigned short*, int, int, IntraPredMode) Unexecuted instantiation: void intra_prediction_sample_filtering<unsigned char>(seq_parameter_set const&, unsigned char*, int, int, IntraPredMode) |
259 | | |
260 | | |
261 | | template <class pixel_t> |
262 | | void intra_prediction_planar(pixel_t* dst, int dstStride, |
263 | | int nT,int cIdx, |
264 | | pixel_t* border) |
265 | 0 | { |
266 | 0 | int Log2_nT = Log2(nT); |
267 | |
|
268 | 0 | for (int y=0;y<nT;y++) |
269 | 0 | for (int x=0;x<nT;x++) |
270 | 0 | { |
271 | 0 | dst[x+y*dstStride] = ((nT-1-x)*border[-1-y] + (x+1)*border[ 1+nT] + |
272 | 0 | (nT-1-y)*border[ 1+x] + (y+1)*border[-1-nT] + nT) >> (Log2_nT+1); |
273 | 0 | } |
274 | | |
275 | |
|
276 | 0 | logtrace(LogIntraPred,"result of planar prediction\n"); |
277 | |
|
278 | 0 | for (int y=0;y<nT;y++) |
279 | 0 | { |
280 | 0 | for (int x=0;x<nT;x++) |
281 | 0 | logtrace(LogIntraPred,"%02x ", dst[x+y*dstStride]); |
282 | |
|
283 | 0 | logtrace(LogIntraPred,"\n"); |
284 | 0 | } |
285 | 0 | } Unexecuted instantiation: void intra_prediction_planar<unsigned char>(unsigned char*, int, int, int, unsigned char*) Unexecuted instantiation: void intra_prediction_planar<unsigned short>(unsigned short*, int, int, int, unsigned short*) |
286 | | |
287 | | |
288 | | template <class pixel_t> |
289 | | void intra_prediction_DC(pixel_t* dst, int dstStride, |
290 | | int nT,int cIdx, |
291 | | pixel_t* border) |
292 | 0 | { |
293 | 0 | int Log2_nT = Log2(nT); |
294 | |
|
295 | 0 | int dcVal = 0; |
296 | 0 | for (int i=0;i<nT;i++) |
297 | 0 | { |
298 | 0 | dcVal += border[ i+1]; |
299 | 0 | dcVal += border[-i-1]; |
300 | 0 | } |
301 | |
|
302 | 0 | dcVal += nT; |
303 | 0 | dcVal >>= Log2_nT+1; |
304 | |
|
305 | 0 | if (cIdx==0 && nT<32) { |
306 | 0 | dst[0] = (border[-1] + 2*dcVal + border[1] +2) >> 2; |
307 | |
|
308 | 0 | for (int x=1;x<nT;x++) { dst[x] = (border[ x+1] + 3*dcVal+2)>>2; } |
309 | 0 | for (int y=1;y<nT;y++) { dst[y*dstStride] = (border[-y-1] + 3*dcVal+2)>>2; } |
310 | 0 | for (int y=1;y<nT;y++) |
311 | 0 | for (int x=1;x<nT;x++) |
312 | 0 | { |
313 | 0 | dst[x+y*dstStride] = dcVal; |
314 | 0 | } |
315 | 0 | } else { |
316 | 0 | for (int y=0;y<nT;y++) |
317 | 0 | for (int x=0;x<nT;x++) |
318 | 0 | { |
319 | 0 | dst[x+y*dstStride] = dcVal; |
320 | 0 | } |
321 | 0 | } |
322 | 0 | } Unexecuted instantiation: void intra_prediction_DC<unsigned char>(unsigned char*, int, int, int, unsigned char*) Unexecuted instantiation: void intra_prediction_DC<unsigned short>(unsigned short*, int, int, int, unsigned short*) |
323 | | |
324 | | |
325 | | extern const int intraPredAngle_table[1+34]; |
326 | | extern const int invAngle_table[25-10]; |
327 | | |
328 | | |
329 | | // (8.4.4.2.6) |
330 | | template <class pixel_t> |
331 | | void intra_prediction_angular(pixel_t* dst, int dstStride, |
332 | | int bit_depth, bool disableIntraBoundaryFilter, |
333 | | int xB0,int yB0, |
334 | | enum IntraPredMode intraPredMode, |
335 | | int nT,int cIdx, |
336 | | pixel_t* border) |
337 | 0 | { |
338 | 0 | pixel_t ref_mem[4*MAX_INTRA_PRED_BLOCK_SIZE+1]; // TODO: what is the required range here ? |
339 | 0 | pixel_t* ref=&ref_mem[2*MAX_INTRA_PRED_BLOCK_SIZE]; |
340 | |
|
341 | 0 | assert(intraPredMode<35); |
342 | 0 | assert(intraPredMode>=2); |
343 | | |
344 | 0 | int intraPredAngle = intraPredAngle_table[intraPredMode]; |
345 | |
|
346 | 0 | if (intraPredMode >= 18) { |
347 | |
|
348 | 0 | for (int x=0;x<=nT;x++) |
349 | 0 | { ref[x] = border[x]; } |
350 | |
|
351 | 0 | if (intraPredAngle<0) { |
352 | 0 | int invAngle = invAngle_table[intraPredMode-11]; |
353 | |
|
354 | 0 | if ((nT*intraPredAngle)>>5 < -1) { |
355 | 0 | for (int x=(nT*intraPredAngle)>>5; x<=-1; x++) { |
356 | 0 | ref[x] = border[0-((x*invAngle+128)>>8)]; |
357 | 0 | } |
358 | 0 | } |
359 | 0 | } else { |
360 | 0 | for (int x=nT+1; x<=2*nT;x++) { |
361 | 0 | ref[x] = border[x]; |
362 | 0 | } |
363 | 0 | } |
364 | |
|
365 | 0 | for (int y=0;y<nT;y++) |
366 | 0 | for (int x=0;x<nT;x++) |
367 | 0 | { |
368 | 0 | int iIdx = ((y+1)*intraPredAngle)>>5; |
369 | 0 | int iFact= ((y+1)*intraPredAngle)&31; |
370 | |
|
371 | 0 | if (iFact != 0) { |
372 | 0 | dst[x+y*dstStride] = ((32-iFact)*ref[x+iIdx+1] + iFact*ref[x+iIdx+2] + 16)>>5; |
373 | 0 | } else { |
374 | 0 | dst[x+y*dstStride] = ref[x+iIdx+1]; |
375 | 0 | } |
376 | 0 | } |
377 | |
|
378 | 0 | if (intraPredMode==26 && cIdx==0 && nT<32 && !disableIntraBoundaryFilter) { |
379 | 0 | for (int y=0;y<nT;y++) { |
380 | 0 | dst[0+y*dstStride] = Clip_BitDepth(border[1] + ((border[-1-y] - border[0])>>1), bit_depth); |
381 | 0 | } |
382 | 0 | } |
383 | 0 | } |
384 | 0 | else { // intraPredAngle < 18 |
385 | |
|
386 | 0 | for (int x=0;x<=nT;x++) |
387 | 0 | { ref[x] = border[-x]; } // DIFF (neg) |
388 | |
|
389 | 0 | if (intraPredAngle<0) { |
390 | 0 | int invAngle = invAngle_table[intraPredMode-11]; |
391 | |
|
392 | 0 | if ((nT*intraPredAngle)>>5 < -1) { |
393 | 0 | for (int x=(nT*intraPredAngle)>>5; x<=-1; x++) { |
394 | 0 | ref[x] = border[((x*invAngle+128)>>8)]; // DIFF (neg) |
395 | 0 | } |
396 | 0 | } |
397 | 0 | } else { |
398 | 0 | for (int x=nT+1; x<=2*nT;x++) { |
399 | 0 | ref[x] = border[-x]; // DIFF (neg) |
400 | 0 | } |
401 | 0 | } |
402 | |
|
403 | 0 | for (int y=0;y<nT;y++) |
404 | 0 | for (int x=0;x<nT;x++) |
405 | 0 | { |
406 | 0 | int iIdx = ((x+1)*intraPredAngle)>>5; // DIFF (x<->y) |
407 | 0 | int iFact= ((x+1)*intraPredAngle)&31; // DIFF (x<->y) |
408 | |
|
409 | 0 | if (iFact != 0) { |
410 | 0 | dst[x+y*dstStride] = ((32-iFact)*ref[y+iIdx+1] + iFact*ref[y+iIdx+2] + 16)>>5; // DIFF (x<->y) |
411 | 0 | } else { |
412 | 0 | dst[x+y*dstStride] = ref[y+iIdx+1]; // DIFF (x<->y) |
413 | 0 | } |
414 | 0 | } |
415 | |
|
416 | 0 | if (intraPredMode==10 && cIdx==0 && nT<32 && !disableIntraBoundaryFilter) { // DIFF 26->10 |
417 | 0 | for (int x=0;x<nT;x++) { // DIFF (x<->y) |
418 | 0 | dst[x] = Clip_BitDepth(border[-1] + ((border[1+x] - border[0])>>1), bit_depth); // DIFF (x<->y && neg) |
419 | 0 | } |
420 | 0 | } |
421 | 0 | } |
422 | | |
423 | |
|
424 | 0 | logtrace(LogIntraPred,"result of angular intra prediction (mode=%d):\n",intraPredMode); |
425 | |
|
426 | 0 | for (int y=0;y<nT;y++) |
427 | 0 | { |
428 | 0 | for (int x=0;x<nT;x++) |
429 | 0 | logtrace(LogIntraPred,"%02x ", dst[x+y*dstStride]); |
430 | |
|
431 | 0 | logtrace(LogIntraPred,"\n"); |
432 | 0 | } |
433 | 0 | } Unexecuted instantiation: void intra_prediction_angular<unsigned char>(unsigned char*, int, int, bool, int, int, IntraPredMode, int, int, unsigned char*) Unexecuted instantiation: void intra_prediction_angular<unsigned short>(unsigned short*, int, int, bool, int, int, IntraPredMode, int, int, unsigned short*) |
434 | | |
435 | | |
436 | | template <class pixel_t> |
437 | | void intra_border_computer<pixel_t>::preproc() |
438 | 0 | { |
439 | 0 | sps = &img->get_sps(); |
440 | 0 | pps = &img->get_pps(); |
441 | |
|
442 | 0 | SubWidth = (cIdx==0) ? 1 : sps->SubWidthC; |
443 | 0 | SubHeight = (cIdx==0) ? 1 : sps->SubHeightC; |
444 | | |
445 | | // --- check for CTB boundaries --- |
446 | |
|
447 | 0 | int xBLuma = xB * SubWidth; |
448 | 0 | int yBLuma = yB * SubHeight; |
449 | |
|
450 | 0 | int log2CtbSize = sps->Log2CtbSizeY; |
451 | 0 | int picWidthInCtbs = sps->PicWidthInCtbsY; |
452 | | |
453 | | |
454 | | //printf("xB/yB: %d %d\n",xB,yB); |
455 | | |
456 | | // are we at left image border |
457 | |
|
458 | 0 | if (xBLuma == 0) { |
459 | 0 | availableLeft = false; |
460 | 0 | availableTopLeft = false; |
461 | 0 | xBLuma = 0; // fake value, available flags are already set to false |
462 | 0 | } |
463 | | |
464 | | |
465 | | // are we at top image border |
466 | |
|
467 | 0 | if (yBLuma == 0) { |
468 | 0 | availableTop = false; |
469 | 0 | availableTopLeft = false; |
470 | 0 | availableTopRight = false; |
471 | 0 | yBLuma = 0; // fake value, available flags are already set to false |
472 | 0 | } |
473 | |
|
474 | 0 | if (xBLuma+nT*SubWidth >= sps->pic_width_in_luma_samples) { |
475 | 0 | availableTopRight=false; |
476 | 0 | } |
477 | | |
478 | | // check for tile and slice boundaries |
479 | |
|
480 | 0 | int xCurrCtb = xBLuma >> log2CtbSize; |
481 | 0 | int yCurrCtb = yBLuma >> log2CtbSize; |
482 | 0 | int xLeftCtb = (xBLuma-1) >> log2CtbSize; |
483 | 0 | int xRightCtb = (xBLuma+nT*SubWidth) >> log2CtbSize; |
484 | 0 | int yTopCtb = (yBLuma-1) >> log2CtbSize; |
485 | |
|
486 | 0 | int currCTBSlice = img->get_SliceAddrRS(xCurrCtb,yCurrCtb); |
487 | 0 | int leftCTBSlice = availableLeft ? img->get_SliceAddrRS(xLeftCtb, yCurrCtb) : -1; |
488 | 0 | int topCTBSlice = availableTop ? img->get_SliceAddrRS(xCurrCtb, yTopCtb) : -1; |
489 | 0 | int toprightCTBSlice = availableTopRight ? img->get_SliceAddrRS(xRightCtb, yTopCtb) : -1; |
490 | 0 | int topleftCTBSlice = availableTopLeft ? img->get_SliceAddrRS(xLeftCtb, yTopCtb) : -1; |
491 | | |
492 | | /* |
493 | | printf("size: %d\n",pps->scan->TileIdRS.size()); |
494 | | printf("curr: %d left: %d top: %d\n", |
495 | | xCurrCtb+yCurrCtb*picWidthInCtbs, |
496 | | availableLeft ? xLeftCtb+yCurrCtb*picWidthInCtbs : 9999, |
497 | | availableTop ? xCurrCtb+yTopCtb*picWidthInCtbs : 9999); |
498 | | */ |
499 | 0 | uint32_t currCTBTileID = pps->scan->TileIdRS[xCurrCtb+yCurrCtb*picWidthInCtbs]; |
500 | 0 | uint32_t leftCTBTileID = availableLeft ? pps->scan->TileIdRS[xLeftCtb+yCurrCtb*picWidthInCtbs] : UINT32_MAX; |
501 | 0 | uint32_t topCTBTileID = availableTop ? pps->scan->TileIdRS[xCurrCtb+yTopCtb*picWidthInCtbs] : UINT32_MAX; |
502 | 0 | uint32_t topleftCTBTileID = availableTopLeft ? pps->scan->TileIdRS[xLeftCtb+yTopCtb*picWidthInCtbs] : UINT32_MAX; |
503 | 0 | uint32_t toprightCTBTileID= availableTopRight? pps->scan->TileIdRS[xRightCtb+yTopCtb*picWidthInCtbs] : UINT32_MAX; |
504 | |
|
505 | 0 | if (leftCTBSlice != currCTBSlice || leftCTBTileID != currCTBTileID ) availableLeft = false; |
506 | 0 | if (topCTBSlice != currCTBSlice || topCTBTileID != currCTBTileID ) availableTop = false; |
507 | 0 | if (topleftCTBSlice !=currCTBSlice||topleftCTBTileID!=currCTBTileID ) availableTopLeft = false; |
508 | 0 | if (toprightCTBSlice!=currCTBSlice||toprightCTBTileID!=currCTBTileID) availableTopRight= false; |
509 | | |
510 | | |
511 | | // number of pixels that are in the valid image area to the right and to the bottom |
512 | |
|
513 | 0 | nBottom = sps->pic_height_in_luma_samples - yB*SubHeight; |
514 | 0 | nBottom=(nBottom+SubHeight-1)/SubHeight; |
515 | 0 | if (nBottom>2*nT) nBottom=2*nT; |
516 | |
|
517 | 0 | nRight = sps->pic_width_in_luma_samples - xB*SubWidth; |
518 | 0 | nRight =(nRight +SubWidth-1)/SubWidth; |
519 | 0 | if (nRight >2*nT) nRight=2*nT; |
520 | |
|
521 | 0 | nAvail=0; |
522 | |
|
523 | 0 | available = &available_data[2*MAX_INTRA_PRED_BLOCK_SIZE]; |
524 | |
|
525 | 0 | memset(available-2*nT, 0, 4*nT+1); |
526 | 0 | } Unexecuted instantiation: intra_border_computer<unsigned short>::preproc() Unexecuted instantiation: intra_border_computer<unsigned char>::preproc() |
527 | | |
528 | | |
529 | | template <class pixel_t> |
530 | | void intra_border_computer<pixel_t>::fill_from_image() |
531 | 0 | { |
532 | 0 | assert(nT<=32); |
533 | | |
534 | 0 | pixel_t* image; |
535 | 0 | ptrdiff_t stride; |
536 | 0 | image = (pixel_t*)img->get_image_plane(cIdx); |
537 | 0 | stride = img->get_image_stride(cIdx); |
538 | |
|
539 | 0 | int xBLuma = xB * SubWidth; |
540 | 0 | int yBLuma = yB * SubHeight; |
541 | |
|
542 | 0 | int currBlockAddr = pps->scan->MinTbAddrZS[ (xBLuma>>sps->Log2MinTrafoSize) + |
543 | 0 | (yBLuma>>sps->Log2MinTrafoSize) * sps->PicWidthInTbsY ]; |
544 | | |
545 | | |
546 | | // copy pixels at left column |
547 | |
|
548 | 0 | for (int y=nBottom-1 ; y>=0 ; y-=4) |
549 | 0 | if (availableLeft) |
550 | 0 | { |
551 | 0 | int NBlockAddr = pps->scan->MinTbAddrZS[ (((xB-1)*SubWidth )>>sps->Log2MinTrafoSize) + |
552 | 0 | (((yB+y)*SubHeight)>>sps->Log2MinTrafoSize) |
553 | 0 | * sps->PicWidthInTbsY ]; |
554 | |
|
555 | 0 | bool availableN = NBlockAddr <= currBlockAddr; |
556 | |
|
557 | 0 | if (pps->constrained_intra_pred_flag) { |
558 | 0 | if (img->get_pred_mode((xB-1)*SubWidth,(yB+y)*SubHeight)!=MODE_INTRA) |
559 | 0 | availableN = false; |
560 | 0 | } |
561 | |
|
562 | 0 | if (availableN) { |
563 | 0 | if (!nAvail) firstValue = image[xB-1 + (yB+y)*stride]; |
564 | |
|
565 | 0 | for (int i=0;i<4;i++) { |
566 | 0 | available[-y+i-1] = availableN; |
567 | 0 | out_border[-y+i-1] = image[xB-1 + (yB+y-i)*stride]; |
568 | 0 | } |
569 | |
|
570 | 0 | nAvail+=4; |
571 | 0 | } |
572 | 0 | } |
573 | | |
574 | | // copy pixel at top-left position |
575 | |
|
576 | 0 | if (availableTopLeft) |
577 | 0 | { |
578 | 0 | int NBlockAddr = pps->scan->MinTbAddrZS[ (((xB-1)*SubWidth )>>sps->Log2MinTrafoSize) + |
579 | 0 | (((yB-1)*SubHeight)>>sps->Log2MinTrafoSize) |
580 | 0 | * sps->PicWidthInTbsY ]; |
581 | |
|
582 | 0 | bool availableN = NBlockAddr <= currBlockAddr; |
583 | |
|
584 | 0 | if (pps->constrained_intra_pred_flag) { |
585 | 0 | if (img->get_pred_mode((xB-1)*SubWidth,(yB-1)*SubHeight)!=MODE_INTRA) { |
586 | 0 | availableN = false; |
587 | 0 | } |
588 | 0 | } |
589 | |
|
590 | 0 | if (availableN) { |
591 | 0 | if (!nAvail) firstValue = image[xB-1 + (yB-1)*stride]; |
592 | |
|
593 | 0 | out_border[0] = image[xB-1 + (yB-1)*stride]; |
594 | 0 | available[0] = availableN; |
595 | 0 | nAvail++; |
596 | 0 | } |
597 | 0 | } |
598 | | |
599 | | // copy pixels at top row |
600 | |
|
601 | 0 | for (int x=0 ; x<nRight ; x+=4) { |
602 | 0 | bool borderAvailable; |
603 | 0 | if (x<nT) borderAvailable=availableTop; |
604 | 0 | else borderAvailable=availableTopRight; |
605 | |
|
606 | 0 | if (borderAvailable) |
607 | 0 | { |
608 | 0 | int NBlockAddr = pps->scan->MinTbAddrZS[ (((xB+x)*SubWidth )>>sps->Log2MinTrafoSize) + |
609 | 0 | (((yB-1)*SubHeight)>>sps->Log2MinTrafoSize) |
610 | 0 | * sps->PicWidthInTbsY ]; |
611 | |
|
612 | 0 | bool availableN = NBlockAddr <= currBlockAddr; |
613 | |
|
614 | 0 | if (pps->constrained_intra_pred_flag) { |
615 | 0 | if (img->get_pred_mode((xB+x)*SubWidth,(yB-1)*SubHeight)!=MODE_INTRA) { |
616 | 0 | availableN = false; |
617 | 0 | } |
618 | 0 | } |
619 | | |
620 | |
|
621 | 0 | if (availableN) { |
622 | 0 | if (!nAvail) firstValue = image[xB+x + (yB-1)*stride]; |
623 | |
|
624 | 0 | for (int i=0;i<4;i++) { |
625 | 0 | out_border[x+i+1] = image[xB+x+i + (yB-1)*stride]; |
626 | 0 | available[x+i+1] = availableN; |
627 | 0 | } |
628 | |
|
629 | 0 | nAvail+=4; |
630 | 0 | } |
631 | 0 | } |
632 | 0 | } |
633 | 0 | } Unexecuted instantiation: intra_border_computer<unsigned short>::fill_from_image() Unexecuted instantiation: intra_border_computer<unsigned char>::fill_from_image() |
634 | | |
635 | | |
636 | | |
637 | | template <class pixel_t> |
638 | | void intra_border_computer<pixel_t>::reference_sample_substitution() |
639 | 0 | { |
640 | | // reference sample substitution |
641 | |
|
642 | 0 | const int bit_depth = img->get_bit_depth(cIdx); |
643 | |
|
644 | 0 | if (nAvail!=4*nT+1) { |
645 | 0 | if (nAvail==0) { |
646 | 0 | if (sizeof(pixel_t)==1) { |
647 | 0 | memset(out_border-2*nT, 1<<(bit_depth-1), 4*nT+1); |
648 | 0 | } |
649 | 0 | else { |
650 | 0 | for (int i = -2*nT; i <= 2*nT ; i++) { |
651 | 0 | out_border[i] = 1<<(bit_depth-1); |
652 | 0 | } |
653 | 0 | } |
654 | 0 | } |
655 | 0 | else { |
656 | 0 | if (!available[-2*nT]) { |
657 | 0 | out_border[-2*nT] = firstValue; |
658 | 0 | } |
659 | |
|
660 | 0 | for (int i=-2*nT+1; i<=2*nT; i++) |
661 | 0 | if (!available[i]) { |
662 | 0 | out_border[i]=out_border[i-1]; |
663 | 0 | } |
664 | 0 | } |
665 | 0 | } |
666 | |
|
667 | 0 | logtrace(LogIntraPred,"availableN: "); |
668 | 0 | print_border(available,nullptr,nT); |
669 | 0 | logtrace(LogIntraPred,"\n"); |
670 | |
|
671 | 0 | logtrace(LogIntraPred,"output: "); |
672 | 0 | print_border(out_border,nullptr,nT); |
673 | 0 | logtrace(LogIntraPred,"\n"); |
674 | 0 | } Unexecuted instantiation: intra_border_computer<unsigned short>::reference_sample_substitution() Unexecuted instantiation: intra_border_computer<unsigned char>::reference_sample_substitution() |
675 | | |
676 | | |
677 | | #endif |