4 * Copyright (C) 2012 - 2013 Guillaume Martres
5 * Copyright (C) 2013 Seppo Tomperi
6 * Copyright (C) 2013 Wassim Hamidouche
8 * This file is part of FFmpeg.
10 * FFmpeg is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * FFmpeg is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with FFmpeg; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "libavutil/common.h"
26 #include "libavutil/internal.h"
28 #include "cabac_functions.h"
32 #include "bit_depth_template.c"
38 static const uint8_t tctable
[54] = {
39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // QP 0...18
40 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, // QP 19...37
41 5, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16, 18, 20, 22, 24 // QP 38...53
44 static const uint8_t betatable
[52] = {
45 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, // QP 0...18
46 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, // QP 19...37
47 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64 // QP 38...51
50 static int chroma_tc(HEVCContext
*s
, int qp_y
, int c_idx
, int tc_offset
)
52 static const int qp_c
[] = {
53 29, 30, 31, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37
55 int qp
, qp_i
, offset
, idxt
;
57 // slice qp offset is not used for deblocking
59 offset
= s
->pps
->cb_qp_offset
;
61 offset
= s
->pps
->cr_qp_offset
;
63 qp_i
= av_clip(qp_y
+ offset
, 0, 57);
64 if (s
->sps
->chroma_format_idc
== 1) {
72 qp
= av_clip(qp_i
, 0, 51);
75 idxt
= av_clip(qp
+ DEFAULT_INTRA_TC_OFFSET
+ tc_offset
, 0, 53);
79 static int get_qPy_pred(HEVCContext
*s
, int xBase
, int yBase
, int log2_cb_size
)
81 HEVCLocalContext
*lc
= s
->HEVClc
;
82 int ctb_size_mask
= (1 << s
->sps
->log2_ctb_size
) - 1;
83 int MinCuQpDeltaSizeMask
= (1 << (s
->sps
->log2_ctb_size
-
84 s
->pps
->diff_cu_qp_delta_depth
)) - 1;
85 int xQgBase
= xBase
- (xBase
& MinCuQpDeltaSizeMask
);
86 int yQgBase
= yBase
- (yBase
& MinCuQpDeltaSizeMask
);
87 int min_cb_width
= s
->sps
->min_cb_width
;
88 int x_cb
= xQgBase
>> s
->sps
->log2_min_cb_size
;
89 int y_cb
= yQgBase
>> s
->sps
->log2_min_cb_size
;
90 int availableA
= (xBase
& ctb_size_mask
) &&
91 (xQgBase
& ctb_size_mask
);
92 int availableB
= (yBase
& ctb_size_mask
) &&
93 (yQgBase
& ctb_size_mask
);
94 int qPy_pred
, qPy_a
, qPy_b
;
97 if (lc
->first_qp_group
|| (!xQgBase
&& !yQgBase
)) {
98 lc
->first_qp_group
= !lc
->tu
.is_cu_qp_delta_coded
;
99 qPy_pred
= s
->sh
.slice_qp
;
101 qPy_pred
= lc
->qPy_pred
;
108 qPy_a
= s
->qp_y_tab
[(x_cb
- 1) + y_cb
* min_cb_width
];
114 qPy_b
= s
->qp_y_tab
[x_cb
+ (y_cb
- 1) * min_cb_width
];
116 av_assert2(qPy_a
>= -s
->sps
->qp_bd_offset
&& qPy_a
< 52);
117 av_assert2(qPy_b
>= -s
->sps
->qp_bd_offset
&& qPy_b
< 52);
119 return (qPy_a
+ qPy_b
+ 1) >> 1;
122 void ff_hevc_set_qPy(HEVCContext
*s
, int xBase
, int yBase
, int log2_cb_size
)
124 int qp_y
= get_qPy_pred(s
, xBase
, yBase
, log2_cb_size
);
126 if (s
->HEVClc
->tu
.cu_qp_delta
!= 0) {
127 int off
= s
->sps
->qp_bd_offset
;
128 s
->HEVClc
->qp_y
= FFUMOD(qp_y
+ s
->HEVClc
->tu
.cu_qp_delta
+ 52 + 2 * off
,
131 s
->HEVClc
->qp_y
= qp_y
;
134 static int get_qPy(HEVCContext
*s
, int xC
, int yC
)
136 int log2_min_cb_size
= s
->sps
->log2_min_cb_size
;
137 int x
= xC
>> log2_min_cb_size
;
138 int y
= yC
>> log2_min_cb_size
;
139 return s
->qp_y_tab
[x
+ y
* s
->sps
->min_cb_width
];
142 static void copy_CTB(uint8_t *dst
, uint8_t *src
,
143 int width
, int height
, int stride_dst
, int stride_src
)
147 for (i
= 0; i
< height
; i
++) {
148 memcpy(dst
, src
, width
);
154 static void restore_tqb_pixels(HEVCContext
*s
, int x0
, int y0
, int width
, int height
, int c_idx
)
156 if ( s
->pps
->transquant_bypass_enable_flag
||
157 (s
->sps
->pcm
.loop_filter_disable_flag
&& s
->sps
->pcm_enabled_flag
)) {
159 ptrdiff_t stride_dst
= s
->sao_frame
->linesize
[c_idx
];
160 ptrdiff_t stride_src
= s
->frame
->linesize
[c_idx
];
161 int min_pu_size
= 1 << s
->sps
->log2_min_pu_size
;
162 int hshift
= s
->sps
->hshift
[c_idx
];
163 int vshift
= s
->sps
->vshift
[c_idx
];
164 int x_min
= ((x0
) >> s
->sps
->log2_min_pu_size
);
165 int y_min
= ((y0
) >> s
->sps
->log2_min_pu_size
);
166 int x_max
= ((x0
+ width
) >> s
->sps
->log2_min_pu_size
);
167 int y_max
= ((y0
+ height
) >> s
->sps
->log2_min_pu_size
);
168 int len
= min_pu_size
>> hshift
;
169 for (y
= y_min
; y
< y_max
; y
++) {
170 for (x
= x_min
; x
< x_max
; x
++) {
171 if (s
->is_pcm
[y
* s
->sps
->min_pu_width
+ x
]) {
173 uint8_t *src
= &s
->frame
->data
[c_idx
][ ((y
<< s
->sps
->log2_min_pu_size
) >> vshift
) * stride_src
+ (((x
<< s
->sps
->log2_min_pu_size
) >> hshift
) << s
->sps
->pixel_shift
)];
174 uint8_t *dst
= &s
->sao_frame
->data
[c_idx
][((y
<< s
->sps
->log2_min_pu_size
) >> vshift
) * stride_dst
+ (((x
<< s
->sps
->log2_min_pu_size
) >> hshift
) << s
->sps
->pixel_shift
)];
175 for (n
= 0; n
< (min_pu_size
>> vshift
); n
++) {
176 memcpy(src
, dst
, len
);
186 #define CTB(tab, x, y) ((tab)[(y) * s->sps->ctb_width + (x)])
188 static void sao_filter_CTB(HEVCContext
*s
, int x
, int y
)
191 int edges
[4]; // 0 left 1 top 2 right 3 bottom
192 int x_ctb
= x
>> s
->sps
->log2_ctb_size
;
193 int y_ctb
= y
>> s
->sps
->log2_ctb_size
;
194 int ctb_addr_rs
= y_ctb
* s
->sps
->ctb_width
+ x_ctb
;
195 int ctb_addr_ts
= s
->pps
->ctb_addr_rs_to_ts
[ctb_addr_rs
];
196 SAOParams
*sao
= &CTB(s
->sao
, x_ctb
, y_ctb
);
197 // flags indicating unfilterable edges
198 uint8_t vert_edge
[] = { 0, 0 };
199 uint8_t horiz_edge
[] = { 0, 0 };
200 uint8_t diag_edge
[] = { 0, 0, 0, 0 };
201 uint8_t lfase
= CTB(s
->filter_slice_edges
, x_ctb
, y_ctb
);
202 uint8_t no_tile_filter
= s
->pps
->tiles_enabled_flag
&&
203 !s
->pps
->loop_filter_across_tiles_enabled_flag
;
204 uint8_t restore
= no_tile_filter
|| !lfase
;
205 uint8_t left_tile_edge
= 0;
206 uint8_t right_tile_edge
= 0;
207 uint8_t up_tile_edge
= 0;
208 uint8_t bottom_tile_edge
= 0;
210 edges
[0] = x_ctb
== 0;
211 edges
[1] = y_ctb
== 0;
212 edges
[2] = x_ctb
== s
->sps
->ctb_width
- 1;
213 edges
[3] = y_ctb
== s
->sps
->ctb_height
- 1;
217 left_tile_edge
= no_tile_filter
&& s
->pps
->tile_id
[ctb_addr_ts
] != s
->pps
->tile_id
[s
->pps
->ctb_addr_rs_to_ts
[ctb_addr_rs
-1]];
218 vert_edge
[0] = (!lfase
&& CTB(s
->tab_slice_address
, x_ctb
, y_ctb
) != CTB(s
->tab_slice_address
, x_ctb
- 1, y_ctb
)) || left_tile_edge
;
221 right_tile_edge
= no_tile_filter
&& s
->pps
->tile_id
[ctb_addr_ts
] != s
->pps
->tile_id
[s
->pps
->ctb_addr_rs_to_ts
[ctb_addr_rs
+1]];
222 vert_edge
[1] = (!lfase
&& CTB(s
->tab_slice_address
, x_ctb
, y_ctb
) != CTB(s
->tab_slice_address
, x_ctb
+ 1, y_ctb
)) || right_tile_edge
;
225 up_tile_edge
= no_tile_filter
&& s
->pps
->tile_id
[ctb_addr_ts
] != s
->pps
->tile_id
[s
->pps
->ctb_addr_rs_to_ts
[ctb_addr_rs
- s
->sps
->ctb_width
]];
226 horiz_edge
[0] = (!lfase
&& CTB(s
->tab_slice_address
, x_ctb
, y_ctb
) != CTB(s
->tab_slice_address
, x_ctb
, y_ctb
- 1)) || up_tile_edge
;
229 bottom_tile_edge
= no_tile_filter
&& s
->pps
->tile_id
[ctb_addr_ts
] != s
->pps
->tile_id
[s
->pps
->ctb_addr_rs_to_ts
[ctb_addr_rs
+ s
->sps
->ctb_width
]];
230 horiz_edge
[1] = (!lfase
&& CTB(s
->tab_slice_address
, x_ctb
, y_ctb
) != CTB(s
->tab_slice_address
, x_ctb
, y_ctb
+ 1)) || bottom_tile_edge
;
232 if (!edges
[0] && !edges
[1]) {
233 diag_edge
[0] = (!lfase
&& CTB(s
->tab_slice_address
, x_ctb
, y_ctb
) != CTB(s
->tab_slice_address
, x_ctb
- 1, y_ctb
- 1)) || left_tile_edge
|| up_tile_edge
;
235 if (!edges
[1] && !edges
[2]) {
236 diag_edge
[1] = (!lfase
&& CTB(s
->tab_slice_address
, x_ctb
, y_ctb
) != CTB(s
->tab_slice_address
, x_ctb
+ 1, y_ctb
- 1)) || right_tile_edge
|| up_tile_edge
;
238 if (!edges
[2] && !edges
[3]) {
239 diag_edge
[2] = (!lfase
&& CTB(s
->tab_slice_address
, x_ctb
, y_ctb
) != CTB(s
->tab_slice_address
, x_ctb
+ 1, y_ctb
+ 1)) || right_tile_edge
|| bottom_tile_edge
;
241 if (!edges
[0] && !edges
[3]) {
242 diag_edge
[3] = (!lfase
&& CTB(s
->tab_slice_address
, x_ctb
, y_ctb
) != CTB(s
->tab_slice_address
, x_ctb
- 1, y_ctb
+ 1)) || left_tile_edge
|| bottom_tile_edge
;
246 for (c_idx
= 0; c_idx
< 3; c_idx
++) {
247 int x0
= x
>> s
->sps
->hshift
[c_idx
];
248 int y0
= y
>> s
->sps
->vshift
[c_idx
];
249 int stride_src
= s
->frame
->linesize
[c_idx
];
250 int stride_dst
= s
->sao_frame
->linesize
[c_idx
];
251 int ctb_size_h
= (1 << (s
->sps
->log2_ctb_size
)) >> s
->sps
->hshift
[c_idx
];
252 int ctb_size_v
= (1 << (s
->sps
->log2_ctb_size
)) >> s
->sps
->vshift
[c_idx
];
253 int width
= FFMIN(ctb_size_h
, (s
->sps
->width
>> s
->sps
->hshift
[c_idx
]) - x0
);
254 int height
= FFMIN(ctb_size_v
, (s
->sps
->height
>> s
->sps
->vshift
[c_idx
]) - y0
);
255 uint8_t *src
= &s
->frame
->data
[c_idx
][y0
* stride_src
+ (x0
<< s
->sps
->pixel_shift
)];
256 uint8_t *dst
= &s
->sao_frame
->data
[c_idx
][y0
* stride_dst
+ (x0
<< s
->sps
->pixel_shift
)];
258 switch (sao
->type_idx
[c_idx
]) {
260 copy_CTB(dst
, src
, width
<< s
->sps
->pixel_shift
, height
, stride_dst
, stride_src
);
261 s
->hevcdsp
.sao_band_filter(src
, dst
,
262 stride_src
, stride_dst
,
266 restore_tqb_pixels(s
, x
, y
, width
, height
, c_idx
);
267 sao
->type_idx
[c_idx
] = SAO_APPLIED
;
271 uint8_t left_pixels
= !edges
[0] && (CTB(s
->sao
, x_ctb
-1, y_ctb
).type_idx
[c_idx
] != SAO_APPLIED
);
273 uint8_t top_left
= !edges
[0] && (CTB(s
->sao
, x_ctb
-1, y_ctb
-1).type_idx
[c_idx
] != SAO_APPLIED
);
274 uint8_t top_right
= !edges
[2] && (CTB(s
->sao
, x_ctb
+1, y_ctb
-1).type_idx
[c_idx
] != SAO_APPLIED
);
275 if (CTB(s
->sao
, x_ctb
, y_ctb
-1).type_idx
[c_idx
] == 0)
276 memcpy( dst
- stride_dst
- (top_left
<< s
->sps
->pixel_shift
),
277 src
- stride_src
- (top_left
<< s
->sps
->pixel_shift
),
278 (top_left
+ width
+ top_right
) << s
->sps
->pixel_shift
);
281 memcpy( dst
- stride_dst
- (1 << s
->sps
->pixel_shift
),
282 src
- stride_src
- (1 << s
->sps
->pixel_shift
),
283 1 << s
->sps
->pixel_shift
);
285 memcpy( dst
- stride_dst
+ (width
<< s
->sps
->pixel_shift
),
286 src
- stride_src
+ (width
<< s
->sps
->pixel_shift
),
287 1 << s
->sps
->pixel_shift
);
290 if (!edges
[3]) { // bottom and bottom right
291 uint8_t bottom_left
= !edges
[0] && (CTB(s
->sao
, x_ctb
-1, y_ctb
+1).type_idx
[c_idx
] != SAO_APPLIED
);
292 memcpy( dst
+ height
* stride_dst
- (bottom_left
<< s
->sps
->pixel_shift
),
293 src
+ height
* stride_src
- (bottom_left
<< s
->sps
->pixel_shift
),
294 (width
+ 1 + bottom_left
) << s
->sps
->pixel_shift
);
296 copy_CTB(dst
- (left_pixels
<< s
->sps
->pixel_shift
),
297 src
- (left_pixels
<< s
->sps
->pixel_shift
),
298 (width
+ 1 + left_pixels
) << s
->sps
->pixel_shift
, height
, stride_dst
, stride_src
);
299 s
->hevcdsp
.sao_edge_filter
[restore
](src
, dst
,
300 stride_src
, stride_dst
,
307 restore_tqb_pixels(s
, x
, y
, width
, height
, c_idx
);
308 sao
->type_idx
[c_idx
] = SAO_APPLIED
;
315 static int get_pcm(HEVCContext
*s
, int x
, int y
)
317 int log2_min_pu_size
= s
->sps
->log2_min_pu_size
;
323 x_pu
= x
>> log2_min_pu_size
;
324 y_pu
= y
>> log2_min_pu_size
;
326 if (x_pu
>= s
->sps
->min_pu_width
|| y_pu
>= s
->sps
->min_pu_height
)
328 return s
->is_pcm
[y_pu
* s
->sps
->min_pu_width
+ x_pu
];
331 #define TC_CALC(qp, bs) \
332 tctable[av_clip((qp) + DEFAULT_INTRA_TC_OFFSET * ((bs) - 1) + \
333 (tc_offset >> 1 << 1), \
334 0, MAX_QP + DEFAULT_INTRA_TC_OFFSET)]
336 static void deblocking_filter_CTB(HEVCContext
*s
, int x0
, int y0
)
341 int32_t c_tc
[2], tc
[2];
342 uint8_t no_p
[2] = { 0 };
343 uint8_t no_q
[2] = { 0 };
345 int log2_ctb_size
= s
->sps
->log2_ctb_size
;
346 int x_end
, x_end2
, y_end
;
347 int ctb_size
= 1 << log2_ctb_size
;
348 int ctb
= (x0
>> log2_ctb_size
) +
349 (y0
>> log2_ctb_size
) * s
->sps
->ctb_width
;
350 int cur_tc_offset
= s
->deblock
[ctb
].tc_offset
;
351 int cur_beta_offset
= s
->deblock
[ctb
].beta_offset
;
352 int left_tc_offset
, left_beta_offset
;
353 int tc_offset
, beta_offset
;
354 int pcmf
= (s
->sps
->pcm_enabled_flag
&&
355 s
->sps
->pcm
.loop_filter_disable_flag
) ||
356 s
->pps
->transquant_bypass_enable_flag
;
359 left_tc_offset
= s
->deblock
[ctb
- 1].tc_offset
;
360 left_beta_offset
= s
->deblock
[ctb
- 1].beta_offset
;
363 left_beta_offset
= 0;
366 x_end
= x0
+ ctb_size
;
367 if (x_end
> s
->sps
->width
)
368 x_end
= s
->sps
->width
;
369 y_end
= y0
+ ctb_size
;
370 if (y_end
> s
->sps
->height
)
371 y_end
= s
->sps
->height
;
373 tc_offset
= cur_tc_offset
;
374 beta_offset
= cur_beta_offset
;
377 if (x_end2
!= s
->sps
->width
)
379 for (y
= y0
; y
< y_end
; y
+= 8) {
380 // vertical filtering luma
381 for (x
= x0
? x0
: 8; x
< x_end
; x
+= 8) {
382 const int bs0
= s
->vertical_bs
[(x
+ y
* s
->bs_width
) >> 2];
383 const int bs1
= s
->vertical_bs
[(x
+ (y
+ 4) * s
->bs_width
) >> 2];
385 const int qp
= (get_qPy(s
, x
- 1, y
) + get_qPy(s
, x
, y
) + 1) >> 1;
387 beta
= betatable
[av_clip(qp
+ beta_offset
, 0, MAX_QP
)];
389 tc
[0] = bs0
? TC_CALC(qp
, bs0
) : 0;
390 tc
[1] = bs1
? TC_CALC(qp
, bs1
) : 0;
391 src
= &s
->frame
->data
[LUMA
][y
* s
->frame
->linesize
[LUMA
] + (x
<< s
->sps
->pixel_shift
)];
393 no_p
[0] = get_pcm(s
, x
- 1, y
);
394 no_p
[1] = get_pcm(s
, x
- 1, y
+ 4);
395 no_q
[0] = get_pcm(s
, x
, y
);
396 no_q
[1] = get_pcm(s
, x
, y
+ 4);
397 s
->hevcdsp
.hevc_v_loop_filter_luma_c(src
,
398 s
->frame
->linesize
[LUMA
],
399 beta
, tc
, no_p
, no_q
);
401 s
->hevcdsp
.hevc_v_loop_filter_luma(src
,
402 s
->frame
->linesize
[LUMA
],
403 beta
, tc
, no_p
, no_q
);
410 // horizontal filtering luma
411 for (x
= x0
? x0
- 8 : 0; x
< x_end2
; x
+= 8) {
412 const int bs0
= s
->horizontal_bs
[( x
+ y
* s
->bs_width
) >> 2];
413 const int bs1
= s
->horizontal_bs
[((x
+ 4) + y
* s
->bs_width
) >> 2];
415 const int qp
= (get_qPy(s
, x
, y
- 1) + get_qPy(s
, x
, y
) + 1) >> 1;
417 tc_offset
= x
>= x0
? cur_tc_offset
: left_tc_offset
;
418 beta_offset
= x
>= x0
? cur_beta_offset
: left_beta_offset
;
420 beta
= betatable
[av_clip(qp
+ beta_offset
, 0, MAX_QP
)];
421 tc
[0] = bs0
? TC_CALC(qp
, bs0
) : 0;
422 tc
[1] = bs1
? TC_CALC(qp
, bs1
) : 0;
423 src
= &s
->frame
->data
[LUMA
][y
* s
->frame
->linesize
[LUMA
] + (x
<< s
->sps
->pixel_shift
)];
425 no_p
[0] = get_pcm(s
, x
, y
- 1);
426 no_p
[1] = get_pcm(s
, x
+ 4, y
- 1);
427 no_q
[0] = get_pcm(s
, x
, y
);
428 no_q
[1] = get_pcm(s
, x
+ 4, y
);
429 s
->hevcdsp
.hevc_h_loop_filter_luma_c(src
,
430 s
->frame
->linesize
[LUMA
],
431 beta
, tc
, no_p
, no_q
);
433 s
->hevcdsp
.hevc_h_loop_filter_luma(src
,
434 s
->frame
->linesize
[LUMA
],
435 beta
, tc
, no_p
, no_q
);
440 for (chroma
= 1; chroma
<= 2; chroma
++) {
441 int h
= 1 << s
->sps
->hshift
[chroma
];
442 int v
= 1 << s
->sps
->vshift
[chroma
];
444 // vertical filtering chroma
445 for (y
= y0
; y
< y_end
; y
+= (8 * v
)) {
446 for (x
= x0
? x0
: 8 * h
; x
< x_end
; x
+= (8 * h
)) {
447 const int bs0
= s
->vertical_bs
[(x
+ y
* s
->bs_width
) >> 2];
448 const int bs1
= s
->vertical_bs
[(x
+ (y
+ (4 * v
)) * s
->bs_width
) >> 2];
450 if ((bs0
== 2) || (bs1
== 2)) {
451 const int qp0
= (get_qPy(s
, x
- 1, y
) + get_qPy(s
, x
, y
) + 1) >> 1;
452 const int qp1
= (get_qPy(s
, x
- 1, y
+ (4 * v
)) + get_qPy(s
, x
, y
+ (4 * v
)) + 1) >> 1;
454 c_tc
[0] = (bs0
== 2) ? chroma_tc(s
, qp0
, chroma
, tc_offset
) : 0;
455 c_tc
[1] = (bs1
== 2) ? chroma_tc(s
, qp1
, chroma
, tc_offset
) : 0;
456 src
= &s
->frame
->data
[chroma
][(y
>> s
->sps
->vshift
[chroma
]) * s
->frame
->linesize
[chroma
] + ((x
>> s
->sps
->hshift
[chroma
]) << s
->sps
->pixel_shift
)];
458 no_p
[0] = get_pcm(s
, x
- 1, y
);
459 no_p
[1] = get_pcm(s
, x
- 1, y
+ (4 * v
));
460 no_q
[0] = get_pcm(s
, x
, y
);
461 no_q
[1] = get_pcm(s
, x
, y
+ (4 * v
));
462 s
->hevcdsp
.hevc_v_loop_filter_chroma_c(src
,
463 s
->frame
->linesize
[chroma
],
466 s
->hevcdsp
.hevc_v_loop_filter_chroma(src
,
467 s
->frame
->linesize
[chroma
],
475 // horizontal filtering chroma
476 tc_offset
= x0
? left_tc_offset
: cur_tc_offset
;
478 if (x_end
!= s
->sps
->width
)
479 x_end2
= x_end
- 8 * h
;
480 for (x
= x0
? x0
- 8 * h
: 0; x
< x_end2
; x
+= (8 * h
)) {
481 const int bs0
= s
->horizontal_bs
[( x
+ y
* s
->bs_width
) >> 2];
482 const int bs1
= s
->horizontal_bs
[((x
+ 4 * h
) + y
* s
->bs_width
) >> 2];
483 if ((bs0
== 2) || (bs1
== 2)) {
484 const int qp0
= bs0
== 2 ? (get_qPy(s
, x
, y
- 1) + get_qPy(s
, x
, y
) + 1) >> 1 : 0;
485 const int qp1
= bs1
== 2 ? (get_qPy(s
, x
+ (4 * h
), y
- 1) + get_qPy(s
, x
+ (4 * h
), y
) + 1) >> 1 : 0;
487 c_tc
[0] = bs0
== 2 ? chroma_tc(s
, qp0
, chroma
, tc_offset
) : 0;
488 c_tc
[1] = bs1
== 2 ? chroma_tc(s
, qp1
, chroma
, cur_tc_offset
) : 0;
489 src
= &s
->frame
->data
[chroma
][(y
>> s
->sps
->vshift
[1]) * s
->frame
->linesize
[chroma
] + ((x
>> s
->sps
->hshift
[1]) << s
->sps
->pixel_shift
)];
491 no_p
[0] = get_pcm(s
, x
, y
- 1);
492 no_p
[1] = get_pcm(s
, x
+ (4 * h
), y
- 1);
493 no_q
[0] = get_pcm(s
, x
, y
);
494 no_q
[1] = get_pcm(s
, x
+ (4 * h
), y
);
495 s
->hevcdsp
.hevc_h_loop_filter_chroma_c(src
,
496 s
->frame
->linesize
[chroma
],
499 s
->hevcdsp
.hevc_h_loop_filter_chroma(src
,
500 s
->frame
->linesize
[chroma
],
508 static int boundary_strength(HEVCContext
*s
, MvField
*curr
, MvField
*neigh
,
509 RefPicList
*neigh_refPicList
)
511 if (curr
->pred_flag
== PF_BI
&& neigh
->pred_flag
== PF_BI
) {
513 if (s
->ref
->refPicList
[0].list
[curr
->ref_idx
[0]] == neigh_refPicList
[0].list
[neigh
->ref_idx
[0]] &&
514 s
->ref
->refPicList
[0].list
[curr
->ref_idx
[0]] == s
->ref
->refPicList
[1].list
[curr
->ref_idx
[1]] &&
515 neigh_refPicList
[0].list
[neigh
->ref_idx
[0]] == neigh_refPicList
[1].list
[neigh
->ref_idx
[1]]) {
516 if ((FFABS(neigh
->mv
[0].x
- curr
->mv
[0].x
) >= 4 || FFABS(neigh
->mv
[0].y
- curr
->mv
[0].y
) >= 4 ||
517 FFABS(neigh
->mv
[1].x
- curr
->mv
[1].x
) >= 4 || FFABS(neigh
->mv
[1].y
- curr
->mv
[1].y
) >= 4) &&
518 (FFABS(neigh
->mv
[1].x
- curr
->mv
[0].x
) >= 4 || FFABS(neigh
->mv
[1].y
- curr
->mv
[0].y
) >= 4 ||
519 FFABS(neigh
->mv
[0].x
- curr
->mv
[1].x
) >= 4 || FFABS(neigh
->mv
[0].y
- curr
->mv
[1].y
) >= 4))
523 } else if (neigh_refPicList
[0].list
[neigh
->ref_idx
[0]] == s
->ref
->refPicList
[0].list
[curr
->ref_idx
[0]] &&
524 neigh_refPicList
[1].list
[neigh
->ref_idx
[1]] == s
->ref
->refPicList
[1].list
[curr
->ref_idx
[1]]) {
525 if (FFABS(neigh
->mv
[0].x
- curr
->mv
[0].x
) >= 4 || FFABS(neigh
->mv
[0].y
- curr
->mv
[0].y
) >= 4 ||
526 FFABS(neigh
->mv
[1].x
- curr
->mv
[1].x
) >= 4 || FFABS(neigh
->mv
[1].y
- curr
->mv
[1].y
) >= 4)
530 } else if (neigh_refPicList
[1].list
[neigh
->ref_idx
[1]] == s
->ref
->refPicList
[0].list
[curr
->ref_idx
[0]] &&
531 neigh_refPicList
[0].list
[neigh
->ref_idx
[0]] == s
->ref
->refPicList
[1].list
[curr
->ref_idx
[1]]) {
532 if (FFABS(neigh
->mv
[1].x
- curr
->mv
[0].x
) >= 4 || FFABS(neigh
->mv
[1].y
- curr
->mv
[0].y
) >= 4 ||
533 FFABS(neigh
->mv
[0].x
- curr
->mv
[1].x
) >= 4 || FFABS(neigh
->mv
[0].y
- curr
->mv
[1].y
) >= 4)
540 } else if ((curr
->pred_flag
!= PF_BI
) && (neigh
->pred_flag
!= PF_BI
)){ // 1 MV
544 if (curr
->pred_flag
& 1) {
546 ref_A
= s
->ref
->refPicList
[0].list
[curr
->ref_idx
[0]];
549 ref_A
= s
->ref
->refPicList
[1].list
[curr
->ref_idx
[1]];
552 if (neigh
->pred_flag
& 1) {
554 ref_B
= neigh_refPicList
[0].list
[neigh
->ref_idx
[0]];
557 ref_B
= neigh_refPicList
[1].list
[neigh
->ref_idx
[1]];
560 if (ref_A
== ref_B
) {
561 if (FFABS(A
.x
- B
.x
) >= 4 || FFABS(A
.y
- B
.y
) >= 4)
572 void ff_hevc_deblocking_boundary_strengths(HEVCContext
*s
, int x0
, int y0
,
575 HEVCLocalContext
*lc
= s
->HEVClc
;
576 MvField
*tab_mvf
= s
->ref
->tab_mvf
;
577 int log2_min_pu_size
= s
->sps
->log2_min_pu_size
;
578 int log2_min_tu_size
= s
->sps
->log2_min_tb_size
;
579 int min_pu_width
= s
->sps
->min_pu_width
;
580 int min_tu_width
= s
->sps
->min_tb_width
;
581 int is_intra
= tab_mvf
[(y0
>> log2_min_pu_size
) * min_pu_width
+
582 (x0
>> log2_min_pu_size
)].pred_flag
== PF_INTRA
;
583 int boundary_upper
, boundary_left
;
586 boundary_upper
= y0
> 0 && !(y0
& 7);
587 if (boundary_upper
&&
588 ((!s
->sh
.slice_loop_filter_across_slices_enabled_flag
&&
589 lc
->boundary_flags
& BOUNDARY_UPPER_SLICE
&&
590 (y0
% (1 << s
->sps
->log2_ctb_size
)) == 0) ||
591 (!s
->pps
->loop_filter_across_tiles_enabled_flag
&&
592 lc
->boundary_flags
& BOUNDARY_UPPER_TILE
&&
593 (y0
% (1 << s
->sps
->log2_ctb_size
)) == 0)))
596 if (boundary_upper
) {
597 RefPicList
*rpl_top
= (lc
->boundary_flags
& BOUNDARY_UPPER_SLICE
) ?
598 ff_hevc_get_ref_list(s
, s
->ref
, x0
, y0
- 1) :
600 int yp_pu
= (y0
- 1) >> log2_min_pu_size
;
601 int yq_pu
= y0
>> log2_min_pu_size
;
602 int yp_tu
= (y0
- 1) >> log2_min_tu_size
;
603 int yq_tu
= y0
>> log2_min_tu_size
;
605 for (i
= 0; i
< (1 << log2_trafo_size
); i
+= 4) {
606 int x_pu
= (x0
+ i
) >> log2_min_pu_size
;
607 int x_tu
= (x0
+ i
) >> log2_min_tu_size
;
608 MvField
*top
= &tab_mvf
[yp_pu
* min_pu_width
+ x_pu
];
609 MvField
*curr
= &tab_mvf
[yq_pu
* min_pu_width
+ x_pu
];
610 uint8_t top_cbf_luma
= s
->cbf_luma
[yp_tu
* min_tu_width
+ x_tu
];
611 uint8_t curr_cbf_luma
= s
->cbf_luma
[yq_tu
* min_tu_width
+ x_tu
];
613 if (curr
->pred_flag
== PF_INTRA
|| top
->pred_flag
== PF_INTRA
)
615 else if (curr_cbf_luma
|| top_cbf_luma
)
618 bs
= boundary_strength(s
, curr
, top
, rpl_top
);
619 s
->horizontal_bs
[((x0
+ i
) + y0
* s
->bs_width
) >> 2] = bs
;
623 // bs for vertical TU boundaries
624 boundary_left
= x0
> 0 && !(x0
& 7);
626 ((!s
->sh
.slice_loop_filter_across_slices_enabled_flag
&&
627 lc
->boundary_flags
& BOUNDARY_LEFT_SLICE
&&
628 (x0
% (1 << s
->sps
->log2_ctb_size
)) == 0) ||
629 (!s
->pps
->loop_filter_across_tiles_enabled_flag
&&
630 lc
->boundary_flags
& BOUNDARY_LEFT_TILE
&&
631 (x0
% (1 << s
->sps
->log2_ctb_size
)) == 0)))
635 RefPicList
*rpl_left
= (lc
->boundary_flags
& BOUNDARY_LEFT_SLICE
) ?
636 ff_hevc_get_ref_list(s
, s
->ref
, x0
- 1, y0
) :
638 int xp_pu
= (x0
- 1) >> log2_min_pu_size
;
639 int xq_pu
= x0
>> log2_min_pu_size
;
640 int xp_tu
= (x0
- 1) >> log2_min_tu_size
;
641 int xq_tu
= x0
>> log2_min_tu_size
;
643 for (i
= 0; i
< (1 << log2_trafo_size
); i
+= 4) {
644 int y_pu
= (y0
+ i
) >> log2_min_pu_size
;
645 int y_tu
= (y0
+ i
) >> log2_min_tu_size
;
646 MvField
*left
= &tab_mvf
[y_pu
* min_pu_width
+ xp_pu
];
647 MvField
*curr
= &tab_mvf
[y_pu
* min_pu_width
+ xq_pu
];
648 uint8_t left_cbf_luma
= s
->cbf_luma
[y_tu
* min_tu_width
+ xp_tu
];
649 uint8_t curr_cbf_luma
= s
->cbf_luma
[y_tu
* min_tu_width
+ xq_tu
];
651 if (curr
->pred_flag
== PF_INTRA
|| left
->pred_flag
== PF_INTRA
)
653 else if (curr_cbf_luma
|| left_cbf_luma
)
656 bs
= boundary_strength(s
, curr
, left
, rpl_left
);
657 s
->vertical_bs
[(x0
+ (y0
+ i
) * s
->bs_width
) >> 2] = bs
;
661 if (log2_trafo_size
> log2_min_pu_size
&& !is_intra
) {
662 RefPicList
*rpl
= s
->ref
->refPicList
;
664 // bs for TU internal horizontal PU boundaries
665 for (j
= 8; j
< (1 << log2_trafo_size
); j
+= 8) {
666 int yp_pu
= (y0
+ j
- 1) >> log2_min_pu_size
;
667 int yq_pu
= (y0
+ j
) >> log2_min_pu_size
;
669 for (i
= 0; i
< (1 << log2_trafo_size
); i
+= 4) {
670 int x_pu
= (x0
+ i
) >> log2_min_pu_size
;
671 MvField
*top
= &tab_mvf
[yp_pu
* min_pu_width
+ x_pu
];
672 MvField
*curr
= &tab_mvf
[yq_pu
* min_pu_width
+ x_pu
];
674 bs
= boundary_strength(s
, curr
, top
, rpl
);
675 s
->horizontal_bs
[((x0
+ i
) + (y0
+ j
) * s
->bs_width
) >> 2] = bs
;
679 // bs for TU internal vertical PU boundaries
680 for (j
= 0; j
< (1 << log2_trafo_size
); j
+= 4) {
681 int y_pu
= (y0
+ j
) >> log2_min_pu_size
;
683 for (i
= 8; i
< (1 << log2_trafo_size
); i
+= 8) {
684 int xp_pu
= (x0
+ i
- 1) >> log2_min_pu_size
;
685 int xq_pu
= (x0
+ i
) >> log2_min_pu_size
;
686 MvField
*left
= &tab_mvf
[y_pu
* min_pu_width
+ xp_pu
];
687 MvField
*curr
= &tab_mvf
[y_pu
* min_pu_width
+ xq_pu
];
689 bs
= boundary_strength(s
, curr
, left
, rpl
);
690 s
->vertical_bs
[((x0
+ i
) + (y0
+ j
) * s
->bs_width
) >> 2] = bs
;
700 void ff_hevc_hls_filter(HEVCContext
*s
, int x
, int y
, int ctb_size
)
702 int x_end
= x
>= s
->sps
->width
- ctb_size
;
703 deblocking_filter_CTB(s
, x
, y
);
704 if (s
->sps
->sao_enabled
) {
705 int y_end
= y
>= s
->sps
->height
- ctb_size
;
707 sao_filter_CTB(s
, x
- ctb_size
, y
- ctb_size
);
709 sao_filter_CTB(s
, x
- ctb_size
, y
);
711 sao_filter_CTB(s
, x
, y
- ctb_size
);
712 if (s
->threads_type
& FF_THREAD_FRAME
)
713 ff_thread_report_progress(&s
->ref
->tf
, y
, 0);
715 if (x_end
&& y_end
) {
716 sao_filter_CTB(s
, x
, y
);
717 if (s
->threads_type
& FF_THREAD_FRAME
)
718 ff_thread_report_progress(&s
->ref
->tf
, y
+ ctb_size
, 0);
720 } else if (s
->threads_type
& FF_THREAD_FRAME
&& x_end
)
721 ff_thread_report_progress(&s
->ref
->tf
, y
+ ctb_size
- 4, 0);
724 void ff_hevc_hls_filters(HEVCContext
*s
, int x_ctb
, int y_ctb
, int ctb_size
)
726 int x_end
= x_ctb
>= s
->sps
->width
- ctb_size
;
727 int y_end
= y_ctb
>= s
->sps
->height
- ctb_size
;
729 ff_hevc_hls_filter(s
, x_ctb
- ctb_size
, y_ctb
- ctb_size
, ctb_size
);
731 ff_hevc_hls_filter(s
, x_ctb
, y_ctb
- ctb_size
, ctb_size
);
733 ff_hevc_hls_filter(s
, x_ctb
- ctb_size
, y_ctb
, ctb_size
);