/work/libde265/libde265/transform.cc
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 | | #include "transform.h" |
22 | | #include "util.h" |
23 | | |
24 | | #include <assert.h> |
25 | | |
26 | | |
27 | | const int tab8_22[] = { 29,30,31,32,33,33,34,34,35,35,36,36,37 /*,37*/ }; |
28 | | |
29 | | |
30 | | // (8.6.1) |
31 | | void decode_quantization_parameters(thread_context* tctx, int xC,int yC, |
32 | | int xCUBase, int yCUBase) |
33 | 0 | { |
34 | 0 | logtrace(LogTransform,">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> decode_quantization_parameters(int xC,int yC)=(%d,%d)\n", xC,yC); |
35 | |
|
36 | 0 | const pic_parameter_set& pps = tctx->img->get_pps(); |
37 | 0 | const seq_parameter_set& sps = tctx->img->get_sps(); |
38 | 0 | slice_segment_header* shdr = tctx->shdr; |
39 | | |
40 | | // top left pixel position of current quantization group |
41 | 0 | int xQG = xCUBase - (xCUBase & ((1<<pps.Log2MinCuQpDeltaSize)-1)); |
42 | 0 | int yQG = yCUBase - (yCUBase & ((1<<pps.Log2MinCuQpDeltaSize)-1)); |
43 | |
|
44 | 0 | logtrace(LogTransform,"QG: %d,%d\n",xQG,yQG); |
45 | | |
46 | | |
47 | | // we only have to set QP in the first call in a quantization-group |
48 | | |
49 | | /* TODO: check why this does not work with HoneyBee stream |
50 | | |
51 | | if (xQG == tctx->currentQG_x && |
52 | | yQG == tctx->currentQG_y) |
53 | | { |
54 | | return; |
55 | | } |
56 | | */ |
57 | | |
58 | | // if first QG in CU, remember last QPY of last CU previous QG |
59 | |
|
60 | 0 | if (xQG != tctx->currentQG_x || |
61 | 0 | yQG != tctx->currentQG_y) |
62 | 0 | { |
63 | 0 | tctx->lastQPYinPreviousQG = tctx->currentQPY; |
64 | 0 | tctx->currentQG_x = xQG; |
65 | 0 | tctx->currentQG_y = yQG; |
66 | 0 | } |
67 | |
|
68 | 0 | int qPY_PRED; |
69 | | |
70 | | // first QG in CTB row ? |
71 | |
|
72 | 0 | int ctbLSBMask = ((1<<sps.Log2CtbSizeY)-1); |
73 | 0 | bool firstInCTBRow = (xQG == 0 && ((yQG & ctbLSBMask)==0)); |
74 | | |
75 | | // first QG in slice ? TODO: a "firstQG" flag in the thread context would be faster |
76 | |
|
77 | 0 | int first_ctb_in_slice_RS = tctx->shdr->SliceAddrRS; |
78 | |
|
79 | 0 | int SliceStartX = (first_ctb_in_slice_RS % sps.PicWidthInCtbsY) * sps.CtbSizeY; |
80 | 0 | int SliceStartY = (first_ctb_in_slice_RS / sps.PicWidthInCtbsY) * sps.CtbSizeY; |
81 | |
|
82 | 0 | bool firstQGInSlice = (SliceStartX == xQG && SliceStartY == yQG); |
83 | | |
84 | | // first QG in tile ? |
85 | |
|
86 | 0 | bool firstQGInTile = false; |
87 | 0 | if (pps.tiles_enabled_flag) { |
88 | 0 | if ((xQG & ((1 << sps.Log2CtbSizeY)-1)) == 0 && |
89 | 0 | (yQG & ((1 << sps.Log2CtbSizeY)-1)) == 0) |
90 | 0 | { |
91 | 0 | int ctbX = xQG >> sps.Log2CtbSizeY; |
92 | 0 | int ctbY = yQG >> sps.Log2CtbSizeY; |
93 | |
|
94 | 0 | firstQGInTile = pps.is_tile_start_CTB(ctbX,ctbY); // TODO: this is slow |
95 | 0 | } |
96 | 0 | } |
97 | | |
98 | |
|
99 | 0 | if (firstQGInSlice || firstQGInTile || |
100 | 0 | (firstInCTBRow && pps.entropy_coding_sync_enabled_flag)) { |
101 | 0 | qPY_PRED = tctx->shdr->SliceQPY; |
102 | 0 | } |
103 | 0 | else { |
104 | 0 | qPY_PRED = tctx->lastQPYinPreviousQG; |
105 | 0 | } |
106 | | |
107 | |
|
108 | 0 | int qPYA,qPYB; |
109 | |
|
110 | 0 | if (tctx->img->available_zscan(xQG,yQG, xQG-1,yQG)) { |
111 | 0 | int xTmp = (xQG-1) >> sps.Log2MinTrafoSize; |
112 | 0 | int yTmp = (yQG ) >> sps.Log2MinTrafoSize; |
113 | 0 | int minTbAddrA = pps.scan->MinTbAddrZS[xTmp + yTmp*sps.PicWidthInTbsY]; |
114 | 0 | uint32_t ctbAddrA = minTbAddrA >> (2 * (sps.Log2CtbSizeY-sps.Log2MinTrafoSize)); |
115 | 0 | if (ctbAddrA == tctx->CtbAddrInTS) { |
116 | 0 | qPYA = tctx->img->get_QPY(xQG-1,yQG); |
117 | 0 | } |
118 | 0 | else { |
119 | 0 | qPYA = qPY_PRED; |
120 | 0 | } |
121 | 0 | } |
122 | 0 | else { |
123 | 0 | qPYA = qPY_PRED; |
124 | 0 | } |
125 | |
|
126 | 0 | if (tctx->img->available_zscan(xQG,yQG, xQG,yQG-1)) { |
127 | 0 | int xTmp = (xQG ) >> sps.Log2MinTrafoSize; |
128 | 0 | int yTmp = (yQG-1) >> sps.Log2MinTrafoSize; |
129 | 0 | uint32_t minTbAddrB = pps.scan->MinTbAddrZS[xTmp + yTmp*sps.PicWidthInTbsY]; |
130 | 0 | uint32_t ctbAddrB = minTbAddrB >> (2 * (sps.Log2CtbSizeY-sps.Log2MinTrafoSize)); |
131 | 0 | if (ctbAddrB == tctx->CtbAddrInTS) { |
132 | 0 | qPYB = tctx->img->get_QPY(xQG,yQG-1); |
133 | 0 | } |
134 | 0 | else { |
135 | 0 | qPYB = qPY_PRED; |
136 | 0 | } |
137 | 0 | } |
138 | 0 | else { |
139 | 0 | qPYB = qPY_PRED; |
140 | 0 | } |
141 | |
|
142 | 0 | qPY_PRED = (qPYA + qPYB + 1)>>1; |
143 | |
|
144 | 0 | logtrace(LogTransform,"qPY_PRED = %d (%d, %d)\n",qPY_PRED, qPYA, qPYB); |
145 | |
|
146 | 0 | int QPY = ((qPY_PRED + tctx->CuQpDelta + 52+2*sps.QpBdOffset_Y) % |
147 | 0 | (52 + sps.QpBdOffset_Y)) - sps.QpBdOffset_Y; |
148 | |
|
149 | 0 | assert(QPY >= -sps.QpBdOffset_Y && QPY <= 51); |
150 | | |
151 | 0 | tctx->qPYPrime = QPY + sps.QpBdOffset_Y; |
152 | |
|
153 | 0 | int qPiCb = Clip3(-sps.QpBdOffset_C,57, QPY+pps.pic_cb_qp_offset + shdr->slice_cb_qp_offset + tctx->CuQpOffsetCb); |
154 | 0 | int qPiCr = Clip3(-sps.QpBdOffset_C,57, QPY+pps.pic_cr_qp_offset + shdr->slice_cr_qp_offset + tctx->CuQpOffsetCr); |
155 | |
|
156 | 0 | logtrace(LogTransform,"qPiCb:%d (%d %d), qPiCr:%d (%d %d)\n", |
157 | 0 | qPiCb, pps.pic_cb_qp_offset, shdr->slice_cb_qp_offset, |
158 | 0 | qPiCr, pps.pic_cr_qp_offset, shdr->slice_cr_qp_offset); |
159 | |
|
160 | 0 | int qPCb,qPCr; |
161 | |
|
162 | 0 | if (sps.ChromaArrayType == CHROMA_420) { |
163 | 0 | qPCb = table8_22(qPiCb); |
164 | 0 | qPCr = table8_22(qPiCr); |
165 | 0 | } |
166 | 0 | else { |
167 | 0 | qPCb = qPiCb; |
168 | 0 | qPCr = qPiCr; |
169 | 0 | } |
170 | | |
171 | | //printf("q: %d %d\n",qPiCb, qPCb); |
172 | |
|
173 | 0 | tctx->qPCbPrime = qPCb + sps.QpBdOffset_C; |
174 | 0 | if (tctx->qPCbPrime<0) { |
175 | 0 | tctx->qPCbPrime = 0; |
176 | 0 | } |
177 | |
|
178 | 0 | tctx->qPCrPrime = qPCr + sps.QpBdOffset_C; |
179 | 0 | if (tctx->qPCrPrime<0) { |
180 | 0 | tctx->qPCrPrime = 0; |
181 | 0 | } |
182 | | |
183 | | /* |
184 | | printf("Q: %d (%d %d %d / %d %d) %d %d %d\n",QPY, |
185 | | sps->QpBdOffset_Y, |
186 | | pps->pic_cb_qp_offset + shdr->slice_cb_qp_offset, |
187 | | pps->pic_cr_qp_offset + shdr->slice_cr_qp_offset, |
188 | | sps->QpBdOffset_C, sps->QpBdOffset_C, |
189 | | tctx->qPYPrime, tctx->qPCbPrime, tctx->qPCrPrime); |
190 | | */ |
191 | |
|
192 | 0 | int log2CbSize = tctx->img->get_log2CbSize(xCUBase, yCUBase); |
193 | | |
194 | | // TODO: On broken input, log2CbSize may be zero (multithreaded only). Not sure yet why. |
195 | | // Maybe another decoding thread is overwriting the value set in slice.cc:read_coding_unit. |
196 | | // id:000163,sig:06,src:002041,op:havoc,rep:16.bin |
197 | 0 | if (log2CbSize<3) { log2CbSize=3; } |
198 | |
|
199 | 0 | tctx->img->set_QPY(xCUBase, yCUBase, log2CbSize, QPY); |
200 | 0 | tctx->currentQPY = QPY; |
201 | | |
202 | | /* |
203 | | printf("SET QPY POC=%d %d;%d-%d;%d = %d\n",ctx->img->PicOrderCntVal,xCUBase,yCUBase, |
204 | | xCUBase+(1<<log2CbSize),yCUBase+(1<<log2CbSize), QPY); |
205 | | */ |
206 | |
|
207 | 0 | logtrace(LogTransform,"qPY(%d,%d,%d)= %d, qPYPrime=%d\n", |
208 | 0 | xCUBase,yCUBase,1<<log2CbSize,QPY,tctx->qPYPrime); |
209 | 0 | } |
210 | | |
211 | | |
212 | | |
213 | | template <class pixel_t> |
214 | | void transform_coefficients(acceleration_functions* acceleration, |
215 | | int16_t* coeff, int coeffStride, int nT, int trType, |
216 | | pixel_t* dst, int dstStride, int bit_depth) |
217 | 0 | { |
218 | 0 | logtrace(LogTransform,"transform --- trType: %d nT: %d\n",trType,nT); |
219 | | |
220 | |
|
221 | 0 | if (trType==1) { |
222 | |
|
223 | 0 | acceleration->transform_4x4_dst_add<pixel_t>(dst, coeff, dstStride, bit_depth); |
224 | |
|
225 | 0 | } else { |
226 | | |
227 | 0 | /**/ if (nT==4) { acceleration->transform_add<pixel_t>(0,dst,coeff,dstStride, bit_depth); } |
228 | 0 | else if (nT==8) { acceleration->transform_add<pixel_t>(1,dst,coeff,dstStride, bit_depth); } |
229 | 0 | else if (nT==16) { acceleration->transform_add<pixel_t>(2,dst,coeff,dstStride, bit_depth); } |
230 | 0 | else { acceleration->transform_add<pixel_t>(3,dst,coeff,dstStride, bit_depth); } |
231 | 0 | } |
232 | |
|
233 | | #if 0 |
234 | | printf("decoded pixels:\n"); |
235 | | for (int y=0;y<nT;y++,printf("\n")) |
236 | | for (int x=0;x<nT;x++) { |
237 | | printf("%02x ",dst[y*dstStride+x]); |
238 | | } |
239 | | #endif |
240 | 0 | } Unexecuted instantiation: void transform_coefficients<unsigned short>(acceleration_functions*, short*, int, int, int, unsigned short*, int, int) Unexecuted instantiation: void transform_coefficients<unsigned char>(acceleration_functions*, short*, int, int, int, unsigned char*, int, int) |
241 | | |
242 | | |
243 | | // TODO: make this an accelerated function |
244 | | void cross_comp_pred(const thread_context* tctx, int32_t* residual, int nT) |
245 | 0 | { |
246 | 0 | const int BitDepthC = tctx->img->get_sps().BitDepth_C; |
247 | 0 | const int BitDepthY = tctx->img->get_sps().BitDepth_Y; |
248 | 0 | const int ResScaleVal = tctx->ResScaleVal; |
249 | | |
250 | | /* (8.6.6): r[x][y] += ( ResScaleVal * ( ( rY[x][y] << BitDepthC ) >> BitDepthY ) ) >> 3 |
251 | | Both shifts operate on a signed value, so together they are a single signed rescaling |
252 | | by (BitDepthC - BitDepthY). It must not be evaluated on an unsigned type: the right |
253 | | shift would then be logical and turn every negative luma residual into a large |
254 | | positive value. Shifting left is expressed as a multiplication because shifting a |
255 | | negative value left is undefined behaviour before C++20. |
256 | | */ |
257 | |
|
258 | 0 | const int shift = BitDepthY - BitDepthC; |
259 | |
|
260 | 0 | if (shift >= 0) { |
261 | 0 | for (int y=0;y<nT;y++) |
262 | 0 | for (int x=0;x<nT;x++) { |
263 | 0 | residual[y*nT+x] += (ResScaleVal * (tctx->residual_luma[y*nT+x] >> shift)) >> 3; |
264 | 0 | } |
265 | 0 | } |
266 | 0 | else { |
267 | 0 | const int32_t factor = 1 << (-shift); |
268 | |
|
269 | 0 | for (int y=0;y<nT;y++) |
270 | 0 | for (int x=0;x<nT;x++) { |
271 | 0 | residual[y*nT+x] += (ResScaleVal * (tctx->residual_luma[y*nT+x] * factor)) >> 3; |
272 | 0 | } |
273 | 0 | } |
274 | 0 | } |
275 | | |
276 | | |
277 | | template <class pixel_t> |
278 | | void transform_coefficients_explicit(thread_context* tctx, |
279 | | int16_t* coeff, int coeffStride, int nT, int trType, |
280 | | pixel_t* dst, int dstStride, int bit_depth, int cIdx) |
281 | 0 | { |
282 | 0 | logtrace(LogTransform,"transform --- trType: %d nT: %d\n",trType,nT); |
283 | |
|
284 | 0 | const acceleration_functions* acceleration = &tctx->decctx->acceleration; |
285 | |
|
286 | 0 | int32_t residual_buffer[32*32]; |
287 | 0 | int32_t* residual; |
288 | 0 | if (cIdx==0) { |
289 | 0 | residual = tctx->residual_luma; |
290 | 0 | } |
291 | 0 | else { |
292 | 0 | residual = residual_buffer; |
293 | 0 | } |
294 | | |
295 | | |
296 | | // TODO |
297 | 0 | int bdShift = 20 - bit_depth; |
298 | 0 | int max_coeff_bits = 15; |
299 | |
|
300 | 0 | if (trType==1) { |
301 | |
|
302 | 0 | acceleration->transform_idst_4x4(residual, coeff, bdShift, max_coeff_bits); |
303 | |
|
304 | 0 | } else { |
305 | | |
306 | 0 | /**/ if (nT==4) { acceleration->transform_idct_4x4(residual,coeff,bdShift,max_coeff_bits); } |
307 | 0 | else if (nT==8) { acceleration->transform_idct_8x8(residual,coeff,bdShift,max_coeff_bits); } |
308 | 0 | else if (nT==16) { acceleration->transform_idct_16x16(residual,coeff,bdShift,max_coeff_bits); } |
309 | 0 | else { acceleration->transform_idct_32x32(residual,coeff,bdShift,max_coeff_bits); } |
310 | 0 | } |
311 | | |
312 | | |
313 | | //printBlk("prediction",(uint8_t*)dst,nT,dstStride); |
314 | | //printBlk("residual",residual,nT,nT); |
315 | |
|
316 | 0 | if (cIdx != 0) { |
317 | 0 | if (tctx->ResScaleVal != 0) { |
318 | 0 | cross_comp_pred(tctx, residual, nT); |
319 | 0 | } |
320 | | |
321 | | //printBlk("cross-comp-pred modified residual",residual,nT,nT); |
322 | 0 | } |
323 | |
|
324 | 0 | acceleration->add_residual(dst,dstStride, residual,nT, bit_depth); |
325 | 0 | } Unexecuted instantiation: void transform_coefficients_explicit<unsigned short>(thread_context*, short*, int, int, int, unsigned short*, int, int, int) Unexecuted instantiation: void transform_coefficients_explicit<unsigned char>(thread_context*, short*, int, int, int, unsigned char*, int, int, int) |
326 | | |
327 | | |
328 | | void inv_transform(acceleration_functions* acceleration, |
329 | | uint8_t* dst, int dstStride, int16_t* coeff, |
330 | | int log2TbSize, int trType) |
331 | 0 | { |
332 | 0 | if (trType==1) { |
333 | 0 | assert(log2TbSize==2); |
334 | | |
335 | 0 | acceleration->transform_4x4_dst_add_8(dst, coeff, dstStride); |
336 | |
|
337 | 0 | } else { |
338 | 0 | acceleration->transform_add_8[log2TbSize-2](dst,coeff,dstStride); |
339 | 0 | } |
340 | | |
341 | |
|
342 | | #if 0 |
343 | | int nT = 1<<log2TbSize; |
344 | | printf("decoded pixels:\n"); |
345 | | for (int y=0;y<nT;y++,printf("\n")) |
346 | | for (int x=0;x<nT;x++) { |
347 | | printf("%02x ",dst[y*dstStride+x]); |
348 | | } |
349 | | #endif |
350 | 0 | } |
351 | | |
352 | | |
353 | | void fwd_transform(acceleration_functions* acceleration, |
354 | | int16_t* coeff, int coeffStride, int log2TbSize, int trType, |
355 | | const int16_t* src, int srcStride) |
356 | 0 | { |
357 | 0 | logtrace(LogTransform,"transform --- trType: %d nT: %d\n",trType,1<<log2TbSize); |
358 | |
|
359 | 0 | if (trType==1) { |
360 | | // DST 4x4 |
361 | |
|
362 | 0 | acceleration->fwd_transform_4x4_dst_8(coeff, src, srcStride); |
363 | 0 | } else { |
364 | | // DCT 4x4, 8x8, 16x16, 32x32 |
365 | |
|
366 | 0 | acceleration->fwd_transform_8[log2TbSize-2](coeff,src,srcStride); |
367 | 0 | } |
368 | 0 | } |
369 | | |
370 | | |
371 | | |
372 | | static const int levelScale[] = { 40,45,51,57,64,72 }; |
373 | | |
374 | | // (8.6.2) and (8.6.3) |
375 | | template <class pixel_t> |
376 | | void scale_coefficients_internal(thread_context* tctx, |
377 | | int xT,int yT, // position of TU in frame (chroma adapted) |
378 | | int x0,int y0, // position of CU in frame (chroma adapted) |
379 | | int nT, int cIdx, |
380 | | bool transform_skip_flag, bool intra, int rdpcmMode) |
381 | 0 | { |
382 | 0 | const seq_parameter_set& sps = tctx->img->get_sps(); |
383 | 0 | const pic_parameter_set& pps = tctx->img->get_pps(); |
384 | |
|
385 | 0 | int qP; |
386 | 0 | switch (cIdx) { |
387 | 0 | case 0: qP = tctx->qPYPrime; break; |
388 | 0 | case 1: qP = tctx->qPCbPrime; break; |
389 | 0 | case 2: qP = tctx->qPCrPrime; break; |
390 | 0 | default: qP = 0; assert(0); break; // should never happen |
391 | 0 | } |
392 | | |
393 | 0 | logtrace(LogTransform,"qP: %d\n",qP); |
394 | | |
395 | |
|
396 | 0 | int16_t* coeff; |
397 | 0 | int coeffStride; |
398 | |
|
399 | 0 | coeff = tctx->coeffBuf; |
400 | 0 | coeffStride = nT; |
401 | | |
402 | | |
403 | | |
404 | | |
405 | |
|
406 | 0 | pixel_t* pred; |
407 | 0 | int stride; |
408 | 0 | pred = tctx->img->get_image_plane_at_pos_NEW<pixel_t>(cIdx, xT,yT); |
409 | 0 | stride = tctx->img->get_image_stride(cIdx); |
410 | | |
411 | | // We explicitly include the case for sizeof(pixel_t)==1 so that the compiler |
412 | | // can optimize away a lot of code for 8-bit pixels. |
413 | 0 | const int bit_depth = ((sizeof(pixel_t)==1) ? 8 : sps.get_bit_depth(cIdx)); |
414 | | |
415 | | //assert(intra == (tctx->img->get_pred_mode(xT,yT)==MODE_INTRA)); |
416 | 0 | int cuPredModeIntra = (tctx->img->get_pred_mode(xT,yT)==MODE_INTRA); |
417 | |
|
418 | 0 | bool rotateCoeffs = (sps.range_extension.transform_skip_rotation_enabled_flag && |
419 | 0 | nT == 4 && |
420 | 0 | cuPredModeIntra); |
421 | |
|
422 | 0 | if (tctx->cu_transquant_bypass_flag) { |
423 | |
|
424 | 0 | int32_t residual_buffer[32*32]; |
425 | |
|
426 | 0 | int32_t* residual; |
427 | 0 | if (cIdx==0) residual = tctx->residual_luma; |
428 | 0 | else residual = residual_buffer; |
429 | | |
430 | | |
431 | | // TODO: we could fold the coefficient rotation into the coefficient expansion here: |
432 | 0 | for (int i=0;i<tctx->nCoeff[cIdx];i++) { |
433 | 0 | int32_t currCoeff = tctx->coeffList[cIdx][i]; |
434 | 0 | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = currCoeff; |
435 | 0 | } |
436 | |
|
437 | 0 | if (rotateCoeffs) { |
438 | 0 | tctx->decctx->acceleration.rotate_coefficients(coeff, nT); |
439 | 0 | } |
440 | |
|
441 | 0 | if (rdpcmMode) { |
442 | 0 | if (rdpcmMode==2) |
443 | 0 | tctx->decctx->acceleration.transform_bypass_rdpcm_v(residual, coeff, nT); |
444 | 0 | else |
445 | 0 | tctx->decctx->acceleration.transform_bypass_rdpcm_h(residual, coeff, nT); |
446 | 0 | } |
447 | 0 | else { |
448 | 0 | tctx->decctx->acceleration.transform_bypass(residual, coeff, nT); |
449 | 0 | } |
450 | |
|
451 | 0 | if (cIdx != 0) { |
452 | 0 | if (tctx->ResScaleVal != 0) { |
453 | 0 | cross_comp_pred(tctx, residual, nT); |
454 | 0 | } |
455 | 0 | } |
456 | |
|
457 | 0 | tctx->decctx->acceleration.add_residual(pred,stride, residual,nT, bit_depth); |
458 | |
|
459 | 0 | if (rotateCoeffs) { |
460 | 0 | memset(coeff, 0, nT*nT*sizeof(int16_t)); // delete all, because we moved the coeffs around |
461 | 0 | } |
462 | 0 | } |
463 | 0 | else { |
464 | | // (8.6.3) |
465 | |
|
466 | 0 | int bdShift = (cIdx==0 ? sps.BitDepth_Y : sps.BitDepth_C) + Log2(nT) - 5; |
467 | |
|
468 | 0 | logtrace(LogTransform,"bdShift=%d\n",bdShift); |
469 | |
|
470 | 0 | logtrace(LogTransform,"dequant %d;%d cIdx=%d qp=%d\n",xT*(cIdx?2:1),yT*(cIdx?2:1),cIdx,qP); |
471 | | |
472 | | |
473 | | // --- inverse quantization --- |
474 | |
|
475 | 0 | if (sps.scaling_list_enable_flag==0) { |
476 | | |
477 | | //const int m_x_y = 16; |
478 | 0 | const int m_x_y = 1; |
479 | 0 | bdShift -= 4; // this is equivalent to having a m_x_y of 16 and we can use 32bit integers |
480 | |
|
481 | 0 | const int offset = (1<<(bdShift-1)); |
482 | 0 | const int fact = m_x_y * levelScale[qP%6] << (qP/6); |
483 | | |
484 | | // Fast path: when coeffList[i]*fact (|coeffList| <= 32767) fits in int32, |
485 | | // the dequant can run in int32 SIMD. Otherwise (very high QP, high bit |
486 | | // depth) fall back to the scalar int64 loop. |
487 | 0 | if (fact <= 32767) { |
488 | 0 | tctx->decctx->acceleration.dequant_coeff_block(tctx->coeffBuf, |
489 | 0 | tctx->coeffList[cIdx], |
490 | 0 | tctx->coeffPos[cIdx], |
491 | 0 | tctx->nCoeff[cIdx], |
492 | 0 | fact, offset, bdShift); |
493 | 0 | } |
494 | 0 | else { |
495 | 0 | for (int i=0;i<tctx->nCoeff[cIdx];i++) { |
496 | 0 | int64_t currCoeff = tctx->coeffList[cIdx][i]; |
497 | 0 | currCoeff = Clip3(-32768,32767, |
498 | 0 | ( (currCoeff * fact + offset ) >> bdShift)); |
499 | 0 | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = currCoeff; |
500 | 0 | } |
501 | 0 | } |
502 | 0 | } |
503 | 0 | else { |
504 | 0 | const int offset = (1<<(bdShift-1)); |
505 | |
|
506 | 0 | const uint8_t* sclist; |
507 | 0 | int matrixID = cIdx; |
508 | |
|
509 | 0 | if (nT==32) { |
510 | 0 | matrixID=0; |
511 | 0 | } |
512 | |
|
513 | 0 | if (!intra) { |
514 | 0 | if (nT<32) { matrixID += 3; } |
515 | 0 | else { matrixID++; } |
516 | 0 | } |
517 | |
|
518 | 0 | switch (nT) { |
519 | 0 | case 4: sclist = &pps.scaling_list.ScalingFactor_Size0[matrixID][0][0]; break; |
520 | 0 | case 8: sclist = &pps.scaling_list.ScalingFactor_Size1[matrixID][0][0]; break; |
521 | 0 | case 16: sclist = &pps.scaling_list.ScalingFactor_Size2[matrixID][0][0]; break; |
522 | 0 | case 32: sclist = &pps.scaling_list.ScalingFactor_Size3[matrixID][0][0]; break; |
523 | 0 | default: assert(0); sclist = nullptr; |
524 | 0 | } |
525 | | |
526 | 0 | for (int i=0;i<tctx->nCoeff[cIdx];i++) { |
527 | 0 | int pos = tctx->coeffPos[cIdx][i]; |
528 | |
|
529 | 0 | const int m_x_y = sclist[pos]; |
530 | 0 | const int fact = m_x_y * levelScale[qP%6] << (qP/6); |
531 | |
|
532 | 0 | int64_t currCoeff = tctx->coeffList[cIdx][i]; |
533 | |
|
534 | 0 | currCoeff = Clip3(-32768,32767, |
535 | 0 | ( (currCoeff * fact + offset ) >> bdShift)); |
536 | |
|
537 | 0 | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = currCoeff; |
538 | 0 | } |
539 | 0 | } |
540 | | |
541 | | |
542 | | // --- do transform or skip --- |
543 | | |
544 | 0 | logtrace(LogTransform,"coefficients OUT:\n"); |
545 | 0 | for (int y=0;y<nT;y++) { |
546 | 0 | logtrace(LogTransform," "); |
547 | 0 | for (int x=0;x<nT;x++) { |
548 | 0 | logtrace(LogTransform,"*%3d ", coeff[x+y*coeffStride]); |
549 | 0 | } |
550 | 0 | logtrace(LogTransform,"*\n"); |
551 | 0 | } |
552 | |
|
553 | | #ifdef DE265_LOG_TRACE |
554 | | int bdShift2 = (cIdx==0) ? 20-sps.BitDepth_Y : 20-sps.BitDepth_C; |
555 | | #endif |
556 | |
|
557 | 0 | logtrace(LogTransform,"bdShift2=%d\n",bdShift2); |
558 | |
|
559 | 0 | logtrace(LogSlice,"get_transform_skip_flag(%d,%d, cIdx=%d)=%d\n",xT,yT,cIdx, |
560 | 0 | transform_skip_flag); |
561 | |
|
562 | 0 | if (transform_skip_flag) { |
563 | |
|
564 | 0 | int extended_precision_processing_flag = 0; |
565 | 0 | int Log2nTbS = Log2(nT); |
566 | 0 | int bdShift = std::max( 20 - bit_depth, extended_precision_processing_flag ? 11 : 0 ); |
567 | 0 | int tsShift = (extended_precision_processing_flag ? std::min( 5, bdShift - 2 ) : 5 ) |
568 | 0 | + Log2nTbS; |
569 | |
|
570 | 0 | if (rotateCoeffs) { |
571 | 0 | tctx->decctx->acceleration.rotate_coefficients(coeff, nT); |
572 | 0 | } |
573 | |
|
574 | 0 | int32_t residual_buffer[32*32]; |
575 | |
|
576 | 0 | int32_t* residual; |
577 | 0 | if (cIdx==0) residual = tctx->residual_luma; |
578 | 0 | else residual = residual_buffer; |
579 | |
|
580 | 0 | if (rdpcmMode) { |
581 | | /* |
582 | | if (rdpcmMode==2) |
583 | | tctx->decctx->acceleration.transform_skip_rdpcm_v(pred,coeff, Log2(nT), stride, bit_depth); |
584 | | else |
585 | | tctx->decctx->acceleration.transform_skip_rdpcm_h(pred,coeff, Log2(nT), stride, bit_depth); |
586 | | */ |
587 | |
|
588 | 0 | if (rdpcmMode==2) |
589 | 0 | tctx->decctx->acceleration.rdpcm_v(residual, coeff,nT, tsShift,bdShift); |
590 | 0 | else |
591 | 0 | tctx->decctx->acceleration.rdpcm_h(residual, coeff,nT, tsShift,bdShift); |
592 | 0 | } |
593 | 0 | else { |
594 | | //tctx->decctx->acceleration.transform_skip(pred, coeff, stride, bit_depth); |
595 | |
|
596 | 0 | tctx->decctx->acceleration.transform_skip_residual(residual, coeff, nT, tsShift, bdShift); |
597 | 0 | } |
598 | |
|
599 | 0 | if (cIdx != 0) { |
600 | 0 | if (tctx->ResScaleVal != 0) { |
601 | 0 | cross_comp_pred(tctx, residual, nT); |
602 | 0 | } |
603 | 0 | } |
604 | |
|
605 | 0 | tctx->decctx->acceleration.add_residual(pred,stride, residual,nT, bit_depth); |
606 | |
|
607 | 0 | if (rotateCoeffs) { |
608 | 0 | memset(coeff, 0, nT*nT*sizeof(int16_t)); // delete all, because we moved the coeffs around |
609 | 0 | } |
610 | 0 | } |
611 | 0 | else { |
612 | 0 | int trType; |
613 | | |
614 | | //if (nT==4 && cIdx==0 && tctx->img->get_pred_mode(xT,yT)==MODE_INTRA) { |
615 | 0 | if (nT==4 && cIdx==0 && cuPredModeIntra) { |
616 | 0 | trType=1; |
617 | 0 | } |
618 | 0 | else { |
619 | 0 | trType=0; |
620 | 0 | } |
621 | |
|
622 | 0 | assert(rdpcmMode==0); |
623 | | |
624 | | |
625 | 0 | if (tctx->img->get_pps().range_extension.cross_component_prediction_enabled_flag) { |
626 | | // cross-component-prediction: transform to residual buffer and add in a separate step |
627 | |
|
628 | 0 | transform_coefficients_explicit(tctx, coeff, coeffStride, nT, trType, |
629 | 0 | pred, stride, bit_depth, cIdx); |
630 | 0 | } |
631 | 0 | else { |
632 | 0 | transform_coefficients(&tctx->decctx->acceleration, coeff, coeffStride, nT, trType, |
633 | 0 | pred, stride, bit_depth); |
634 | 0 | } |
635 | 0 | } |
636 | 0 | } |
637 | | |
638 | | |
639 | 0 | logtrace(LogTransform,"pixels (cIdx:%d), position %d %d:\n",cIdx, xT,yT); |
640 | |
|
641 | 0 | for (int y=0;y<nT;y++) { |
642 | 0 | logtrace(LogTransform,"RECO-%3d-%3d-%d ",xT,yT+y,cIdx); |
643 | |
|
644 | 0 | for (int x=0;x<nT;x++) { |
645 | 0 | logtrace(LogTransform,"*%03x ", pred[x+y*stride]); |
646 | 0 | } |
647 | |
|
648 | 0 | logtrace(LogTransform,"*\n"); |
649 | 0 | } |
650 | | |
651 | | // zero out scrap coefficient buffer again |
652 | |
|
653 | 0 | for (int i=0;i<tctx->nCoeff[cIdx];i++) { |
654 | 0 | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = 0; |
655 | 0 | } |
656 | 0 | } Unexecuted instantiation: void scale_coefficients_internal<unsigned short>(thread_context*, int, int, int, int, int, int, bool, bool, int) Unexecuted instantiation: void scale_coefficients_internal<unsigned char>(thread_context*, int, int, int, int, int, int, bool, bool, int) |
657 | | |
658 | | |
659 | | void scale_coefficients(thread_context* tctx, |
660 | | int xT,int yT, // position of TU in frame (chroma adapted) |
661 | | int x0,int y0, // position of CU in frame (chroma adapted) |
662 | | int nT, int cIdx, |
663 | | bool transform_skip_flag, bool intra, |
664 | | int rdpcmMode // 0 - off, 1 - Horizontal, 2 - Vertical |
665 | | ) |
666 | 0 | { |
667 | 0 | if (tctx->img->high_bit_depth(cIdx)) { |
668 | 0 | scale_coefficients_internal<uint16_t>(tctx, xT,yT, x0,y0, nT,cIdx, transform_skip_flag, intra, |
669 | 0 | rdpcmMode); |
670 | 0 | } else { |
671 | 0 | scale_coefficients_internal<uint8_t> (tctx, xT,yT, x0,y0, nT,cIdx, transform_skip_flag, intra, |
672 | 0 | rdpcmMode); |
673 | 0 | } |
674 | 0 | } |
675 | | |
676 | | |
677 | | //#define QUANT_IQUANT_SHIFT 20 // Q(QP%6) * IQ(QP%6) = 2^20 |
678 | 0 | #define QUANT_SHIFT 14 // Q(4) = 2^14 |
679 | | //#define SCALE_BITS 15 // Inherited from TMuC, presumably for fractional bit estimates in RDOQ |
680 | 0 | #define MAX_TR_DYNAMIC_RANGE 15 // Maximum transform dynamic range (excluding sign bit) |
681 | | |
682 | | |
683 | | const static uint16_t g_quantScales[6] = { |
684 | | 26214,23302,20560,18396,16384,14564 |
685 | | }; |
686 | | |
687 | | void quant_coefficients(//encoder_context* ectx, |
688 | | int16_t* out_coeff, |
689 | | const int16_t* in_coeff, |
690 | | int log2TrSize, int qp, |
691 | | bool intra) |
692 | 0 | { |
693 | 0 | const int qpDiv6 = qp / 6; |
694 | 0 | const int qpMod6 = qp % 6; |
695 | | |
696 | | //int uiLog2TrSize = xLog2( iWidth - 1); |
697 | |
|
698 | 0 | int uiQ = g_quantScales[qpMod6]; |
699 | 0 | int bitDepth = 8; |
700 | 0 | int transformShift = MAX_TR_DYNAMIC_RANGE - bitDepth - log2TrSize; // Represents scaling through forward transform |
701 | 0 | int qBits = QUANT_SHIFT + qpDiv6 + transformShift; |
702 | | |
703 | | /* TODO: originally, this was checking for intra slices, why not for intra mode ? |
704 | | */ |
705 | 0 | int rnd = (intra ? 171 : 85) << (qBits-9); |
706 | |
|
707 | 0 | int x, y; |
708 | |
|
709 | 0 | int nStride = (1<<log2TrSize); |
710 | |
|
711 | 0 | for (y=0; y < (1<<log2TrSize) ; y++) { |
712 | 0 | for (x=0; x < (1<<log2TrSize) ; x++) { |
713 | 0 | int level; |
714 | 0 | int sign; |
715 | 0 | int blockPos = y * nStride + x; |
716 | 0 | level = in_coeff[blockPos]; |
717 | | //logtrace(LogTransform,"(%d,%d) %d -> ", x,y,level); |
718 | 0 | sign = (level < 0 ? -1: 1); |
719 | |
|
720 | 0 | level = (std::abs(level) * uiQ + rnd ) >> qBits; |
721 | 0 | level *= sign; |
722 | 0 | out_coeff[blockPos] = Clip3(-32768, 32767, level); |
723 | | //logtrace(LogTransform,"%d\n", out_coeff[blockPos]); |
724 | 0 | } |
725 | 0 | } |
726 | 0 | } |
727 | | |
728 | | |
729 | | void dequant_coefficients(int16_t* out_coeff, |
730 | | const int16_t* in_coeff, |
731 | | int log2TrSize, int qP) |
732 | 0 | { |
733 | 0 | const int m_x_y = 1; |
734 | 0 | int bitDepth = 8; |
735 | 0 | int bdShift = bitDepth + log2TrSize - 5; |
736 | 0 | bdShift -= 4; // this is equivalent to having a m_x_y of 16 and we can use 32bit integers |
737 | |
|
738 | 0 | const int offset = (1<<(bdShift-1)); |
739 | 0 | const int fact = m_x_y * levelScale[qP%6] << (qP/6); |
740 | | |
741 | | //int blkSize = (1<<log2TrSize); |
742 | 0 | int nCoeff = (1<<(log2TrSize<<1)); |
743 | |
|
744 | 0 | for (int i=0;i<nCoeff;i++) { |
745 | | |
746 | | // usually, this needs to be 64bit, but because we modify the shift above, we can use 16 bit |
747 | 0 | int32_t currCoeff = in_coeff[i]; |
748 | | |
749 | | //logtrace(LogTransform,"coefficient[%d] = %d\n",i,currCoeff); |
750 | |
|
751 | 0 | currCoeff = Clip3(-32768,32767, |
752 | 0 | ( (currCoeff * fact + offset ) >> bdShift)); |
753 | | |
754 | | //logtrace(LogTransform," -> %d\n",currCoeff); |
755 | |
|
756 | 0 | out_coeff[i] = currCoeff; |
757 | 0 | } |
758 | 0 | } |