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
7 * This file is part of FFmpeg.
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.
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.
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
26 * VC-1 and WMV3 loopfilter
30 #include "mpegvideo.h"
34 void ff_vc1_loop_filter_iblk(VC1Context *v, int pq)
36 MpegEncContext *s = &v->s;
38 if (!s->first_slice_line) {
39 v->vc1dsp.vc1_v_loop_filter16(s->dest[0], s->linesize, pq);
41 v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize, s->linesize, pq);
42 v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize + 8, s->linesize, pq);
43 if (!CONFIG_GRAY || !(s->avctx->flags & AV_CODEC_FLAG_GRAY))
44 for (j = 0; j < 2; j++) {
45 v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1], s->uvlinesize, pq);
47 v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq);
50 v->vc1dsp.vc1_v_loop_filter16(s->dest[0] + 8 * s->linesize, s->linesize, pq);
52 if (s->mb_y == s->end_mb_y - 1) {
54 v->vc1dsp.vc1_h_loop_filter16(s->dest[0], s->linesize, pq);
55 if (!CONFIG_GRAY || !(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
56 v->vc1dsp.vc1_h_loop_filter8(s->dest[1], s->uvlinesize, pq);
57 v->vc1dsp.vc1_h_loop_filter8(s->dest[2], s->uvlinesize, pq);
60 v->vc1dsp.vc1_h_loop_filter16(s->dest[0] + 8, s->linesize, pq);
64 static av_always_inline void vc1_h_overlap_filter(VC1Context *v, int16_t (*left_block)[64],
65 int16_t (*right_block)[64], int block_num)
67 if (left_block != right_block || (block_num & 5) == 1) {
69 v->vc1dsp.vc1_h_s_overlap(left_block[block_num], right_block[block_num]);
70 else if (block_num & 1)
71 v->vc1dsp.vc1_h_s_overlap(right_block[block_num - 1], right_block[block_num]);
73 v->vc1dsp.vc1_h_s_overlap(left_block[block_num + 1], right_block[block_num]);
77 static av_always_inline void vc1_v_overlap_filter(VC1Context *v, int16_t (*top_block)[64],
78 int16_t (*bottom_block)[64], int block_num)
80 if (top_block != bottom_block || block_num & 2) {
82 v->vc1dsp.vc1_v_s_overlap(top_block[block_num], bottom_block[block_num]);
83 else if (block_num & 2)
84 v->vc1dsp.vc1_v_s_overlap(bottom_block[block_num - 2], bottom_block[block_num]);
86 v->vc1dsp.vc1_v_s_overlap(top_block[block_num + 2], bottom_block[block_num]);
90 void ff_vc1_i_overlap_filter(VC1Context *v)
92 MpegEncContext *s = &v->s;
93 int16_t (*topleft_blk)[64], (*top_blk)[64], (*left_blk)[64], (*cur_blk)[64];
94 int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
95 int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
98 topleft_blk = v->block[v->topleft_blk_idx];
99 top_blk = v->block[v->top_blk_idx];
100 left_blk = v->block[v->left_blk_idx];
101 cur_blk = v->block[v->cur_blk_idx];
103 /* Within a MB, the horizontal overlap always runs before the vertical.
104 * To accomplish that, we run the H on the left and internal vertical
105 * borders of the currently decoded MB. Then, we wait for the next overlap
106 * iteration to do H overlap on the right edge of this MB, before moving
107 * over and running the V overlap on the top and internal horizontal
108 * borders. Therefore, the H overlap trails by one MB col and the
109 * V overlap trails by one MB row. This is reflected in the time at which
110 * we run the put_pixels loop, i.e. delayed by one row and one column. */
111 for (i = 0; i < block_count; i++)
112 if (v->pq >= 9 || v->condover == CONDOVER_ALL ||
113 (v->over_flags_plane[mb_pos] && ((i & 5) == 1 || (s->mb_x && v->over_flags_plane[mb_pos - 1]))))
114 vc1_h_overlap_filter(v, s->mb_x ? left_blk : cur_blk, cur_blk, i);
116 if (v->fcm != ILACE_FRAME)
117 for (i = 0; i < block_count; i++) {
118 if (s->mb_x && (v->pq >= 9 || v->condover == CONDOVER_ALL ||
119 (v->over_flags_plane[mb_pos - 1] &&
120 ((i & 2) || (!s->first_slice_line && v->over_flags_plane[mb_pos - 1 - s->mb_stride])))))
121 vc1_v_overlap_filter(v, s->first_slice_line ? left_blk : topleft_blk, left_blk, i);
122 if (s->mb_x == s->mb_width - 1)
123 if (v->pq >= 9 || v->condover == CONDOVER_ALL ||
124 (v->over_flags_plane[mb_pos] &&
125 ((i & 2) || (!s->first_slice_line && v->over_flags_plane[mb_pos - s->mb_stride]))))
126 vc1_v_overlap_filter(v, s->first_slice_line ? cur_blk : top_blk, cur_blk, i);
130 void ff_vc1_p_overlap_filter(VC1Context *v)
132 MpegEncContext *s = &v->s;
133 int16_t (*topleft_blk)[64], (*top_blk)[64], (*left_blk)[64], (*cur_blk)[64];
134 int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
137 topleft_blk = v->block[v->topleft_blk_idx];
138 top_blk = v->block[v->top_blk_idx];
139 left_blk = v->block[v->left_blk_idx];
140 cur_blk = v->block[v->cur_blk_idx];
142 for (i = 0; i < block_count; i++)
143 if (v->mb_type[0][s->block_index[i]] && (s->mb_x == 0 || v->mb_type[0][s->block_index[i] - 1]))
144 vc1_h_overlap_filter(v, s->mb_x ? left_blk : cur_blk, cur_blk, i);
146 if (v->fcm != ILACE_FRAME)
147 for (i = 0; i < block_count; i++) {
148 if (s->mb_x && v->mb_type[0][s->block_index[i] - 1] &&
149 (s->first_slice_line || v->mb_type[0][s->block_index[i] - s->block_wrap[i] - 1]))
150 vc1_v_overlap_filter(v, s->first_slice_line ? left_blk : topleft_blk, left_blk, i);
151 if (s->mb_x == s->mb_width - 1)
152 if (v->mb_type[0][s->block_index[i]] &&
153 (s->first_slice_line || v->mb_type[0][s->block_index[i] - s->block_wrap[i]]))
154 vc1_v_overlap_filter(v, s->first_slice_line ? cur_blk : top_blk, cur_blk, i);
158 #define LEFT_EDGE (1 << 0)
159 #define RIGHT_EDGE (1 << 1)
160 #define TOP_EDGE (1 << 2)
161 #define BOTTOM_EDGE (1 << 3)
163 static av_always_inline void vc1_i_h_loop_filter(VC1Context *v, uint8_t *dest,
164 uint32_t flags, int block_num)
166 MpegEncContext *s = &v->s;
173 if (!(flags & LEFT_EDGE) || (block_num & 5) == 1) {
177 dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
179 if (v->fcm == ILACE_FRAME)
181 v->vc1dsp.vc1_h_loop_filter4(dst, 2 * s->uvlinesize, pq);
182 v->vc1dsp.vc1_h_loop_filter4(dst + s->uvlinesize, 2 * s->uvlinesize, pq);
184 v->vc1dsp.vc1_h_loop_filter8(dst, 2 * s->linesize, pq);
185 v->vc1dsp.vc1_h_loop_filter8(dst + s->linesize, 2 * s->linesize, pq);
189 v->vc1dsp.vc1_h_loop_filter8(dst, s->uvlinesize, pq);
191 v->vc1dsp.vc1_h_loop_filter16(dst, s->linesize, pq);
195 static av_always_inline void vc1_i_v_loop_filter(VC1Context *v, uint8_t *dest,
196 uint32_t flags, uint8_t fieldtx,
199 MpegEncContext *s = &v->s;
203 if ((block_num & 5) == 1)
206 if (!(flags & TOP_EDGE) || block_num & 2) {
210 dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
212 if (v->fcm == ILACE_FRAME) {
214 v->vc1dsp.vc1_v_loop_filter8(dst, 2 * s->uvlinesize, pq);
215 v->vc1dsp.vc1_v_loop_filter8(dst + s->uvlinesize, 2 * s->uvlinesize, pq);
216 } else if (block_num < 2 || !fieldtx) {
217 v->vc1dsp.vc1_v_loop_filter16(dst, 2 * s->linesize, pq);
218 v->vc1dsp.vc1_v_loop_filter16(dst + s->linesize, 2 * s->linesize, pq);
222 v->vc1dsp.vc1_v_loop_filter8(dst, s->uvlinesize, pq);
224 v->vc1dsp.vc1_v_loop_filter16(dst, s->linesize, pq);
228 void ff_vc1_i_loop_filter(VC1Context *v)
230 MpegEncContext *s = &v->s;
231 int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
232 int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
233 uint8_t *dest, fieldtx;
237 /* Within a MB, the vertical loop filter always runs before the horizontal.
238 * To accomplish that, we run the V loop filter on top and internal
239 * horizontal borders of the last overlap filtered MB. Then, we wait for
240 * the loop filter iteration on the next row to do V loop filter on the
241 * bottom edge of this MB, before moving over and running the H loop
242 * filter on the left and internal vertical borders. Therefore, the loop
243 * filter trails by one row and one column relative to the overlap filter
244 * and two rows and two colums relative to the decoding loop. */
245 if (!s->first_slice_line) {
246 dest = s->dest[0] - 16 * s->linesize - 16;
247 flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
249 fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride - 1];
250 for (i = 0; i < block_count; i++)
251 vc1_i_v_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, flags, fieldtx, i);
253 if (s->mb_x == s->mb_width - 1) {
255 fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride];
256 for (i = 0; i < block_count; i++)
257 vc1_i_v_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, flags, fieldtx, i);
260 if (s->mb_y == s->end_mb_y - 1) {
261 dest = s->dest[0] - 16;
262 flags = s->first_slice_line ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
264 fieldtx = v->fieldtx_plane[mb_pos - 1];
265 for (i = 0; i < block_count; i++)
266 vc1_i_v_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, flags, fieldtx, i);
268 if (s->mb_x == s->mb_width - 1) {
270 fieldtx = v->fieldtx_plane[mb_pos];
271 for (i = 0; i < block_count; i++)
272 vc1_i_v_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, flags, fieldtx, i);
276 if (s->mb_y >= s->start_mb_y + 2) {
277 dest = s->dest[0] - 32 * s->linesize - 16;
279 flags = s->mb_x == 1 ? LEFT_EDGE : 0;
280 for (i = 0; i < block_count; i++)
281 vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 8 : dest, flags, i);
283 if (s->mb_x == s->mb_width - 1) {
285 flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
286 for (i = 0; i < block_count; i++)
287 vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize : dest, flags, i);
290 if (s->mb_y == s->end_mb_y - 1) {
291 if (s->mb_y >= s->start_mb_y + 1) {
292 dest = s->dest[0] - 16 * s->linesize - 16;
294 flags = s->mb_x == 1 ? LEFT_EDGE : 0;
295 for (i = 0; i < block_count; i++)
296 vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, flags, i);
298 if (s->mb_x == s->mb_width - 1) {
299 flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
301 for (i = 0; i < block_count; i++)
302 vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, flags, i);
305 dest = s->dest[0] - 16;
307 flags = s->mb_x == 1 ? LEFT_EDGE : 0;
308 for (i = 0; i < block_count; i++)
309 vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, flags, i);
311 if (s->mb_x == s->mb_width - 1) {
313 flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
314 for (i = 0; i < block_count; i++)
315 vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, flags, i);
320 static av_always_inline void vc1_p_h_loop_filter(VC1Context *v, uint8_t *dest, uint32_t *cbp,
321 uint8_t *is_intra, int16_t (*mv)[2], uint8_t *mv_f,
322 int *ttblk, uint32_t flags, int block_num)
324 MpegEncContext *s = &v->s;
326 uint32_t left_cbp = cbp[0] >> (block_num * 4), right_cbp;
327 uint8_t left_is_intra, right_is_intra;
329 int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize;
335 dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
337 if (!(flags & RIGHT_EDGE) || !(block_num & 5)) {
338 left_is_intra = is_intra[0] & (1 << block_num);
341 right_is_intra = is_intra[1] & (1 << block_num);
342 right_cbp = cbp[1] >> (block_num * 4);
343 } else if (block_num & 1) {
344 right_is_intra = is_intra[1] & (1 << block_num - 1);
345 right_cbp = cbp[1] >> ((block_num - 1) * 4);
347 right_is_intra = is_intra[0] & (1 << block_num + 1);
348 right_cbp = cbp[0] >> ((block_num + 1) * 4);
351 if (left_is_intra || right_is_intra ||
352 mv[0][0] != mv[1][0] || mv[0][1] != mv[1][1] ||
353 (v->fcm == ILACE_FIELD && mv_f[0] != mv_f[1]))
354 v->vc1dsp.vc1_h_loop_filter8(dst + 8, linesize, pq);
356 idx = (left_cbp | (right_cbp >> 1)) & 5;
358 v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize + 8, linesize, pq);
360 v->vc1dsp.vc1_h_loop_filter4(dst + 8, linesize, pq);
364 tt = ttblk[0] >> (block_num * 4) & 0xf;
365 if (tt == TT_4X4 || tt == TT_4X8) {
367 v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
369 v->vc1dsp.vc1_h_loop_filter4(dst + 4, linesize, pq);
373 static av_always_inline void vc1_p_v_loop_filter(VC1Context *v, uint8_t *dest, uint32_t *cbp,
374 uint8_t *is_intra, int16_t (*mv)[2], uint8_t *mv_f,
375 int *ttblk, uint32_t flags, int block_num)
377 MpegEncContext *s = &v->s;
379 uint32_t top_cbp = cbp[0] >> (block_num * 4), bottom_cbp;
380 uint8_t top_is_intra, bottom_is_intra;
382 int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize;
388 dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
390 if(!(flags & BOTTOM_EDGE) || block_num < 2) {
391 top_is_intra = is_intra[0] & (1 << block_num);
394 bottom_is_intra = is_intra[s->mb_stride] & (1 << block_num);
395 bottom_cbp = cbp[s->mb_stride] >> (block_num * 4);
396 } else if (block_num < 2) {
397 bottom_is_intra = is_intra[0] & (1 << block_num + 2);
398 bottom_cbp = cbp[0] >> ((block_num + 2) * 4);
400 bottom_is_intra = is_intra[s->mb_stride] & (1 << block_num - 2);
401 bottom_cbp = cbp[s->mb_stride] >> ((block_num - 2) * 4);
404 if (top_is_intra || bottom_is_intra ||
405 mv[0][0] != mv[block_num > 3 ? s->mb_stride : s->b8_stride][0] ||
406 mv[0][1] != mv[block_num > 3 ? s->mb_stride : s->b8_stride][1] ||
407 (v->fcm == ILACE_FIELD && mv_f[0] != mv_f[block_num > 3 ? s->mb_stride : s->b8_stride]))
408 v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, linesize, pq);
410 idx = (top_cbp | (bottom_cbp >> 2)) & 3;
412 v->vc1dsp.vc1_v_loop_filter4(dst + 8 * linesize + 4, linesize, pq);
414 v->vc1dsp.vc1_v_loop_filter4(dst + 8 * linesize, linesize, pq);
418 tt = ttblk[0] >> (block_num * 4) & 0xf;
419 if (tt == TT_4X4 || tt == TT_8X4) {
421 v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
423 v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize, linesize, pq);
427 void ff_vc1_p_loop_filter(VC1Context *v)
429 MpegEncContext *s = &v->s;
430 int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
439 /* Within a MB, the vertical loop filter always runs before the horizontal.
440 * To accomplish that, we run the V loop filter on all applicable
441 * horizontal borders of the MB above the last overlap filtered MB. Then,
442 * we wait for the next loop filter iteration to do H loop filter on all
443 * applicable vertical borders of this MB. Therefore, the loop filter
444 * trails by one row and one column relative to the overlap filter and two
445 * rows and two colums relative to the decoding loop. */
446 if (s->mb_y >= s->start_mb_y + 2) {
448 dest = s->dest[0] - 32 * s->linesize - 16;
449 cbp = &v->cbp[s->mb_x - 2 * s->mb_stride - 1];
450 is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride - 1];
451 uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride - 1];
452 ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 1];
453 flags = s->mb_y == s->start_mb_y + 2 ? TOP_EDGE : 0;
454 for (i = 0; i < block_count; i++)
455 vc1_p_v_loop_filter(v,
456 i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 8 : dest,
460 &s->current_picture.motion_val[0][s->block_index[i] - 4 * s->b8_stride - 2 + v->blocks_off],
461 i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride - 1 + v->mb_off] :
462 &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride - 2 + v->blocks_off],
467 if (s->mb_x == s->mb_width - 1) {
468 dest = s->dest[0] - 32 * s->linesize;
469 cbp = &v->cbp[s->mb_x - 2 * s->mb_stride];
470 is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride];
471 uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride];
472 ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride];
473 flags = s->mb_y == s->start_mb_y + 2 ? TOP_EDGE : 0;
474 for (i = 0; i < block_count; i++)
475 vc1_p_v_loop_filter(v,
476 i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize : dest,
480 &s->current_picture.motion_val[0][s->block_index[i] - 4 * s->b8_stride + v->blocks_off],
481 i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride + v->mb_off] :
482 &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride + v->blocks_off],
488 if (s->mb_y == s->end_mb_y - 1) {
490 if (s->mb_y >= s->start_mb_y + 1) {
491 dest = s->dest[0] - 16 * s->linesize - 16;
492 cbp = &v->cbp[s->mb_x - s->mb_stride - 1];
493 is_intra = &v->is_intra[s->mb_x - s->mb_stride - 1];
494 uvmv = &v->luma_mv[s->mb_x - s->mb_stride - 1];
495 ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
496 flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
497 for (i = 0; i < block_count; i++)
498 vc1_p_v_loop_filter(v,
499 i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest,
503 &s->current_picture.motion_val[0][s->block_index[i] - 2 * s->b8_stride - 2 + v->blocks_off],
504 i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride - 1 + v->mb_off] :
505 &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride - 2 + v->blocks_off],
510 dest = s->dest[0] - 16;
511 cbp = &v->cbp[s->mb_x - 1];
512 is_intra = &v->is_intra[s->mb_x - 1];
513 uvmv = &v->luma_mv[s->mb_x - 1];
514 ttblk = &v->ttblk[s->mb_x - 1];
515 flags = s->mb_y == s->start_mb_y ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
516 for (i = 0; i < block_count; i++)
517 vc1_p_v_loop_filter(v,
518 i > 3 ? s->dest[i - 3] - 8 : dest,
522 &s->current_picture.motion_val[0][s->block_index[i] - 2 + v->blocks_off],
523 i > 3 ? &v->mv_f[0][s->block_index[i] - 1 + v->mb_off] :
524 &v->mv_f[0][s->block_index[i] - 2 + v->blocks_off],
529 if (s->mb_x == s->mb_width - 1) {
530 if (s->mb_y >= s->start_mb_y + 1) {
531 dest = s->dest[0] - 16 * s->linesize;
532 cbp = &v->cbp[s->mb_x - s->mb_stride];
533 is_intra = &v->is_intra[s->mb_x - s->mb_stride];
534 uvmv = &v->luma_mv[s->mb_x - s->mb_stride];
535 ttblk = &v->ttblk[s->mb_x - s->mb_stride];
536 flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
537 for (i = 0; i < block_count; i++)
538 vc1_p_v_loop_filter(v,
539 i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest,
543 &s->current_picture.motion_val[0][s->block_index[i] - 2 * s->b8_stride + v->blocks_off],
544 i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride + v->mb_off] :
545 &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride + v->blocks_off],
551 cbp = &v->cbp[s->mb_x];
552 is_intra = &v->is_intra[s->mb_x];
553 uvmv = &v->luma_mv[s->mb_x];
554 ttblk = &v->ttblk[s->mb_x];
555 flags = s->mb_y == s->start_mb_y ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
556 for (i = 0; i < block_count; i++)
557 vc1_p_v_loop_filter(v,
558 i > 3 ? s->dest[i - 3] : dest,
562 &s->current_picture.motion_val[0][s->block_index[i] + v->blocks_off],
563 i > 3 ? &v->mv_f[0][s->block_index[i] + v->mb_off] :
564 &v->mv_f[0][s->block_index[i] + v->blocks_off],
571 if (s->mb_y >= s->start_mb_y + 2) {
573 dest = s->dest[0] - 32 * s->linesize - 32;
574 cbp = &v->cbp[s->mb_x - 2 * s->mb_stride - 2];
575 is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride - 2];
576 uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride - 2];
577 ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 2];
578 flags = s->mb_x == 2 ? LEFT_EDGE : 0;
579 for (i = 0; i < block_count; i++)
580 vc1_p_h_loop_filter(v,
581 i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 16 : dest,
585 &s->current_picture.motion_val[0][s->block_index[i] - 4 * s->b8_stride - 4 + v->blocks_off],
586 i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride - 2 + v->mb_off] :
587 &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride - 4 + v->blocks_off],
592 if (s->mb_x == s->mb_width - 1) {
594 dest = s->dest[0] - 32 * s->linesize - 16;
595 cbp = &v->cbp[s->mb_x - 2 * s->mb_stride - 1];
596 is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride - 1];
597 uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride - 1];
598 ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 1];
599 flags = s->mb_x == 1 ? LEFT_EDGE : 0;
600 for (i = 0; i < block_count; i++)
601 vc1_p_h_loop_filter(v,
602 i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 8 : dest,
606 &s->current_picture.motion_val[0][s->block_index[i] - 4 * s->b8_stride - 2 + v->blocks_off],
607 i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride - 1 + v->mb_off] :
608 &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride - 2 + v->blocks_off],
613 dest = s->dest[0] - 32 * s->linesize;
614 cbp = &v->cbp[s->mb_x - 2 * s->mb_stride];
615 is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride];
616 uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride];
617 ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride];
618 flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
619 for (i = 0; i < block_count; i++)
620 vc1_p_h_loop_filter(v,
621 i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize : dest,
625 &s->current_picture.motion_val[0][s->block_index[i] - 4 * s->b8_stride + v->blocks_off],
626 i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride + v->mb_off] :
627 &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride + v->blocks_off],
633 if (s->mb_y == s->end_mb_y - 1) {
634 if (s->mb_y >= s->start_mb_y + 1) {
636 dest = s->dest[0] - 16 * s->linesize - 32;
637 cbp = &v->cbp[s->mb_x - s->mb_stride - 2];
638 is_intra = &v->is_intra[s->mb_x - s->mb_stride - 2];
639 uvmv = &v->luma_mv[s->mb_x - s->mb_stride - 2];
640 ttblk = &v->ttblk[s->mb_x - s->mb_stride - 2];
641 flags = s->mb_x == 2 ? LEFT_EDGE : 0;
642 for (i = 0; i < block_count; i++)
643 vc1_p_h_loop_filter(v,
644 i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 16 : dest,
648 &s->current_picture.motion_val[0][s->block_index[i] - 2 * s->b8_stride - 4 + v->blocks_off],
649 i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride - 2 + v->mb_off] :
650 &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride - 4 + v->blocks_off],
655 if (s->mb_x == s->mb_width - 1) {
657 dest = s->dest[0] - 16 * s->linesize - 16;
658 cbp = &v->cbp[s->mb_x - s->mb_stride - 1];
659 is_intra = &v->is_intra[s->mb_x - s->mb_stride - 1];
660 uvmv = &v->luma_mv[s->mb_x - s->mb_stride - 1];
661 ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
662 flags = s->mb_x == 1 ? LEFT_EDGE : 0;
663 for (i = 0; i < block_count; i++)
664 vc1_p_h_loop_filter(v,
665 i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest,
669 &s->current_picture.motion_val[0][s->block_index[i] - 2 * s->b8_stride - 2 + v->blocks_off],
670 i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride - 1 + v->mb_off] :
671 &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride - 2 + v->blocks_off],
676 dest = s->dest[0] - 16 * s->linesize;
677 cbp = &v->cbp[s->mb_x - s->mb_stride];
678 is_intra = &v->is_intra[s->mb_x - s->mb_stride];
679 uvmv = &v->luma_mv[s->mb_x - s->mb_stride];
680 ttblk = &v->ttblk[s->mb_x - s->mb_stride];
681 flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
682 for (i = 0; i < block_count; i++)
683 vc1_p_h_loop_filter(v,
684 i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest,
688 &s->current_picture.motion_val[0][s->block_index[i] - 2 * s->b8_stride + v->blocks_off],
689 i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride + v->mb_off] :
690 &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride + v->blocks_off],
697 dest = s->dest[0] - 32;
698 cbp = &v->cbp[s->mb_x - 2];
699 is_intra = &v->is_intra[s->mb_x - 2];
700 uvmv = &v->luma_mv[s->mb_x - 2];
701 ttblk = &v->ttblk[s->mb_x - 2];
702 flags = s->mb_x == 2 ? LEFT_EDGE : 0;
703 for (i = 0; i < block_count; i++)
704 vc1_p_h_loop_filter(v,
705 i > 3 ? s->dest[i - 3] - 16 : dest,
709 &s->current_picture.motion_val[0][s->block_index[i] - 4 + v->blocks_off],
710 i > 3 ? &v->mv_f[0][s->block_index[i] - 2 + v->mb_off] :
711 &v->mv_f[0][s->block_index[i] - 4 + v->blocks_off],
716 if (s->mb_x == s->mb_width - 1) {
718 dest = s->dest[0] - 16;
719 cbp = &v->cbp[s->mb_x - 1];
720 is_intra = &v->is_intra[s->mb_x - 1];
721 uvmv = &v->luma_mv[s->mb_x - 1];
722 ttblk = &v->ttblk[s->mb_x - 1];
723 flags = s->mb_x == 1 ? LEFT_EDGE : 0;
724 for (i = 0; i < block_count; i++)
725 vc1_p_h_loop_filter(v,
726 i > 3 ? s->dest[i - 3] - 8 : dest,
730 &s->current_picture.motion_val[0][s->block_index[i] - 2 + v->blocks_off],
731 i > 3 ? &v->mv_f[0][s->block_index[i] - 1 + v->mb_off] :
732 &v->mv_f[0][s->block_index[i] - 2 + v->blocks_off],
738 cbp = &v->cbp[s->mb_x];
739 is_intra = &v->is_intra[s->mb_x];
740 uvmv = &v->luma_mv[s->mb_x];
741 ttblk = &v->ttblk[s->mb_x];
742 flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
743 for (i = 0; i < block_count; i++)
744 vc1_p_h_loop_filter(v,
745 i > 3 ? s->dest[i - 3] : dest,
749 &s->current_picture.motion_val[0][s->block_index[i] + v->blocks_off],
750 i > 3 ? &v->mv_f[0][s->block_index[i] + v->mb_off] :
751 &v->mv_f[0][s->block_index[i] + v->blocks_off],
759 static av_always_inline void vc1_p_h_intfr_loop_filter(VC1Context *v, uint8_t *dest, int *ttblk,
760 uint32_t flags, uint8_t fieldtx, int block_num)
762 MpegEncContext *s = &v->s;
765 int linesize = block_num > 3 ? s->uvlinesize : s->linesize;
771 dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
773 tt = ttblk[0] >> (block_num * 4) & 0xf;
777 if (tt == TT_4X4 || tt == TT_4X8)
778 v->vc1dsp.vc1_h_loop_filter8(dst + 4, 2 * linesize, pq);
779 if (!(flags & RIGHT_EDGE) || block_num == 0)
780 v->vc1dsp.vc1_h_loop_filter8(dst + 8, 2 * linesize, pq);
782 if (tt == TT_4X4 || tt == TT_4X8)
783 v->vc1dsp.vc1_h_loop_filter8(dst - 7 * linesize + 4, 2 * linesize, pq);
784 if (!(flags & RIGHT_EDGE) || block_num == 2)
785 v->vc1dsp.vc1_h_loop_filter8(dst - 7 * linesize + 8, 2 * linesize, pq);
788 if(tt == TT_4X4 || tt == TT_4X8) {
789 v->vc1dsp.vc1_h_loop_filter4(dst + 4, 2 * linesize, pq);
790 v->vc1dsp.vc1_h_loop_filter4(dst + linesize + 4, 2 * linesize, pq);
792 if (!(flags & RIGHT_EDGE) || !(block_num & 5)) {
793 v->vc1dsp.vc1_h_loop_filter4(dst + 8, 2 * linesize, pq);
794 v->vc1dsp.vc1_h_loop_filter4(dst + linesize + 8, 2 * linesize, pq);
798 if (tt == TT_4X4 || tt == TT_4X8) {
799 v->vc1dsp.vc1_h_loop_filter4(dst + 4, 2 * linesize, pq);
800 v->vc1dsp.vc1_h_loop_filter4(dst + linesize + 4, 2 * linesize, pq);
802 if (!(flags & RIGHT_EDGE)) {
803 v->vc1dsp.vc1_h_loop_filter4(dst + 8, 2 * linesize, pq);
804 v->vc1dsp.vc1_h_loop_filter4(dst + linesize + 8, 2 * linesize, pq);
809 static av_always_inline void vc1_p_v_intfr_loop_filter(VC1Context *v, uint8_t *dest, int *ttblk,
810 uint32_t flags, uint8_t fieldtx, int block_num)
812 MpegEncContext *s = &v->s;
815 int linesize = block_num > 3 ? s->uvlinesize : s->linesize;
821 dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
823 tt = ttblk[0] >> (block_num * 4) & 0xf;
827 if (tt == TT_4X4 || tt == TT_8X4)
828 v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, 2 * linesize, pq);
829 if (!(flags & BOTTOM_EDGE))
830 v->vc1dsp.vc1_v_loop_filter8(dst + 16 * linesize, 2 * linesize, pq);
832 if (tt == TT_4X4 || tt == TT_8X4)
833 v->vc1dsp.vc1_v_loop_filter8(dst + linesize, 2 * linesize, pq);
834 if (!(flags & BOTTOM_EDGE))
835 v->vc1dsp.vc1_v_loop_filter8(dst + 9 * linesize, 2 * linesize, pq);
839 if (!(flags & TOP_EDGE) && (tt == TT_4X4 || tt == TT_8X4)) {
840 v->vc1dsp.vc1_v_loop_filter8(dst + 4 * linesize, 2 * linesize, pq);
841 v->vc1dsp.vc1_v_loop_filter8(dst + 5 * linesize, 2 * linesize, pq);
843 v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, 2 * linesize, pq);
844 v->vc1dsp.vc1_v_loop_filter8(dst + 9 * linesize, 2 * linesize, pq);
845 } else if (!(flags & BOTTOM_EDGE)) {
846 if (tt == TT_4X4 || tt == TT_8X4) {
847 v->vc1dsp.vc1_v_loop_filter8(dst + 4 * linesize, 2 * linesize, pq);
848 v->vc1dsp.vc1_v_loop_filter8(dst + 5 * linesize, 2 * linesize, pq);
850 v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, 2 * linesize, pq);
851 v->vc1dsp.vc1_v_loop_filter8(dst + 9 * linesize, 2 * linesize, pq);
855 if (!(flags & BOTTOM_EDGE)) {
856 if (!(flags & TOP_EDGE) && (tt == TT_4X4 || tt == TT_8X4)) {
857 v->vc1dsp.vc1_v_loop_filter8(dst + 4 * linesize, 2 * linesize, pq);
858 v->vc1dsp.vc1_v_loop_filter8(dst + 5 * linesize, 2 * linesize, pq);
860 v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, 2 * linesize, pq);
861 v->vc1dsp.vc1_v_loop_filter8(dst + 9 * linesize, 2 * linesize, pq);
866 void ff_vc1_p_intfr_loop_filter(VC1Context *v)
868 MpegEncContext *s = &v->s;
869 int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
870 int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
877 /* Within a MB, the vertical loop filter always runs before the horizontal.
878 * To accomplish that, we run the V loop filter on all applicable
879 * horizontal borders of the MB above the last overlap filtered MB. Then,
880 * we wait for the loop filter iteration on the next row and next column to
881 * do H loop filter on all applicable vertical borders of this MB.
882 * Therefore, the loop filter trails by two rows and one column relative to
883 * the overlap filter and two rows and two colums relative to the decoding
886 if (s->mb_y >= s->start_mb_y + 1) {
887 dest = s->dest[0] - 16 * s->linesize - 16;
888 ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
889 flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
890 fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride - 1];
891 for (i = 0; i < block_count; i++)
892 vc1_p_v_intfr_loop_filter(v,
893 i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest,
900 if (s->mb_x == s->mb_width - 1) {
901 if (s->mb_y >= s->start_mb_y + 1) {
902 dest = s->dest[0] - 16 * s->linesize;
903 ttblk = &v->ttblk[s->mb_x - s->mb_stride];
904 flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
905 fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride];
906 for (i = 0; i < block_count; i++)
907 vc1_p_v_intfr_loop_filter(v,
908 i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest,
915 if (s->mb_y == s->end_mb_y - 1) {
917 dest = s->dest[0] - 16;
918 ttblk = &v->ttblk[s->mb_x - 1];
919 flags = s->mb_y == s->start_mb_y ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
920 fieldtx = v->fieldtx_plane[mb_pos - 1];
921 for (i = 0; i < block_count; i++)
922 vc1_p_v_intfr_loop_filter(v,
923 i > 3 ? s->dest[i - 3] - 8 : dest,
929 if (s->mb_x == s->mb_width - 1) {
931 ttblk = &v->ttblk[s->mb_x];
932 flags = s->mb_y == s->start_mb_y ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
933 fieldtx = v->fieldtx_plane[mb_pos];
934 for (i = 0; i < block_count; i++)
935 vc1_p_v_intfr_loop_filter(v,
936 i > 3 ? s->dest[i - 3] : dest,
944 if (s->mb_y >= s->start_mb_y + 2) {
946 dest = s->dest[0] - 32 * s->linesize - 32;
947 ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 2];
948 flags = s->mb_x == 2 ? LEFT_EDGE : 0;
949 fieldtx = v->fieldtx_plane[mb_pos - 2 * s->mb_stride - 2];
950 for (i = 0; i < block_count; i++)
951 vc1_p_h_intfr_loop_filter(v,
952 i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 16 : dest,
958 if (s->mb_x == s->mb_width - 1) {
960 dest = s->dest[0] - 32 * s->linesize - 16;
961 ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 1];
962 flags = s->mb_x == 1 ? LEFT_EDGE : 0;
963 fieldtx = v->fieldtx_plane[mb_pos - 2 * s->mb_stride - 1];
964 for (i = 0; i < block_count; i++)
965 vc1_p_h_intfr_loop_filter(v,
966 i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 8 : dest,
972 dest = s->dest[0] - 32 * s->linesize;
973 ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride];
974 flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
975 fieldtx = v->fieldtx_plane[mb_pos - 2 * s->mb_stride];
976 for (i = 0; i < block_count; i++)
977 vc1_p_h_intfr_loop_filter(v,
978 i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize : dest,
985 if (s->mb_y == s->end_mb_y - 1) {
986 if (s->mb_y >= s->start_mb_y + 1) {
988 dest = s->dest[0] - 16 * s->linesize - 32;
989 ttblk = &v->ttblk[s->mb_x - s->mb_stride - 2];
990 flags = s->mb_x == 2 ? LEFT_EDGE : 0;
991 fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride - 2];
992 for (i = 0; i < block_count; i++)
993 vc1_p_h_intfr_loop_filter(v,
994 i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 16 : dest,
1000 if (s->mb_x == s->mb_width - 1) {
1002 dest = s->dest[0] - 16 * s->linesize - 16;
1003 ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
1004 flags = s->mb_x == 1 ? LEFT_EDGE : 0;
1005 fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride - 1];
1006 for (i = 0; i < block_count; i++)
1007 vc1_p_h_intfr_loop_filter(v,
1008 i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest,
1014 dest = s->dest[0] - 16 * s->linesize;
1015 ttblk = &v->ttblk[s->mb_x - s->mb_stride];
1016 flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
1017 fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride];
1018 for (i = 0; i < block_count; i++)
1019 vc1_p_h_intfr_loop_filter(v,
1020 i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest,
1028 dest = s->dest[0] - 32;
1029 ttblk = &v->ttblk[s->mb_x - 2];
1030 flags = s->mb_x == 2 ? LEFT_EDGE : 0;
1031 fieldtx = v->fieldtx_plane[mb_pos - 2];
1032 for (i = 0; i < block_count; i++)
1033 vc1_p_h_intfr_loop_filter(v,
1034 i > 3 ? s->dest[i - 3] - 16 : dest,
1040 if (s->mb_x == s->mb_width - 1) {
1042 dest = s->dest[0] - 16;
1043 ttblk = &v->ttblk[s->mb_x - 1];
1044 flags = s->mb_x == 1 ? LEFT_EDGE : 0;
1045 fieldtx = v->fieldtx_plane[mb_pos - 1];
1046 for (i = 0; i < block_count; i++)
1047 vc1_p_h_intfr_loop_filter(v,
1048 i > 3 ? s->dest[i - 3] - 8 : dest,
1055 ttblk = &v->ttblk[s->mb_x];
1056 flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
1057 fieldtx = v->fieldtx_plane[mb_pos];
1058 for (i = 0; i < block_count; i++)
1059 vc1_p_h_intfr_loop_filter(v,
1060 i > 3 ? s->dest[i - 3] : dest,
1069 static av_always_inline void vc1_b_h_intfi_loop_filter(VC1Context *v, uint8_t *dest, uint32_t *cbp,
1070 int *ttblk, uint32_t flags, int block_num)
1072 MpegEncContext *s = &v->s;
1075 uint32_t block_cbp = cbp[0] >> (block_num * 4);
1077 int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize;
1082 dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
1084 if (!(flags & RIGHT_EDGE) || !(block_num & 5)) {
1086 v->vc1dsp.vc1_h_loop_filter8(dst + 8, linesize, pq);
1088 v->vc1dsp.vc1_h_loop_filter8(dst + 8, linesize, pq);
1091 tt = ttblk[0] >> (block_num * 4) & 0xf;
1092 if (tt == TT_4X4 || tt == TT_4X8) {
1093 idx = (block_cbp | (block_cbp >> 1)) & 5;
1095 v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
1097 v->vc1dsp.vc1_h_loop_filter4(dst + 4, linesize, pq);
1101 static av_always_inline void vc1_b_v_intfi_loop_filter(VC1Context *v, uint8_t *dest, uint32_t *cbp,
1102 int *ttblk, uint32_t flags, int block_num)
1104 MpegEncContext *s = &v->s;
1107 uint32_t block_cbp = cbp[0] >> (block_num * 4);
1109 int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize;
1114 dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
1116 if(!(flags & BOTTOM_EDGE) || block_num < 2)
1117 v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, linesize, pq);
1119 tt = ttblk[0] >> (block_num * 4) & 0xf;
1120 if (tt == TT_4X4 || tt == TT_8X4) {
1121 idx = (block_cbp | (block_cbp >> 2)) & 3;
1123 v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
1125 v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize, linesize, pq);
1129 void ff_vc1_b_intfi_loop_filter(VC1Context *v)
1131 MpegEncContext *s = &v->s;
1132 int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
1139 /* Within a MB, the vertical loop filter always runs before the horizontal.
1140 * To accomplish that, we run the V loop filter on all applicable
1141 * horizontal borders of the MB above the currently decoded MB. Then,
1142 * we wait for the next loop filter iteration to do H loop filter on all
1143 * applicable vertical borders of this MB. Therefore, the loop filter
1144 * trails by one row and one column relative to the decoding loop. */
1145 if (!s->first_slice_line) {
1146 dest = s->dest[0] - 16 * s->linesize;
1147 cbp = &v->cbp[s->mb_x - s->mb_stride];
1148 ttblk = &v->ttblk[s->mb_x - s->mb_stride];
1149 flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
1150 for (i = 0; i < block_count; i++)
1151 vc1_b_v_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, cbp, ttblk, flags, i);
1153 if (s->mb_y == s->end_mb_y - 1) {
1155 cbp = &v->cbp[s->mb_x];
1156 ttblk = &v->ttblk[s->mb_x];
1157 flags = s->first_slice_line ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
1158 for (i = 0; i < block_count; i++)
1159 vc1_b_v_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, cbp, ttblk, flags, i);
1162 if (!s->first_slice_line) {
1163 dest = s->dest[0] - 16 * s->linesize - 16;
1164 cbp = &v->cbp[s->mb_x - s->mb_stride - 1];
1165 ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
1167 flags = s->mb_x == 1 ? LEFT_EDGE : 0;
1168 for (i = 0; i < block_count; i++)
1169 vc1_b_h_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, cbp, ttblk, flags, i);
1171 if (s->mb_x == s->mb_width - 1) {
1175 flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
1176 for (i = 0; i < block_count; i++)
1177 vc1_b_h_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, cbp, ttblk, flags, i);
1180 if (s->mb_y == s->end_mb_y - 1) {
1181 dest = s->dest[0] - 16;
1182 cbp = &v->cbp[s->mb_x - 1];
1183 ttblk = &v->ttblk[s->mb_x - 1];
1185 flags = s->mb_x == 1 ? LEFT_EDGE : 0;
1186 for (i = 0; i < block_count; i++)
1187 vc1_b_h_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, cbp, ttblk, flags, i);
1189 if (s->mb_x == s->mb_width - 1) {
1193 flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
1194 for (i = 0; i < block_count; i++)
1195 vc1_b_h_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, cbp, ttblk, flags, i);