FFmpeg
vc1_loopfilter.c
Go to the documentation of this file.
1 /*
2  * VC-1 and WMV3 decoder
3  * Copyright (c) 2011 Mashiat Sarker Shakkhar
4  * Copyright (c) 2006-2007 Konstantin Shishkov
5  * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 /**
25  * @file
26  * VC-1 and WMV3 loopfilter
27  */
28 
29 #include "avcodec.h"
30 #include "mpegvideo.h"
31 #include "vc1.h"
32 #include "vc1dsp.h"
33 
34 static av_always_inline void vc1_h_overlap_filter(VC1Context *v, int16_t (*left_block)[64],
35  int16_t (*right_block)[64], int left_fieldtx,
36  int right_fieldtx, int block_num)
37 {
38  switch (block_num) {
39  case 0:
40  v->vc1dsp.vc1_h_s_overlap(left_block[2],
41  right_block[0],
42  left_fieldtx ^ right_fieldtx ? 16 - 8 * left_fieldtx : 8,
43  left_fieldtx ^ right_fieldtx ? 16 - 8 * right_fieldtx : 8,
44  left_fieldtx || right_fieldtx ? 0 : 1);
45  break;
46 
47  case 1:
48  v->vc1dsp.vc1_h_s_overlap(right_block[0],
49  right_block[2],
50  8,
51  8,
52  right_fieldtx ? 0 : 1);
53  break;
54 
55  case 2:
56  v->vc1dsp.vc1_h_s_overlap(!left_fieldtx && right_fieldtx ? left_block[2] + 8 : left_block[3],
57  left_fieldtx && !right_fieldtx ? right_block[0] + 8 : right_block[1],
58  left_fieldtx ^ right_fieldtx ? 16 - 8 * left_fieldtx : 8,
59  left_fieldtx ^ right_fieldtx ? 16 - 8 * right_fieldtx : 8,
60  left_fieldtx || right_fieldtx ? 2 : 1);
61  break;
62 
63  case 3:
64  v->vc1dsp.vc1_h_s_overlap(right_block[1],
65  right_block[3],
66  8,
67  8,
68  right_fieldtx ? 2 : 1);
69  break;
70 
71  case 4:
72  case 5:
73  v->vc1dsp.vc1_h_s_overlap(left_block[block_num], right_block[block_num], 8, 8, 1);
74  break;
75  }
76 }
77 
78 static av_always_inline void vc1_v_overlap_filter(VC1Context *v, int16_t (*top_block)[64],
79  int16_t (*bottom_block)[64], int block_num)
80 {
81  switch (block_num) {
82  case 0:
83  v->vc1dsp.vc1_v_s_overlap(top_block[1], bottom_block[0]);
84  break;
85 
86  case 1:
87  v->vc1dsp.vc1_v_s_overlap(top_block[3], bottom_block[2]);
88  break;
89 
90  case 2:
91  v->vc1dsp.vc1_v_s_overlap(bottom_block[0], bottom_block[1]);
92  break;
93 
94  case 3:
95  v->vc1dsp.vc1_v_s_overlap(bottom_block[2], bottom_block[3]);
96  break;
97 
98  case 4:
99  case 5:
100  v->vc1dsp.vc1_v_s_overlap(top_block[block_num], bottom_block[block_num]);
101  break;
102  }
103 }
104 
106 {
107  MpegEncContext *s = &v->s;
108  int16_t (*topleft_blk)[64], (*top_blk)[64], (*left_blk)[64], (*cur_blk)[64];
109  int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
110  int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
111  int i;
112 
113  topleft_blk = v->block[v->topleft_blk_idx];
114  top_blk = v->block[v->top_blk_idx];
115  left_blk = v->block[v->left_blk_idx];
116  cur_blk = v->block[v->cur_blk_idx];
117 
118  /* Within a MB, the horizontal overlap always runs before the vertical.
119  * To accomplish that, we run the H on the left and internal vertical
120  * borders of the currently decoded MB. Then, we wait for the next overlap
121  * iteration to do H overlap on the right edge of this MB, before moving
122  * over and running the V overlap on the top and internal horizontal
123  * borders. Therefore, the H overlap trails by one MB col and the
124  * V overlap trails by one MB row. This is reflected in the time at which
125  * we run the put_pixels loop, i.e. delayed by one row and one column. */
126  for (i = 0; i < block_count; i++) {
127  if (s->mb_x == 0 && (i & 5) != 1)
128  continue;
129 
130  if (v->pq >= 9 || (v->profile == PROFILE_ADVANCED &&
131  (v->condover == CONDOVER_ALL ||
132  (v->over_flags_plane[mb_pos] &&
133  ((i & 5) == 1 || v->over_flags_plane[mb_pos - 1])))))
135  s->mb_x ? left_blk : cur_blk, cur_blk,
136  v->fcm == ILACE_FRAME && s->mb_x && v->fieldtx_plane[mb_pos - 1],
137  v->fcm == ILACE_FRAME && v->fieldtx_plane[mb_pos],
138  i);
139  }
140 
141  if (v->fcm != ILACE_FRAME)
142  for (i = 0; i < block_count; i++) {
143  if (s->first_slice_line && !(i & 2))
144  continue;
145 
146  if (s->mb_x &&
147  (v->pq >= 9 || (v->profile == PROFILE_ADVANCED &&
148  (v->condover == CONDOVER_ALL ||
149  (v->over_flags_plane[mb_pos - 1] &&
150  ((i & 2) || v->over_flags_plane[mb_pos - 1 - s->mb_stride]))))))
151  vc1_v_overlap_filter(v, s->first_slice_line ? left_blk : topleft_blk, left_blk, i);
152  if (s->mb_x == s->mb_width - 1 &&
153  (v->pq >= 9 || (v->profile == PROFILE_ADVANCED &&
154  (v->condover == CONDOVER_ALL ||
155  (v->over_flags_plane[mb_pos] &&
156  ((i & 2) || v->over_flags_plane[mb_pos - s->mb_stride]))))))
157  vc1_v_overlap_filter(v, s->first_slice_line ? cur_blk : top_blk, cur_blk, i);
158  }
159 }
160 
162 {
163  MpegEncContext *s = &v->s;
164  int16_t (*topleft_blk)[64], (*top_blk)[64], (*left_blk)[64], (*cur_blk)[64];
165  int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
166  int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
167  int i;
168 
169  topleft_blk = v->block[v->topleft_blk_idx];
170  top_blk = v->block[v->top_blk_idx];
171  left_blk = v->block[v->left_blk_idx];
172  cur_blk = v->block[v->cur_blk_idx];
173 
174  for (i = 0; i < block_count; i++) {
175  if (s->mb_x == 0 && (i & 5) != 1)
176  continue;
177 
178  if (v->mb_type[0][s->block_index[i]] && v->mb_type[0][s->block_index[i] - 1])
180  s->mb_x ? left_blk : cur_blk, cur_blk,
181  v->fcm == ILACE_FRAME && s->mb_x && v->fieldtx_plane[mb_pos - 1],
182  v->fcm == ILACE_FRAME && v->fieldtx_plane[mb_pos],
183  i);
184  }
185 
186  if (v->fcm != ILACE_FRAME)
187  for (i = 0; i < block_count; i++) {
188  if (s->first_slice_line && !(i & 2))
189  continue;
190 
191  if (s->mb_x && v->mb_type[0][s->block_index[i] - 2 + (i > 3)] &&
192  v->mb_type[0][s->block_index[i] - s->block_wrap[i] - 2 + (i > 3)])
193  vc1_v_overlap_filter(v, s->first_slice_line ? left_blk : topleft_blk, left_blk, i);
194  if (s->mb_x == s->mb_width - 1)
195  if (v->mb_type[0][s->block_index[i]] &&
196  v->mb_type[0][s->block_index[i] - s->block_wrap[i]])
197  vc1_v_overlap_filter(v, s->first_slice_line ? cur_blk : top_blk, cur_blk, i);
198  }
199 }
200 
201 #define LEFT_EDGE (1 << 0)
202 #define RIGHT_EDGE (1 << 1)
203 #define TOP_EDGE (1 << 2)
204 #define BOTTOM_EDGE (1 << 3)
205 
206 static av_always_inline void vc1_i_h_loop_filter(VC1Context *v, uint8_t *dest,
207  uint32_t flags, int block_num)
208 {
209  MpegEncContext *s = &v->s;
210  int pq = v->pq;
211  uint8_t *dst;
212 
213  if (block_num & 2)
214  return;
215 
216  if (!(flags & LEFT_EDGE) || (block_num & 5) == 1) {
217  if (block_num > 3)
218  dst = dest;
219  else
220  dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
221 
222  if (v->fcm == ILACE_FRAME)
223  if (block_num > 3) {
224  v->vc1dsp.vc1_h_loop_filter4(dst, 2 * s->uvlinesize, pq);
225  v->vc1dsp.vc1_h_loop_filter4(dst + s->uvlinesize, 2 * s->uvlinesize, pq);
226  } else {
227  v->vc1dsp.vc1_h_loop_filter8(dst, 2 * s->linesize, pq);
228  v->vc1dsp.vc1_h_loop_filter8(dst + s->linesize, 2 * s->linesize, pq);
229  }
230  else
231  if (block_num > 3)
232  v->vc1dsp.vc1_h_loop_filter8(dst, s->uvlinesize, pq);
233  else
234  v->vc1dsp.vc1_h_loop_filter16(dst, s->linesize, pq);
235  }
236 }
237 
238 static av_always_inline void vc1_i_v_loop_filter(VC1Context *v, uint8_t *dest,
239  uint32_t flags, uint8_t fieldtx,
240  int block_num)
241 {
242  MpegEncContext *s = &v->s;
243  int pq = v->pq;
244  uint8_t *dst;
245 
246  if ((block_num & 5) == 1)
247  return;
248 
249  if (!(flags & TOP_EDGE) || block_num & 2) {
250  if (block_num > 3)
251  dst = dest;
252  else
253  dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
254 
255  if (v->fcm == ILACE_FRAME) {
256  if (block_num > 3) {
257  v->vc1dsp.vc1_v_loop_filter8(dst, 2 * s->uvlinesize, pq);
258  v->vc1dsp.vc1_v_loop_filter8(dst + s->uvlinesize, 2 * s->uvlinesize, pq);
259  } else if (block_num < 2 || !fieldtx) {
260  v->vc1dsp.vc1_v_loop_filter16(dst, 2 * s->linesize, pq);
261  v->vc1dsp.vc1_v_loop_filter16(dst + s->linesize, 2 * s->linesize, pq);
262  }
263  } else
264  if (block_num > 3)
265  v->vc1dsp.vc1_v_loop_filter8(dst, s->uvlinesize, pq);
266  else
267  v->vc1dsp.vc1_v_loop_filter16(dst, s->linesize, pq);
268  }
269 }
270 
272 {
273  MpegEncContext *s = &v->s;
274  int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
275  int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
276  uint8_t *dest, fieldtx;
277  uint32_t flags = 0;
278  int i;
279 
280  /* Within a MB, the vertical loop filter always runs before the horizontal.
281  * To accomplish that, we run the V loop filter on top and internal
282  * horizontal borders of the last overlap filtered MB. Then, we wait for
283  * the loop filter iteration on the next row to do V loop filter on the
284  * bottom edge of this MB, before moving over and running the H loop
285  * filter on the left and internal vertical borders. Therefore, the loop
286  * filter trails by one row and one column relative to the overlap filter
287  * and two rows and two columns relative to the decoding loop. */
288  if (!s->first_slice_line) {
289  dest = s->dest[0] - 16 * s->linesize - 16;
290  flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
291  if (s->mb_x) {
292  fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride - 1];
293  for (i = 0; i < block_count; i++)
294  vc1_i_v_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, flags, fieldtx, i);
295  }
296  if (s->mb_x == v->end_mb_x - 1) {
297  dest += 16;
298  fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride];
299  for (i = 0; i < block_count; i++)
300  vc1_i_v_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, flags, fieldtx, i);
301  }
302  }
303  if (s->mb_y == s->end_mb_y - 1) {
304  dest = s->dest[0] - 16;
305  flags = s->first_slice_line ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
306  if (s->mb_x) {
307  fieldtx = v->fieldtx_plane[mb_pos - 1];
308  for (i = 0; i < block_count; i++)
309  vc1_i_v_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, flags, fieldtx, i);
310  }
311  if (s->mb_x == v->end_mb_x - 1) {
312  dest += 16;
313  fieldtx = v->fieldtx_plane[mb_pos];
314  for (i = 0; i < block_count; i++)
315  vc1_i_v_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, flags, fieldtx, i);
316  }
317  }
318 
319  if (s->mb_y >= s->start_mb_y + 2) {
320  dest = s->dest[0] - 32 * s->linesize - 16;
321  if (s->mb_x) {
322  flags = s->mb_x == 1 ? LEFT_EDGE : 0;
323  for (i = 0; i < block_count; i++)
324  vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 8 : dest, flags, i);
325  }
326  if (s->mb_x == v->end_mb_x - 1) {
327  dest += 16;
328  flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
329  for (i = 0; i < block_count; i++)
330  vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize : dest, flags, i);
331  }
332  }
333  if (s->mb_y == s->end_mb_y - 1) {
334  if (s->mb_y >= s->start_mb_y + 1) {
335  dest = s->dest[0] - 16 * s->linesize - 16;
336  if (s->mb_x) {
337  flags = s->mb_x == 1 ? LEFT_EDGE : 0;
338  for (i = 0; i < block_count; i++)
339  vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, flags, i);
340  }
341  if (s->mb_x == v->end_mb_x - 1) {
342  flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
343  dest += 16;
344  for (i = 0; i < block_count; i++)
345  vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, flags, i);
346  }
347  }
348  dest = s->dest[0] - 16;
349  if (s->mb_x) {
350  flags = s->mb_x == 1 ? LEFT_EDGE : 0;
351  for (i = 0; i < block_count; i++)
352  vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, flags, i);
353  }
354  if (s->mb_x == v->end_mb_x - 1) {
355  dest += 16;
356  flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
357  for (i = 0; i < block_count; i++)
358  vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, flags, i);
359  }
360  }
361 }
362 
363 static av_always_inline void vc1_p_h_loop_filter(VC1Context *v, uint8_t *dest, uint32_t *cbp,
364  uint8_t *is_intra, int16_t (*mv)[2], uint8_t *mv_f,
365  int *ttblk, uint32_t flags, int block_num)
366 {
367  MpegEncContext *s = &v->s;
368  int pq = v->pq;
369  uint32_t left_cbp = cbp[0] >> (block_num * 4), right_cbp;
370  uint8_t left_is_intra, right_is_intra;
371  int tt;
372  int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize;
373  uint8_t *dst;
374 
375  if (block_num > 3)
376  dst = dest;
377  else
378  dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
379 
380  if (!(flags & RIGHT_EDGE) || !(block_num & 5)) {
381  left_is_intra = is_intra[0] & (1 << block_num);
382 
383  if (block_num > 3) {
384  right_is_intra = is_intra[1] & (1 << block_num);
385  right_cbp = cbp[1] >> (block_num * 4);
386  } else if (block_num & 1) {
387  right_is_intra = is_intra[1] & (1 << block_num - 1);
388  right_cbp = cbp[1] >> ((block_num - 1) * 4);
389  } else {
390  right_is_intra = is_intra[0] & (1 << block_num + 1);
391  right_cbp = cbp[0] >> ((block_num + 1) * 4);
392  }
393 
394  if (left_is_intra || right_is_intra ||
395  mv[0][0] != mv[1][0] || mv[0][1] != mv[1][1] ||
396  (v->fcm == ILACE_FIELD && mv_f[0] != mv_f[1]))
397  v->vc1dsp.vc1_h_loop_filter8(dst + 8, linesize, pq);
398  else {
399  idx = (left_cbp | (right_cbp >> 1)) & 5;
400  if (idx & 1)
401  v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize + 8, linesize, pq);
402  if (idx & 4)
403  v->vc1dsp.vc1_h_loop_filter4(dst + 8, linesize, pq);
404  }
405  }
406 
407  tt = ttblk[0] >> (block_num * 4) & 0xf;
408  if (tt == TT_4X4 || tt == TT_4X8) {
409  if (left_cbp & 3)
410  v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
411  if (left_cbp & 12)
412  v->vc1dsp.vc1_h_loop_filter4(dst + 4, linesize, pq);
413  }
414 }
415 
416 static av_always_inline
417 void vc1_p_v_loop_filter(VC1Context *v, uint8_t *dest, const uint32_t *cbp,
418  const uint8_t *is_intra, int16_t (*mv)[2], const uint8_t *mv_f,
419  const int *ttblk, uint32_t flags, int block_num)
420 {
421  MpegEncContext *s = &v->s;
422  int pq = v->pq;
423  uint32_t top_cbp = cbp[0] >> (block_num * 4), bottom_cbp;
424  uint8_t top_is_intra, bottom_is_intra;
425  int tt;
426  int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize;
427  uint8_t *dst;
428 
429  if (block_num > 3)
430  dst = dest;
431  else
432  dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
433 
434  if(!(flags & BOTTOM_EDGE) || block_num < 2) {
435  top_is_intra = is_intra[0] & (1 << block_num);
436 
437  if (block_num > 3) {
438  bottom_is_intra = is_intra[s->mb_stride] & (1 << block_num);
439  bottom_cbp = cbp[s->mb_stride] >> (block_num * 4);
440  } else if (block_num < 2) {
441  bottom_is_intra = is_intra[0] & (1 << block_num + 2);
442  bottom_cbp = cbp[0] >> ((block_num + 2) * 4);
443  } else {
444  bottom_is_intra = is_intra[s->mb_stride] & (1 << block_num - 2);
445  bottom_cbp = cbp[s->mb_stride] >> ((block_num - 2) * 4);
446  }
447 
448  if (top_is_intra || bottom_is_intra ||
449  mv[0][0] != mv[block_num > 3 ? s->mb_stride : s->b8_stride][0] ||
450  mv[0][1] != mv[block_num > 3 ? s->mb_stride : s->b8_stride][1] ||
451  (v->fcm == ILACE_FIELD && mv_f[0] != mv_f[block_num > 3 ? s->mb_stride : s->b8_stride]))
452  v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, linesize, pq);
453  else {
454  idx = (top_cbp | (bottom_cbp >> 2)) & 3;
455  if (idx & 1)
456  v->vc1dsp.vc1_v_loop_filter4(dst + 8 * linesize + 4, linesize, pq);
457  if (idx & 2)
458  v->vc1dsp.vc1_v_loop_filter4(dst + 8 * linesize, linesize, pq);
459  }
460  }
461 
462  tt = ttblk[0] >> (block_num * 4) & 0xf;
463  if (tt == TT_4X4 || tt == TT_8X4) {
464  if (top_cbp & 5)
465  v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
466  if (top_cbp & 10)
467  v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize, linesize, pq);
468  }
469 }
470 
472 {
473  MpegEncContext *s = &v->s;
474  int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
475  uint8_t *dest;
476  uint32_t *cbp;
477  uint8_t *is_intra;
478  int16_t (*uvmv)[2];
479  int *ttblk;
480  uint32_t flags;
481  int i;
482 
483  /* Within a MB, the vertical loop filter always runs before the horizontal.
484  * To accomplish that, we run the V loop filter on all applicable
485  * horizontal borders of the MB above the last overlap filtered MB. Then,
486  * we wait for the next loop filter iteration to do H loop filter on all
487  * applicable vertical borders of this MB. Therefore, the loop filter
488  * trails by one row and one column relative to the overlap filter and two
489  * rows and two columns relative to the decoding loop. */
490  if (s->mb_y >= s->start_mb_y + 2) {
491  if (s->mb_x) {
492  dest = s->dest[0] - 32 * s->linesize - 16;
493  cbp = &v->cbp[s->mb_x - 2 * s->mb_stride - 1];
494  is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride - 1];
495  uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride - 1];
496  ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 1];
497  flags = s->mb_y == s->start_mb_y + 2 ? TOP_EDGE : 0;
498  for (i = 0; i < block_count; i++)
500  i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 8 : dest,
501  cbp,
502  is_intra,
503  i > 3 ? uvmv :
504  &s->cur_pic.motion_val[0][s->block_index[i] - 4 * s->b8_stride - 2 + v->blocks_off],
505  i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride - 1 + v->mb_off] :
506  &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride - 2 + v->blocks_off],
507  ttblk,
508  flags,
509  i);
510  }
511  if (s->mb_x == s->mb_width - 1) {
512  dest = s->dest[0] - 32 * s->linesize;
513  cbp = &v->cbp[s->mb_x - 2 * s->mb_stride];
514  is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride];
515  uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride];
516  ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride];
517  flags = s->mb_y == s->start_mb_y + 2 ? TOP_EDGE : 0;
518  for (i = 0; i < block_count; i++)
520  i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize : dest,
521  cbp,
522  is_intra,
523  i > 3 ? uvmv :
524  &s->cur_pic.motion_val[0][s->block_index[i] - 4 * s->b8_stride + v->blocks_off],
525  i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride + v->mb_off] :
526  &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride + v->blocks_off],
527  ttblk,
528  flags,
529  i);
530  }
531  }
532  if (s->mb_y == s->end_mb_y - 1) {
533  if (s->mb_x) {
534  if (s->mb_y >= s->start_mb_y + 1) {
535  dest = s->dest[0] - 16 * s->linesize - 16;
536  cbp = &v->cbp[s->mb_x - s->mb_stride - 1];
537  is_intra = &v->is_intra[s->mb_x - s->mb_stride - 1];
538  uvmv = &v->luma_mv[s->mb_x - s->mb_stride - 1];
539  ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
540  flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
541  for (i = 0; i < block_count; i++)
543  i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest,
544  cbp,
545  is_intra,
546  i > 3 ? uvmv :
547  &s->cur_pic.motion_val[0][s->block_index[i] - 2 * s->b8_stride - 2 + v->blocks_off],
548  i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride - 1 + v->mb_off] :
549  &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride - 2 + v->blocks_off],
550  ttblk,
551  flags,
552  i);
553  }
554  dest = s->dest[0] - 16;
555  cbp = &v->cbp[s->mb_x - 1];
556  is_intra = &v->is_intra[s->mb_x - 1];
557  uvmv = &v->luma_mv[s->mb_x - 1];
558  ttblk = &v->ttblk[s->mb_x - 1];
559  flags = s->mb_y == s->start_mb_y ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
560  for (i = 0; i < block_count; i++)
562  i > 3 ? s->dest[i - 3] - 8 : dest,
563  cbp,
564  is_intra,
565  i > 3 ? uvmv :
566  &s->cur_pic.motion_val[0][s->block_index[i] - 2 + v->blocks_off],
567  i > 3 ? &v->mv_f[0][s->block_index[i] - 1 + v->mb_off] :
568  &v->mv_f[0][s->block_index[i] - 2 + v->blocks_off],
569  ttblk,
570  flags,
571  i);
572  }
573  if (s->mb_x == s->mb_width - 1) {
574  if (s->mb_y >= s->start_mb_y + 1) {
575  dest = s->dest[0] - 16 * s->linesize;
576  cbp = &v->cbp[s->mb_x - s->mb_stride];
577  is_intra = &v->is_intra[s->mb_x - s->mb_stride];
578  uvmv = &v->luma_mv[s->mb_x - s->mb_stride];
579  ttblk = &v->ttblk[s->mb_x - s->mb_stride];
580  flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
581  for (i = 0; i < block_count; i++)
583  i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest,
584  cbp,
585  is_intra,
586  i > 3 ? uvmv :
587  &s->cur_pic.motion_val[0][s->block_index[i] - 2 * s->b8_stride + v->blocks_off],
588  i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride + v->mb_off] :
589  &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride + v->blocks_off],
590  ttblk,
591  flags,
592  i);
593  }
594  dest = s->dest[0];
595  cbp = &v->cbp[s->mb_x];
596  is_intra = &v->is_intra[s->mb_x];
597  uvmv = &v->luma_mv[s->mb_x];
598  ttblk = &v->ttblk[s->mb_x];
599  flags = s->mb_y == s->start_mb_y ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
600  for (i = 0; i < block_count; i++)
602  i > 3 ? s->dest[i - 3] : dest,
603  cbp,
604  is_intra,
605  i > 3 ? uvmv :
606  &s->cur_pic.motion_val[0][s->block_index[i] + v->blocks_off],
607  i > 3 ? &v->mv_f[0][s->block_index[i] + v->mb_off] :
608  &v->mv_f[0][s->block_index[i] + v->blocks_off],
609  ttblk,
610  flags,
611  i);
612  }
613  }
614 
615  if (s->mb_y >= s->start_mb_y + 2) {
616  if (s->mb_x >= 2) {
617  dest = s->dest[0] - 32 * s->linesize - 32;
618  cbp = &v->cbp[s->mb_x - 2 * s->mb_stride - 2];
619  is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride - 2];
620  uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride - 2];
621  ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 2];
622  flags = s->mb_x == 2 ? LEFT_EDGE : 0;
623  for (i = 0; i < block_count; i++)
625  i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 16 : dest,
626  cbp,
627  is_intra,
628  i > 3 ? uvmv :
629  &s->cur_pic.motion_val[0][s->block_index[i] - 4 * s->b8_stride - 4 + v->blocks_off],
630  i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride - 2 + v->mb_off] :
631  &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride - 4 + v->blocks_off],
632  ttblk,
633  flags,
634  i);
635  }
636  if (s->mb_x == s->mb_width - 1) {
637  if (s->mb_x >= 1) {
638  dest = s->dest[0] - 32 * s->linesize - 16;
639  cbp = &v->cbp[s->mb_x - 2 * s->mb_stride - 1];
640  is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride - 1];
641  uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride - 1];
642  ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 1];
643  flags = s->mb_x == 1 ? LEFT_EDGE : 0;
644  for (i = 0; i < block_count; i++)
646  i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 8 : dest,
647  cbp,
648  is_intra,
649  i > 3 ? uvmv :
650  &s->cur_pic.motion_val[0][s->block_index[i] - 4 * s->b8_stride - 2 + v->blocks_off],
651  i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride - 1 + v->mb_off] :
652  &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride - 2 + v->blocks_off],
653  ttblk,
654  flags,
655  i);
656  }
657  dest = s->dest[0] - 32 * s->linesize;
658  cbp = &v->cbp[s->mb_x - 2 * s->mb_stride];
659  is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride];
660  uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride];
661  ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride];
662  flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
663  for (i = 0; i < block_count; i++)
665  i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize : dest,
666  cbp,
667  is_intra,
668  i > 3 ? uvmv :
669  &s->cur_pic.motion_val[0][s->block_index[i] - 4 * s->b8_stride + v->blocks_off],
670  i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride + v->mb_off] :
671  &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride + v->blocks_off],
672  ttblk,
673  flags,
674  i);
675  }
676  }
677  if (s->mb_y == s->end_mb_y - 1) {
678  if (s->mb_y >= s->start_mb_y + 1) {
679  if (s->mb_x >= 2) {
680  dest = s->dest[0] - 16 * s->linesize - 32;
681  cbp = &v->cbp[s->mb_x - s->mb_stride - 2];
682  is_intra = &v->is_intra[s->mb_x - s->mb_stride - 2];
683  uvmv = &v->luma_mv[s->mb_x - s->mb_stride - 2];
684  ttblk = &v->ttblk[s->mb_x - s->mb_stride - 2];
685  flags = s->mb_x == 2 ? LEFT_EDGE : 0;
686  for (i = 0; i < block_count; i++)
688  i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 16 : dest,
689  cbp,
690  is_intra,
691  i > 3 ? uvmv :
692  &s->cur_pic.motion_val[0][s->block_index[i] - 2 * s->b8_stride - 4 + v->blocks_off],
693  i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride - 2 + v->mb_off] :
694  &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride - 4 + v->blocks_off],
695  ttblk,
696  flags,
697  i);
698  }
699  if (s->mb_x == s->mb_width - 1) {
700  if (s->mb_x >= 1) {
701  dest = s->dest[0] - 16 * s->linesize - 16;
702  cbp = &v->cbp[s->mb_x - s->mb_stride - 1];
703  is_intra = &v->is_intra[s->mb_x - s->mb_stride - 1];
704  uvmv = &v->luma_mv[s->mb_x - s->mb_stride - 1];
705  ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
706  flags = s->mb_x == 1 ? LEFT_EDGE : 0;
707  for (i = 0; i < block_count; i++)
709  i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest,
710  cbp,
711  is_intra,
712  i > 3 ? uvmv :
713  &s->cur_pic.motion_val[0][s->block_index[i] - 2 * s->b8_stride - 2 + v->blocks_off],
714  i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride - 1 + v->mb_off] :
715  &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride - 2 + v->blocks_off],
716  ttblk,
717  flags,
718  i);
719  }
720  dest = s->dest[0] - 16 * s->linesize;
721  cbp = &v->cbp[s->mb_x - s->mb_stride];
722  is_intra = &v->is_intra[s->mb_x - s->mb_stride];
723  uvmv = &v->luma_mv[s->mb_x - s->mb_stride];
724  ttblk = &v->ttblk[s->mb_x - s->mb_stride];
725  flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
726  for (i = 0; i < block_count; i++)
728  i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest,
729  cbp,
730  is_intra,
731  i > 3 ? uvmv :
732  &s->cur_pic.motion_val[0][s->block_index[i] - 2 * s->b8_stride + v->blocks_off],
733  i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride + v->mb_off] :
734  &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride + v->blocks_off],
735  ttblk,
736  flags,
737  i);
738  }
739  }
740  if (s->mb_x >= 2) {
741  dest = s->dest[0] - 32;
742  cbp = &v->cbp[s->mb_x - 2];
743  is_intra = &v->is_intra[s->mb_x - 2];
744  uvmv = &v->luma_mv[s->mb_x - 2];
745  ttblk = &v->ttblk[s->mb_x - 2];
746  flags = s->mb_x == 2 ? LEFT_EDGE : 0;
747  for (i = 0; i < block_count; i++)
749  i > 3 ? s->dest[i - 3] - 16 : dest,
750  cbp,
751  is_intra,
752  i > 3 ? uvmv :
753  &s->cur_pic.motion_val[0][s->block_index[i] - 4 + v->blocks_off],
754  i > 3 ? &v->mv_f[0][s->block_index[i] - 2 + v->mb_off] :
755  &v->mv_f[0][s->block_index[i] - 4 + v->blocks_off],
756  ttblk,
757  flags,
758  i);
759  }
760  if (s->mb_x == s->mb_width - 1) {
761  if (s->mb_x >= 1) {
762  dest = s->dest[0] - 16;
763  cbp = &v->cbp[s->mb_x - 1];
764  is_intra = &v->is_intra[s->mb_x - 1];
765  uvmv = &v->luma_mv[s->mb_x - 1];
766  ttblk = &v->ttblk[s->mb_x - 1];
767  flags = s->mb_x == 1 ? LEFT_EDGE : 0;
768  for (i = 0; i < block_count; i++)
770  i > 3 ? s->dest[i - 3] - 8 : dest,
771  cbp,
772  is_intra,
773  i > 3 ? uvmv :
774  &s->cur_pic.motion_val[0][s->block_index[i] - 2 + v->blocks_off],
775  i > 3 ? &v->mv_f[0][s->block_index[i] - 1 + v->mb_off] :
776  &v->mv_f[0][s->block_index[i] - 2 + v->blocks_off],
777  ttblk,
778  flags,
779  i);
780  }
781  dest = s->dest[0];
782  cbp = &v->cbp[s->mb_x];
783  is_intra = &v->is_intra[s->mb_x];
784  uvmv = &v->luma_mv[s->mb_x];
785  ttblk = &v->ttblk[s->mb_x];
786  flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
787  for (i = 0; i < block_count; i++)
789  i > 3 ? s->dest[i - 3] : dest,
790  cbp,
791  is_intra,
792  i > 3 ? uvmv :
793  &s->cur_pic.motion_val[0][s->block_index[i] + v->blocks_off],
794  i > 3 ? &v->mv_f[0][s->block_index[i] + v->mb_off] :
795  &v->mv_f[0][s->block_index[i] + v->blocks_off],
796  ttblk,
797  flags,
798  i);
799  }
800  }
801 }
802 
803 static av_always_inline void vc1_p_h_intfr_loop_filter(VC1Context *v, uint8_t *dest, const int *ttblk,
804  uint32_t flags, uint8_t fieldtx, int block_num)
805 {
806  MpegEncContext *s = &v->s;
807  int pq = v->pq;
808  int tt;
809  int linesize = block_num > 3 ? s->uvlinesize : s->linesize;
810  uint8_t *dst;
811 
812  if (block_num > 3)
813  dst = dest;
814  else
815  dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
816 
817  tt = ttblk[0] >> (block_num * 4) & 0xf;
818  if (block_num < 4) {
819  if (fieldtx) {
820  if (block_num < 2) {
821  if (tt == TT_4X4 || tt == TT_4X8)
822  v->vc1dsp.vc1_h_loop_filter8(dst + 4, 2 * linesize, pq);
823  if (!(flags & RIGHT_EDGE) || block_num == 0)
824  v->vc1dsp.vc1_h_loop_filter8(dst + 8, 2 * linesize, pq);
825  } else {
826  if (tt == TT_4X4 || tt == TT_4X8)
827  v->vc1dsp.vc1_h_loop_filter8(dst - 7 * linesize + 4, 2 * linesize, pq);
828  if (!(flags & RIGHT_EDGE) || block_num == 2)
829  v->vc1dsp.vc1_h_loop_filter8(dst - 7 * linesize + 8, 2 * linesize, pq);
830  }
831  } else {
832  if(tt == TT_4X4 || tt == TT_4X8) {
833  v->vc1dsp.vc1_h_loop_filter4(dst + 4, 2 * linesize, pq);
834  v->vc1dsp.vc1_h_loop_filter4(dst + linesize + 4, 2 * linesize, pq);
835  }
836  if (!(flags & RIGHT_EDGE) || !(block_num & 5)) {
837  v->vc1dsp.vc1_h_loop_filter4(dst + 8, 2 * linesize, pq);
838  v->vc1dsp.vc1_h_loop_filter4(dst + linesize + 8, 2 * linesize, pq);
839  }
840  }
841  } else {
842  if (tt == TT_4X4 || tt == TT_4X8) {
843  v->vc1dsp.vc1_h_loop_filter4(dst + 4, 2 * linesize, pq);
844  v->vc1dsp.vc1_h_loop_filter4(dst + linesize + 4, 2 * linesize, pq);
845  }
846  if (!(flags & RIGHT_EDGE)) {
847  v->vc1dsp.vc1_h_loop_filter4(dst + 8, 2 * linesize, pq);
848  v->vc1dsp.vc1_h_loop_filter4(dst + linesize + 8, 2 * linesize, pq);
849  }
850  }
851 }
852 
853 static av_always_inline
854 void vc1_p_v_intfr_loop_filter(VC1Context *v, uint8_t *dest, const int *ttblk,
855  uint32_t flags, uint8_t fieldtx, int block_num)
856 {
857  MpegEncContext *s = &v->s;
858  int pq = v->pq;
859  int tt;
860  int linesize = block_num > 3 ? s->uvlinesize : s->linesize;
861  uint8_t *dst;
862 
863  if (block_num > 3)
864  dst = dest;
865  else
866  dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
867 
868  tt = ttblk[0] >> (block_num * 4) & 0xf;
869  if (block_num < 4) {
870  if (fieldtx) {
871  if (block_num < 2) {
872  if (tt == TT_4X4 || tt == TT_8X4)
873  v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, 2 * linesize, pq);
874  if (!(flags & BOTTOM_EDGE))
875  v->vc1dsp.vc1_v_loop_filter8(dst + 16 * linesize, 2 * linesize, pq);
876  } else {
877  if (tt == TT_4X4 || tt == TT_8X4)
878  v->vc1dsp.vc1_v_loop_filter8(dst + linesize, 2 * linesize, pq);
879  if (!(flags & BOTTOM_EDGE))
880  v->vc1dsp.vc1_v_loop_filter8(dst + 9 * linesize, 2 * linesize, pq);
881  }
882  } else {
883  if (block_num < 2) {
884  if (!(flags & TOP_EDGE) && (tt == TT_4X4 || tt == TT_8X4)) {
885  v->vc1dsp.vc1_v_loop_filter8(dst + 4 * linesize, 2 * linesize, pq);
886  v->vc1dsp.vc1_v_loop_filter8(dst + 5 * linesize, 2 * linesize, pq);
887  }
888  v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, 2 * linesize, pq);
889  v->vc1dsp.vc1_v_loop_filter8(dst + 9 * linesize, 2 * linesize, pq);
890  } else if (!(flags & BOTTOM_EDGE)) {
891  if (tt == TT_4X4 || tt == TT_8X4) {
892  v->vc1dsp.vc1_v_loop_filter8(dst + 4 * linesize, 2 * linesize, pq);
893  v->vc1dsp.vc1_v_loop_filter8(dst + 5 * linesize, 2 * linesize, pq);
894  }
895  v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, 2 * linesize, pq);
896  v->vc1dsp.vc1_v_loop_filter8(dst + 9 * linesize, 2 * linesize, pq);
897  }
898  }
899  } else {
900  if (!(flags & BOTTOM_EDGE)) {
901  if (!(flags & TOP_EDGE) && (tt == TT_4X4 || tt == TT_8X4)) {
902  v->vc1dsp.vc1_v_loop_filter8(dst + 4 * linesize, 2 * linesize, pq);
903  v->vc1dsp.vc1_v_loop_filter8(dst + 5 * linesize, 2 * linesize, pq);
904  }
905  v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, 2 * linesize, pq);
906  v->vc1dsp.vc1_v_loop_filter8(dst + 9 * linesize, 2 * linesize, pq);
907  }
908  }
909 }
910 
912 {
913  MpegEncContext *s = &v->s;
914  int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
915  int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
916  uint8_t *dest;
917  int *ttblk;
918  uint32_t flags;
919  uint8_t fieldtx;
920  int i;
921 
922  /* Within a MB, the vertical loop filter always runs before the horizontal.
923  * To accomplish that, we run the V loop filter on all applicable
924  * horizontal borders of the MB above the last overlap filtered MB. Then,
925  * we wait for the loop filter iteration on the next row and next column to
926  * do H loop filter on all applicable vertical borders of this MB.
927  * Therefore, the loop filter trails by two rows and one column relative to
928  * the overlap filter and two rows and two columns relative to the decoding
929  * loop. */
930  if (s->mb_x) {
931  if (s->mb_y >= s->start_mb_y + 1) {
932  dest = s->dest[0] - 16 * s->linesize - 16;
933  ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
934  flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
935  fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride - 1];
936  for (i = 0; i < block_count; i++)
938  i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest,
939  ttblk,
940  flags,
941  fieldtx,
942  i);
943  }
944  }
945  if (s->mb_x == s->mb_width - 1) {
946  if (s->mb_y >= s->start_mb_y + 1) {
947  dest = s->dest[0] - 16 * s->linesize;
948  ttblk = &v->ttblk[s->mb_x - s->mb_stride];
949  flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
950  fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride];
951  for (i = 0; i < block_count; i++)
953  i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest,
954  ttblk,
955  flags,
956  fieldtx,
957  i);
958  }
959  }
960  if (s->mb_y == s->end_mb_y - 1) {
961  if (s->mb_x) {
962  dest = s->dest[0] - 16;
963  ttblk = &v->ttblk[s->mb_x - 1];
964  flags = s->mb_y == s->start_mb_y ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
965  fieldtx = v->fieldtx_plane[mb_pos - 1];
966  for (i = 0; i < block_count; i++)
968  i > 3 ? s->dest[i - 3] - 8 : dest,
969  ttblk,
970  flags,
971  fieldtx,
972  i);
973  }
974  if (s->mb_x == s->mb_width - 1) {
975  dest = s->dest[0];
976  ttblk = &v->ttblk[s->mb_x];
977  flags = s->mb_y == s->start_mb_y ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
978  fieldtx = v->fieldtx_plane[mb_pos];
979  for (i = 0; i < block_count; i++)
981  i > 3 ? s->dest[i - 3] : dest,
982  ttblk,
983  flags,
984  fieldtx,
985  i);
986  }
987  }
988 
989  if (s->mb_y >= s->start_mb_y + 2) {
990  if (s->mb_x >= 2) {
991  dest = s->dest[0] - 32 * s->linesize - 32;
992  ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 2];
993  flags = s->mb_x == 2 ? LEFT_EDGE : 0;
994  fieldtx = v->fieldtx_plane[mb_pos - 2 * s->mb_stride - 2];
995  for (i = 0; i < block_count; i++)
997  i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 16 : dest,
998  ttblk,
999  flags,
1000  fieldtx,
1001  i);
1002  }
1003  if (s->mb_x == s->mb_width - 1) {
1004  if (s->mb_x >= 1) {
1005  dest = s->dest[0] - 32 * s->linesize - 16;
1006  ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 1];
1007  flags = s->mb_x == 1 ? LEFT_EDGE : 0;
1008  fieldtx = v->fieldtx_plane[mb_pos - 2 * s->mb_stride - 1];
1009  for (i = 0; i < block_count; i++)
1011  i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 8 : dest,
1012  ttblk,
1013  flags,
1014  fieldtx,
1015  i);
1016  }
1017  dest = s->dest[0] - 32 * s->linesize;
1018  ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride];
1019  flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
1020  fieldtx = v->fieldtx_plane[mb_pos - 2 * s->mb_stride];
1021  for (i = 0; i < block_count; i++)
1023  i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize : dest,
1024  ttblk,
1025  flags,
1026  fieldtx,
1027  i);
1028  }
1029  }
1030  if (s->mb_y == s->end_mb_y - 1) {
1031  if (s->mb_y >= s->start_mb_y + 1) {
1032  if (s->mb_x >= 2) {
1033  dest = s->dest[0] - 16 * s->linesize - 32;
1034  ttblk = &v->ttblk[s->mb_x - s->mb_stride - 2];
1035  flags = s->mb_x == 2 ? LEFT_EDGE : 0;
1036  fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride - 2];
1037  for (i = 0; i < block_count; i++)
1039  i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 16 : dest,
1040  ttblk,
1041  flags,
1042  fieldtx,
1043  i);
1044  }
1045  if (s->mb_x == s->mb_width - 1) {
1046  if (s->mb_x >= 1) {
1047  dest = s->dest[0] - 16 * s->linesize - 16;
1048  ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
1049  flags = s->mb_x == 1 ? LEFT_EDGE : 0;
1050  fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride - 1];
1051  for (i = 0; i < block_count; i++)
1053  i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest,
1054  ttblk,
1055  flags,
1056  fieldtx,
1057  i);
1058  }
1059  dest = s->dest[0] - 16 * s->linesize;
1060  ttblk = &v->ttblk[s->mb_x - s->mb_stride];
1061  flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
1062  fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride];
1063  for (i = 0; i < block_count; i++)
1065  i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest,
1066  ttblk,
1067  flags,
1068  fieldtx,
1069  i);
1070  }
1071  }
1072  if (s->mb_x >= 2) {
1073  dest = s->dest[0] - 32;
1074  ttblk = &v->ttblk[s->mb_x - 2];
1075  flags = s->mb_x == 2 ? LEFT_EDGE : 0;
1076  fieldtx = v->fieldtx_plane[mb_pos - 2];
1077  for (i = 0; i < block_count; i++)
1079  i > 3 ? s->dest[i - 3] - 16 : dest,
1080  ttblk,
1081  flags,
1082  fieldtx,
1083  i);
1084  }
1085  if (s->mb_x == s->mb_width - 1) {
1086  if (s->mb_x >= 1) {
1087  dest = s->dest[0] - 16;
1088  ttblk = &v->ttblk[s->mb_x - 1];
1089  flags = s->mb_x == 1 ? LEFT_EDGE : 0;
1090  fieldtx = v->fieldtx_plane[mb_pos - 1];
1091  for (i = 0; i < block_count; i++)
1093  i > 3 ? s->dest[i - 3] - 8 : dest,
1094  ttblk,
1095  flags,
1096  fieldtx,
1097  i);
1098  }
1099  dest = s->dest[0];
1100  ttblk = &v->ttblk[s->mb_x];
1101  flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
1102  fieldtx = v->fieldtx_plane[mb_pos];
1103  for (i = 0; i < block_count; i++)
1105  i > 3 ? s->dest[i - 3] : dest,
1106  ttblk,
1107  flags,
1108  fieldtx,
1109  i);
1110  }
1111  }
1112 }
1113 
1114 static av_always_inline
1115 void vc1_b_h_intfi_loop_filter(VC1Context *v, uint8_t *dest, const uint32_t *cbp,
1116  const int *ttblk, uint32_t flags, int block_num)
1117 {
1118  MpegEncContext *s = &v->s;
1119  int pq = v->pq;
1120  uint8_t *dst;
1121  uint32_t block_cbp = cbp[0] >> (block_num * 4);
1122  int tt;
1123  int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize;
1124 
1125  if (block_num > 3)
1126  dst = dest;
1127  else
1128  dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
1129 
1130  if (!(flags & RIGHT_EDGE) || !(block_num & 5)) {
1131  v->vc1dsp.vc1_h_loop_filter8(dst + 8, linesize, pq);
1132  }
1133 
1134  tt = ttblk[0] >> (block_num * 4) & 0xf;
1135  if (tt == TT_4X4 || tt == TT_4X8) {
1136  idx = (block_cbp | (block_cbp >> 1)) & 5;
1137  if (idx & 1)
1138  v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
1139  if (idx & 4)
1140  v->vc1dsp.vc1_h_loop_filter4(dst + 4, linesize, pq);
1141  }
1142 }
1143 
1144 static av_always_inline
1145 void vc1_b_v_intfi_loop_filter(VC1Context *v, uint8_t *dest, const uint32_t *cbp,
1146  const int *ttblk, uint32_t flags, int block_num)
1147 {
1148  MpegEncContext *s = &v->s;
1149  int pq = v->pq;
1150  uint8_t *dst;
1151  uint32_t block_cbp = cbp[0] >> (block_num * 4);
1152  int tt;
1153  int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize;
1154 
1155  if (block_num > 3)
1156  dst = dest;
1157  else
1158  dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
1159 
1160  if(!(flags & BOTTOM_EDGE) || block_num < 2)
1161  v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, linesize, pq);
1162 
1163  tt = ttblk[0] >> (block_num * 4) & 0xf;
1164  if (tt == TT_4X4 || tt == TT_8X4) {
1165  idx = (block_cbp | (block_cbp >> 2)) & 3;
1166  if (idx & 1)
1167  v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
1168  if (idx & 2)
1169  v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize, linesize, pq);
1170  }
1171 }
1172 
1174 {
1175  MpegEncContext *s = &v->s;
1176  int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
1177  uint8_t *dest;
1178  const uint32_t *cbp;
1179  int *ttblk;
1180  uint32_t flags = 0;
1181  int i;
1182 
1183  /* Within a MB, the vertical loop filter always runs before the horizontal.
1184  * To accomplish that, we run the V loop filter on all applicable
1185  * horizontal borders of the MB above the currently decoded MB. Then,
1186  * we wait for the next loop filter iteration to do H loop filter on all
1187  * applicable vertical borders of this MB. Therefore, the loop filter
1188  * trails by one row and one column relative to the decoding loop. */
1189  if (!s->first_slice_line) {
1190  dest = s->dest[0] - 16 * s->linesize;
1191  cbp = &v->cbp[s->mb_x - s->mb_stride];
1192  ttblk = &v->ttblk[s->mb_x - s->mb_stride];
1193  flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
1194  for (i = 0; i < block_count; i++)
1195  vc1_b_v_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, cbp, ttblk, flags, i);
1196  }
1197  if (s->mb_y == s->end_mb_y - 1) {
1198  dest = s->dest[0];
1199  cbp = &v->cbp[s->mb_x];
1200  ttblk = &v->ttblk[s->mb_x];
1201  flags = s->first_slice_line ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
1202  for (i = 0; i < block_count; i++)
1203  vc1_b_v_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, cbp, ttblk, flags, i);
1204  }
1205 
1206  if (!s->first_slice_line) {
1207  dest = s->dest[0] - 16 * s->linesize - 16;
1208  cbp = &v->cbp[s->mb_x - s->mb_stride - 1];
1209  ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
1210  if (s->mb_x) {
1211  flags = s->mb_x == 1 ? LEFT_EDGE : 0;
1212  for (i = 0; i < block_count; i++)
1213  vc1_b_h_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, cbp, ttblk, flags, i);
1214  }
1215  if (s->mb_x == s->mb_width - 1) {
1216  dest += 16;
1217  cbp++;
1218  ttblk++;
1219  flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
1220  for (i = 0; i < block_count; i++)
1221  vc1_b_h_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, cbp, ttblk, flags, i);
1222  }
1223  }
1224  if (s->mb_y == s->end_mb_y - 1) {
1225  dest = s->dest[0] - 16;
1226  cbp = &v->cbp[s->mb_x - 1];
1227  ttblk = &v->ttblk[s->mb_x - 1];
1228  if (s->mb_x) {
1229  flags = s->mb_x == 1 ? LEFT_EDGE : 0;
1230  for (i = 0; i < block_count; i++)
1231  vc1_b_h_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, cbp, ttblk, flags, i);
1232  }
1233  if (s->mb_x == s->mb_width - 1) {
1234  dest += 16;
1235  cbp++;
1236  ttblk++;
1237  flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
1238  for (i = 0; i < block_count; i++)
1239  vc1_b_h_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, cbp, ttblk, flags, i);
1240  }
1241  }
1242 }
VC1DSPContext::vc1_v_loop_filter16
void(* vc1_v_loop_filter16)(uint8_t *src, ptrdiff_t stride, int pq)
Definition: vc1dsp.h:53
VC1Context
The VC1 Context.
Definition: vc1.h:173
ff_vc1_i_overlap_filter
void ff_vc1_i_overlap_filter(VC1Context *v)
Definition: vc1_loopfilter.c:105
VC1Context::condover
uint8_t condover
Definition: vc1.h:325
VC1Context::left_blk_idx
int left_blk_idx
Definition: vc1.h:388
VC1Context::topleft_blk_idx
int topleft_blk_idx
Definition: vc1.h:388
VC1Context::cbp
uint32_t * cbp
Definition: vc1.h:389
VC1Context::end_mb_x
int end_mb_x
Horizontal macroblock limit (used only by mss2)
Definition: vc1.h:396
vc1dsp.h
vc1.h
ILACE_FRAME
@ ILACE_FRAME
in the bitstream is reported as 10b
Definition: vc1.h:150
mv
static const int8_t mv[256][2]
Definition: 4xm.c:81
vc1_h_overlap_filter
static av_always_inline void vc1_h_overlap_filter(VC1Context *v, int16_t(*left_block)[64], int16_t(*right_block)[64], int left_fieldtx, int right_fieldtx, int block_num)
Definition: vc1_loopfilter.c:34
ff_vc1_i_loop_filter
void ff_vc1_i_loop_filter(VC1Context *v)
Definition: vc1_loopfilter.c:271
mpegvideo.h
VC1Context::luma_mv
int16_t((* luma_mv)[2]
Definition: vc1.h:391
VC1DSPContext::vc1_v_loop_filter4
void(* vc1_v_loop_filter4)(uint8_t *src, ptrdiff_t stride, int pq)
Definition: vc1dsp.h:49
vc1_p_h_loop_filter
static av_always_inline void vc1_p_h_loop_filter(VC1Context *v, uint8_t *dest, uint32_t *cbp, uint8_t *is_intra, int16_t(*mv)[2], uint8_t *mv_f, int *ttblk, uint32_t flags, int block_num)
Definition: vc1_loopfilter.c:363
ILACE_FIELD
@ ILACE_FIELD
in the bitstream is reported as 11b
Definition: vc1.h:151
VC1DSPContext::vc1_h_loop_filter4
void(* vc1_h_loop_filter4)(uint8_t *src, ptrdiff_t stride, int pq)
Definition: vc1dsp.h:50
vc1_i_v_loop_filter
static av_always_inline void vc1_i_v_loop_filter(VC1Context *v, uint8_t *dest, uint32_t flags, uint8_t fieldtx, int block_num)
Definition: vc1_loopfilter.c:238
VC1DSPContext::vc1_h_loop_filter16
void(* vc1_h_loop_filter16)(uint8_t *src, ptrdiff_t stride, int pq)
Definition: vc1dsp.h:54
VC1Context::mb_type
uint8_t * mb_type[3]
Definition: vc1.h:262
s
#define s(width, name)
Definition: cbs_vp9.c:198
RIGHT_EDGE
#define RIGHT_EDGE
Definition: vc1_loopfilter.c:202
VC1Context::mv_f
uint8_t * mv_f[2]
0: MV obtained from same field, 1: opposite field
Definition: vc1.h:348
VC1Context::over_flags_plane
uint8_t * over_flags_plane
Overflags bitplane.
Definition: vc1.h:323
TT_8X4
@ TT_8X4
Definition: vc1.h:115
PROFILE_ADVANCED
@ PROFILE_ADVANCED
Definition: vc1_common.h:52
ff_vc1_p_intfr_loop_filter
void ff_vc1_p_intfr_loop_filter(VC1Context *v)
Definition: vc1_loopfilter.c:911
vc1_p_v_intfr_loop_filter
static av_always_inline void vc1_p_v_intfr_loop_filter(VC1Context *v, uint8_t *dest, const int *ttblk, uint32_t flags, uint8_t fieldtx, int block_num)
Definition: vc1_loopfilter.c:854
VC1Context::pq
uint8_t pq
Definition: vc1.h:236
ff_vc1_b_intfi_loop_filter
void ff_vc1_b_intfi_loop_filter(VC1Context *v)
Definition: vc1_loopfilter.c:1173
VC1Context::block
int16_t(* block)[6][64]
Definition: vc1.h:387
VC1Context::vc1dsp
VC1DSPContext vc1dsp
Definition: vc1.h:177
VC1Context::fieldtx_plane
uint8_t * fieldtx_plane
Definition: vc1.h:344
CONDOVER_ALL
@ CONDOVER_ALL
Definition: vc1.h:138
vc1_p_v_loop_filter
static av_always_inline void vc1_p_v_loop_filter(VC1Context *v, uint8_t *dest, const uint32_t *cbp, const uint8_t *is_intra, int16_t(*mv)[2], const uint8_t *mv_f, const int *ttblk, uint32_t flags, int block_num)
Definition: vc1_loopfilter.c:417
VC1Context::is_intra
uint8_t * is_intra
Definition: vc1.h:390
AV_CODEC_FLAG_GRAY
#define AV_CODEC_FLAG_GRAY
Only decode/encode grayscale.
Definition: avcodec.h:322
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
VC1Context::mb_off
int mb_off
Definition: vc1.h:362
VC1Context::top_blk_idx
int top_blk_idx
Definition: vc1.h:388
vc1_v_overlap_filter
static av_always_inline void vc1_v_overlap_filter(VC1Context *v, int16_t(*top_block)[64], int16_t(*bottom_block)[64], int block_num)
Definition: vc1_loopfilter.c:78
LEFT_EDGE
#define LEFT_EDGE
Definition: vc1_loopfilter.c:201
vc1_i_h_loop_filter
static av_always_inline void vc1_i_h_loop_filter(VC1Context *v, uint8_t *dest, uint32_t flags, int block_num)
Definition: vc1_loopfilter.c:206
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
vc1_p_h_intfr_loop_filter
static av_always_inline void vc1_p_h_intfr_loop_filter(VC1Context *v, uint8_t *dest, const int *ttblk, uint32_t flags, uint8_t fieldtx, int block_num)
Definition: vc1_loopfilter.c:803
TOP_EDGE
#define TOP_EDGE
Definition: vc1_loopfilter.c:203
xf
#define xf(width, name, var, range_min, range_max, subs,...)
Definition: cbs_av1.c:598
av_always_inline
#define av_always_inline
Definition: attributes.h:49
vc1_b_h_intfi_loop_filter
static av_always_inline void vc1_b_h_intfi_loop_filter(VC1Context *v, uint8_t *dest, const uint32_t *cbp, const int *ttblk, uint32_t flags, int block_num)
Definition: vc1_loopfilter.c:1115
VC1Context::s
MpegEncContext s
Definition: vc1.h:174
VC1Context::ttblk
int * ttblk
Transform type at the block level.
Definition: vc1.h:257
avcodec.h
VC1DSPContext::vc1_h_loop_filter8
void(* vc1_h_loop_filter8)(uint8_t *src, ptrdiff_t stride, int pq)
Definition: vc1dsp.h:52
BOTTOM_EDGE
#define BOTTOM_EDGE
Definition: vc1_loopfilter.c:204
VC1DSPContext::vc1_v_loop_filter8
void(* vc1_v_loop_filter8)(uint8_t *src, ptrdiff_t stride, int pq)
Definition: vc1dsp.h:51
VC1Context::profile
int profile
Sequence header data for all Profiles TODO: choose between ints, uint8_ts and monobit flags.
Definition: vc1.h:216
TT_4X8
@ TT_4X8
Definition: vc1.h:118
VC1Context::fcm
enum FrameCodingMode fcm
Frame decoding info for Advanced profile.
Definition: vc1.h:308
ff_vc1_p_loop_filter
void ff_vc1_p_loop_filter(VC1Context *v)
Definition: vc1_loopfilter.c:471
VC1Context::cur_blk_idx
int cur_blk_idx
Definition: vc1.h:388
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
vc1_b_v_intfi_loop_filter
static av_always_inline void vc1_b_v_intfi_loop_filter(VC1Context *v, uint8_t *dest, const uint32_t *cbp, const int *ttblk, uint32_t flags, int block_num)
Definition: vc1_loopfilter.c:1145
VC1Context::blocks_off
int blocks_off
Definition: vc1.h:362
TT_4X4
@ TT_4X4
Definition: vc1.h:119
MpegEncContext
MpegEncContext.
Definition: mpegvideo.h:73
VC1DSPContext::vc1_v_s_overlap
void(* vc1_v_s_overlap)(int16_t *top, int16_t *bottom)
Definition: vc1dsp.h:47
VC1DSPContext::vc1_h_s_overlap
void(* vc1_h_s_overlap)(int16_t *left, int16_t *right, ptrdiff_t left_stride, ptrdiff_t right_stride, int flags)
Definition: vc1dsp.h:48
ff_vc1_p_overlap_filter
void ff_vc1_p_overlap_filter(VC1Context *v)
Definition: vc1_loopfilter.c:161