/work/libde265/libde265/deblock.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 "deblock.h" |
22 | | #include "util.h" |
23 | | #include "transform.h" |
24 | | #include "de265.h" |
25 | | #include "decctx.h" |
26 | | #include "fallback-deblk.h" |
27 | | |
28 | | #include <assert.h> |
29 | | |
30 | | |
31 | | |
32 | | // 8.7.2.1 for both EDGE_HOR and EDGE_VER at the same time |
33 | | void markTransformBlockBoundary(de265_image* img, int x0,int y0, |
34 | | int log2TrafoSize,int trafoDepth, |
35 | | int filterLeftCbEdge, int filterTopCbEdge) |
36 | 0 | { |
37 | 0 | logtrace(LogDeblock,"markTransformBlockBoundary(%d,%d, %d,%d, %d,%d)\n",x0,y0, |
38 | 0 | log2TrafoSize,trafoDepth, filterLeftCbEdge,filterTopCbEdge); |
39 | |
|
40 | 0 | int split_transform = img->get_split_transform_flag(x0,y0,trafoDepth); |
41 | 0 | if (split_transform) { |
42 | 0 | int x1 = x0 + ((1<<log2TrafoSize)>>1); |
43 | 0 | int y1 = y0 + ((1<<log2TrafoSize)>>1); |
44 | |
|
45 | 0 | markTransformBlockBoundary(img,x0,y0,log2TrafoSize-1,trafoDepth+1, filterLeftCbEdge, filterTopCbEdge); |
46 | 0 | markTransformBlockBoundary(img,x1,y0,log2TrafoSize-1,trafoDepth+1, DEBLOCK_FLAG_VERTI, filterTopCbEdge); |
47 | 0 | markTransformBlockBoundary(img,x0,y1,log2TrafoSize-1,trafoDepth+1, filterLeftCbEdge, DEBLOCK_FLAG_HORIZ); |
48 | 0 | markTransformBlockBoundary(img,x1,y1,log2TrafoSize-1,trafoDepth+1, DEBLOCK_FLAG_VERTI, DEBLOCK_FLAG_HORIZ); |
49 | 0 | } |
50 | 0 | else { |
51 | | // VER |
52 | |
|
53 | 0 | for (int k=0;k<(1<<log2TrafoSize);k+=4) { |
54 | 0 | img->set_deblk_flags(x0,y0+k, filterLeftCbEdge); |
55 | 0 | } |
56 | | |
57 | | // HOR |
58 | |
|
59 | 0 | for (int k=0;k<(1<<log2TrafoSize);k+=4) { |
60 | 0 | img->set_deblk_flags(x0+k,y0, filterTopCbEdge); |
61 | 0 | } |
62 | 0 | } |
63 | 0 | } |
64 | | |
65 | | |
66 | | |
67 | | // 8.7.2.2 for both EDGE_HOR and EDGE_VER at the same time |
68 | | void markPredictionBlockBoundary(de265_image* img, int x0,int y0, |
69 | | int log2CbSize, |
70 | | int filterLeftCbEdge, int filterTopCbEdge) |
71 | 0 | { |
72 | 0 | logtrace(LogDeblock,"markPredictionBlockBoundary(%d,%d, %d, %d,%d)\n",x0,y0, |
73 | 0 | log2CbSize, filterLeftCbEdge,filterTopCbEdge); |
74 | |
|
75 | 0 | enum PartMode partMode = img->get_PartMode(x0,y0); |
76 | |
|
77 | 0 | int cbSize = 1<<log2CbSize; |
78 | 0 | int cbSize2 = 1<<(log2CbSize-1); |
79 | 0 | int cbSize4 = 1<<(log2CbSize-2); |
80 | |
|
81 | 0 | switch (partMode) { |
82 | 0 | case PART_NxN: |
83 | 0 | for (int k=0;k<cbSize;k++) { |
84 | 0 | img->set_deblk_flags(x0+cbSize2,y0+k, DEBLOCK_PB_EDGE_VERTI); |
85 | 0 | img->set_deblk_flags(x0+k,y0+cbSize2, DEBLOCK_PB_EDGE_HORIZ); |
86 | 0 | } |
87 | 0 | break; |
88 | | |
89 | 0 | case PART_Nx2N: |
90 | 0 | for (int k=0;k<cbSize;k++) { |
91 | 0 | img->set_deblk_flags(x0+cbSize2,y0+k, DEBLOCK_PB_EDGE_VERTI); |
92 | 0 | } |
93 | 0 | break; |
94 | | |
95 | 0 | case PART_2NxN: |
96 | 0 | for (int k=0;k<cbSize;k++) { |
97 | 0 | img->set_deblk_flags(x0+k,y0+cbSize2, DEBLOCK_PB_EDGE_HORIZ); |
98 | 0 | } |
99 | 0 | break; |
100 | | |
101 | 0 | case PART_nLx2N: |
102 | 0 | for (int k=0;k<cbSize;k++) { |
103 | 0 | img->set_deblk_flags(x0+cbSize4,y0+k, DEBLOCK_PB_EDGE_VERTI); |
104 | 0 | } |
105 | 0 | break; |
106 | | |
107 | 0 | case PART_nRx2N: |
108 | 0 | for (int k=0;k<cbSize;k++) { |
109 | 0 | img->set_deblk_flags(x0+cbSize2+cbSize4,y0+k, DEBLOCK_PB_EDGE_VERTI); |
110 | 0 | } |
111 | 0 | break; |
112 | | |
113 | 0 | case PART_2NxnU: |
114 | 0 | for (int k=0;k<cbSize;k++) { |
115 | 0 | img->set_deblk_flags(x0+k,y0+cbSize4, DEBLOCK_PB_EDGE_HORIZ); |
116 | 0 | } |
117 | 0 | break; |
118 | | |
119 | 0 | case PART_2NxnD: |
120 | 0 | for (int k=0;k<cbSize;k++) { |
121 | 0 | img->set_deblk_flags(x0+k,y0+cbSize2+cbSize4, DEBLOCK_PB_EDGE_HORIZ); |
122 | 0 | } |
123 | 0 | break; |
124 | | |
125 | 0 | case PART_2Nx2N: |
126 | | // NOP |
127 | 0 | break; |
128 | 0 | } |
129 | 0 | } |
130 | | |
131 | | |
132 | | bool derive_edgeFlags_CTBRow(de265_image* img, uint16_t ctby) |
133 | 0 | { |
134 | 0 | const seq_parameter_set& sps = img->get_sps(); |
135 | 0 | const pic_parameter_set& pps = img->get_pps(); |
136 | |
|
137 | 0 | const int minCbSize = sps.MinCbSizeY; |
138 | 0 | bool deblocking_enabled=false; // whether deblocking is enabled in some part of the image |
139 | |
|
140 | 0 | int ctb_mask = (1<<sps.Log2CtbSizeY)-1; |
141 | 0 | int picWidthInCtbs = sps.PicWidthInCtbsY; |
142 | 0 | int ctbshift = sps.Log2CtbSizeY; |
143 | | |
144 | |
|
145 | 0 | uint16_t cb_y_start = ( ctby << sps.Log2CtbSizeY) >> sps.Log2MinCbSizeY; |
146 | 0 | uint16_t cb_y_end = ((ctby+1) << sps.Log2CtbSizeY) >> sps.Log2MinCbSizeY; |
147 | |
|
148 | 0 | cb_y_end = std::min(cb_y_end, sps.PicHeightInMinCbsY); |
149 | |
|
150 | 0 | for (int cb_y=cb_y_start;cb_y<cb_y_end;cb_y++) |
151 | 0 | for (int cb_x=0;cb_x<img->get_sps().PicWidthInMinCbsY;cb_x++) |
152 | 0 | { |
153 | 0 | int log2CbSize = img->get_log2CbSize_cbUnits(cb_x,cb_y); |
154 | 0 | if (log2CbSize==0) { |
155 | 0 | continue; |
156 | 0 | } |
157 | | |
158 | | // we are now at the top corner of a CB |
159 | | |
160 | 0 | int x0 = cb_x * minCbSize; |
161 | 0 | int y0 = cb_y * minCbSize; |
162 | |
|
163 | 0 | int x0ctb = x0 >> ctbshift; |
164 | 0 | int y0ctb = y0 >> ctbshift; |
165 | | |
166 | | // check for corrupted streams |
167 | 0 | if (img->is_SliceHeader_available(x0,y0)==false) { |
168 | 0 | return false; |
169 | 0 | } |
170 | | |
171 | | // check whether we should filter this slice |
172 | | |
173 | 0 | slice_segment_header* shdr = img->get_SliceHeader(x0,y0); |
174 | | |
175 | | // check whether to filter left and top edge |
176 | |
|
177 | 0 | uint8_t filterLeftCbEdge = DEBLOCK_FLAG_VERTI; |
178 | 0 | uint8_t filterTopCbEdge = DEBLOCK_FLAG_HORIZ; |
179 | 0 | if (x0 == 0) filterLeftCbEdge = 0; |
180 | 0 | if (y0 == 0) filterTopCbEdge = 0; |
181 | | |
182 | | // check for slice and tile boundaries (8.7.2, step 2 in both processes) |
183 | |
|
184 | 0 | if (x0 && ((x0 & ctb_mask) == 0)) { // left edge at CTB boundary |
185 | 0 | if (shdr->slice_loop_filter_across_slices_enabled_flag == 0 && |
186 | 0 | img->is_SliceHeader_available(x0-1,y0) && // for corrupted streams |
187 | 0 | shdr->SliceAddrRS != img->get_SliceHeader(x0-1,y0)->SliceAddrRS) |
188 | 0 | { |
189 | 0 | filterLeftCbEdge = 0; |
190 | 0 | } |
191 | 0 | else if (pps.loop_filter_across_tiles_enabled_flag == 0 && |
192 | 0 | pps.scan->TileIdRS[ x0ctb +y0ctb*picWidthInCtbs] != |
193 | 0 | pps.scan->TileIdRS[((x0-1)>>ctbshift)+y0ctb*picWidthInCtbs]) { |
194 | 0 | filterLeftCbEdge = 0; |
195 | 0 | } |
196 | 0 | } |
197 | |
|
198 | 0 | if (y0 && ((y0 & ctb_mask) == 0)) { // top edge at CTB boundary |
199 | 0 | if (shdr->slice_loop_filter_across_slices_enabled_flag == 0 && |
200 | 0 | img->is_SliceHeader_available(x0,y0-1) && // for corrupted streams |
201 | 0 | shdr->SliceAddrRS != img->get_SliceHeader(x0,y0-1)->SliceAddrRS) |
202 | 0 | { |
203 | 0 | filterTopCbEdge = 0; |
204 | 0 | } |
205 | 0 | else if (pps.loop_filter_across_tiles_enabled_flag == 0 && |
206 | 0 | pps.scan->TileIdRS[x0ctb+ y0ctb *picWidthInCtbs] != |
207 | 0 | pps.scan->TileIdRS[x0ctb+((y0-1)>>ctbshift)*picWidthInCtbs]) { |
208 | 0 | filterTopCbEdge = 0; |
209 | 0 | } |
210 | 0 | } |
211 | | |
212 | | |
213 | | // mark edges |
214 | |
|
215 | 0 | if (shdr->slice_deblocking_filter_disabled_flag==0) { |
216 | 0 | deblocking_enabled=true; |
217 | |
|
218 | 0 | markTransformBlockBoundary(img, x0,y0, log2CbSize,0, |
219 | 0 | filterLeftCbEdge, filterTopCbEdge); |
220 | |
|
221 | 0 | markPredictionBlockBoundary(img, x0,y0, log2CbSize, |
222 | 0 | filterLeftCbEdge, filterTopCbEdge); |
223 | 0 | } |
224 | 0 | } |
225 | | |
226 | 0 | return deblocking_enabled; |
227 | 0 | } |
228 | | |
229 | | |
230 | | bool derive_edgeFlags(de265_image* img) |
231 | 0 | { |
232 | 0 | bool deblocking_enabled=false; |
233 | |
|
234 | 0 | for (int y=0;y<img->get_sps().PicHeightInCtbsY;y++) { |
235 | 0 | deblocking_enabled |= derive_edgeFlags_CTBRow(img,y); |
236 | 0 | } |
237 | |
|
238 | 0 | return deblocking_enabled; |
239 | 0 | } |
240 | | |
241 | | |
242 | | // 8.7.2.3 (both, EDGE_VER and EDGE_HOR) |
243 | | void derive_boundaryStrength(de265_image* img, bool vertical, int yStart,int yEnd, |
244 | | int xStart,int xEnd) |
245 | 0 | { |
246 | 0 | int xIncr = vertical ? 2 : 1; |
247 | 0 | int yIncr = vertical ? 1 : 2; |
248 | 0 | int xOffs = vertical ? 1 : 0; |
249 | 0 | int yOffs = vertical ? 0 : 1; |
250 | 0 | int edgeMask = vertical ? |
251 | 0 | (DEBLOCK_FLAG_VERTI | DEBLOCK_PB_EDGE_VERTI) : |
252 | 0 | (DEBLOCK_FLAG_HORIZ | DEBLOCK_PB_EDGE_HORIZ); |
253 | 0 | int transformEdgeMask = vertical ? DEBLOCK_FLAG_VERTI : DEBLOCK_FLAG_HORIZ; |
254 | |
|
255 | 0 | xEnd = std::min(xEnd,img->get_deblk_width()); |
256 | 0 | yEnd = std::min(yEnd,img->get_deblk_height()); |
257 | | |
258 | | //int TUShift = img->get_sps().Log2MinTrafoSize; |
259 | | //int TUStride= img->get_sps().PicWidthInTbsY; |
260 | |
|
261 | 0 | for (int y=yStart;y<yEnd;y+=yIncr) |
262 | 0 | for (int x=xStart;x<xEnd;x+=xIncr) { |
263 | 0 | int xDi = x<<2; |
264 | 0 | int yDi = y<<2; |
265 | |
|
266 | 0 | logtrace(LogDeblock,"%d %d %s = %s\n",xDi,yDi, vertical?"Vertical":"Horizontal", |
267 | 0 | (img->get_deblk_flags(xDi,yDi) & edgeMask) ? "edge" : "..."); |
268 | |
|
269 | 0 | uint8_t edgeFlags = img->get_deblk_flags(xDi,yDi); |
270 | |
|
271 | 0 | if (edgeFlags & edgeMask) { |
272 | 0 | bool p_is_intra_pred = (img->get_pred_mode(xDi-xOffs, yDi-yOffs) == MODE_INTRA); |
273 | 0 | bool q_is_intra_pred = (img->get_pred_mode(xDi, yDi ) == MODE_INTRA); |
274 | |
|
275 | 0 | int bS; |
276 | |
|
277 | 0 | if (p_is_intra_pred || q_is_intra_pred) { |
278 | 0 | bS = 2; |
279 | 0 | } |
280 | 0 | else { |
281 | | // opposing site |
282 | 0 | int xDiOpp = xDi-xOffs; |
283 | 0 | int yDiOpp = yDi-yOffs; |
284 | |
|
285 | 0 | if ((edgeFlags & transformEdgeMask) && |
286 | 0 | (img->get_nonzero_coefficient(xDi ,yDi) || |
287 | 0 | img->get_nonzero_coefficient(xDiOpp,yDiOpp))) { |
288 | 0 | bS = 1; |
289 | 0 | } |
290 | 0 | else { |
291 | |
|
292 | 0 | bS = 0; |
293 | |
|
294 | 0 | const PBMotion& mviP = img->get_mv_info(xDiOpp,yDiOpp); |
295 | 0 | const PBMotion& mviQ = img->get_mv_info(xDi ,yDi); |
296 | |
|
297 | 0 | slice_segment_header* shdrP = img->get_SliceHeader(xDiOpp,yDiOpp); |
298 | 0 | slice_segment_header* shdrQ = img->get_SliceHeader(xDi ,yDi); |
299 | |
|
300 | 0 | if (shdrP && shdrQ) { |
301 | |
|
302 | 0 | int refPicP0 = mviP.predFlag[0] ? shdrP->RefPicList[0][ mviP.refIdx[0] ] : -1; |
303 | 0 | int refPicP1 = mviP.predFlag[1] ? shdrP->RefPicList[1][ mviP.refIdx[1] ] : -1; |
304 | 0 | int refPicQ0 = mviQ.predFlag[0] ? shdrQ->RefPicList[0][ mviQ.refIdx[0] ] : -1; |
305 | 0 | int refPicQ1 = mviQ.predFlag[1] ? shdrQ->RefPicList[1][ mviQ.refIdx[1] ] : -1; |
306 | |
|
307 | 0 | bool samePics = ((refPicP0==refPicQ0 && refPicP1==refPicQ1) || |
308 | 0 | (refPicP0==refPicQ1 && refPicP1==refPicQ0)); |
309 | |
|
310 | 0 | if (!samePics) { |
311 | 0 | bS = 1; |
312 | 0 | } |
313 | 0 | else { |
314 | 0 | MotionVector mvP0 = mviP.mv[0]; if (!mviP.predFlag[0]) { mvP0.x=mvP0.y=0; } |
315 | 0 | MotionVector mvP1 = mviP.mv[1]; if (!mviP.predFlag[1]) { mvP1.x=mvP1.y=0; } |
316 | 0 | MotionVector mvQ0 = mviQ.mv[0]; if (!mviQ.predFlag[0]) { mvQ0.x=mvQ0.y=0; } |
317 | 0 | MotionVector mvQ1 = mviQ.mv[1]; if (!mviQ.predFlag[1]) { mvQ1.x=mvQ1.y=0; } |
318 | |
|
319 | 0 | int numMV_P = mviP.predFlag[0] + mviP.predFlag[1]; |
320 | 0 | int numMV_Q = mviQ.predFlag[0] + mviQ.predFlag[1]; |
321 | |
|
322 | 0 | if (numMV_P!=numMV_Q) { |
323 | 0 | img->decctx->add_warning(DE265_WARNING_NUMMVP_NOT_EQUAL_TO_NUMMVQ, false); |
324 | 0 | img->integrity = INTEGRITY_DECODING_ERRORS; |
325 | 0 | } |
326 | | |
327 | | // two different reference pictures or only one reference picture |
328 | 0 | if (refPicP0 != refPicP1) { |
329 | |
|
330 | 0 | if (refPicP0 == refPicQ0) { |
331 | 0 | if (std::abs(mvP0.x-mvQ0.x) >= 4 || |
332 | 0 | std::abs(mvP0.y-mvQ0.y) >= 4 || |
333 | 0 | std::abs(mvP1.x-mvQ1.x) >= 4 || |
334 | 0 | std::abs(mvP1.y-mvQ1.y) >= 4) { |
335 | 0 | bS = 1; |
336 | 0 | } |
337 | 0 | } |
338 | 0 | else { |
339 | 0 | if (std::abs(mvP0.x-mvQ1.x) >= 4 || |
340 | 0 | std::abs(mvP0.y-mvQ1.y) >= 4 || |
341 | 0 | std::abs(mvP1.x-mvQ0.x) >= 4 || |
342 | 0 | std::abs(mvP1.y-mvQ0.y) >= 4) { |
343 | 0 | bS = 1; |
344 | 0 | } |
345 | 0 | } |
346 | 0 | } |
347 | 0 | else { |
348 | 0 | assert(refPicQ0==refPicQ1); |
349 | | |
350 | 0 | if ((std::abs(mvP0.x-mvQ0.x) >= 4 || |
351 | 0 | std::abs(mvP0.y-mvQ0.y) >= 4 || |
352 | 0 | std::abs(mvP1.x-mvQ1.x) >= 4 || |
353 | 0 | std::abs(mvP1.y-mvQ1.y) >= 4) |
354 | 0 | && |
355 | 0 | (std::abs(mvP0.x-mvQ1.x) >= 4 || |
356 | 0 | std::abs(mvP0.y-mvQ1.y) >= 4 || |
357 | 0 | std::abs(mvP1.x-mvQ0.x) >= 4 || |
358 | 0 | std::abs(mvP1.y-mvQ0.y) >= 4)) { |
359 | 0 | bS = 1; |
360 | 0 | } |
361 | 0 | } |
362 | 0 | } |
363 | 0 | } |
364 | 0 | else { |
365 | 0 | bS = 0; // if shdrP==nullptr or shdrQ==nullptr |
366 | 0 | } |
367 | | |
368 | | /* |
369 | | printf("unimplemented deblocking code for CU at %d;%d\n",xDi,yDi); |
370 | | |
371 | | logerror(LogDeblock, "unimplemented code reached (file %s, line %d)\n", |
372 | | __FILE__, __LINE__); |
373 | | */ |
374 | 0 | } |
375 | 0 | } |
376 | | |
377 | 0 | img->set_deblk_bS(xDi,yDi, bS); |
378 | 0 | } |
379 | 0 | else { |
380 | 0 | img->set_deblk_bS(xDi,yDi, 0); |
381 | 0 | } |
382 | 0 | } |
383 | 0 | } |
384 | | |
385 | | |
386 | | void derive_boundaryStrength_CTB(de265_image* img, bool vertical, int xCtb,int yCtb) |
387 | 0 | { |
388 | 0 | int ctbSize = img->get_sps().CtbSizeY; |
389 | 0 | int deblkSize = ctbSize/4; |
390 | |
|
391 | 0 | derive_boundaryStrength(img,vertical, |
392 | 0 | yCtb*deblkSize, (yCtb+1)*deblkSize, |
393 | 0 | xCtb*deblkSize, (xCtb+1)*deblkSize); |
394 | 0 | } |
395 | | |
396 | | |
397 | | static uint8_t table_8_23_beta[52] = { |
398 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, |
399 | | 9,10,11,12,13,14,15,16,17,18,20,22,24,26,28,30,32,34,36, |
400 | | 38,40,42,44,46,48,50,52,54,56,58,60,62,64 |
401 | | }; |
402 | | |
403 | | static uint8_t table_8_23_tc[54] = { |
404 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, |
405 | | 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, |
406 | | 5, 5, 6, 6, 7, 8, 9,10,11,13,14,16,18,20,22,24 |
407 | | }; |
408 | | |
409 | | |
410 | | |
411 | | // 8.7.2.4 |
412 | | template <class pixel_t> |
413 | | void edge_filtering_luma_internal(de265_image* img, bool vertical, |
414 | | int yStart,int yEnd, int xStart,int xEnd) |
415 | 0 | { |
416 | | //printf("luma %d-%d %d-%d\n",xStart,xEnd,yStart,yEnd); |
417 | |
|
418 | 0 | const seq_parameter_set& sps = img->get_sps(); |
419 | |
|
420 | 0 | int xIncr = vertical ? 2 : 1; |
421 | 0 | int yIncr = vertical ? 1 : 2; |
422 | |
|
423 | 0 | const int stride = img->get_image_stride(0); |
424 | |
|
425 | 0 | int bitDepth_Y = sps.BitDepth_Y; |
426 | |
|
427 | 0 | xEnd = std::min(xEnd,img->get_deblk_width()); |
428 | 0 | yEnd = std::min(yEnd,img->get_deblk_height()); |
429 | |
|
430 | 0 | for (int y=yStart;y<yEnd;y+=yIncr) |
431 | 0 | for (int x=xStart;x<xEnd;x+=xIncr) { |
432 | | // x;y in deblocking units (4x4 pixels) |
433 | |
|
434 | 0 | int xDi = x<<2; // *4 -> pixel resolution |
435 | 0 | int yDi = y<<2; // *4 -> pixel resolution |
436 | 0 | int bS = img->get_deblk_bS(xDi,yDi); |
437 | | |
438 | | //printf("x,y:%d,%d xDi,yDi:%d,%d\n",x,y,xDi,yDi); |
439 | |
|
440 | 0 | logtrace(LogDeblock,"deblock POC=%d %c --- x:%d y:%d bS:%d---\n", |
441 | 0 | img->PicOrderCntVal,vertical ? 'V':'H',xDi,yDi,bS); |
442 | |
|
443 | | #if 0 |
444 | | { |
445 | | uint8_t* ptr = img->y + stride*yDi + xDi; |
446 | | |
447 | | for (int dy=-4;dy<4;dy++) { |
448 | | for (int dx=-4;dx<4;dx++) { |
449 | | printf("%02x ", ptr[dy*stride + dx]); |
450 | | if (dx==-1) printf("| "); |
451 | | } |
452 | | printf("\n"); |
453 | | if (dy==-1) printf("-------------------------\n"); |
454 | | } |
455 | | } |
456 | | #endif |
457 | |
|
458 | | #if 0 |
459 | | if (!vertical) |
460 | | { |
461 | | uint8_t* ptr = img->y + stride*yDi + xDi; |
462 | | |
463 | | for (int dy=-4;dy<4;dy++) { |
464 | | for (int dx=0;dx<4;dx++) { |
465 | | printf("%02x ", ptr[dy*stride + dx]); |
466 | | if (dx==-1) printf("| "); |
467 | | } |
468 | | printf("\n"); |
469 | | if (dy==-1) printf("-------------------------\n"); |
470 | | } |
471 | | } |
472 | | #endif |
473 | |
|
474 | 0 | if (bS>0) { |
475 | | |
476 | | // 8.7.2.4.3 |
477 | |
|
478 | 0 | pixel_t* ptr = img->get_image_plane_at_pos_NEW<pixel_t>(0, xDi,yDi); |
479 | |
|
480 | 0 | pixel_t q[4][4], p[4][4]; |
481 | 0 | for (int k=0;k<4;k++) |
482 | 0 | for (int i=0;i<4;i++) |
483 | 0 | { |
484 | 0 | if (vertical) { |
485 | 0 | q[k][i] = ptr[ i +k*stride]; |
486 | 0 | p[k][i] = ptr[-i-1+k*stride]; |
487 | 0 | } |
488 | 0 | else { |
489 | 0 | q[k][i] = ptr[k + i *stride]; |
490 | 0 | p[k][i] = ptr[k -(i+1)*stride]; |
491 | 0 | } |
492 | 0 | } |
493 | |
|
494 | | #if 0 |
495 | | for (int k=0;k<4;k++) |
496 | | { |
497 | | for (int i=0;i<4;i++) |
498 | | { |
499 | | printf("%02x ", p[k][3-i]); |
500 | | } |
501 | | |
502 | | printf("| "); |
503 | | |
504 | | for (int i=0;i<4;i++) |
505 | | { |
506 | | printf("%02x ", q[k][i]); |
507 | | } |
508 | | printf("\n"); |
509 | | } |
510 | | #endif |
511 | | |
512 | |
|
513 | 0 | int QP_Q = img->get_QPY(xDi,yDi); |
514 | 0 | int QP_P = (vertical ? |
515 | 0 | img->get_QPY(xDi-1,yDi) : |
516 | 0 | img->get_QPY(xDi,yDi-1) ); |
517 | 0 | int qP_L = (QP_Q+QP_P+1)>>1; |
518 | |
|
519 | 0 | logtrace(LogDeblock,"QP: %d & %d -> %d\n",QP_Q,QP_P,qP_L); |
520 | |
|
521 | 0 | int sliceIndexQ00 = img->get_SliceHeaderIndex(xDi,yDi); |
522 | 0 | int beta_offset = img->slices[sliceIndexQ00]->slice_beta_offset; |
523 | 0 | int tc_offset = img->slices[sliceIndexQ00]->slice_tc_offset; |
524 | |
|
525 | 0 | int Q_beta = Clip3(0,51, qP_L + beta_offset); |
526 | 0 | int betaPrime = table_8_23_beta[Q_beta]; |
527 | 0 | int beta = betaPrime * (1<<(bitDepth_Y - 8)); |
528 | |
|
529 | 0 | int Q_tc = Clip3(0,53, qP_L + 2*(bS-1) + tc_offset); |
530 | 0 | int tcPrime = table_8_23_tc[Q_tc]; |
531 | 0 | int tc = tcPrime * (1<<(bitDepth_Y - 8)); |
532 | |
|
533 | 0 | logtrace(LogDeblock,"beta: %d (%d) tc: %d (%d)\n",beta,beta_offset, tc,tc_offset); |
534 | |
|
535 | 0 | int dE=0, dEp=0, dEq=0; |
536 | |
|
537 | 0 | int dp0 = std::abs(p[0][2] - 2*p[0][1] + p[0][0]); |
538 | 0 | int dp3 = std::abs(p[3][2] - 2*p[3][1] + p[3][0]); |
539 | 0 | int dq0 = std::abs(q[0][2] - 2*q[0][1] + q[0][0]); |
540 | 0 | int dq3 = std::abs(q[3][2] - 2*q[3][1] + q[3][0]); |
541 | |
|
542 | 0 | int dpq0 = dp0 + dq0; |
543 | 0 | int dpq3 = dp3 + dq3; |
544 | |
|
545 | 0 | int dp = dp0 + dp3; |
546 | 0 | int dq = dq0 + dq3; |
547 | 0 | int d = dpq0 + dpq3; |
548 | |
|
549 | 0 | if (d < beta) { |
550 | | //int dpq = 2*dpq0; |
551 | 0 | bool dSam0 = (2 * dpq0 < (beta >> 2) && |
552 | 0 | std::abs(p[0][3]-p[0][0]) + std::abs(q[0][0]-q[0][3]) < (beta >> 3) && |
553 | 0 | std::abs(p[0][0]-q[0][0]) < ((5 * tc + 1) >> 1)); |
554 | |
|
555 | 0 | bool dSam3 = (2 * dpq3 < (beta >> 2) && |
556 | 0 | std::abs(p[3][3]-p[3][0]) + std::abs(q[3][0]-q[3][3]) < (beta >> 3) && |
557 | 0 | std::abs(p[3][0]-q[3][0]) < ((5 * tc + 1) >> 1)); |
558 | |
|
559 | 0 | if (dSam0 && dSam3) { |
560 | 0 | dE = 2; |
561 | 0 | } |
562 | 0 | else { |
563 | 0 | dE = 1; |
564 | 0 | } |
565 | |
|
566 | 0 | if (dp < ((beta + (beta >> 1)) >> 3)) { dEp = 1; } |
567 | 0 | if (dq < ((beta + (beta >> 1)) >> 3)) { dEq = 1; } |
568 | |
|
569 | 0 | logtrace(LogDeblock, "dE:%d dEp:%d dEq:%d\n", dE, dEp, dEq); |
570 | 0 | } |
571 | | |
572 | | |
573 | | // 8.7.2.4.4 |
574 | |
|
575 | 0 | if (dE != 0) { |
576 | 0 | bool filterP = true; |
577 | 0 | bool filterQ = true; |
578 | |
|
579 | 0 | if (vertical) { |
580 | 0 | if (sps.pcm_loop_filter_disable_flag && img->get_pcm_flag(xDi-1,yDi)) filterP=false; |
581 | 0 | if (img->get_cu_transquant_bypass(xDi-1,yDi)) filterP=false; |
582 | |
|
583 | 0 | if (sps.pcm_loop_filter_disable_flag && img->get_pcm_flag(xDi,yDi)) filterQ=false; |
584 | 0 | if (img->get_cu_transquant_bypass(xDi,yDi)) filterQ=false; |
585 | 0 | } |
586 | 0 | else { |
587 | 0 | if (sps.pcm_loop_filter_disable_flag && img->get_pcm_flag(xDi,yDi-1)) filterP=false; |
588 | 0 | if (img->get_cu_transquant_bypass(xDi,yDi-1)) filterP=false; |
589 | |
|
590 | 0 | if (sps.pcm_loop_filter_disable_flag && img->get_pcm_flag(xDi,yDi)) filterQ=false; |
591 | 0 | if (img->get_cu_transquant_bypass(xDi,yDi)) filterQ=false; |
592 | 0 | } |
593 | |
|
594 | 0 | if constexpr (sizeof(pixel_t)==1) { |
595 | 0 | img->decctx->acceleration.deblock_luma_8((uint8_t*)ptr, stride, vertical, |
596 | 0 | dE,dEp,dEq,tc, filterP,filterQ); |
597 | | } |
598 | 0 | else { |
599 | 0 | deblock_luma_kernel<pixel_t>(ptr, stride, vertical, |
600 | 0 | dE,dEp,dEq,tc, filterP,filterQ, bitDepth_Y); |
601 | 0 | } |
602 | 0 | } |
603 | 0 | } |
604 | 0 | } |
605 | 0 | } Unexecuted instantiation: void edge_filtering_luma_internal<unsigned short>(de265_image*, bool, int, int, int, int) Unexecuted instantiation: void edge_filtering_luma_internal<unsigned char>(de265_image*, bool, int, int, int, int) |
606 | | |
607 | | |
608 | | void edge_filtering_luma(de265_image* img, bool vertical, |
609 | | int yStart,int yEnd, int xStart,int xEnd) |
610 | 0 | { |
611 | 0 | if (img->high_bit_depth(0)) { |
612 | 0 | edge_filtering_luma_internal<uint16_t>(img,vertical,yStart,yEnd,xStart,xEnd); |
613 | 0 | } |
614 | 0 | else { |
615 | 0 | edge_filtering_luma_internal<uint8_t>(img,vertical,yStart,yEnd,xStart,xEnd); |
616 | 0 | } |
617 | 0 | } |
618 | | |
619 | | void edge_filtering_luma_CTB(de265_image* img, bool vertical, int xCtb,int yCtb) |
620 | 0 | { |
621 | 0 | int ctbSize = img->get_sps().CtbSizeY; |
622 | 0 | int deblkSize = ctbSize/4; |
623 | |
|
624 | 0 | edge_filtering_luma(img,vertical, |
625 | 0 | yCtb*deblkSize, (yCtb+1)*deblkSize, |
626 | 0 | xCtb*deblkSize, (xCtb+1)*deblkSize); |
627 | 0 | } |
628 | | |
629 | | |
630 | | |
631 | | |
632 | | // 8.7.2.4 |
633 | | /** ?Start and ?End values in 4-luma pixels resolution. |
634 | | */ |
635 | | template <class pixel_t> |
636 | | void edge_filtering_chroma_internal(de265_image* img, bool vertical, |
637 | | int yStart,int yEnd, |
638 | | int xStart,int xEnd) |
639 | 0 | { |
640 | | //printf("chroma %d-%d %d-%d\n",xStart,xEnd,yStart,yEnd); |
641 | |
|
642 | 0 | const seq_parameter_set& sps = img->get_sps(); |
643 | |
|
644 | 0 | const int SubWidthC = sps.SubWidthC; |
645 | 0 | const int SubHeightC = sps.SubHeightC; |
646 | |
|
647 | 0 | int xIncr = vertical ? 2 : 1; |
648 | 0 | int yIncr = vertical ? 1 : 2; |
649 | |
|
650 | 0 | xIncr *= SubWidthC; |
651 | 0 | yIncr *= SubHeightC; |
652 | |
|
653 | 0 | const int stride = img->get_image_stride(1); |
654 | |
|
655 | 0 | xEnd = std::min(xEnd,img->get_deblk_width()); |
656 | 0 | yEnd = std::min(yEnd,img->get_deblk_height()); |
657 | |
|
658 | 0 | int bitDepth_C = sps.BitDepth_C; |
659 | |
|
660 | 0 | for (int y=yStart;y<yEnd;y+=yIncr) |
661 | 0 | for (int x=xStart;x<xEnd;x+=xIncr) { |
662 | 0 | int xDi = x << (3-SubWidthC); |
663 | 0 | int yDi = y << (3-SubHeightC); |
664 | | |
665 | | //printf("x,y:%d,%d xDi,yDi:%d,%d\n",x,y,xDi,yDi); |
666 | |
|
667 | 0 | int bS = img->get_deblk_bS(xDi*SubWidthC,yDi*SubHeightC); |
668 | |
|
669 | 0 | if (bS>1) { |
670 | | // 8.7.2.4.5 |
671 | |
|
672 | 0 | for (int cplane=0;cplane<2;cplane++) { |
673 | 0 | int cQpPicOffset = (cplane==0 ? |
674 | 0 | img->get_pps().pic_cb_qp_offset : |
675 | 0 | img->get_pps().pic_cr_qp_offset); |
676 | |
|
677 | 0 | pixel_t* ptr = img->get_image_plane_at_pos_NEW<pixel_t>(cplane+1, xDi,yDi); |
678 | | |
679 | |
|
680 | | #if 0 |
681 | | for (int k=0;k<4;k++) |
682 | | { |
683 | | for (int i=0;i<2;i++) |
684 | | { |
685 | | printf("%02x ", p[1-i][k]); |
686 | | } |
687 | | |
688 | | printf("| "); |
689 | | |
690 | | for (int i=0;i<2;i++) |
691 | | { |
692 | | printf("%02x ", q[i][k]); |
693 | | } |
694 | | printf("\n"); |
695 | | } |
696 | | #endif |
697 | |
|
698 | 0 | int QP_Q = img->get_QPY(SubWidthC*xDi,SubHeightC*yDi); |
699 | 0 | int QP_P = (vertical ? |
700 | 0 | img->get_QPY(SubWidthC*xDi-1,SubHeightC*yDi) : |
701 | 0 | img->get_QPY(SubWidthC*xDi,SubHeightC*yDi-1)); |
702 | 0 | int qP_i = ((QP_Q+QP_P+1)>>1) + cQpPicOffset; |
703 | 0 | int QP_C; |
704 | 0 | if (sps.ChromaArrayType == CHROMA_420) { |
705 | 0 | QP_C = table8_22(qP_i); |
706 | 0 | } else { |
707 | 0 | QP_C = std::min(qP_i, 51); |
708 | 0 | } |
709 | | |
710 | | |
711 | | //printf("POC=%d\n",ctx->img->PicOrderCntVal); |
712 | 0 | logtrace(LogDeblock,"%d %d: ((%d+%d+1)>>1) + %d = qP_i=%d (QP_C=%d)\n", |
713 | 0 | SubWidthC*xDi,SubHeightC*yDi, QP_Q,QP_P,cQpPicOffset,qP_i,QP_C); |
714 | |
|
715 | 0 | int sliceIndexQ00 = img->get_SliceHeaderIndex(SubWidthC*xDi,SubHeightC*yDi); |
716 | 0 | int tc_offset = img->slices[sliceIndexQ00]->slice_tc_offset; |
717 | |
|
718 | 0 | int Q = Clip3(0,53, QP_C + 2*(bS-1) + tc_offset); |
719 | |
|
720 | 0 | int tcPrime = table_8_23_tc[Q]; |
721 | 0 | int tc = tcPrime * (1<<(sps.BitDepth_C - 8)); |
722 | |
|
723 | 0 | logtrace(LogDeblock,"tc_offset=%d Q=%d tc'=%d tc=%d\n",tc_offset,Q,tcPrime,tc); |
724 | |
|
725 | 0 | if (vertical) { |
726 | 0 | bool filterP = true; |
727 | 0 | if (sps.pcm_loop_filter_disable_flag && img->get_pcm_flag(SubWidthC*xDi-1,SubHeightC*yDi)) filterP=false; |
728 | 0 | if (img->get_cu_transquant_bypass(SubWidthC*xDi-1,SubHeightC*yDi)) filterP=false; |
729 | |
|
730 | 0 | bool filterQ = true; |
731 | 0 | if (sps.pcm_loop_filter_disable_flag && img->get_pcm_flag(SubWidthC*xDi,SubHeightC*yDi)) filterQ=false; |
732 | 0 | if (img->get_cu_transquant_bypass(SubWidthC*xDi,SubHeightC*yDi)) filterQ=false; |
733 | | |
734 | |
|
735 | 0 | if constexpr (sizeof(pixel_t)==1) { |
736 | 0 | img->decctx->acceleration.deblock_chroma_8((uint8_t*)ptr, stride, 1, tc, filterP,filterQ); |
737 | | } |
738 | 0 | else { |
739 | 0 | deblock_chroma_kernel<pixel_t>(ptr, stride, true, tc, filterP,filterQ, bitDepth_C); |
740 | 0 | } |
741 | 0 | } |
742 | 0 | else { |
743 | 0 | bool filterP = true; |
744 | 0 | if (sps.pcm_loop_filter_disable_flag && img->get_pcm_flag(SubWidthC*xDi,SubHeightC*yDi-1)) filterP=false; |
745 | 0 | if (img->get_cu_transquant_bypass(SubWidthC*xDi,SubHeightC*yDi-1)) filterP=false; |
746 | |
|
747 | 0 | bool filterQ = true; |
748 | 0 | if (sps.pcm_loop_filter_disable_flag && img->get_pcm_flag(SubWidthC*xDi,SubHeightC*yDi)) filterQ=false; |
749 | 0 | if (img->get_cu_transquant_bypass(SubWidthC*xDi,SubHeightC*yDi)) filterQ=false; |
750 | |
|
751 | 0 | if constexpr (sizeof(pixel_t)==1) { |
752 | 0 | img->decctx->acceleration.deblock_chroma_8((uint8_t*)ptr, stride, 0, tc, filterP,filterQ); |
753 | | } |
754 | 0 | else { |
755 | 0 | deblock_chroma_kernel<pixel_t>(ptr, stride, false, tc, filterP,filterQ, bitDepth_C); |
756 | 0 | } |
757 | 0 | } |
758 | 0 | } |
759 | 0 | } |
760 | 0 | } |
761 | 0 | } Unexecuted instantiation: void edge_filtering_chroma_internal<unsigned short>(de265_image*, bool, int, int, int, int) Unexecuted instantiation: void edge_filtering_chroma_internal<unsigned char>(de265_image*, bool, int, int, int, int) |
762 | | |
763 | | |
764 | | void edge_filtering_chroma(de265_image* img, bool vertical, int yStart,int yEnd, |
765 | | int xStart,int xEnd) |
766 | 0 | { |
767 | 0 | if (img->high_bit_depth(1)) { |
768 | 0 | edge_filtering_chroma_internal<uint16_t>(img,vertical,yStart,yEnd,xStart,xEnd); |
769 | 0 | } |
770 | 0 | else { |
771 | 0 | edge_filtering_chroma_internal<uint8_t>(img,vertical,yStart,yEnd,xStart,xEnd); |
772 | 0 | } |
773 | 0 | } |
774 | | |
775 | | |
776 | | void edge_filtering_chroma_CTB(de265_image* img, bool vertical, int xCtb,int yCtb) |
777 | 0 | { |
778 | 0 | int ctbSize = img->get_sps().CtbSizeY; |
779 | 0 | int deblkSize = ctbSize/4; |
780 | |
|
781 | 0 | edge_filtering_chroma(img,vertical, |
782 | 0 | yCtb*deblkSize, (yCtb+1)*deblkSize, |
783 | 0 | xCtb*deblkSize, (xCtb+1)*deblkSize); |
784 | 0 | } |
785 | | |
786 | | |
787 | | |
788 | | class thread_task_deblock_CTBRow : public thread_task |
789 | | { |
790 | | public: |
791 | | struct de265_image* img; |
792 | | int ctb_y; |
793 | | bool vertical; |
794 | | |
795 | | virtual void work(); |
796 | 0 | virtual std::string name() const { |
797 | 0 | char buf[100]; |
798 | 0 | sprintf(buf,"deblock-%d",ctb_y); |
799 | 0 | return buf; |
800 | 0 | } |
801 | | }; |
802 | | |
803 | | |
804 | | void thread_task_deblock_CTBRow::work() |
805 | 0 | { |
806 | 0 | state = Running; |
807 | 0 | img->thread_run(this); |
808 | |
|
809 | 0 | int xStart=0; |
810 | 0 | int xEnd = img->get_deblk_width(); |
811 | |
|
812 | 0 | int ctbSize = img->get_sps().CtbSizeY; |
813 | 0 | int deblkSize = ctbSize/4; |
814 | |
|
815 | 0 | int first = ctb_y * deblkSize; |
816 | 0 | int last = (ctb_y+1) * deblkSize; |
817 | 0 | if (last > img->get_deblk_height()) { |
818 | 0 | last = img->get_deblk_height(); |
819 | 0 | } |
820 | |
|
821 | 0 | int finalProgress = CTB_PROGRESS_DEBLK_V; |
822 | 0 | if (!vertical) finalProgress = CTB_PROGRESS_DEBLK_H; |
823 | |
|
824 | 0 | int rightCtb = img->get_sps().PicWidthInCtbsY-1; |
825 | |
|
826 | 0 | if (vertical) { |
827 | | // pass 1: vertical |
828 | |
|
829 | 0 | int CtbRow = std::min(ctb_y+1 , img->get_sps().PicHeightInCtbsY-1); |
830 | 0 | img->wait_for_progress(this, rightCtb,CtbRow, CTB_PROGRESS_PREFILTER); |
831 | 0 | } |
832 | 0 | else { |
833 | | // pass 2: horizontal |
834 | |
|
835 | 0 | if (ctb_y>0) { |
836 | 0 | img->wait_for_progress(this, rightCtb,ctb_y-1, CTB_PROGRESS_DEBLK_V); |
837 | 0 | } |
838 | |
|
839 | 0 | img->wait_for_progress(this, rightCtb,ctb_y, CTB_PROGRESS_DEBLK_V); |
840 | |
|
841 | 0 | if (ctb_y+1<img->get_sps().PicHeightInCtbsY) { |
842 | 0 | img->wait_for_progress(this, rightCtb,ctb_y+1, CTB_PROGRESS_DEBLK_V); |
843 | 0 | } |
844 | 0 | } |
845 | | |
846 | | //printf("deblock %d to %d orientation: %d\n",first,last,vertical); |
847 | |
|
848 | 0 | bool deblocking_enabled; |
849 | | |
850 | | // first pass: check edge flags and whether we have to deblock |
851 | 0 | if (vertical) { |
852 | 0 | deblocking_enabled = derive_edgeFlags_CTBRow(img, ctb_y); |
853 | | |
854 | | //for (int x=0;x<=rightCtb;x++) { |
855 | 0 | int x=0; img->set_CtbDeblockFlag(x,ctb_y, deblocking_enabled); |
856 | | //} |
857 | 0 | } |
858 | 0 | else { |
859 | 0 | int x=0; deblocking_enabled=img->get_CtbDeblockFlag(x,ctb_y); |
860 | 0 | } |
861 | |
|
862 | 0 | if (deblocking_enabled) { |
863 | 0 | derive_boundaryStrength(img, vertical, first,last, xStart,xEnd); |
864 | |
|
865 | 0 | edge_filtering_luma(img, vertical, first,last, xStart,xEnd); |
866 | |
|
867 | 0 | if (img->get_sps().ChromaArrayType != CHROMA_MONO) { |
868 | 0 | edge_filtering_chroma(img, vertical, first,last, xStart,xEnd); |
869 | 0 | } |
870 | 0 | } |
871 | |
|
872 | 0 | for (int x=0;x<=rightCtb;x++) { |
873 | 0 | const int CtbWidth = img->get_sps().PicWidthInCtbsY; |
874 | 0 | img->ctb_progress[x+ctb_y*CtbWidth].set_progress(finalProgress); |
875 | 0 | } |
876 | |
|
877 | 0 | state = Finished; |
878 | 0 | img->thread_finishes(this); |
879 | 0 | } |
880 | | |
881 | | |
882 | | void add_deblocking_tasks(image_unit* imgunit) |
883 | 0 | { |
884 | 0 | de265_image* img = imgunit->img; |
885 | 0 | decoder_context* ctx = img->decctx; |
886 | |
|
887 | 0 | int nRows = img->get_sps().PicHeightInCtbsY; |
888 | |
|
889 | 0 | img->thread_start(nRows*2); |
890 | |
|
891 | 0 | for (int pass=0;pass<2;pass++) |
892 | 0 | { |
893 | 0 | for (int y=0;y<img->get_sps().PicHeightInCtbsY;y++) |
894 | 0 | { |
895 | 0 | thread_task_deblock_CTBRow* task = new thread_task_deblock_CTBRow; |
896 | |
|
897 | 0 | task->img = img; |
898 | 0 | task->ctb_y = y; |
899 | 0 | task->vertical = (pass==0); |
900 | |
|
901 | 0 | imgunit->tasks.push_back(task); |
902 | 0 | ctx->thread_pool_.add_task(task); |
903 | 0 | } |
904 | 0 | } |
905 | 0 | } |
906 | | |
907 | | |
908 | | void apply_deblocking_filter(de265_image* img) // decoder_context* ctx) |
909 | 0 | { |
910 | | //decoder_context* ctx = img->decctx; |
911 | |
|
912 | 0 | char enabled_deblocking = derive_edgeFlags(img); |
913 | |
|
914 | 0 | if (enabled_deblocking) |
915 | 0 | { |
916 | | // vertical filtering |
917 | |
|
918 | 0 | logtrace(LogDeblock,"VERTICAL\n"); |
919 | 0 | derive_boundaryStrength(img, true ,0,img->get_deblk_height(),0,img->get_deblk_width()); |
920 | 0 | edge_filtering_luma (img, true ,0,img->get_deblk_height(),0,img->get_deblk_width()); |
921 | |
|
922 | 0 | if (img->get_sps().ChromaArrayType != CHROMA_MONO) { |
923 | 0 | edge_filtering_chroma (img, true ,0,img->get_deblk_height(),0,img->get_deblk_width()); |
924 | 0 | } |
925 | | #if 0 |
926 | | char buf[1000]; |
927 | | sprintf(buf,"lf-after-V-%05d.yuv", ctx->img->PicOrderCntVal); |
928 | | write_picture_to_file(ctx->img, buf); |
929 | | #endif |
930 | | |
931 | | // horizontal filtering |
932 | |
|
933 | 0 | logtrace(LogDeblock,"HORIZONTAL\n"); |
934 | 0 | derive_boundaryStrength(img, false ,0,img->get_deblk_height(),0,img->get_deblk_width()); |
935 | 0 | edge_filtering_luma (img, false ,0,img->get_deblk_height(),0,img->get_deblk_width()); |
936 | |
|
937 | 0 | if (img->get_sps().ChromaArrayType != CHROMA_MONO) { |
938 | 0 | edge_filtering_chroma (img, false ,0,img->get_deblk_height(),0,img->get_deblk_width()); |
939 | 0 | } |
940 | |
|
941 | | #if 0 |
942 | | sprintf(buf,"lf-after-H-%05d.yuv", ctx->img->PicOrderCntVal); |
943 | | write_picture_to_file(ctx->img, buf); |
944 | | #endif |
945 | 0 | } |
946 | 0 | } |