Coverage Report

Created: 2026-02-26 06:25

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