1 /*****************************************************************************
2 * Copyright (C) 2013 x265 project
4 * Author: Gopu Govindaswamy <gopu@multicorewareinc.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
20 * This program is also available under a commercial proprietary license.
21 * For more information, contact us at license @ x265.com.
22 *****************************************************************************/
26 #include "framedata.h"
33 #define DEBLOCK_SMALLEST_BLOCK 8
34 #define DEFAULT_INTRA_TC_OFFSET 2
36 void Deblock::deblockCTU(CUData
* cu
, int32_t dir
)
38 uint8_t blockingStrength
[MAX_NUM_PARTITIONS
];
40 memset(blockingStrength
, 0, sizeof(uint8_t) * m_numPartitions
);
42 deblockCU(cu
, 0, 0, dir
, blockingStrength
);
45 /* Deblocking filter process in CU-based (the same function as conventional's)
46 * param Edge the direction of the edge in block boundary (horizonta/vertical), which is added newly */
47 void Deblock::deblockCU(CUData
* cu
, uint32_t absPartIdx
, uint32_t depth
, const int32_t dir
, uint8_t blockingStrength
[])
49 if (cu
->m_partSize
[absPartIdx
] == SIZE_NONE
)
52 uint32_t curNumParts
= NUM_CU_PARTITIONS
>> (depth
<< 1);
54 const SPS
& sps
= *cu
->m_slice
->m_sps
;
56 if (cu
->m_cuDepth
[absPartIdx
] > depth
)
58 uint32_t qNumParts
= curNumParts
>> 2;
59 uint32_t xmax
= sps
.picWidthInLumaSamples
- cu
->m_cuPelX
;
60 uint32_t ymax
= sps
.picHeightInLumaSamples
- cu
->m_cuPelY
;
61 for (uint32_t partIdx
= 0; partIdx
< 4; partIdx
++, absPartIdx
+= qNumParts
)
62 if (g_zscanToPelX
[absPartIdx
] < xmax
&& g_zscanToPelY
[absPartIdx
] < ymax
)
63 deblockCU(cu
, absPartIdx
, depth
+ 1, dir
, blockingStrength
);
67 const uint32_t widthInBaseUnits
= sps
.numPartInCUSize
>> depth
;
69 setLoopfilterParam(cu
, absPartIdx
, ¶ms
);
70 setEdgefilterPU(cu
, absPartIdx
, dir
, blockingStrength
, widthInBaseUnits
);
71 setEdgefilterTU(cu
, absPartIdx
, depth
, dir
, blockingStrength
);
72 setEdgefilterMultiple(cu
, absPartIdx
, dir
, 0, (dir
== EDGE_VER
? params
.leftEdge
: params
.topEdge
), blockingStrength
, widthInBaseUnits
);
74 for (uint32_t partIdx
= absPartIdx
; partIdx
< absPartIdx
+ curNumParts
; partIdx
++)
76 uint32_t bsCheck
= !(partIdx
& (1 << dir
));
78 if (bsCheck
&& blockingStrength
[partIdx
])
79 getBoundaryStrengthSingle(cu
, dir
, partIdx
, blockingStrength
);
82 const uint32_t partIdxIncr
= DEBLOCK_SMALLEST_BLOCK
>> LOG2_UNIT_SIZE
;
83 uint32_t sizeInPU
= sps
.numPartInCUSize
>> depth
;
84 uint32_t shiftFactor
= (dir
== EDGE_VER
) ? cu
->m_hChromaShift
: cu
->m_vChromaShift
;
85 uint32_t chromaMask
= ((DEBLOCK_SMALLEST_BLOCK
<< shiftFactor
) >> LOG2_UNIT_SIZE
) - 1;
86 uint32_t e0
= (dir
== EDGE_VER
? g_zscanToPelX
[absPartIdx
] : g_zscanToPelY
[absPartIdx
]) >> LOG2_UNIT_SIZE
;
88 for (uint32_t e
= 0; e
< sizeInPU
; e
+= partIdxIncr
)
90 edgeFilterLuma(cu
, absPartIdx
, depth
, dir
, e
, blockingStrength
);
91 if (!((e0
+ e
) & chromaMask
))
92 edgeFilterChroma(cu
, absPartIdx
, depth
, dir
, e
, blockingStrength
);
96 static inline uint32_t calcBsIdx(CUData
* cu
, uint32_t absPartIdx
, int32_t dir
, int32_t edgeIdx
, int32_t baseUnitIdx
)
98 uint32_t ctuWidthInBaseUnits
= cu
->m_slice
->m_sps
->numPartInCUSize
;
101 return g_rasterToZscan
[g_zscanToRaster
[absPartIdx
] + edgeIdx
* ctuWidthInBaseUnits
+ baseUnitIdx
];
103 return g_rasterToZscan
[g_zscanToRaster
[absPartIdx
] + baseUnitIdx
* ctuWidthInBaseUnits
+ edgeIdx
];
106 void Deblock::setEdgefilterMultiple(CUData
* cu
, uint32_t scanIdx
, int32_t dir
, int32_t edgeIdx
, uint8_t value
, uint8_t blockingStrength
[], uint32_t widthInBaseUnits
)
108 const uint32_t numElem
= widthInBaseUnits
;
109 X265_CHECK(numElem
> 0, "numElem edge filter check\n");
110 for (uint32_t i
= 0; i
< numElem
; i
++)
112 const uint32_t bsidx
= calcBsIdx(cu
, scanIdx
, dir
, edgeIdx
, i
);
113 blockingStrength
[bsidx
] = value
;
117 void Deblock::setEdgefilterTU(CUData
* cu
, uint32_t absPartIdx
, uint32_t depth
, int32_t dir
, uint8_t blockingStrength
[])
119 if ((uint32_t)cu
->m_tuDepth
[absPartIdx
] + cu
->m_cuDepth
[absPartIdx
] > depth
)
121 const uint32_t curNumParts
= NUM_CU_PARTITIONS
>> (depth
<< 1);
122 const uint32_t qNumParts
= curNumParts
>> 2;
124 for (uint32_t partIdx
= 0; partIdx
< 4; partIdx
++, absPartIdx
+= qNumParts
)
125 setEdgefilterTU(cu
, absPartIdx
, depth
+ 1, dir
, blockingStrength
);
129 uint32_t widthInBaseUnits
= 1 << (cu
->m_log2CUSize
[absPartIdx
] - cu
->m_tuDepth
[absPartIdx
] - LOG2_UNIT_SIZE
);
130 setEdgefilterMultiple(cu
, absPartIdx
, dir
, 0, 2, blockingStrength
, widthInBaseUnits
);
133 void Deblock::setEdgefilterPU(CUData
* cu
, uint32_t absPartIdx
, int32_t dir
, uint8_t blockingStrength
[], uint32_t widthInBaseUnits
)
135 const uint32_t hWidthInBaseUnits
= widthInBaseUnits
>> 1;
136 const uint32_t qWidthInBaseUnits
= widthInBaseUnits
>> 2;
138 switch (cu
->m_partSize
[absPartIdx
])
142 setEdgefilterMultiple(cu
, absPartIdx
, dir
, hWidthInBaseUnits
, 1, blockingStrength
, widthInBaseUnits
);
146 setEdgefilterMultiple(cu
, absPartIdx
, dir
, hWidthInBaseUnits
, 1, blockingStrength
, widthInBaseUnits
);
149 setEdgefilterMultiple(cu
, absPartIdx
, dir
, hWidthInBaseUnits
, 1, blockingStrength
, widthInBaseUnits
);
153 setEdgefilterMultiple(cu
, absPartIdx
, dir
, qWidthInBaseUnits
, 1, blockingStrength
, widthInBaseUnits
);
157 setEdgefilterMultiple(cu
, absPartIdx
, dir
, qWidthInBaseUnits
, 1, blockingStrength
, widthInBaseUnits
);
161 setEdgefilterMultiple(cu
, absPartIdx
, dir
, widthInBaseUnits
- qWidthInBaseUnits
, 1, blockingStrength
, widthInBaseUnits
);
165 setEdgefilterMultiple(cu
, absPartIdx
, dir
, widthInBaseUnits
- qWidthInBaseUnits
, 1, blockingStrength
, widthInBaseUnits
);
174 void Deblock::setLoopfilterParam(CUData
* cu
, uint32_t absPartIdx
, Param
*params
)
176 uint32_t x
= cu
->m_cuPelX
+ g_zscanToPelX
[absPartIdx
];
177 uint32_t y
= cu
->m_cuPelY
+ g_zscanToPelY
[absPartIdx
];
179 const CUData
* tempCU
;
180 uint32_t tempPartIdx
;
183 params
->leftEdge
= 0;
186 tempCU
= cu
->getPULeft(tempPartIdx
, absPartIdx
);
188 params
->leftEdge
= 2;
190 params
->leftEdge
= 0;
197 tempCU
= cu
->getPUAbove(tempPartIdx
, absPartIdx
);
205 void Deblock::getBoundaryStrengthSingle(CUData
* cu
, int32_t dir
, uint32_t absPartIdx
, uint8_t blockingStrength
[])
207 const Slice
* const slice
= cu
->m_slice
;
208 const uint32_t partQ
= absPartIdx
;
209 CUData
* const cuQ
= cu
;
215 // Calculate block index
217 cuP
= cuQ
->getPULeft(partP
, partQ
);
218 else // (dir == EDGE_HOR)
219 cuP
= cuQ
->getPUAbove(partP
, partQ
);
221 // Set BS for Intra MB : BS = 4 or 3
222 if (cuP
->isIntra(partP
) || cuQ
->isIntra(partQ
))
225 // Set BS for not Intra MB : BS = 2 or 1 or 0
226 if (!cuP
->isIntra(partP
) && !cuQ
->isIntra(partQ
))
228 uint32_t nsPartQ
= partQ
;
229 uint32_t nsPartP
= partP
;
231 if (blockingStrength
[absPartIdx
] > 1 &&
232 (cuQ
->getCbf(nsPartQ
, TEXT_LUMA
, cuQ
->m_tuDepth
[nsPartQ
]) ||
233 cuP
->getCbf(nsPartP
, TEXT_LUMA
, cuP
->m_tuDepth
[nsPartP
])))
238 cuP
= cuQ
->getPUAbove(partP
, partQ
);
240 if (slice
->isInterB() || cuP
->m_slice
->isInterB())
243 Frame
*refP0
, *refP1
, *refQ0
, *refQ1
;
244 refIdx
= cuP
->m_refIdx
[0][partP
];
245 refP0
= (refIdx
< 0) ? NULL
: cuP
->m_slice
->m_refPicList
[0][refIdx
];
246 refIdx
= cuP
->m_refIdx
[1][partP
];
247 refP1
= (refIdx
< 0) ? NULL
: cuP
->m_slice
->m_refPicList
[1][refIdx
];
248 refIdx
= cuQ
->m_refIdx
[0][partQ
];
249 refQ0
= (refIdx
< 0) ? NULL
: slice
->m_refPicList
[0][refIdx
];
250 refIdx
= cuQ
->m_refIdx
[1][partQ
];
251 refQ1
= (refIdx
< 0) ? NULL
: slice
->m_refPicList
[1][refIdx
];
253 MV mvp0
= cuP
->m_mv
[0][partP
];
254 MV mvp1
= cuP
->m_mv
[1][partP
];
255 MV mvq0
= cuQ
->m_mv
[0][partQ
];
256 MV mvq1
= cuQ
->m_mv
[1][partQ
];
258 if (!refP0
) mvp0
= 0;
259 if (!refP1
) mvp1
= 0;
260 if (!refQ0
) mvq0
= 0;
261 if (!refQ1
) mvq1
= 0;
263 if (((refP0
== refQ0
) && (refP1
== refQ1
)) || ((refP0
== refQ1
) && (refP1
== refQ0
)))
265 if (refP0
!= refP1
) // Different L0 & L1
269 bs
= ((abs(mvq0
.x
- mvp0
.x
) >= 4) ||
270 (abs(mvq0
.y
- mvp0
.y
) >= 4) ||
271 (abs(mvq1
.x
- mvp1
.x
) >= 4) ||
272 (abs(mvq1
.y
- mvp1
.y
) >= 4)) ? 1 : 0;
276 bs
= ((abs(mvq1
.x
- mvp0
.x
) >= 4) ||
277 (abs(mvq1
.y
- mvp0
.y
) >= 4) ||
278 (abs(mvq0
.x
- mvp1
.x
) >= 4) ||
279 (abs(mvq0
.y
- mvp1
.y
) >= 4)) ? 1 : 0;
284 bs
= ((abs(mvq0
.x
- mvp0
.x
) >= 4) ||
285 (abs(mvq0
.y
- mvp0
.y
) >= 4) ||
286 (abs(mvq1
.x
- mvp1
.x
) >= 4) ||
287 (abs(mvq1
.y
- mvp1
.y
) >= 4)) &&
288 ((abs(mvq1
.x
- mvp0
.x
) >= 4) ||
289 (abs(mvq1
.y
- mvp0
.y
) >= 4) ||
290 (abs(mvq0
.x
- mvp1
.x
) >= 4) ||
291 (abs(mvq0
.y
- mvp1
.y
) >= 4)) ? 1 : 0;
294 else // for all different Ref_Idx
297 else // slice->isInterP()
300 Frame
*refp0
, *refq0
;
301 refIdx
= cuP
->m_refIdx
[0][partP
];
302 refp0
= (refIdx
< 0) ? NULL
: cuP
->m_slice
->m_refPicList
[0][refIdx
];
303 refIdx
= cuQ
->m_refIdx
[0][partQ
];
304 refq0
= (refIdx
< 0) ? NULL
: slice
->m_refPicList
[0][refIdx
];
305 MV mvp0
= cuP
->m_mv
[0][partP
];
306 MV mvq0
= cuQ
->m_mv
[0][partQ
];
308 if (!refp0
) mvp0
= 0;
309 if (!refq0
) mvq0
= 0;
311 bs
= ((refp0
!= refq0
) ||
312 (abs(mvq0
.x
- mvp0
.x
) >= 4) ||
313 (abs(mvq0
.y
- mvp0
.y
) >= 4)) ? 1 : 0;
318 blockingStrength
[absPartIdx
] = bs
;
321 static inline int32_t calcDP(pixel
* src
, intptr_t offset
)
323 return abs(static_cast<int32_t>(src
[-offset
* 3]) - 2 * src
[-offset
* 2] + src
[-offset
]);
326 static inline int32_t calcDQ(pixel
* src
, intptr_t offset
)
328 return abs(static_cast<int32_t>(src
[0]) - 2 * src
[offset
] + src
[offset
* 2]);
331 static inline bool useStrongFiltering(intptr_t offset
, int32_t beta
, int32_t tc
, pixel
* src
)
333 int16_t m4
= (int16_t)src
[0];
334 int16_t m3
= (int16_t)src
[-offset
];
335 int16_t m7
= (int16_t)src
[offset
* 3];
336 int16_t m0
= (int16_t)src
[-offset
* 4];
337 int32_t strong
= abs(m0
- m3
) + abs(m7
- m4
);
339 return (strong
< (beta
>> 3)) && (abs(m3
- m4
) < ((tc
* 5 + 1) >> 1));
342 /* Deblocking for the luminance component with strong or weak filter
343 * \param src pointer to picture data
344 * \param offset offset value for picture data
346 * \param partPNoFilter indicator to disable filtering on partP
347 * \param partQNoFilter indicator to disable filtering on partQ
348 * \param filterSecondP decision weak filter/no filter for partP
349 * \param filterSecondQ decision weak filter/no filter for partQ */
350 static inline void pelFilterLumaStrong(pixel
* src
, intptr_t srcStep
, intptr_t offset
, int32_t tc
, bool partPNoFilter
, bool partQNoFilter
)
352 for (int32_t i
= 0; i
< UNIT_SIZE
; i
++, src
+= srcStep
)
354 int16_t m4
= (int16_t)src
[0];
355 int16_t m3
= (int16_t)src
[-offset
];
356 int16_t m5
= (int16_t)src
[offset
];
357 int16_t m2
= (int16_t)src
[-offset
* 2];
358 int32_t tc2
= 2 * tc
;
361 int16_t m1
= (int16_t)src
[-offset
* 3];
362 int16_t m0
= (int16_t)src
[-offset
* 4];
363 src
[-offset
* 3] = (pixel
)(Clip3(-tc2
, tc2
, ((2 * m0
+ 3 * m1
+ m2
+ m3
+ m4
+ 4) >> 3) - m1
) + m1
);
364 src
[-offset
* 2] = (pixel
)(Clip3(-tc2
, tc2
, ((m1
+ m2
+ m3
+ m4
+ 2) >> 2) - m2
) + m2
);
365 src
[-offset
] = (pixel
)(Clip3(-tc2
, tc2
, ((m1
+ 2 * m2
+ 2 * m3
+ 2 * m4
+ m5
+ 4) >> 3) - m3
) + m3
);
369 int16_t m6
= (int16_t)src
[offset
* 2];
370 int16_t m7
= (int16_t)src
[offset
* 3];
371 src
[0] = (pixel
)(Clip3(-tc2
, tc2
, ((m2
+ 2 * m3
+ 2 * m4
+ 2 * m5
+ m6
+ 4) >> 3) - m4
) + m4
);
372 src
[offset
] = (pixel
)(Clip3(-tc2
, tc2
, ((m3
+ m4
+ m5
+ m6
+ 2) >> 2) - m5
) + m5
);
373 src
[offset
* 2] = (pixel
)(Clip3(-tc2
, tc2
, ((m3
+ m4
+ m5
+ 3 * m6
+ 2 * m7
+ 4) >> 3) - m6
) + m6
);
379 static inline void pelFilterLuma(pixel
* src
, intptr_t srcStep
, intptr_t offset
, int32_t tc
, bool partPNoFilter
, bool partQNoFilter
,
380 bool filterSecondP
, bool filterSecondQ
)
382 int32_t thrCut
= tc
* 10;
384 for (int32_t i
= 0; i
< UNIT_SIZE
; i
++, src
+= srcStep
)
386 int16_t m4
= (int16_t)src
[0];
387 int16_t m3
= (int16_t)src
[-offset
];
388 int16_t m5
= (int16_t)src
[offset
];
389 int16_t m2
= (int16_t)src
[-offset
* 2];
391 int32_t delta
= (9 * (m4
- m3
) - 3 * (m5
- m2
) + 8) >> 4;
393 if (abs(delta
) < thrCut
)
395 delta
= Clip3(-tc
, tc
, delta
);
397 int32_t tc2
= tc
>> 1;
400 src
[-offset
] = Clip(m3
+ delta
);
403 int16_t m1
= (int16_t)src
[-offset
* 3];
404 int32_t delta1
= Clip3(-tc2
, tc2
, ((((m1
+ m3
+ 1) >> 1) - m2
+ delta
) >> 1));
405 src
[-offset
* 2] = Clip(m2
+ delta1
);
410 src
[0] = Clip(m4
- delta
);
413 int16_t m6
= (int16_t)src
[offset
* 2];
414 int32_t delta2
= Clip3(-tc2
, tc2
, ((((m6
+ m4
+ 1) >> 1) - m5
- delta
) >> 1));
415 src
[offset
] = Clip(m5
+ delta2
);
422 /* Deblocking of one line/column for the chrominance component
423 * \param src pointer to picture data
424 * \param offset offset value for picture data
426 * \param partPNoFilter indicator to disable filtering on partP
427 * \param partQNoFilter indicator to disable filtering on partQ */
428 static inline void pelFilterChroma(pixel
* src
, intptr_t srcStep
, intptr_t offset
, int32_t tc
, bool partPNoFilter
, bool partQNoFilter
)
430 for (int32_t i
= 0; i
< UNIT_SIZE
; i
++, src
+= srcStep
)
432 int16_t m4
= (int16_t)src
[0];
433 int16_t m3
= (int16_t)src
[-offset
];
434 int16_t m5
= (int16_t)src
[offset
];
435 int16_t m2
= (int16_t)src
[-offset
* 2];
437 int32_t delta
= Clip3(-tc
, tc
, ((((m4
- m3
) << 2) + m2
- m5
+ 4) >> 3));
439 src
[-offset
] = Clip(m3
+ delta
);
441 src
[0] = Clip(m4
- delta
);
445 void Deblock::edgeFilterLuma(CUData
* cu
, uint32_t absPartIdx
, uint32_t depth
, int32_t dir
, int32_t edge
, const uint8_t blockingStrength
[])
447 PicYuv
* reconYuv
= cu
->m_encData
->m_reconPicYuv
;
448 pixel
* src
= reconYuv
->getLumaAddr(cu
->m_cuAddr
, absPartIdx
);
450 intptr_t stride
= reconYuv
->m_stride
;
451 uint32_t numParts
= cu
->m_slice
->m_sps
->numPartInCUSize
>> depth
;
453 intptr_t offset
, srcStep
;
455 bool partPNoFilter
= false;
456 bool partQNoFilter
= false;
459 const CUData
* cuP
= cu
;
460 const CUData
* cuQ
= cu
;
461 int32_t betaOffset
= cuQ
->m_slice
->m_pps
->deblockingFilterBetaOffsetDiv2
<< 1;
462 int32_t tcOffset
= cuQ
->m_slice
->m_pps
->deblockingFilterTcOffsetDiv2
<< 1;
468 src
+= (edge
<< LOG2_UNIT_SIZE
);
470 else // (dir == EDGE_HOR)
474 src
+= (edge
<< LOG2_UNIT_SIZE
) * stride
;
477 for (uint32_t idx
= 0; idx
< numParts
; idx
++)
479 uint32_t unitOffset
= idx
<< LOG2_UNIT_SIZE
;
480 uint32_t bsAbsIdx
= calcBsIdx(cu
, absPartIdx
, dir
, edge
, idx
);
481 uint32_t bs
= blockingStrength
[bsAbsIdx
];
484 int32_t qpQ
= cu
->m_qp
[bsAbsIdx
];
487 // Derive neighboring PU index
489 cuP
= cuQ
->getPULeft(partP
, partQ
);
490 else // (dir == EDGE_HOR)
491 cuP
= cuQ
->getPUAbove(partP
, partQ
);
493 int32_t qpP
= cuP
->m_qp
[partP
];
494 int32_t qp
= (qpP
+ qpQ
+ 1) >> 1;
496 int32_t indexB
= Clip3(0, QP_MAX_SPEC
, qp
+ betaOffset
);
498 const int32_t bitdepthShift
= X265_DEPTH
- 8;
499 int32_t beta
= s_betaTable
[indexB
] << bitdepthShift
;
501 int32_t dp0
= calcDP(src
+ srcStep
* (unitOffset
+ 0), offset
);
502 int32_t dq0
= calcDQ(src
+ srcStep
* (unitOffset
+ 0), offset
);
503 int32_t dp3
= calcDP(src
+ srcStep
* (unitOffset
+ 3), offset
);
504 int32_t dq3
= calcDQ(src
+ srcStep
* (unitOffset
+ 3), offset
);
505 int32_t d0
= dp0
+ dq0
;
506 int32_t d3
= dp3
+ dq3
;
512 if (cu
->m_slice
->m_pps
->bTransquantBypassEnabled
)
514 // check if each of PUs is lossless coded
515 partPNoFilter
= !!cuP
->m_tqBypass
[partP
];
516 partQNoFilter
= !!cuQ
->m_tqBypass
[partQ
];
519 int32_t indexTC
= Clip3(0, QP_MAX_SPEC
+ DEFAULT_INTRA_TC_OFFSET
, int32_t(qp
+ DEFAULT_INTRA_TC_OFFSET
* (bs
- 1) + tcOffset
));
520 int32_t tc
= s_tcTable
[indexTC
] << bitdepthShift
;
522 bool sw
= (2 * d0
< (beta
>> 2) &&
523 2 * d3
< (beta
>> 2) &&
524 useStrongFiltering(offset
, beta
, tc
, src
+ srcStep
* (unitOffset
+ 0)) &&
525 useStrongFiltering(offset
, beta
, tc
, src
+ srcStep
* (unitOffset
+ 3)));
528 pelFilterLumaStrong(src
+ srcStep
* unitOffset
, srcStep
, offset
, tc
, partPNoFilter
, partQNoFilter
);
531 int32_t sideThreshold
= (beta
+ (beta
>> 1)) >> 3;
532 int32_t dp
= dp0
+ dp3
;
533 int32_t dq
= dq0
+ dq3
;
534 bool filterP
= (dp
< sideThreshold
);
535 bool filterQ
= (dq
< sideThreshold
);
537 pelFilterLuma(src
+ srcStep
* unitOffset
, srcStep
, offset
, tc
, partPNoFilter
, partQNoFilter
, filterP
, filterQ
);
544 void Deblock::edgeFilterChroma(CUData
* cu
, uint32_t absPartIdx
, uint32_t depth
, int32_t dir
, int32_t edge
, const uint8_t blockingStrength
[])
546 int32_t chFmt
= cu
->m_chromaFormat
, chromaShift
;
547 intptr_t offset
, srcStep
;
549 bool partPNoFilter
= false;
550 bool partQNoFilter
= false;
554 const CUData
* cuQ
= cu
;
555 int32_t tcOffset
= cu
->m_slice
->m_pps
->deblockingFilterTcOffsetDiv2
<< 1;
557 X265_CHECK(((dir
== EDGE_VER
)
558 ? ((g_zscanToPelX
[absPartIdx
] + edge
* UNIT_SIZE
) >> cu
->m_hChromaShift
)
559 : ((g_zscanToPelY
[absPartIdx
] + edge
* UNIT_SIZE
) >> cu
->m_vChromaShift
)) % DEBLOCK_SMALLEST_BLOCK
== 0,
562 PicYuv
* reconPic
= cu
->m_encData
->m_reconPicYuv
;
563 intptr_t stride
= reconPic
->m_strideC
;
564 intptr_t srcOffset
= reconPic
->getChromaAddrOffset(cu
->m_cuAddr
, absPartIdx
);
568 chromaShift
= cu
->m_vChromaShift
;
569 srcOffset
+= (edge
<< (LOG2_UNIT_SIZE
- cu
->m_hChromaShift
));
573 else // (dir == EDGE_HOR)
575 chromaShift
= cu
->m_hChromaShift
;
576 srcOffset
+= edge
* stride
<< (LOG2_UNIT_SIZE
- cu
->m_vChromaShift
);
582 srcChroma
[0] = reconPic
->m_picOrg
[1] + srcOffset
;
583 srcChroma
[1] = reconPic
->m_picOrg
[2] + srcOffset
;
585 uint32_t numUnits
= cu
->m_slice
->m_sps
->numPartInCUSize
>> (depth
+ chromaShift
);
587 for (uint32_t idx
= 0; idx
< numUnits
; idx
++)
589 uint32_t unitOffset
= idx
<< LOG2_UNIT_SIZE
;
590 uint32_t bsAbsIdx
= calcBsIdx(cu
, absPartIdx
, dir
, edge
, idx
<< chromaShift
);
591 uint32_t bs
= blockingStrength
[bsAbsIdx
];
595 int32_t qpQ
= cu
->m_qp
[bsAbsIdx
];
598 // Derive neighboring PU index
600 cuP
= cuQ
->getPULeft(partP
, partQ
);
601 else // (dir == EDGE_HOR)
602 cuP
= cuQ
->getPUAbove(partP
, partQ
);
604 int32_t qpP
= cuP
->m_qp
[partP
];
606 if (cu
->m_slice
->m_pps
->bTransquantBypassEnabled
)
608 // check if each of PUs is lossless coded
609 partPNoFilter
= !!cuP
->m_tqBypass
[partP
];
610 partQNoFilter
= !!cuQ
->m_tqBypass
[partQ
];
613 for (uint32_t chromaIdx
= 0; chromaIdx
< 2; chromaIdx
++)
615 int32_t chromaQPOffset
= !chromaIdx
? cu
->m_slice
->m_pps
->chromaCbQpOffset
: cu
->m_slice
->m_pps
->chromaCrQpOffset
;
616 int32_t qp
= ((qpP
+ qpQ
+ 1) >> 1) + chromaQPOffset
;
619 if (chFmt
== X265_CSP_I420
)
620 qp
= g_chromaScale
[qp
];
622 qp
= X265_MIN(qp
, 51);
625 int32_t indexTC
= Clip3(0, QP_MAX_SPEC
+ DEFAULT_INTRA_TC_OFFSET
, int32_t(qp
+ DEFAULT_INTRA_TC_OFFSET
+ tcOffset
));
626 const int32_t bitdepthShift
= X265_DEPTH
- 8;
627 int32_t tc
= s_tcTable
[indexTC
] << bitdepthShift
;
628 pixel
* srcC
= srcChroma
[chromaIdx
];
630 pelFilterChroma(srcC
+ srcStep
* unitOffset
, srcStep
, offset
, tc
, partPNoFilter
, partQNoFilter
);
636 const uint8_t Deblock::s_tcTable
[54] =
638 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
639 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 24
642 const uint8_t Deblock::s_betaTable
[52] =
644 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
645 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64