FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hevc_filter.c
Go to the documentation of this file.
1 /*
2  * HEVC video decoder
3  *
4  * Copyright (C) 2012 - 2013 Guillaume Martres
5  * Copyright (C) 2013 Seppo Tomperi
6  * Copyright (C) 2013 Wassim Hamidouche
7  *
8  * This file is part of FFmpeg.
9  *
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.
14  *
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.
19  *
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
23  */
24 
25 #include "libavutil/common.h"
26 #include "libavutil/internal.h"
27 
28 #include "cabac_functions.h"
29 #include "golomb.h"
30 #include "hevc.h"
31 
32 #include "bit_depth_template.c"
33 
34 #define LUMA 0
35 #define CB 1
36 #define CR 2
37 
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
42 };
43 
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
48 };
49 
50 static int chroma_tc(HEVCContext *s, int qp_y, int c_idx, int tc_offset)
51 {
52  static const int qp_c[] = {
53  29, 30, 31, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37
54  };
55  int qp, qp_i, offset, idxt;
56 
57  // slice qp offset is not used for deblocking
58  if (c_idx == 1)
59  offset = s->pps->cb_qp_offset;
60  else
61  offset = s->pps->cr_qp_offset;
62 
63  qp_i = av_clip(qp_y + offset, 0, 57);
64  if (s->sps->chroma_format_idc == 1) {
65  if (qp_i < 30)
66  qp = qp_i;
67  else if (qp_i > 43)
68  qp = qp_i - 6;
69  else
70  qp = qp_c[qp_i - 30];
71  } else {
72  qp = av_clip(qp_i, 0, 51);
73  }
74 
75  idxt = av_clip(qp + DEFAULT_INTRA_TC_OFFSET + tc_offset, 0, 53);
76  return tctable[idxt];
77 }
78 
79 static int get_qPy_pred(HEVCContext *s, int xC, int yC,
80  int xBase, int yBase, int log2_cb_size)
81 {
82  HEVCLocalContext *lc = s->HEVClc;
83  int ctb_size_mask = (1 << s->sps->log2_ctb_size) - 1;
84  int MinCuQpDeltaSizeMask = (1 << (s->sps->log2_ctb_size -
85  s->pps->diff_cu_qp_delta_depth)) - 1;
86  int xQgBase = xBase - (xBase & MinCuQpDeltaSizeMask);
87  int yQgBase = yBase - (yBase & MinCuQpDeltaSizeMask);
88  int min_cb_width = s->sps->min_cb_width;
89  int x_cb = xQgBase >> s->sps->log2_min_cb_size;
90  int y_cb = yQgBase >> s->sps->log2_min_cb_size;
91  int availableA = (xBase & ctb_size_mask) &&
92  (xQgBase & ctb_size_mask);
93  int availableB = (yBase & ctb_size_mask) &&
94  (yQgBase & ctb_size_mask);
95  int qPy_pred, qPy_a, qPy_b;
96 
97  // qPy_pred
98  if (lc->first_qp_group || (!xQgBase && !yQgBase)) {
100  qPy_pred = s->sh.slice_qp;
101  } else {
102  qPy_pred = lc->qPy_pred;
103  }
104 
105  // qPy_a
106  if (availableA == 0)
107  qPy_a = qPy_pred;
108  else
109  qPy_a = s->qp_y_tab[(x_cb - 1) + y_cb * min_cb_width];
110 
111  // qPy_b
112  if (availableB == 0)
113  qPy_b = qPy_pred;
114  else
115  qPy_b = s->qp_y_tab[x_cb + (y_cb - 1) * min_cb_width];
116 
117  av_assert2(qPy_a >= -s->sps->qp_bd_offset && qPy_a < 52);
118  av_assert2(qPy_b >= -s->sps->qp_bd_offset && qPy_b < 52);
119 
120  return (qPy_a + qPy_b + 1) >> 1;
121 }
122 
123 void ff_hevc_set_qPy(HEVCContext *s, int xC, int yC,
124  int xBase, int yBase, int log2_cb_size)
125 {
126  int qp_y = get_qPy_pred(s, xC, yC, xBase, yBase, log2_cb_size);
127 
128  if (s->HEVClc->tu.cu_qp_delta != 0) {
129  int off = s->sps->qp_bd_offset;
130  s->HEVClc->qp_y = FFUMOD(qp_y + s->HEVClc->tu.cu_qp_delta + 52 + 2 * off,
131  52 + off) - off;
132  } else
133  s->HEVClc->qp_y = qp_y;
134 }
135 
136 static int get_qPy(HEVCContext *s, int xC, int yC)
137 {
138  int log2_min_cb_size = s->sps->log2_min_cb_size;
139  int x = xC >> log2_min_cb_size;
140  int y = yC >> log2_min_cb_size;
141  return s->qp_y_tab[x + y * s->sps->min_cb_width];
142 }
143 
144 static void copy_CTB(uint8_t *dst, uint8_t *src,
145  int width, int height, int stride)
146 {
147  int i;
148 
149  for (i = 0; i < height; i++) {
150  memcpy(dst, src, width);
151  dst += stride;
152  src += stride;
153  }
154 }
155 
156 static void restore_tqb_pixels(HEVCContext *s, int x0, int y0, int width, int height, int c_idx)
157 {
160  int x, y;
161  ptrdiff_t stride = s->frame->linesize[c_idx];
162  int min_pu_size = 1 << s->sps->log2_min_pu_size;
163  int hshift = s->sps->hshift[c_idx];
164  int vshift = s->sps->vshift[c_idx];
165  int x_min = ((x0 ) >> s->sps->log2_min_pu_size);
166  int y_min = ((y0 ) >> s->sps->log2_min_pu_size);
167  int x_max = ((x0 + width ) >> s->sps->log2_min_pu_size);
168  int y_max = ((y0 + height) >> s->sps->log2_min_pu_size);
169  int len = min_pu_size >> hshift;
170  for (y = y_min; y < y_max; y++) {
171  for (x = x_min; x < x_max; x++) {
172  if (s->is_pcm[y * s->sps->min_pu_width + x]) {
173  int n;
174  uint8_t *src = &s->frame->data[c_idx][ ((y << s->sps->log2_min_pu_size) >> vshift) * stride + (((x << s->sps->log2_min_pu_size) >> hshift) << s->sps->pixel_shift)];
175  uint8_t *dst = &s->sao_frame->data[c_idx][((y << s->sps->log2_min_pu_size) >> vshift) * stride + (((x << s->sps->log2_min_pu_size) >> hshift) << s->sps->pixel_shift)];
176  for (n = 0; n < (min_pu_size >> vshift); n++) {
177  memcpy(dst, src, len);
178  src += stride;
179  dst += stride;
180  }
181  }
182  }
183  }
184  }
185 }
186 
187 #define CTB(tab, x, y) ((tab)[(y) * s->sps->ctb_width + (x)])
188 
189 static void sao_filter_CTB(HEVCContext *s, int x, int y)
190 {
191  int c_idx;
192  int edges[4]; // 0 left 1 top 2 right 3 bottom
193  int x_ctb = x >> s->sps->log2_ctb_size;
194  int y_ctb = y >> s->sps->log2_ctb_size;
195  int ctb_addr_rs = y_ctb * s->sps->ctb_width + x_ctb;
196  int ctb_addr_ts = s->pps->ctb_addr_rs_to_ts[ctb_addr_rs];
197  SAOParams *sao = &CTB(s->sao, x_ctb, y_ctb);
198  // flags indicating unfilterable edges
199  uint8_t vert_edge[] = { 0, 0 };
200  uint8_t horiz_edge[] = { 0, 0 };
201  uint8_t diag_edge[] = { 0, 0, 0, 0 };
202  uint8_t lfase = CTB(s->filter_slice_edges, x_ctb, y_ctb);
203  uint8_t no_tile_filter = s->pps->tiles_enabled_flag &&
205  uint8_t restore = no_tile_filter || !lfase;
206  uint8_t left_tile_edge = 0;
207  uint8_t right_tile_edge = 0;
208  uint8_t up_tile_edge = 0;
209  uint8_t bottom_tile_edge = 0;
210 
211  edges[0] = x_ctb == 0;
212  edges[1] = y_ctb == 0;
213  edges[2] = x_ctb == s->sps->ctb_width - 1;
214  edges[3] = y_ctb == s->sps->ctb_height - 1;
215 
216  if (restore) {
217  if (!edges[0]) {
218  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]];
219  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;
220  }
221  if (!edges[2]) {
222  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]];
223  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;
224  }
225  if (!edges[1]) {
226  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]];
227  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;
228  }
229  if (!edges[3]) {
230  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]];
231  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  }
233  if (!edges[0] && !edges[1]) {
234  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  }
236  if (!edges[1] && !edges[2]) {
237  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  }
239  if (!edges[2] && !edges[3]) {
240  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  }
242  if (!edges[0] && !edges[3]) {
243  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;
244  }
245  }
246 
247  for (c_idx = 0; c_idx < 3; c_idx++) {
248  int x0 = x >> s->sps->hshift[c_idx];
249  int y0 = y >> s->sps->vshift[c_idx];
250  int stride = s->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,
254  (s->sps->width >> s->sps->hshift[c_idx]) - x0);
255  int height = FFMIN(ctb_size_v,
256  (s->sps->height >> s->sps->vshift[c_idx]) - y0);
257 
258  uint8_t *src = &s->frame->data[c_idx][y0 * stride + (x0 << s->sps->pixel_shift)];
259  uint8_t *dst = &s->sao_frame->data[c_idx][y0 * stride + (x0 << s->sps->pixel_shift)];
260 
261  switch (sao->type_idx[c_idx]) {
262  case SAO_BAND:
263  s->hevcdsp.sao_band_filter(dst, src,
264  stride,
265  sao,
266  edges, width,
267  height, c_idx);
268  restore_tqb_pixels(s, x, y, width, height, c_idx);
269  break;
270  case SAO_EDGE:
271  s->hevcdsp.sao_edge_filter[restore](dst, src,
272  stride,
273  sao,
274  edges, width,
275  height, c_idx,
276  vert_edge,
277  horiz_edge,
278  diag_edge);
279  restore_tqb_pixels(s, x, y, width, height, c_idx);
280  break;
281  default :
282  copy_CTB(dst, src, width << s->sps->pixel_shift, height, stride);
283  break;
284  }
285  }
286 }
287 
288 static int get_pcm(HEVCContext *s, int x, int y)
289 {
290  int log2_min_pu_size = s->sps->log2_min_pu_size;
291  int x_pu, y_pu;
292 
293  if (x < 0 || y < 0)
294  return 2;
295 
296  x_pu = x >> log2_min_pu_size;
297  y_pu = y >> log2_min_pu_size;
298 
299  if (x_pu >= s->sps->min_pu_width || y_pu >= s->sps->min_pu_height)
300  return 2;
301  return s->is_pcm[y_pu * s->sps->min_pu_width + x_pu];
302 }
303 
304 #define TC_CALC(qp, bs) \
305  tctable[av_clip((qp) + DEFAULT_INTRA_TC_OFFSET * ((bs) - 1) + \
306  (tc_offset >> 1 << 1), \
307  0, MAX_QP + DEFAULT_INTRA_TC_OFFSET)]
308 
309 static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0)
310 {
311  uint8_t *src;
312  int x, y;
313  int chroma;
314  int c_tc[2], beta[2], tc[2];
315  uint8_t no_p[2] = { 0 };
316  uint8_t no_q[2] = { 0 };
317 
318  int log2_ctb_size = s->sps->log2_ctb_size;
319  int x_end, y_end;
320  int ctb_size = 1 << log2_ctb_size;
321  int ctb = (x0 >> log2_ctb_size) +
322  (y0 >> log2_ctb_size) * s->sps->ctb_width;
323  int cur_tc_offset = s->deblock[ctb].tc_offset;
324  int cur_beta_offset = s->deblock[ctb].beta_offset;
325  int left_tc_offset, left_beta_offset;
326  int tc_offset, beta_offset;
327  int pcmf = (s->sps->pcm_enabled_flag &&
330 
331  if (x0) {
332  left_tc_offset = s->deblock[ctb - 1].tc_offset;
333  left_beta_offset = s->deblock[ctb - 1].beta_offset;
334  } else {
335  left_tc_offset = 0;
336  left_beta_offset = 0;
337  }
338 
339  x_end = x0 + ctb_size;
340  if (x_end > s->sps->width)
341  x_end = s->sps->width;
342  y_end = y0 + ctb_size;
343  if (y_end > s->sps->height)
344  y_end = s->sps->height;
345 
346  tc_offset = cur_tc_offset;
347  beta_offset = cur_beta_offset;
348 
349  // vertical filtering luma
350  for (y = y0; y < y_end; y += 8) {
351  for (x = x0 ? x0 : 8; x < x_end; x += 8) {
352  const int bs0 = s->vertical_bs[(x >> 3) + (y >> 2) * s->bs_width];
353  const int bs1 = s->vertical_bs[(x >> 3) + ((y + 4) >> 2) * s->bs_width];
354  if (bs0 || bs1) {
355  const int qp0 = (get_qPy(s, x - 1, y) + get_qPy(s, x, y) + 1) >> 1;
356  const int qp1 = (get_qPy(s, x - 1, y + 4) + get_qPy(s, x, y + 4) + 1) >> 1;
357 
358  beta[0] = betatable[av_clip(qp0 + beta_offset, 0, MAX_QP)];
359  beta[1] = betatable[av_clip(qp1 + beta_offset, 0, MAX_QP)];
360  tc[0] = bs0 ? TC_CALC(qp0, bs0) : 0;
361  tc[1] = bs1 ? TC_CALC(qp1, bs1) : 0;
362  src = &s->frame->data[LUMA][y * s->frame->linesize[LUMA] + (x << s->sps->pixel_shift)];
363  if (pcmf) {
364  no_p[0] = get_pcm(s, x - 1, y);
365  no_p[1] = get_pcm(s, x - 1, y + 4);
366  no_q[0] = get_pcm(s, x, y);
367  no_q[1] = get_pcm(s, x, y + 4);
369  s->frame->linesize[LUMA],
370  beta, tc, no_p, no_q);
371  } else
373  s->frame->linesize[LUMA],
374  beta, tc, no_p, no_q);
375  }
376  }
377  }
378 
379  // vertical filtering chroma
380  for (chroma = 1; chroma <= 2; chroma++) {
381  int h = 1 << s->sps->hshift[chroma];
382  int v = 1 << s->sps->vshift[chroma];
383  for (y = y0; y < y_end; y += (8 * v)) {
384  for (x = x0 ? x0 : 8 * h; x < x_end; x += (8 * h)) {
385  const int bs0 = s->vertical_bs[(x >> 3) + (y >> 2) * s->bs_width];
386  const int bs1 = s->vertical_bs[(x >> 3) + ((y + (4 * v)) >> 2) * s->bs_width];
387 
388  if ((bs0 == 2) || (bs1 == 2)) {
389  const int qp0 = (get_qPy(s, x - 1, y) + get_qPy(s, x, y) + 1) >> 1;
390  const int qp1 = (get_qPy(s, x - 1, y + (4 * v)) + get_qPy(s, x, y + (4 * v)) + 1) >> 1;
391 
392  c_tc[0] = (bs0 == 2) ? chroma_tc(s, qp0, chroma, tc_offset) : 0;
393  c_tc[1] = (bs1 == 2) ? chroma_tc(s, qp1, chroma, tc_offset) : 0;
394  src = &s->frame->data[chroma][(y >> s->sps->vshift[chroma]) * s->frame->linesize[chroma] + ((x >> s->sps->hshift[chroma]) << s->sps->pixel_shift)];
395  if (pcmf) {
396  no_p[0] = get_pcm(s, x - 1, y);
397  no_p[1] = get_pcm(s, x - 1, y + (4 * v));
398  no_q[0] = get_pcm(s, x, y);
399  no_q[1] = get_pcm(s, x, y + (4 * v));
401  s->frame->linesize[chroma],
402  c_tc, no_p, no_q);
403  } else
405  s->frame->linesize[chroma],
406  c_tc, no_p, no_q);
407  }
408  }
409  }
410  }
411 
412  // horizontal filtering luma
413  if (x_end != s->sps->width)
414  x_end -= 8;
415  for (y = y0 ? y0 : 8; y < y_end; y += 8) {
416  for (x = x0 ? x0 - 8 : 0; x < x_end; x += 8) {
417  const int bs0 = s->horizontal_bs[(x + y * s->bs_width) >> 2];
418  const int bs1 = s->horizontal_bs[(x + 4 + y * s->bs_width) >> 2];
419  if (bs0 || bs1) {
420  const int qp0 = (get_qPy(s, x, y - 1) + get_qPy(s, x, y) + 1) >> 1;
421  const int qp1 = (get_qPy(s, x + 4, y - 1) + get_qPy(s, x + 4, y) + 1) >> 1;
422 
423  tc_offset = x >= x0 ? cur_tc_offset : left_tc_offset;
424  beta_offset = x >= x0 ? cur_beta_offset : left_beta_offset;
425 
426  beta[0] = betatable[av_clip(qp0 + beta_offset, 0, MAX_QP)];
427  beta[1] = betatable[av_clip(qp1 + beta_offset, 0, MAX_QP)];
428  tc[0] = bs0 ? TC_CALC(qp0, bs0) : 0;
429  tc[1] = bs1 ? TC_CALC(qp1, bs1) : 0;
430  src = &s->frame->data[LUMA][y * s->frame->linesize[LUMA] + (x << s->sps->pixel_shift)];
431  if (pcmf) {
432  no_p[0] = get_pcm(s, x, y - 1);
433  no_p[1] = get_pcm(s, x + 4, y - 1);
434  no_q[0] = get_pcm(s, x, y);
435  no_q[1] = get_pcm(s, x + 4, y);
437  s->frame->linesize[LUMA],
438  beta, tc, no_p, no_q);
439  } else
441  s->frame->linesize[LUMA],
442  beta, tc, no_p, no_q);
443  }
444  }
445  }
446 
447  // horizontal filtering chroma
448  for (chroma = 1; chroma <= 2; chroma++) {
449  int h = 1 << s->sps->hshift[chroma];
450  int v = 1 << s->sps->vshift[chroma];
451  for (y = y0 ? y0 : 8 * v; y < y_end; y += (8 * v)) {
452  for (x = x0 - 8; x < x_end; x += (8 * h)) {
453  int bs0, bs1;
454  // to make sure no memory access over boundary when x = -8
455  // TODO: simplify with row based deblocking
456  if (x < 0) {
457  bs0 = 0;
458  bs1 = s->horizontal_bs[(x + (4 * h) + y * s->bs_width) >> 2];
459  } else if (x >= x_end - 4 * h) {
460  bs0 = s->horizontal_bs[(x + y * s->bs_width) >> 2];
461  bs1 = 0;
462  } else {
463  bs0 = s->horizontal_bs[(x + y * s->bs_width) >> 2];
464  bs1 = s->horizontal_bs[(x + (4 * h) + y * s->bs_width) >> 2];
465  }
466 
467  if ((bs0 == 2) || (bs1 == 2)) {
468  const int qp0 = bs0 == 2 ? (get_qPy(s, x, y - 1) + get_qPy(s, x, y) + 1) >> 1 : 0;
469  const int qp1 = bs1 == 2 ? (get_qPy(s, x + (4 * h), y - 1) + get_qPy(s, x + (4 * h), y) + 1) >> 1 : 0;
470 
471  tc_offset = x >= x0 ? cur_tc_offset : left_tc_offset;
472  c_tc[0] = bs0 == 2 ? chroma_tc(s, qp0, chroma, tc_offset) : 0;
473  c_tc[1] = bs1 == 2 ? chroma_tc(s, qp1, chroma, cur_tc_offset) : 0;
474  src = &s->frame->data[chroma][(y >> s->sps->vshift[1]) * s->frame->linesize[chroma] + ((x >> s->sps->hshift[1]) << s->sps->pixel_shift)];
475  if (pcmf) {
476  no_p[0] = get_pcm(s, x, y - 1);
477  no_p[1] = get_pcm(s, x + (4 * h), y - 1);
478  no_q[0] = get_pcm(s, x, y);
479  no_q[1] = get_pcm(s, x + (4 * h), y);
481  s->frame->linesize[chroma],
482  c_tc, no_p, no_q);
483  } else
485  s->frame->linesize[chroma],
486  c_tc, no_p, no_q);
487  }
488  }
489  }
490  }
491 }
492 
493 static int boundary_strength(HEVCContext *s, MvField *curr, MvField *neigh,
494  RefPicList *neigh_refPicList)
495 {
496  if (curr->pred_flag == PF_BI && neigh->pred_flag == PF_BI) {
497  // same L0 and L1
498  if (s->ref->refPicList[0].list[curr->ref_idx[0]] == neigh_refPicList[0].list[neigh->ref_idx[0]] &&
499  s->ref->refPicList[0].list[curr->ref_idx[0]] == s->ref->refPicList[1].list[curr->ref_idx[1]] &&
500  neigh_refPicList[0].list[neigh->ref_idx[0]] == neigh_refPicList[1].list[neigh->ref_idx[1]]) {
501  if ((FFABS(neigh->mv[0].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 4 ||
502  FFABS(neigh->mv[1].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 4) &&
503  (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 4 ||
504  FFABS(neigh->mv[0].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 4))
505  return 1;
506  else
507  return 0;
508  } else if (neigh_refPicList[0].list[neigh->ref_idx[0]] == s->ref->refPicList[0].list[curr->ref_idx[0]] &&
509  neigh_refPicList[1].list[neigh->ref_idx[1]] == s->ref->refPicList[1].list[curr->ref_idx[1]]) {
510  if (FFABS(neigh->mv[0].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 4 ||
511  FFABS(neigh->mv[1].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 4)
512  return 1;
513  else
514  return 0;
515  } else if (neigh_refPicList[1].list[neigh->ref_idx[1]] == s->ref->refPicList[0].list[curr->ref_idx[0]] &&
516  neigh_refPicList[0].list[neigh->ref_idx[0]] == s->ref->refPicList[1].list[curr->ref_idx[1]]) {
517  if (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 4 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 4 ||
518  FFABS(neigh->mv[0].x - curr->mv[1].x) >= 4 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 4)
519  return 1;
520  else
521  return 0;
522  } else {
523  return 1;
524  }
525  } else if ((curr->pred_flag != PF_BI) && (neigh->pred_flag != PF_BI)){ // 1 MV
526  Mv A, B;
527  int ref_A, ref_B;
528 
529  if (curr->pred_flag & 1) {
530  A = curr->mv[0];
531  ref_A = s->ref->refPicList[0].list[curr->ref_idx[0]];
532  } else {
533  A = curr->mv[1];
534  ref_A = s->ref->refPicList[1].list[curr->ref_idx[1]];
535  }
536 
537  if (neigh->pred_flag & 1) {
538  B = neigh->mv[0];
539  ref_B = neigh_refPicList[0].list[neigh->ref_idx[0]];
540  } else {
541  B = neigh->mv[1];
542  ref_B = neigh_refPicList[1].list[neigh->ref_idx[1]];
543  }
544 
545  if (ref_A == ref_B) {
546  if (FFABS(A.x - B.x) >= 4 || FFABS(A.y - B.y) >= 4)
547  return 1;
548  else
549  return 0;
550  } else
551  return 1;
552  }
553 
554  return 1;
555 }
556 
558  int log2_trafo_size)
559 {
560  HEVCLocalContext *lc = s->HEVClc;
561  MvField *tab_mvf = s->ref->tab_mvf;
562  int log2_min_pu_size = s->sps->log2_min_pu_size;
563  int log2_min_tu_size = s->sps->log2_min_tb_size;
564  int min_pu_width = s->sps->min_pu_width;
565  int min_tu_width = s->sps->min_tb_width;
566  int is_intra = tab_mvf[(y0 >> log2_min_pu_size) * min_pu_width +
567  (x0 >> log2_min_pu_size)].pred_flag == PF_INTRA;
568  int i, j, bs;
569 
570  if (y0 > 0 && (y0 & 7) == 0) {
571  int bd_ctby = y0 & ((1 << s->sps->log2_ctb_size) - 1);
573  !(lc->slice_or_tiles_up_boundary & 1);
574  int bd_tiles = s->pps->loop_filter_across_tiles_enabled_flag ||
575  !(lc->slice_or_tiles_up_boundary & 2);
576  if (((bd_slice && bd_tiles) || bd_ctby)) {
577  int yp_pu = (y0 - 1) >> log2_min_pu_size;
578  int yq_pu = y0 >> log2_min_pu_size;
579  int yp_tu = (y0 - 1) >> log2_min_tu_size;
580  int yq_tu = y0 >> log2_min_tu_size;
581  RefPicList *top_refPicList = ff_hevc_get_ref_list(s, s->ref,
582  x0, y0 - 1);
583 
584  for (i = 0; i < (1 << log2_trafo_size); i += 4) {
585  int x_pu = (x0 + i) >> log2_min_pu_size;
586  int x_tu = (x0 + i) >> log2_min_tu_size;
587  MvField *top = &tab_mvf[yp_pu * min_pu_width + x_pu];
588  MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu];
589  uint8_t top_cbf_luma = s->cbf_luma[yp_tu * min_tu_width + x_tu];
590  uint8_t curr_cbf_luma = s->cbf_luma[yq_tu * min_tu_width + x_tu];
591 
592  if (curr->pred_flag == PF_INTRA || top->pred_flag == PF_INTRA)
593  bs = 2;
594  else if (curr_cbf_luma || top_cbf_luma)
595  bs = 1;
596  else
597  bs = boundary_strength(s, curr, top, top_refPicList);
598  s->horizontal_bs[((x0 + i) + y0 * s->bs_width) >> 2] = bs;
599  }
600  }
601  }
602 
603  // bs for vertical TU boundaries
604  if (x0 > 0 && (x0 & 7) == 0) {
605  int bd_ctbx = x0 & ((1 << s->sps->log2_ctb_size) - 1);
607  !(lc->slice_or_tiles_left_boundary & 1);
608  int bd_tiles = s->pps->loop_filter_across_tiles_enabled_flag ||
609  !(lc->slice_or_tiles_left_boundary & 2);
610  if (((bd_slice && bd_tiles) || bd_ctbx)) {
611  int xp_pu = (x0 - 1) >> log2_min_pu_size;
612  int xq_pu = x0 >> log2_min_pu_size;
613  int xp_tu = (x0 - 1) >> log2_min_tu_size;
614  int xq_tu = x0 >> log2_min_tu_size;
615  RefPicList *left_refPicList = ff_hevc_get_ref_list(s, s->ref,
616  x0 - 1, y0);
617 
618  for (i = 0; i < (1 << log2_trafo_size); i += 4) {
619  int y_pu = (y0 + i) >> log2_min_pu_size;
620  int y_tu = (y0 + i) >> log2_min_tu_size;
621  MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu];
622  MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu];
623  uint8_t left_cbf_luma = s->cbf_luma[y_tu * min_tu_width + xp_tu];
624  uint8_t curr_cbf_luma = s->cbf_luma[y_tu * min_tu_width + xq_tu];
625 
626  if (curr->pred_flag == PF_INTRA || left->pred_flag == PF_INTRA)
627  bs = 2;
628  else if (curr_cbf_luma || left_cbf_luma)
629  bs = 1;
630  else
631  bs = boundary_strength(s, curr, left, left_refPicList);
632  s->vertical_bs[(x0 >> 3) + ((y0 + i) >> 2) * s->bs_width] = bs;
633  }
634  }
635  }
636 
637  if (log2_trafo_size > log2_min_pu_size && !is_intra) {
638  RefPicList *refPicList = ff_hevc_get_ref_list(s, s->ref,
639  x0,
640  y0);
641  // bs for TU internal horizontal PU boundaries
642  for (j = 8; j < (1 << log2_trafo_size); j += 8) {
643  int yp_pu = (y0 + j - 1) >> log2_min_pu_size;
644  int yq_pu = (y0 + j) >> log2_min_pu_size;
645 
646  for (i = 0; i < (1 << log2_trafo_size); i += 4) {
647  int x_pu = (x0 + i) >> log2_min_pu_size;
648  MvField *top = &tab_mvf[yp_pu * min_pu_width + x_pu];
649  MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu];
650 
651  bs = boundary_strength(s, curr, top, refPicList);
652  s->horizontal_bs[((x0 + i) + (y0 + j) * s->bs_width) >> 2] = bs;
653  }
654  }
655 
656  // bs for TU internal vertical PU boundaries
657  for (j = 0; j < (1 << log2_trafo_size); j += 4) {
658  int y_pu = (y0 + j) >> log2_min_pu_size;
659 
660  for (i = 8; i < (1 << log2_trafo_size); i += 8) {
661  int xp_pu = (x0 + i - 1) >> log2_min_pu_size;
662  int xq_pu = (x0 + i) >> log2_min_pu_size;
663  MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu];
664  MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu];
665 
666  bs = boundary_strength(s, curr, left, refPicList);
667  s->vertical_bs[((x0 + i) >> 3) + ((y0 + j) >> 2) * s->bs_width] = bs;
668  }
669  }
670  }
671 }
672 
673 #undef LUMA
674 #undef CB
675 #undef CR
676 
677 void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size)
678 {
679  deblocking_filter_CTB(s, x, y);
680  if (s->sps->sao_enabled) {
681  int x_end = x >= s->sps->width - ctb_size;
682  int y_end = y >= s->sps->height - ctb_size;
683  if (y && x)
684  sao_filter_CTB(s, x - ctb_size, y - ctb_size);
685  if (x && y_end)
686  sao_filter_CTB(s, x - ctb_size, y);
687  if (y && x_end) {
688  sao_filter_CTB(s, x, y - ctb_size);
689  if (s->threads_type & FF_THREAD_FRAME )
690  ff_thread_report_progress(&s->ref->tf, y - ctb_size, 0);
691  }
692  if (x_end && y_end) {
693  sao_filter_CTB(s, x , y);
694  if (s->threads_type & FF_THREAD_FRAME )
695  ff_thread_report_progress(&s->ref->tf, y, 0);
696  }
697  } else {
698  if (y && x >= s->sps->width - ctb_size)
699  if (s->threads_type & FF_THREAD_FRAME )
700  ff_thread_report_progress(&s->ref->tf, y, 0);
701  }
702 }
703 
704 void ff_hevc_hls_filters(HEVCContext *s, int x_ctb, int y_ctb, int ctb_size)
705 {
706  int x_end = x_ctb >= s->sps->width - ctb_size;
707  int y_end = y_ctb >= s->sps->height - ctb_size;
708  if (y_ctb && x_ctb)
709  ff_hevc_hls_filter(s, x_ctb - ctb_size, y_ctb - ctb_size, ctb_size);
710  if (y_ctb && x_end)
711  ff_hevc_hls_filter(s, x_ctb, y_ctb - ctb_size, ctb_size);
712  if (x_ctb && y_end)
713  ff_hevc_hls_filter(s, x_ctb - ctb_size, y_ctb, ctb_size);
714 }