/src/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 | 11.9M | { |
34 | 11.9M | logtrace(LogTransform,">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> decode_quantization_parameters(int xC,int yC)=(%d,%d)\n", xC,yC); |
35 | | |
36 | 11.9M | const pic_parameter_set& pps = tctx->img->get_pps(); |
37 | 11.9M | const seq_parameter_set& sps = tctx->img->get_sps(); |
38 | 11.9M | slice_segment_header* shdr = tctx->shdr; |
39 | | |
40 | | // top left pixel position of current quantization group |
41 | 11.9M | int xQG = xCUBase - (xCUBase & ((1<<pps.Log2MinCuQpDeltaSize)-1)); |
42 | 11.9M | int yQG = yCUBase - (yCUBase & ((1<<pps.Log2MinCuQpDeltaSize)-1)); |
43 | | |
44 | 11.9M | 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 | 11.9M | if (xQG != tctx->currentQG_x || |
61 | 11.3M | yQG != tctx->currentQG_y) |
62 | 663k | { |
63 | 663k | tctx->lastQPYinPreviousQG = tctx->currentQPY; |
64 | 663k | tctx->currentQG_x = xQG; |
65 | 663k | tctx->currentQG_y = yQG; |
66 | 663k | } |
67 | | |
68 | 11.9M | int qPY_PRED; |
69 | | |
70 | | // first QG in CTB row ? |
71 | | |
72 | 11.9M | int ctbLSBMask = ((1<<sps.Log2CtbSizeY)-1); |
73 | 11.9M | 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 | 11.9M | int first_ctb_in_slice_RS = tctx->shdr->SliceAddrRS; |
78 | | |
79 | 11.9M | int SliceStartX = (first_ctb_in_slice_RS % sps.PicWidthInCtbsY) * sps.CtbSizeY; |
80 | 11.9M | int SliceStartY = (first_ctb_in_slice_RS / sps.PicWidthInCtbsY) * sps.CtbSizeY; |
81 | | |
82 | 11.9M | bool firstQGInSlice = (SliceStartX == xQG && SliceStartY == yQG); |
83 | | |
84 | | // first QG in tile ? |
85 | | |
86 | 11.9M | bool firstQGInTile = false; |
87 | 11.9M | if (pps.tiles_enabled_flag) { |
88 | 359k | if ((xQG & ((1 << sps.Log2CtbSizeY)-1)) == 0 && |
89 | 359k | (yQG & ((1 << sps.Log2CtbSizeY)-1)) == 0) |
90 | 359k | { |
91 | 359k | int ctbX = xQG >> sps.Log2CtbSizeY; |
92 | 359k | int ctbY = yQG >> sps.Log2CtbSizeY; |
93 | | |
94 | 359k | firstQGInTile = pps.is_tile_start_CTB(ctbX,ctbY); // TODO: this is slow |
95 | 359k | } |
96 | 359k | } |
97 | | |
98 | | |
99 | 11.9M | if (firstQGInSlice || firstQGInTile || |
100 | 11.7M | (firstInCTBRow && pps.entropy_coding_sync_enabled_flag)) { |
101 | 371k | qPY_PRED = tctx->shdr->SliceQPY; |
102 | 371k | } |
103 | 11.6M | else { |
104 | 11.6M | qPY_PRED = tctx->lastQPYinPreviousQG; |
105 | 11.6M | } |
106 | | |
107 | | |
108 | 11.9M | int qPYA,qPYB; |
109 | | |
110 | 11.9M | if (tctx->img->available_zscan(xQG,yQG, xQG-1,yQG)) { |
111 | 11.0M | int xTmp = (xQG-1) >> sps.Log2MinTrafoSize; |
112 | 11.0M | int yTmp = (yQG ) >> sps.Log2MinTrafoSize; |
113 | 11.0M | int minTbAddrA = pps.scan->MinTbAddrZS[xTmp + yTmp*sps.PicWidthInTbsY]; |
114 | 11.0M | uint32_t ctbAddrA = minTbAddrA >> (2 * (sps.Log2CtbSizeY-sps.Log2MinTrafoSize)); |
115 | 11.0M | if (ctbAddrA == tctx->CtbAddrInTS) { |
116 | 601k | qPYA = tctx->img->get_QPY(xQG-1,yQG); |
117 | 601k | } |
118 | 10.4M | else { |
119 | 10.4M | qPYA = qPY_PRED; |
120 | 10.4M | } |
121 | 11.0M | } |
122 | 946k | else { |
123 | 946k | qPYA = qPY_PRED; |
124 | 946k | } |
125 | | |
126 | 11.9M | if (tctx->img->available_zscan(xQG,yQG, xQG,yQG-1)) { |
127 | 9.61M | int xTmp = (xQG ) >> sps.Log2MinTrafoSize; |
128 | 9.61M | int yTmp = (yQG-1) >> sps.Log2MinTrafoSize; |
129 | 9.61M | uint32_t minTbAddrB = pps.scan->MinTbAddrZS[xTmp + yTmp*sps.PicWidthInTbsY]; |
130 | 9.61M | uint32_t ctbAddrB = minTbAddrB >> (2 * (sps.Log2CtbSizeY-sps.Log2MinTrafoSize)); |
131 | 9.61M | if (ctbAddrB == tctx->CtbAddrInTS) { |
132 | 620k | qPYB = tctx->img->get_QPY(xQG,yQG-1); |
133 | 620k | } |
134 | 8.99M | else { |
135 | 8.99M | qPYB = qPY_PRED; |
136 | 8.99M | } |
137 | 9.61M | } |
138 | 2.37M | else { |
139 | 2.37M | qPYB = qPY_PRED; |
140 | 2.37M | } |
141 | | |
142 | 11.9M | qPY_PRED = (qPYA + qPYB + 1)>>1; |
143 | | |
144 | 11.9M | logtrace(LogTransform,"qPY_PRED = %d (%d, %d)\n",qPY_PRED, qPYA, qPYB); |
145 | | |
146 | 11.9M | int QPY = ((qPY_PRED + tctx->CuQpDelta + 52+2*sps.QpBdOffset_Y) % |
147 | 11.9M | (52 + sps.QpBdOffset_Y)) - sps.QpBdOffset_Y; |
148 | | |
149 | 11.9M | assert(QPY >= -sps.QpBdOffset_Y && QPY <= 51); |
150 | | |
151 | 11.9M | tctx->qPYPrime = QPY + sps.QpBdOffset_Y; |
152 | | |
153 | 11.9M | int qPiCb = Clip3(-sps.QpBdOffset_C,57, QPY+pps.pic_cb_qp_offset + shdr->slice_cb_qp_offset + tctx->CuQpOffsetCb); |
154 | 11.9M | int qPiCr = Clip3(-sps.QpBdOffset_C,57, QPY+pps.pic_cr_qp_offset + shdr->slice_cr_qp_offset + tctx->CuQpOffsetCr); |
155 | | |
156 | 11.9M | logtrace(LogTransform,"qPiCb:%d (%d %d), qPiCr:%d (%d %d)\n", |
157 | 11.9M | qPiCb, pps.pic_cb_qp_offset, shdr->slice_cb_qp_offset, |
158 | 11.9M | qPiCr, pps.pic_cr_qp_offset, shdr->slice_cr_qp_offset); |
159 | | |
160 | 11.9M | int qPCb,qPCr; |
161 | | |
162 | 11.9M | if (sps.ChromaArrayType == CHROMA_420) { |
163 | 8.97M | qPCb = table8_22(qPiCb); |
164 | 8.97M | qPCr = table8_22(qPiCr); |
165 | 8.97M | } |
166 | 2.98M | else { |
167 | 2.98M | qPCb = qPiCb; |
168 | 2.98M | qPCr = qPiCr; |
169 | 2.98M | } |
170 | | |
171 | | //printf("q: %d %d\n",qPiCb, qPCb); |
172 | | |
173 | 11.9M | tctx->qPCbPrime = qPCb + sps.QpBdOffset_C; |
174 | 11.9M | if (tctx->qPCbPrime<0) { |
175 | 0 | tctx->qPCbPrime = 0; |
176 | 0 | } |
177 | | |
178 | 11.9M | tctx->qPCrPrime = qPCr + sps.QpBdOffset_C; |
179 | 11.9M | 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 | 11.9M | 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 | 11.9M | if (log2CbSize<3) { log2CbSize=3; } |
198 | | |
199 | 11.9M | tctx->img->set_QPY(xCUBase, yCUBase, log2CbSize, QPY); |
200 | 11.9M | 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 | 11.9M | logtrace(LogTransform,"qPY(%d,%d,%d)= %d, qPYPrime=%d\n", |
208 | 11.9M | xCUBase,yCUBase,1<<log2CbSize,QPY,tctx->qPYPrime); |
209 | 11.9M | } |
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 | 25.0M | { |
218 | 25.0M | logtrace(LogTransform,"transform --- trType: %d nT: %d\n",trType,nT); |
219 | | |
220 | | |
221 | 25.0M | if (trType==1) { |
222 | | |
223 | 12.0M | acceleration->transform_4x4_dst_add<pixel_t>(dst, coeff, dstStride, bit_depth); |
224 | | |
225 | 12.9M | } else { |
226 | | |
227 | 12.9M | /**/ if (nT==4) { acceleration->transform_add<pixel_t>(0,dst,coeff,dstStride, bit_depth); } |
228 | 5.08M | else if (nT==8) { acceleration->transform_add<pixel_t>(1,dst,coeff,dstStride, bit_depth); } |
229 | 1.62M | else if (nT==16) { acceleration->transform_add<pixel_t>(2,dst,coeff,dstStride, bit_depth); } |
230 | 330k | else { acceleration->transform_add<pixel_t>(3,dst,coeff,dstStride, bit_depth); } |
231 | 12.9M | } |
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 | 25.0M | } void transform_coefficients<unsigned short>(acceleration_functions*, short*, int, int, int, unsigned short*, int, int) Line | Count | Source | 217 | 3.75M | { | 218 | 3.75M | logtrace(LogTransform,"transform --- trType: %d nT: %d\n",trType,nT); | 219 | | | 220 | | | 221 | 3.75M | if (trType==1) { | 222 | | | 223 | 2.04M | acceleration->transform_4x4_dst_add<pixel_t>(dst, coeff, dstStride, bit_depth); | 224 | | | 225 | 2.04M | } else { | 226 | | | 227 | 1.70M | /**/ if (nT==4) { acceleration->transform_add<pixel_t>(0,dst,coeff,dstStride, bit_depth); } | 228 | 370k | else if (nT==8) { acceleration->transform_add<pixel_t>(1,dst,coeff,dstStride, bit_depth); } | 229 | 65.3k | else if (nT==16) { acceleration->transform_add<pixel_t>(2,dst,coeff,dstStride, bit_depth); } | 230 | 20.8k | else { acceleration->transform_add<pixel_t>(3,dst,coeff,dstStride, bit_depth); } | 231 | 1.70M | } | 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 | 3.75M | } |
void transform_coefficients<unsigned char>(acceleration_functions*, short*, int, int, int, unsigned char*, int, int) Line | Count | Source | 217 | 21.2M | { | 218 | 21.2M | logtrace(LogTransform,"transform --- trType: %d nT: %d\n",trType,nT); | 219 | | | 220 | | | 221 | 21.2M | if (trType==1) { | 222 | | | 223 | 10.0M | acceleration->transform_4x4_dst_add<pixel_t>(dst, coeff, dstStride, bit_depth); | 224 | | | 225 | 11.2M | } else { | 226 | | | 227 | 11.2M | /**/ if (nT==4) { acceleration->transform_add<pixel_t>(0,dst,coeff,dstStride, bit_depth); } | 228 | 4.71M | else if (nT==8) { acceleration->transform_add<pixel_t>(1,dst,coeff,dstStride, bit_depth); } | 229 | 1.56M | else if (nT==16) { acceleration->transform_add<pixel_t>(2,dst,coeff,dstStride, bit_depth); } | 230 | 309k | else { acceleration->transform_add<pixel_t>(3,dst,coeff,dstStride, bit_depth); } | 231 | 11.2M | } | 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 | 21.2M | } |
|
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 | |
|
249 | 0 | for (int y=0;y<nT;y++) |
250 | 0 | for (int x=0;x<nT;x++) { |
251 | | /* TODO: the most usual case is definitely BitDepthY == BitDepthC, in which case |
252 | | we could just omit two shifts. The second most common case is probably |
253 | | BitDepthY>BitDepthC, for which we could also eliminate one shift. The remaining |
254 | | case is also one shift only. |
255 | | */ |
256 | |
|
257 | 0 | residual[y*nT+x] += (tctx->ResScaleVal * |
258 | 0 | static_cast<int32_t>((static_cast<uint32_t>(tctx->residual_luma[y*nT+x]) << BitDepthC ) >> BitDepthY ) ) >> 3; |
259 | 0 | } |
260 | 0 | } |
261 | | |
262 | | |
263 | | template <class pixel_t> |
264 | | void transform_coefficients_explicit(thread_context* tctx, |
265 | | int16_t* coeff, int coeffStride, int nT, int trType, |
266 | | pixel_t* dst, int dstStride, int bit_depth, int cIdx) |
267 | 0 | { |
268 | 0 | logtrace(LogTransform,"transform --- trType: %d nT: %d\n",trType,nT); |
269 | |
|
270 | 0 | const acceleration_functions* acceleration = &tctx->decctx->acceleration; |
271 | |
|
272 | 0 | int32_t residual_buffer[32*32]; |
273 | 0 | int32_t* residual; |
274 | 0 | if (cIdx==0) { |
275 | 0 | residual = tctx->residual_luma; |
276 | 0 | } |
277 | 0 | else { |
278 | 0 | residual = residual_buffer; |
279 | 0 | } |
280 | | |
281 | | |
282 | | // TODO |
283 | 0 | int bdShift = 20 - bit_depth; |
284 | 0 | int max_coeff_bits = 15; |
285 | |
|
286 | 0 | if (trType==1) { |
287 | |
|
288 | 0 | acceleration->transform_idst_4x4(residual, coeff, bdShift, max_coeff_bits); |
289 | |
|
290 | 0 | } else { |
291 | | |
292 | 0 | /**/ if (nT==4) { acceleration->transform_idct_4x4(residual,coeff,bdShift,max_coeff_bits); } |
293 | 0 | else if (nT==8) { acceleration->transform_idct_8x8(residual,coeff,bdShift,max_coeff_bits); } |
294 | 0 | else if (nT==16) { acceleration->transform_idct_16x16(residual,coeff,bdShift,max_coeff_bits); } |
295 | 0 | else { acceleration->transform_idct_32x32(residual,coeff,bdShift,max_coeff_bits); } |
296 | 0 | } |
297 | | |
298 | | |
299 | | //printBlk("prediction",(uint8_t*)dst,nT,dstStride); |
300 | | //printBlk("residual",residual,nT,nT); |
301 | |
|
302 | 0 | if (cIdx != 0) { |
303 | 0 | if (tctx->ResScaleVal != 0) { |
304 | 0 | cross_comp_pred(tctx, residual, nT); |
305 | 0 | } |
306 | | |
307 | | //printBlk("cross-comp-pred modified residual",residual,nT,nT); |
308 | 0 | } |
309 | |
|
310 | 0 | acceleration->add_residual(dst,dstStride, residual,nT, bit_depth); |
311 | 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) |
312 | | |
313 | | |
314 | | void inv_transform(acceleration_functions* acceleration, |
315 | | uint8_t* dst, int dstStride, int16_t* coeff, |
316 | | int log2TbSize, int trType) |
317 | 0 | { |
318 | 0 | if (trType==1) { |
319 | 0 | assert(log2TbSize==2); |
320 | | |
321 | 0 | acceleration->transform_4x4_dst_add_8(dst, coeff, dstStride); |
322 | |
|
323 | 0 | } else { |
324 | 0 | acceleration->transform_add_8[log2TbSize-2](dst,coeff,dstStride); |
325 | 0 | } |
326 | | |
327 | |
|
328 | | #if 0 |
329 | | int nT = 1<<log2TbSize; |
330 | | printf("decoded pixels:\n"); |
331 | | for (int y=0;y<nT;y++,printf("\n")) |
332 | | for (int x=0;x<nT;x++) { |
333 | | printf("%02x ",dst[y*dstStride+x]); |
334 | | } |
335 | | #endif |
336 | 0 | } |
337 | | |
338 | | |
339 | | void fwd_transform(acceleration_functions* acceleration, |
340 | | int16_t* coeff, int coeffStride, int log2TbSize, int trType, |
341 | | const int16_t* src, int srcStride) |
342 | 0 | { |
343 | 0 | logtrace(LogTransform,"transform --- trType: %d nT: %d\n",trType,1<<log2TbSize); |
344 | |
|
345 | 0 | if (trType==1) { |
346 | | // DST 4x4 |
347 | |
|
348 | 0 | acceleration->fwd_transform_4x4_dst_8(coeff, src, srcStride); |
349 | 0 | } else { |
350 | | // DCT 4x4, 8x8, 16x16, 32x32 |
351 | |
|
352 | 0 | acceleration->fwd_transform_8[log2TbSize-2](coeff,src,srcStride); |
353 | 0 | } |
354 | 0 | } |
355 | | |
356 | | |
357 | | |
358 | | static const int levelScale[] = { 40,45,51,57,64,72 }; |
359 | | |
360 | | // (8.6.2) and (8.6.3) |
361 | | template <class pixel_t> |
362 | | void scale_coefficients_internal(thread_context* tctx, |
363 | | int xT,int yT, // position of TU in frame (chroma adapted) |
364 | | int x0,int y0, // position of CU in frame (chroma adapted) |
365 | | int nT, int cIdx, |
366 | | bool transform_skip_flag, bool intra, int rdpcmMode) |
367 | 37.5M | { |
368 | 37.5M | const seq_parameter_set& sps = tctx->img->get_sps(); |
369 | 37.5M | const pic_parameter_set& pps = tctx->img->get_pps(); |
370 | | |
371 | 37.5M | int qP; |
372 | 37.5M | switch (cIdx) { |
373 | 23.9M | case 0: qP = tctx->qPYPrime; break; |
374 | 6.81M | case 1: qP = tctx->qPCbPrime; break; |
375 | 6.78M | case 2: qP = tctx->qPCrPrime; break; |
376 | 0 | default: qP = 0; assert(0); break; // should never happen |
377 | 37.5M | } |
378 | | |
379 | 37.5M | logtrace(LogTransform,"qP: %d\n",qP); |
380 | | |
381 | | |
382 | 37.5M | int16_t* coeff; |
383 | 37.5M | int coeffStride; |
384 | | |
385 | 37.5M | coeff = tctx->coeffBuf; |
386 | 37.5M | coeffStride = nT; |
387 | | |
388 | | |
389 | | |
390 | | |
391 | | |
392 | 37.5M | pixel_t* pred; |
393 | 37.5M | int stride; |
394 | 37.5M | pred = tctx->img->get_image_plane_at_pos_NEW<pixel_t>(cIdx, xT,yT); |
395 | 37.5M | stride = tctx->img->get_image_stride(cIdx); |
396 | | |
397 | | // We explicitly include the case for sizeof(pixel_t)==1 so that the compiler |
398 | | // can optimize away a lot of code for 8-bit pixels. |
399 | 37.5M | const int bit_depth = ((sizeof(pixel_t)==1) ? 8 : sps.get_bit_depth(cIdx)); |
400 | | |
401 | | //assert(intra == (tctx->img->get_pred_mode(xT,yT)==MODE_INTRA)); |
402 | 37.5M | int cuPredModeIntra = (tctx->img->get_pred_mode(xT,yT)==MODE_INTRA); |
403 | | |
404 | 37.5M | bool rotateCoeffs = (sps.range_extension.transform_skip_rotation_enabled_flag && |
405 | 4.39M | nT == 4 && |
406 | 3.86M | cuPredModeIntra); |
407 | | |
408 | 37.5M | if (tctx->cu_transquant_bypass_flag) { |
409 | | |
410 | 2.80M | int32_t residual_buffer[32*32]; |
411 | | |
412 | 2.80M | int32_t* residual; |
413 | 2.80M | if (cIdx==0) residual = tctx->residual_luma; |
414 | 1.06M | else residual = residual_buffer; |
415 | | |
416 | | |
417 | | // TODO: we could fold the coefficient rotation into the coefficient expansion here: |
418 | 31.0M | for (int i=0;i<tctx->nCoeff[cIdx];i++) { |
419 | 28.2M | int32_t currCoeff = tctx->coeffList[cIdx][i]; |
420 | 28.2M | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = currCoeff; |
421 | 28.2M | } |
422 | | |
423 | 2.80M | if (rotateCoeffs) { |
424 | 1.42M | tctx->decctx->acceleration.rotate_coefficients(coeff, nT); |
425 | 1.42M | } |
426 | | |
427 | 2.80M | if (rdpcmMode) { |
428 | 349k | if (rdpcmMode==2) |
429 | 208k | tctx->decctx->acceleration.transform_bypass_rdpcm_v(residual, coeff, nT); |
430 | 140k | else |
431 | 140k | tctx->decctx->acceleration.transform_bypass_rdpcm_h(residual, coeff, nT); |
432 | 349k | } |
433 | 2.45M | else { |
434 | 2.45M | tctx->decctx->acceleration.transform_bypass(residual, coeff, nT); |
435 | 2.45M | } |
436 | | |
437 | 2.80M | if (cIdx != 0) { |
438 | 1.06M | if (tctx->ResScaleVal != 0) { |
439 | 0 | cross_comp_pred(tctx, residual, nT); |
440 | 0 | } |
441 | 1.06M | } |
442 | | |
443 | 2.80M | tctx->decctx->acceleration.add_residual(pred,stride, residual,nT, bit_depth); |
444 | | |
445 | 2.80M | if (rotateCoeffs) { |
446 | 1.42M | memset(coeff, 0, nT*nT*sizeof(int16_t)); // delete all, because we moved the coeffs around |
447 | 1.42M | } |
448 | 2.80M | } |
449 | 34.7M | else { |
450 | | // (8.6.3) |
451 | | |
452 | 34.7M | int bdShift = (cIdx==0 ? sps.BitDepth_Y : sps.BitDepth_C) + Log2(nT) - 5; |
453 | | |
454 | 34.7M | logtrace(LogTransform,"bdShift=%d\n",bdShift); |
455 | | |
456 | 34.7M | logtrace(LogTransform,"dequant %d;%d cIdx=%d qp=%d\n",xT*(cIdx?2:1),yT*(cIdx?2:1),cIdx,qP); |
457 | | |
458 | | |
459 | | // --- inverse quantization --- |
460 | | |
461 | 34.7M | if (sps.scaling_list_enable_flag==0) { |
462 | | |
463 | | //const int m_x_y = 16; |
464 | 33.0M | const int m_x_y = 1; |
465 | 33.0M | bdShift -= 4; // this is equivalent to having a m_x_y of 16 and we can use 32bit integers |
466 | | |
467 | 33.0M | const int offset = (1<<(bdShift-1)); |
468 | 33.0M | const int fact = m_x_y * levelScale[qP%6] << (qP/6); |
469 | | |
470 | | // Fast path: when coeffList[i]*fact (|coeffList| <= 32767) fits in int32, |
471 | | // the dequant can run in int32 SIMD. Otherwise (very high QP, high bit |
472 | | // depth) fall back to the scalar int64 loop. |
473 | 33.0M | if (fact <= 32767) { |
474 | 32.7M | tctx->decctx->acceleration.dequant_coeff_block(tctx->coeffBuf, |
475 | 32.7M | tctx->coeffList[cIdx], |
476 | 32.7M | tctx->coeffPos[cIdx], |
477 | 32.7M | tctx->nCoeff[cIdx], |
478 | 32.7M | fact, offset, bdShift); |
479 | 32.7M | } |
480 | 281k | else { |
481 | 4.05M | for (int i=0;i<tctx->nCoeff[cIdx];i++) { |
482 | 3.77M | int64_t currCoeff = tctx->coeffList[cIdx][i]; |
483 | 3.77M | currCoeff = Clip3(-32768,32767, |
484 | 3.77M | ( (currCoeff * fact + offset ) >> bdShift)); |
485 | 3.77M | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = currCoeff; |
486 | 3.77M | } |
487 | 281k | } |
488 | 33.0M | } |
489 | 1.67M | else { |
490 | 1.67M | const int offset = (1<<(bdShift-1)); |
491 | | |
492 | 1.67M | const uint8_t* sclist; |
493 | 1.67M | int matrixID = cIdx; |
494 | | |
495 | 1.67M | if (nT==32) { |
496 | 11.4k | matrixID=0; |
497 | 11.4k | } |
498 | | |
499 | 1.67M | if (!intra) { |
500 | 54.9k | if (nT<32) { matrixID += 3; } |
501 | 588 | else { matrixID++; } |
502 | 54.9k | } |
503 | | |
504 | 1.67M | switch (nT) { |
505 | 1.37M | case 4: sclist = &pps.scaling_list.ScalingFactor_Size0[matrixID][0][0]; break; |
506 | 200k | case 8: sclist = &pps.scaling_list.ScalingFactor_Size1[matrixID][0][0]; break; |
507 | 23.1k | case 16: sclist = &pps.scaling_list.ScalingFactor_Size2[matrixID][0][0]; break; |
508 | 11.4k | case 32: sclist = &pps.scaling_list.ScalingFactor_Size3[matrixID][0][0]; break; |
509 | 0 | default: assert(0); sclist = nullptr; |
510 | 1.67M | } |
511 | | |
512 | 10.3M | for (int i=0;i<tctx->nCoeff[cIdx];i++) { |
513 | 8.72M | int pos = tctx->coeffPos[cIdx][i]; |
514 | | |
515 | 8.72M | const int m_x_y = sclist[pos]; |
516 | 8.72M | const int fact = m_x_y * levelScale[qP%6] << (qP/6); |
517 | | |
518 | 8.72M | int64_t currCoeff = tctx->coeffList[cIdx][i]; |
519 | | |
520 | 8.72M | currCoeff = Clip3(-32768,32767, |
521 | 8.72M | ( (currCoeff * fact + offset ) >> bdShift)); |
522 | | |
523 | 8.72M | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = currCoeff; |
524 | 8.72M | } |
525 | 1.61M | } |
526 | | |
527 | | |
528 | | // --- do transform or skip --- |
529 | | |
530 | 34.6M | logtrace(LogTransform,"coefficients OUT:\n"); |
531 | 212M | for (int y=0;y<nT;y++) { |
532 | 178M | logtrace(LogTransform," "); |
533 | 1.58G | for (int x=0;x<nT;x++) { |
534 | 1.40G | logtrace(LogTransform,"*%3d ", coeff[x+y*coeffStride]); |
535 | 1.40G | } |
536 | 178M | logtrace(LogTransform,"*\n"); |
537 | 178M | } |
538 | | |
539 | | #ifdef DE265_LOG_TRACE |
540 | | int bdShift2 = (cIdx==0) ? 20-sps.BitDepth_Y : 20-sps.BitDepth_C; |
541 | | #endif |
542 | | |
543 | 34.6M | logtrace(LogTransform,"bdShift2=%d\n",bdShift2); |
544 | | |
545 | 34.6M | logtrace(LogSlice,"get_transform_skip_flag(%d,%d, cIdx=%d)=%d\n",xT,yT,cIdx, |
546 | 34.6M | transform_skip_flag); |
547 | | |
548 | 34.6M | if (transform_skip_flag) { |
549 | | |
550 | 9.64M | int extended_precision_processing_flag = 0; |
551 | 9.64M | int Log2nTbS = Log2(nT); |
552 | 9.64M | int bdShift = std::max( 20 - bit_depth, extended_precision_processing_flag ? 11 : 0 ); |
553 | 9.64M | int tsShift = (extended_precision_processing_flag ? std::min( 5, bdShift - 2 ) : 5 ) |
554 | 9.64M | + Log2nTbS; |
555 | | |
556 | 9.64M | if (rotateCoeffs) { |
557 | 861k | tctx->decctx->acceleration.rotate_coefficients(coeff, nT); |
558 | 861k | } |
559 | | |
560 | 9.64M | int32_t residual_buffer[32*32]; |
561 | | |
562 | 9.64M | int32_t* residual; |
563 | 9.64M | if (cIdx==0) residual = tctx->residual_luma; |
564 | 3.49M | else residual = residual_buffer; |
565 | | |
566 | 9.64M | if (rdpcmMode) { |
567 | | /* |
568 | | if (rdpcmMode==2) |
569 | | tctx->decctx->acceleration.transform_skip_rdpcm_v(pred,coeff, Log2(nT), stride, bit_depth); |
570 | | else |
571 | | tctx->decctx->acceleration.transform_skip_rdpcm_h(pred,coeff, Log2(nT), stride, bit_depth); |
572 | | */ |
573 | | |
574 | 109k | if (rdpcmMode==2) |
575 | 62.8k | tctx->decctx->acceleration.rdpcm_v(residual, coeff,nT, tsShift,bdShift); |
576 | 46.6k | else |
577 | 46.6k | tctx->decctx->acceleration.rdpcm_h(residual, coeff,nT, tsShift,bdShift); |
578 | 109k | } |
579 | 9.53M | else { |
580 | | //tctx->decctx->acceleration.transform_skip(pred, coeff, stride, bit_depth); |
581 | | |
582 | 9.53M | tctx->decctx->acceleration.transform_skip_residual(residual, coeff, nT, tsShift, bdShift); |
583 | 9.53M | } |
584 | | |
585 | 9.64M | if (cIdx != 0) { |
586 | 3.49M | if (tctx->ResScaleVal != 0) { |
587 | 0 | cross_comp_pred(tctx, residual, nT); |
588 | 0 | } |
589 | 3.49M | } |
590 | | |
591 | 9.64M | tctx->decctx->acceleration.add_residual(pred,stride, residual,nT, bit_depth); |
592 | | |
593 | 9.64M | if (rotateCoeffs) { |
594 | 861k | memset(coeff, 0, nT*nT*sizeof(int16_t)); // delete all, because we moved the coeffs around |
595 | 861k | } |
596 | 9.64M | } |
597 | 25.0M | else { |
598 | 25.0M | int trType; |
599 | | |
600 | | //if (nT==4 && cIdx==0 && tctx->img->get_pred_mode(xT,yT)==MODE_INTRA) { |
601 | 25.0M | if (nT==4 && cIdx==0 && cuPredModeIntra) { |
602 | 12.0M | trType=1; |
603 | 12.0M | } |
604 | 12.9M | else { |
605 | 12.9M | trType=0; |
606 | 12.9M | } |
607 | | |
608 | 25.0M | assert(rdpcmMode==0); |
609 | | |
610 | | |
611 | 25.0M | if (tctx->img->get_pps().range_extension.cross_component_prediction_enabled_flag) { |
612 | | // cross-component-prediction: transform to residual buffer and add in a separate step |
613 | |
|
614 | 0 | transform_coefficients_explicit(tctx, coeff, coeffStride, nT, trType, |
615 | 0 | pred, stride, bit_depth, cIdx); |
616 | 0 | } |
617 | 25.0M | else { |
618 | 25.0M | transform_coefficients(&tctx->decctx->acceleration, coeff, coeffStride, nT, trType, |
619 | 25.0M | pred, stride, bit_depth); |
620 | 25.0M | } |
621 | 25.0M | } |
622 | 34.6M | } |
623 | | |
624 | | |
625 | 37.4M | logtrace(LogTransform,"pixels (cIdx:%d), position %d %d:\n",cIdx, xT,yT); |
626 | | |
627 | 229M | for (int y=0;y<nT;y++) { |
628 | 192M | logtrace(LogTransform,"RECO-%3d-%3d-%d ",xT,yT+y,cIdx); |
629 | | |
630 | 1.68G | for (int x=0;x<nT;x++) { |
631 | 1.49G | logtrace(LogTransform,"*%03x ", pred[x+y*stride]); |
632 | 1.49G | } |
633 | | |
634 | 192M | logtrace(LogTransform,"*\n"); |
635 | 192M | } |
636 | | |
637 | | // zero out scrap coefficient buffer again |
638 | | |
639 | 307M | for (int i=0;i<tctx->nCoeff[cIdx];i++) { |
640 | 270M | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = 0; |
641 | 270M | } |
642 | 37.4M | } void scale_coefficients_internal<unsigned short>(thread_context*, int, int, int, int, int, int, bool, bool, int) Line | Count | Source | 367 | 4.64M | { | 368 | 4.64M | const seq_parameter_set& sps = tctx->img->get_sps(); | 369 | 4.64M | const pic_parameter_set& pps = tctx->img->get_pps(); | 370 | | | 371 | 4.64M | int qP; | 372 | 4.64M | switch (cIdx) { | 373 | 3.10M | case 0: qP = tctx->qPYPrime; break; | 374 | 769k | case 1: qP = tctx->qPCbPrime; break; | 375 | 770k | case 2: qP = tctx->qPCrPrime; break; | 376 | 0 | default: qP = 0; assert(0); break; // should never happen | 377 | 4.64M | } | 378 | | | 379 | 4.64M | logtrace(LogTransform,"qP: %d\n",qP); | 380 | | | 381 | | | 382 | 4.64M | int16_t* coeff; | 383 | 4.64M | int coeffStride; | 384 | | | 385 | 4.64M | coeff = tctx->coeffBuf; | 386 | 4.64M | coeffStride = nT; | 387 | | | 388 | | | 389 | | | 390 | | | 391 | | | 392 | 4.64M | pixel_t* pred; | 393 | 4.64M | int stride; | 394 | 4.64M | pred = tctx->img->get_image_plane_at_pos_NEW<pixel_t>(cIdx, xT,yT); | 395 | 4.64M | stride = tctx->img->get_image_stride(cIdx); | 396 | | | 397 | | // We explicitly include the case for sizeof(pixel_t)==1 so that the compiler | 398 | | // can optimize away a lot of code for 8-bit pixels. | 399 | 4.64M | const int bit_depth = ((sizeof(pixel_t)==1) ? 8 : sps.get_bit_depth(cIdx)); | 400 | | | 401 | | //assert(intra == (tctx->img->get_pred_mode(xT,yT)==MODE_INTRA)); | 402 | 4.64M | int cuPredModeIntra = (tctx->img->get_pred_mode(xT,yT)==MODE_INTRA); | 403 | | | 404 | 4.64M | bool rotateCoeffs = (sps.range_extension.transform_skip_rotation_enabled_flag && | 405 | 1.31M | nT == 4 && | 406 | 1.11M | cuPredModeIntra); | 407 | | | 408 | 4.64M | if (tctx->cu_transquant_bypass_flag) { | 409 | | | 410 | 663k | int32_t residual_buffer[32*32]; | 411 | | | 412 | 663k | int32_t* residual; | 413 | 663k | if (cIdx==0) residual = tctx->residual_luma; | 414 | 106k | else residual = residual_buffer; | 415 | | | 416 | | | 417 | | // TODO: we could fold the coefficient rotation into the coefficient expansion here: | 418 | 7.28M | for (int i=0;i<tctx->nCoeff[cIdx];i++) { | 419 | 6.62M | int32_t currCoeff = tctx->coeffList[cIdx][i]; | 420 | 6.62M | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = currCoeff; | 421 | 6.62M | } | 422 | | | 423 | 663k | if (rotateCoeffs) { | 424 | 368k | tctx->decctx->acceleration.rotate_coefficients(coeff, nT); | 425 | 368k | } | 426 | | | 427 | 663k | if (rdpcmMode) { | 428 | 93.4k | if (rdpcmMode==2) | 429 | 55.8k | tctx->decctx->acceleration.transform_bypass_rdpcm_v(residual, coeff, nT); | 430 | 37.5k | else | 431 | 37.5k | tctx->decctx->acceleration.transform_bypass_rdpcm_h(residual, coeff, nT); | 432 | 93.4k | } | 433 | 569k | else { | 434 | 569k | tctx->decctx->acceleration.transform_bypass(residual, coeff, nT); | 435 | 569k | } | 436 | | | 437 | 663k | if (cIdx != 0) { | 438 | 106k | if (tctx->ResScaleVal != 0) { | 439 | 0 | cross_comp_pred(tctx, residual, nT); | 440 | 0 | } | 441 | 106k | } | 442 | | | 443 | 663k | tctx->decctx->acceleration.add_residual(pred,stride, residual,nT, bit_depth); | 444 | | | 445 | 663k | if (rotateCoeffs) { | 446 | 368k | memset(coeff, 0, nT*nT*sizeof(int16_t)); // delete all, because we moved the coeffs around | 447 | 368k | } | 448 | 663k | } | 449 | 3.97M | else { | 450 | | // (8.6.3) | 451 | | | 452 | 3.97M | int bdShift = (cIdx==0 ? sps.BitDepth_Y : sps.BitDepth_C) + Log2(nT) - 5; | 453 | | | 454 | 3.97M | logtrace(LogTransform,"bdShift=%d\n",bdShift); | 455 | | | 456 | 3.97M | logtrace(LogTransform,"dequant %d;%d cIdx=%d qp=%d\n",xT*(cIdx?2:1),yT*(cIdx?2:1),cIdx,qP); | 457 | | | 458 | | | 459 | | // --- inverse quantization --- | 460 | | | 461 | 3.97M | if (sps.scaling_list_enable_flag==0) { | 462 | | | 463 | | //const int m_x_y = 16; | 464 | 3.69M | const int m_x_y = 1; | 465 | 3.69M | bdShift -= 4; // this is equivalent to having a m_x_y of 16 and we can use 32bit integers | 466 | | | 467 | 3.69M | const int offset = (1<<(bdShift-1)); | 468 | 3.69M | const int fact = m_x_y * levelScale[qP%6] << (qP/6); | 469 | | | 470 | | // Fast path: when coeffList[i]*fact (|coeffList| <= 32767) fits in int32, | 471 | | // the dequant can run in int32 SIMD. Otherwise (very high QP, high bit | 472 | | // depth) fall back to the scalar int64 loop. | 473 | 3.69M | if (fact <= 32767) { | 474 | 3.41M | tctx->decctx->acceleration.dequant_coeff_block(tctx->coeffBuf, | 475 | 3.41M | tctx->coeffList[cIdx], | 476 | 3.41M | tctx->coeffPos[cIdx], | 477 | 3.41M | tctx->nCoeff[cIdx], | 478 | 3.41M | fact, offset, bdShift); | 479 | 3.41M | } | 480 | 282k | else { | 481 | 4.05M | for (int i=0;i<tctx->nCoeff[cIdx];i++) { | 482 | 3.77M | int64_t currCoeff = tctx->coeffList[cIdx][i]; | 483 | 3.77M | currCoeff = Clip3(-32768,32767, | 484 | 3.77M | ( (currCoeff * fact + offset ) >> bdShift)); | 485 | 3.77M | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = currCoeff; | 486 | 3.77M | } | 487 | 282k | } | 488 | 3.69M | } | 489 | 283k | else { | 490 | 283k | const int offset = (1<<(bdShift-1)); | 491 | | | 492 | 283k | const uint8_t* sclist; | 493 | 283k | int matrixID = cIdx; | 494 | | | 495 | 283k | if (nT==32) { | 496 | 731 | matrixID=0; | 497 | 731 | } | 498 | | | 499 | 283k | if (!intra) { | 500 | 16.1k | if (nT<32) { matrixID += 3; } | 501 | 33 | else { matrixID++; } | 502 | 16.1k | } | 503 | | | 504 | 283k | switch (nT) { | 505 | 232k | case 4: sclist = &pps.scaling_list.ScalingFactor_Size0[matrixID][0][0]; break; | 506 | 49.0k | case 8: sclist = &pps.scaling_list.ScalingFactor_Size1[matrixID][0][0]; break; | 507 | 1.00k | case 16: sclist = &pps.scaling_list.ScalingFactor_Size2[matrixID][0][0]; break; | 508 | 731 | case 32: sclist = &pps.scaling_list.ScalingFactor_Size3[matrixID][0][0]; break; | 509 | 0 | default: assert(0); sclist = nullptr; | 510 | 283k | } | 511 | | | 512 | 2.14M | for (int i=0;i<tctx->nCoeff[cIdx];i++) { | 513 | 1.86M | int pos = tctx->coeffPos[cIdx][i]; | 514 | | | 515 | 1.86M | const int m_x_y = sclist[pos]; | 516 | 1.86M | const int fact = m_x_y * levelScale[qP%6] << (qP/6); | 517 | | | 518 | 1.86M | int64_t currCoeff = tctx->coeffList[cIdx][i]; | 519 | | | 520 | 1.86M | currCoeff = Clip3(-32768,32767, | 521 | 1.86M | ( (currCoeff * fact + offset ) >> bdShift)); | 522 | | | 523 | 1.86M | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = currCoeff; | 524 | 1.86M | } | 525 | 283k | } | 526 | | | 527 | | | 528 | | // --- do transform or skip --- | 529 | | | 530 | 3.97M | logtrace(LogTransform,"coefficients OUT:\n"); | 531 | 22.2M | for (int y=0;y<nT;y++) { | 532 | 18.2M | logtrace(LogTransform," "); | 533 | 128M | for (int x=0;x<nT;x++) { | 534 | 109M | logtrace(LogTransform,"*%3d ", coeff[x+y*coeffStride]); | 535 | 109M | } | 536 | 18.2M | logtrace(LogTransform,"*\n"); | 537 | 18.2M | } | 538 | | | 539 | | #ifdef DE265_LOG_TRACE | 540 | | int bdShift2 = (cIdx==0) ? 20-sps.BitDepth_Y : 20-sps.BitDepth_C; | 541 | | #endif | 542 | | | 543 | 3.97M | logtrace(LogTransform,"bdShift2=%d\n",bdShift2); | 544 | | | 545 | 3.97M | logtrace(LogSlice,"get_transform_skip_flag(%d,%d, cIdx=%d)=%d\n",xT,yT,cIdx, | 546 | 3.97M | transform_skip_flag); | 547 | | | 548 | 3.97M | if (transform_skip_flag) { | 549 | | | 550 | 221k | int extended_precision_processing_flag = 0; | 551 | 221k | int Log2nTbS = Log2(nT); | 552 | 221k | int bdShift = std::max( 20 - bit_depth, extended_precision_processing_flag ? 11 : 0 ); | 553 | 221k | int tsShift = (extended_precision_processing_flag ? std::min( 5, bdShift - 2 ) : 5 ) | 554 | 221k | + Log2nTbS; | 555 | | | 556 | 221k | if (rotateCoeffs) { | 557 | 139k | tctx->decctx->acceleration.rotate_coefficients(coeff, nT); | 558 | 139k | } | 559 | | | 560 | 221k | int32_t residual_buffer[32*32]; | 561 | | | 562 | 221k | int32_t* residual; | 563 | 221k | if (cIdx==0) residual = tctx->residual_luma; | 564 | 37.8k | else residual = residual_buffer; | 565 | | | 566 | 221k | if (rdpcmMode) { | 567 | | /* | 568 | | if (rdpcmMode==2) | 569 | | tctx->decctx->acceleration.transform_skip_rdpcm_v(pred,coeff, Log2(nT), stride, bit_depth); | 570 | | else | 571 | | tctx->decctx->acceleration.transform_skip_rdpcm_h(pred,coeff, Log2(nT), stride, bit_depth); | 572 | | */ | 573 | | | 574 | 14.9k | if (rdpcmMode==2) | 575 | 6.48k | tctx->decctx->acceleration.rdpcm_v(residual, coeff,nT, tsShift,bdShift); | 576 | 8.51k | else | 577 | 8.51k | tctx->decctx->acceleration.rdpcm_h(residual, coeff,nT, tsShift,bdShift); | 578 | 14.9k | } | 579 | 206k | else { | 580 | | //tctx->decctx->acceleration.transform_skip(pred, coeff, stride, bit_depth); | 581 | | | 582 | 206k | tctx->decctx->acceleration.transform_skip_residual(residual, coeff, nT, tsShift, bdShift); | 583 | 206k | } | 584 | | | 585 | 221k | if (cIdx != 0) { | 586 | 37.8k | if (tctx->ResScaleVal != 0) { | 587 | 0 | cross_comp_pred(tctx, residual, nT); | 588 | 0 | } | 589 | 37.8k | } | 590 | | | 591 | 221k | tctx->decctx->acceleration.add_residual(pred,stride, residual,nT, bit_depth); | 592 | | | 593 | 221k | if (rotateCoeffs) { | 594 | 139k | memset(coeff, 0, nT*nT*sizeof(int16_t)); // delete all, because we moved the coeffs around | 595 | 139k | } | 596 | 221k | } | 597 | 3.75M | else { | 598 | 3.75M | int trType; | 599 | | | 600 | | //if (nT==4 && cIdx==0 && tctx->img->get_pred_mode(xT,yT)==MODE_INTRA) { | 601 | 3.75M | if (nT==4 && cIdx==0 && cuPredModeIntra) { | 602 | 2.04M | trType=1; | 603 | 2.04M | } | 604 | 1.70M | else { | 605 | 1.70M | trType=0; | 606 | 1.70M | } | 607 | | | 608 | 3.75M | assert(rdpcmMode==0); | 609 | | | 610 | | | 611 | 3.75M | if (tctx->img->get_pps().range_extension.cross_component_prediction_enabled_flag) { | 612 | | // cross-component-prediction: transform to residual buffer and add in a separate step | 613 | |
| 614 | 0 | transform_coefficients_explicit(tctx, coeff, coeffStride, nT, trType, | 615 | 0 | pred, stride, bit_depth, cIdx); | 616 | 0 | } | 617 | 3.75M | else { | 618 | 3.75M | transform_coefficients(&tctx->decctx->acceleration, coeff, coeffStride, nT, trType, | 619 | 3.75M | pred, stride, bit_depth); | 620 | 3.75M | } | 621 | 3.75M | } | 622 | 3.97M | } | 623 | | | 624 | | | 625 | 4.64M | logtrace(LogTransform,"pixels (cIdx:%d), position %d %d:\n",cIdx, xT,yT); | 626 | | | 627 | 26.2M | for (int y=0;y<nT;y++) { | 628 | 21.5M | logtrace(LogTransform,"RECO-%3d-%3d-%d ",xT,yT+y,cIdx); | 629 | | | 630 | 155M | for (int x=0;x<nT;x++) { | 631 | 133M | logtrace(LogTransform,"*%03x ", pred[x+y*stride]); | 632 | 133M | } | 633 | | | 634 | 21.5M | logtrace(LogTransform,"*\n"); | 635 | 21.5M | } | 636 | | | 637 | | // zero out scrap coefficient buffer again | 638 | | | 639 | 49.1M | for (int i=0;i<tctx->nCoeff[cIdx];i++) { | 640 | 44.5M | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = 0; | 641 | 44.5M | } | 642 | 4.64M | } |
void scale_coefficients_internal<unsigned char>(thread_context*, int, int, int, int, int, int, bool, bool, int) Line | Count | Source | 367 | 32.9M | { | 368 | 32.9M | const seq_parameter_set& sps = tctx->img->get_sps(); | 369 | 32.9M | const pic_parameter_set& pps = tctx->img->get_pps(); | 370 | | | 371 | 32.9M | int qP; | 372 | 32.9M | switch (cIdx) { | 373 | 20.8M | case 0: qP = tctx->qPYPrime; break; | 374 | 6.04M | case 1: qP = tctx->qPCbPrime; break; | 375 | 6.01M | case 2: qP = tctx->qPCrPrime; break; | 376 | 0 | default: qP = 0; assert(0); break; // should never happen | 377 | 32.9M | } | 378 | | | 379 | 32.9M | logtrace(LogTransform,"qP: %d\n",qP); | 380 | | | 381 | | | 382 | 32.9M | int16_t* coeff; | 383 | 32.9M | int coeffStride; | 384 | | | 385 | 32.9M | coeff = tctx->coeffBuf; | 386 | 32.9M | coeffStride = nT; | 387 | | | 388 | | | 389 | | | 390 | | | 391 | | | 392 | 32.9M | pixel_t* pred; | 393 | 32.9M | int stride; | 394 | 32.9M | pred = tctx->img->get_image_plane_at_pos_NEW<pixel_t>(cIdx, xT,yT); | 395 | 32.9M | stride = tctx->img->get_image_stride(cIdx); | 396 | | | 397 | | // We explicitly include the case for sizeof(pixel_t)==1 so that the compiler | 398 | | // can optimize away a lot of code for 8-bit pixels. | 399 | 32.9M | const int bit_depth = ((sizeof(pixel_t)==1) ? 8 : sps.get_bit_depth(cIdx)); | 400 | | | 401 | | //assert(intra == (tctx->img->get_pred_mode(xT,yT)==MODE_INTRA)); | 402 | 32.9M | int cuPredModeIntra = (tctx->img->get_pred_mode(xT,yT)==MODE_INTRA); | 403 | | | 404 | 32.9M | bool rotateCoeffs = (sps.range_extension.transform_skip_rotation_enabled_flag && | 405 | 3.07M | nT == 4 && | 406 | 2.74M | cuPredModeIntra); | 407 | | | 408 | 32.9M | if (tctx->cu_transquant_bypass_flag) { | 409 | | | 410 | 2.13M | int32_t residual_buffer[32*32]; | 411 | | | 412 | 2.13M | int32_t* residual; | 413 | 2.13M | if (cIdx==0) residual = tctx->residual_luma; | 414 | 959k | else residual = residual_buffer; | 415 | | | 416 | | | 417 | | // TODO: we could fold the coefficient rotation into the coefficient expansion here: | 418 | 23.7M | for (int i=0;i<tctx->nCoeff[cIdx];i++) { | 419 | 21.6M | int32_t currCoeff = tctx->coeffList[cIdx][i]; | 420 | 21.6M | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = currCoeff; | 421 | 21.6M | } | 422 | | | 423 | 2.13M | if (rotateCoeffs) { | 424 | 1.05M | tctx->decctx->acceleration.rotate_coefficients(coeff, nT); | 425 | 1.05M | } | 426 | | | 427 | 2.13M | if (rdpcmMode) { | 428 | 255k | if (rdpcmMode==2) | 429 | 152k | tctx->decctx->acceleration.transform_bypass_rdpcm_v(residual, coeff, nT); | 430 | 103k | else | 431 | 103k | tctx->decctx->acceleration.transform_bypass_rdpcm_h(residual, coeff, nT); | 432 | 255k | } | 433 | 1.88M | else { | 434 | 1.88M | tctx->decctx->acceleration.transform_bypass(residual, coeff, nT); | 435 | 1.88M | } | 436 | | | 437 | 2.13M | if (cIdx != 0) { | 438 | 959k | if (tctx->ResScaleVal != 0) { | 439 | 0 | cross_comp_pred(tctx, residual, nT); | 440 | 0 | } | 441 | 959k | } | 442 | | | 443 | 2.13M | tctx->decctx->acceleration.add_residual(pred,stride, residual,nT, bit_depth); | 444 | | | 445 | 2.13M | if (rotateCoeffs) { | 446 | 1.05M | memset(coeff, 0, nT*nT*sizeof(int16_t)); // delete all, because we moved the coeffs around | 447 | 1.05M | } | 448 | 2.13M | } | 449 | 30.7M | else { | 450 | | // (8.6.3) | 451 | | | 452 | 30.7M | int bdShift = (cIdx==0 ? sps.BitDepth_Y : sps.BitDepth_C) + Log2(nT) - 5; | 453 | | | 454 | 30.7M | logtrace(LogTransform,"bdShift=%d\n",bdShift); | 455 | | | 456 | 30.7M | logtrace(LogTransform,"dequant %d;%d cIdx=%d qp=%d\n",xT*(cIdx?2:1),yT*(cIdx?2:1),cIdx,qP); | 457 | | | 458 | | | 459 | | // --- inverse quantization --- | 460 | | | 461 | 30.7M | if (sps.scaling_list_enable_flag==0) { | 462 | | | 463 | | //const int m_x_y = 16; | 464 | 29.3M | const int m_x_y = 1; | 465 | 29.3M | bdShift -= 4; // this is equivalent to having a m_x_y of 16 and we can use 32bit integers | 466 | | | 467 | 29.3M | const int offset = (1<<(bdShift-1)); | 468 | 29.3M | const int fact = m_x_y * levelScale[qP%6] << (qP/6); | 469 | | | 470 | | // Fast path: when coeffList[i]*fact (|coeffList| <= 32767) fits in int32, | 471 | | // the dequant can run in int32 SIMD. Otherwise (very high QP, high bit | 472 | | // depth) fall back to the scalar int64 loop. | 473 | 29.3M | if (fact <= 32767) { | 474 | 29.3M | tctx->decctx->acceleration.dequant_coeff_block(tctx->coeffBuf, | 475 | 29.3M | tctx->coeffList[cIdx], | 476 | 29.3M | tctx->coeffPos[cIdx], | 477 | 29.3M | tctx->nCoeff[cIdx], | 478 | 29.3M | fact, offset, bdShift); | 479 | 29.3M | } | 480 | 18.4E | else { | 481 | 18.4E | for (int i=0;i<tctx->nCoeff[cIdx];i++) { | 482 | 0 | int64_t currCoeff = tctx->coeffList[cIdx][i]; | 483 | 0 | currCoeff = Clip3(-32768,32767, | 484 | 0 | ( (currCoeff * fact + offset ) >> bdShift)); | 485 | 0 | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = currCoeff; | 486 | 0 | } | 487 | 18.4E | } | 488 | 29.3M | } | 489 | 1.38M | else { | 490 | 1.38M | const int offset = (1<<(bdShift-1)); | 491 | | | 492 | 1.38M | const uint8_t* sclist; | 493 | 1.38M | int matrixID = cIdx; | 494 | | | 495 | 1.38M | if (nT==32) { | 496 | 10.7k | matrixID=0; | 497 | 10.7k | } | 498 | | | 499 | 1.38M | if (!intra) { | 500 | 38.8k | if (nT<32) { matrixID += 3; } | 501 | 555 | else { matrixID++; } | 502 | 38.8k | } | 503 | | | 504 | 1.38M | switch (nT) { | 505 | 1.14M | case 4: sclist = &pps.scaling_list.ScalingFactor_Size0[matrixID][0][0]; break; | 506 | 151k | case 8: sclist = &pps.scaling_list.ScalingFactor_Size1[matrixID][0][0]; break; | 507 | 22.1k | case 16: sclist = &pps.scaling_list.ScalingFactor_Size2[matrixID][0][0]; break; | 508 | 10.7k | case 32: sclist = &pps.scaling_list.ScalingFactor_Size3[matrixID][0][0]; break; | 509 | 0 | default: assert(0); sclist = nullptr; | 510 | 1.38M | } | 511 | | | 512 | 8.19M | for (int i=0;i<tctx->nCoeff[cIdx];i++) { | 513 | 6.86M | int pos = tctx->coeffPos[cIdx][i]; | 514 | | | 515 | 6.86M | const int m_x_y = sclist[pos]; | 516 | 6.86M | const int fact = m_x_y * levelScale[qP%6] << (qP/6); | 517 | | | 518 | 6.86M | int64_t currCoeff = tctx->coeffList[cIdx][i]; | 519 | | | 520 | 6.86M | currCoeff = Clip3(-32768,32767, | 521 | 6.86M | ( (currCoeff * fact + offset ) >> bdShift)); | 522 | | | 523 | 6.86M | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = currCoeff; | 524 | 6.86M | } | 525 | 1.32M | } | 526 | | | 527 | | | 528 | | // --- do transform or skip --- | 529 | | | 530 | 30.7M | logtrace(LogTransform,"coefficients OUT:\n"); | 531 | 190M | for (int y=0;y<nT;y++) { | 532 | 159M | logtrace(LogTransform," "); | 533 | 1.45G | for (int x=0;x<nT;x++) { | 534 | 1.29G | logtrace(LogTransform,"*%3d ", coeff[x+y*coeffStride]); | 535 | 1.29G | } | 536 | 159M | logtrace(LogTransform,"*\n"); | 537 | 159M | } | 538 | | | 539 | | #ifdef DE265_LOG_TRACE | 540 | | int bdShift2 = (cIdx==0) ? 20-sps.BitDepth_Y : 20-sps.BitDepth_C; | 541 | | #endif | 542 | | | 543 | 30.7M | logtrace(LogTransform,"bdShift2=%d\n",bdShift2); | 544 | | | 545 | 30.7M | logtrace(LogSlice,"get_transform_skip_flag(%d,%d, cIdx=%d)=%d\n",xT,yT,cIdx, | 546 | 30.7M | transform_skip_flag); | 547 | | | 548 | 30.7M | if (transform_skip_flag) { | 549 | | | 550 | 9.42M | int extended_precision_processing_flag = 0; | 551 | 9.42M | int Log2nTbS = Log2(nT); | 552 | 9.42M | int bdShift = std::max( 20 - bit_depth, extended_precision_processing_flag ? 11 : 0 ); | 553 | 9.42M | int tsShift = (extended_precision_processing_flag ? std::min( 5, bdShift - 2 ) : 5 ) | 554 | 9.42M | + Log2nTbS; | 555 | | | 556 | 9.42M | if (rotateCoeffs) { | 557 | 722k | tctx->decctx->acceleration.rotate_coefficients(coeff, nT); | 558 | 722k | } | 559 | | | 560 | 9.42M | int32_t residual_buffer[32*32]; | 561 | | | 562 | 9.42M | int32_t* residual; | 563 | 9.42M | if (cIdx==0) residual = tctx->residual_luma; | 564 | 3.45M | else residual = residual_buffer; | 565 | | | 566 | 9.42M | if (rdpcmMode) { | 567 | | /* | 568 | | if (rdpcmMode==2) | 569 | | tctx->decctx->acceleration.transform_skip_rdpcm_v(pred,coeff, Log2(nT), stride, bit_depth); | 570 | | else | 571 | | tctx->decctx->acceleration.transform_skip_rdpcm_h(pred,coeff, Log2(nT), stride, bit_depth); | 572 | | */ | 573 | | | 574 | 94.5k | if (rdpcmMode==2) | 575 | 56.3k | tctx->decctx->acceleration.rdpcm_v(residual, coeff,nT, tsShift,bdShift); | 576 | 38.1k | else | 577 | 38.1k | tctx->decctx->acceleration.rdpcm_h(residual, coeff,nT, tsShift,bdShift); | 578 | 94.5k | } | 579 | 9.32M | else { | 580 | | //tctx->decctx->acceleration.transform_skip(pred, coeff, stride, bit_depth); | 581 | | | 582 | 9.32M | tctx->decctx->acceleration.transform_skip_residual(residual, coeff, nT, tsShift, bdShift); | 583 | 9.32M | } | 584 | | | 585 | 9.42M | if (cIdx != 0) { | 586 | 3.45M | if (tctx->ResScaleVal != 0) { | 587 | 0 | cross_comp_pred(tctx, residual, nT); | 588 | 0 | } | 589 | 3.45M | } | 590 | | | 591 | 9.42M | tctx->decctx->acceleration.add_residual(pred,stride, residual,nT, bit_depth); | 592 | | | 593 | 9.42M | if (rotateCoeffs) { | 594 | 722k | memset(coeff, 0, nT*nT*sizeof(int16_t)); // delete all, because we moved the coeffs around | 595 | 722k | } | 596 | 9.42M | } | 597 | 21.2M | else { | 598 | 21.2M | int trType; | 599 | | | 600 | | //if (nT==4 && cIdx==0 && tctx->img->get_pred_mode(xT,yT)==MODE_INTRA) { | 601 | 21.2M | if (nT==4 && cIdx==0 && cuPredModeIntra) { | 602 | 10.0M | trType=1; | 603 | 10.0M | } | 604 | 11.2M | else { | 605 | 11.2M | trType=0; | 606 | 11.2M | } | 607 | | | 608 | 21.2M | assert(rdpcmMode==0); | 609 | | | 610 | | | 611 | 21.2M | if (tctx->img->get_pps().range_extension.cross_component_prediction_enabled_flag) { | 612 | | // cross-component-prediction: transform to residual buffer and add in a separate step | 613 | |
| 614 | 0 | transform_coefficients_explicit(tctx, coeff, coeffStride, nT, trType, | 615 | 0 | pred, stride, bit_depth, cIdx); | 616 | 0 | } | 617 | 21.2M | else { | 618 | 21.2M | transform_coefficients(&tctx->decctx->acceleration, coeff, coeffStride, nT, trType, | 619 | 21.2M | pred, stride, bit_depth); | 620 | 21.2M | } | 621 | 21.2M | } | 622 | 30.7M | } | 623 | | | 624 | | | 625 | 32.8M | logtrace(LogTransform,"pixels (cIdx:%d), position %d %d:\n",cIdx, xT,yT); | 626 | | | 627 | 203M | for (int y=0;y<nT;y++) { | 628 | 170M | logtrace(LogTransform,"RECO-%3d-%3d-%d ",xT,yT+y,cIdx); | 629 | | | 630 | 1.53G | for (int x=0;x<nT;x++) { | 631 | 1.36G | logtrace(LogTransform,"*%03x ", pred[x+y*stride]); | 632 | 1.36G | } | 633 | | | 634 | 170M | logtrace(LogTransform,"*\n"); | 635 | 170M | } | 636 | | | 637 | | // zero out scrap coefficient buffer again | 638 | | | 639 | 258M | for (int i=0;i<tctx->nCoeff[cIdx];i++) { | 640 | 225M | tctx->coeffBuf[ tctx->coeffPos[cIdx][i] ] = 0; | 641 | 225M | } | 642 | 32.8M | } |
|
643 | | |
644 | | |
645 | | void scale_coefficients(thread_context* tctx, |
646 | | int xT,int yT, // position of TU in frame (chroma adapted) |
647 | | int x0,int y0, // position of CU in frame (chroma adapted) |
648 | | int nT, int cIdx, |
649 | | bool transform_skip_flag, bool intra, |
650 | | int rdpcmMode // 0 - off, 1 - Horizontal, 2 - Vertical |
651 | | ) |
652 | 37.5M | { |
653 | 37.5M | if (tctx->img->high_bit_depth(cIdx)) { |
654 | 4.64M | scale_coefficients_internal<uint16_t>(tctx, xT,yT, x0,y0, nT,cIdx, transform_skip_flag, intra, |
655 | 4.64M | rdpcmMode); |
656 | 32.9M | } else { |
657 | 32.9M | scale_coefficients_internal<uint8_t> (tctx, xT,yT, x0,y0, nT,cIdx, transform_skip_flag, intra, |
658 | 32.9M | rdpcmMode); |
659 | 32.9M | } |
660 | 37.5M | } |
661 | | |
662 | | |
663 | | //#define QUANT_IQUANT_SHIFT 20 // Q(QP%6) * IQ(QP%6) = 2^20 |
664 | 0 | #define QUANT_SHIFT 14 // Q(4) = 2^14 |
665 | | //#define SCALE_BITS 15 // Inherited from TMuC, presumably for fractional bit estimates in RDOQ |
666 | 0 | #define MAX_TR_DYNAMIC_RANGE 15 // Maximum transform dynamic range (excluding sign bit) |
667 | | |
668 | | |
669 | | const static uint16_t g_quantScales[6] = { |
670 | | 26214,23302,20560,18396,16384,14564 |
671 | | }; |
672 | | |
673 | | void quant_coefficients(//encoder_context* ectx, |
674 | | int16_t* out_coeff, |
675 | | const int16_t* in_coeff, |
676 | | int log2TrSize, int qp, |
677 | | bool intra) |
678 | 0 | { |
679 | 0 | const int qpDiv6 = qp / 6; |
680 | 0 | const int qpMod6 = qp % 6; |
681 | | |
682 | | //int uiLog2TrSize = xLog2( iWidth - 1); |
683 | |
|
684 | 0 | int uiQ = g_quantScales[qpMod6]; |
685 | 0 | int bitDepth = 8; |
686 | 0 | int transformShift = MAX_TR_DYNAMIC_RANGE - bitDepth - log2TrSize; // Represents scaling through forward transform |
687 | 0 | int qBits = QUANT_SHIFT + qpDiv6 + transformShift; |
688 | | |
689 | | /* TODO: originally, this was checking for intra slices, why not for intra mode ? |
690 | | */ |
691 | 0 | int rnd = (intra ? 171 : 85) << (qBits-9); |
692 | |
|
693 | 0 | int x, y; |
694 | |
|
695 | 0 | int nStride = (1<<log2TrSize); |
696 | |
|
697 | 0 | for (y=0; y < (1<<log2TrSize) ; y++) { |
698 | 0 | for (x=0; x < (1<<log2TrSize) ; x++) { |
699 | 0 | int level; |
700 | 0 | int sign; |
701 | 0 | int blockPos = y * nStride + x; |
702 | 0 | level = in_coeff[blockPos]; |
703 | | //logtrace(LogTransform,"(%d,%d) %d -> ", x,y,level); |
704 | 0 | sign = (level < 0 ? -1: 1); |
705 | |
|
706 | 0 | level = (std::abs(level) * uiQ + rnd ) >> qBits; |
707 | 0 | level *= sign; |
708 | 0 | out_coeff[blockPos] = Clip3(-32768, 32767, level); |
709 | | //logtrace(LogTransform,"%d\n", out_coeff[blockPos]); |
710 | 0 | } |
711 | 0 | } |
712 | 0 | } |
713 | | |
714 | | |
715 | | void dequant_coefficients(int16_t* out_coeff, |
716 | | const int16_t* in_coeff, |
717 | | int log2TrSize, int qP) |
718 | 0 | { |
719 | 0 | const int m_x_y = 1; |
720 | 0 | int bitDepth = 8; |
721 | 0 | int bdShift = bitDepth + log2TrSize - 5; |
722 | 0 | bdShift -= 4; // this is equivalent to having a m_x_y of 16 and we can use 32bit integers |
723 | |
|
724 | 0 | const int offset = (1<<(bdShift-1)); |
725 | 0 | const int fact = m_x_y * levelScale[qP%6] << (qP/6); |
726 | | |
727 | | //int blkSize = (1<<log2TrSize); |
728 | 0 | int nCoeff = (1<<(log2TrSize<<1)); |
729 | |
|
730 | 0 | for (int i=0;i<nCoeff;i++) { |
731 | | |
732 | | // usually, this needs to be 64bit, but because we modify the shift above, we can use 16 bit |
733 | 0 | int32_t currCoeff = in_coeff[i]; |
734 | | |
735 | | //logtrace(LogTransform,"coefficient[%d] = %d\n",i,currCoeff); |
736 | |
|
737 | 0 | currCoeff = Clip3(-32768,32767, |
738 | 0 | ( (currCoeff * fact + offset ) >> bdShift)); |
739 | | |
740 | | //logtrace(LogTransform," -> %d\n",currCoeff); |
741 | |
|
742 | 0 | out_coeff[i] = currCoeff; |
743 | 0 | } |
744 | 0 | } |