]> git.sesse.net Git - ffmpeg/blob - libavcodec/vc1_loopfilter.c
avcodec/g2meet: Check RGB upper limit
[ffmpeg] / libavcodec / vc1_loopfilter.c
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 void ff_vc1_loop_filter_iblk(VC1Context *v, int pq)
35 {
36     MpegEncContext *s = &v->s;
37     int j;
38     if (!s->first_slice_line) {
39         v->vc1dsp.vc1_v_loop_filter16(s->dest[0], s->linesize, pq);
40         if (s->mb_x)
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);
46             if (s->mb_x)
47                 v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq);
48         }
49     }
50     v->vc1dsp.vc1_v_loop_filter16(s->dest[0] + 8 * s->linesize, s->linesize, pq);
51
52     if (s->mb_y == s->end_mb_y - 1) {
53         if (s->mb_x) {
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);
58             }
59         }
60         v->vc1dsp.vc1_h_loop_filter16(s->dest[0] + 8, s->linesize, pq);
61     }
62 }
63
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)
66 {
67     if (left_block != right_block || (block_num & 5) == 1) {
68         if (block_num > 3)
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]);
72         else
73             v->vc1dsp.vc1_h_s_overlap(left_block[block_num + 1], right_block[block_num]);
74     }
75 }
76
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)
79 {
80     if (top_block != bottom_block || block_num & 2) {
81         if (block_num > 3)
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]);
85         else
86             v->vc1dsp.vc1_v_s_overlap(top_block[block_num + 2], bottom_block[block_num]);
87     }
88 }
89
90 void ff_vc1_i_overlap_filter(VC1Context *v)
91 {
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;
96     int i;
97
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];
102
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);
115
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);
127         }
128 }
129
130 void ff_vc1_p_overlap_filter(VC1Context *v)
131 {
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;
135     int i;
136
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];
141
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);
145
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);
155         }
156 }
157
158 #define LEFT_EDGE   (1 << 0)
159 #define RIGHT_EDGE  (1 << 1)
160 #define TOP_EDGE    (1 << 2)
161 #define BOTTOM_EDGE (1 << 3)
162
163 static av_always_inline void vc1_i_h_loop_filter(VC1Context *v, uint8_t *dest,
164                                                  uint32_t flags, int block_num)
165 {
166     MpegEncContext *s  = &v->s;
167     int pq = v->pq;
168     uint8_t *dst;
169
170     if (block_num & 2)
171         return;
172
173     if (!(flags & LEFT_EDGE) || (block_num & 5) == 1) {
174         if (block_num > 3)
175             dst = dest;
176         else
177             dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
178
179         if (v->fcm == ILACE_FRAME)
180             if (block_num > 3) {
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);
183             } else {
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);
186             }
187         else
188             if (block_num > 3)
189                 v->vc1dsp.vc1_h_loop_filter8(dst, s->uvlinesize, pq);
190             else
191                 v->vc1dsp.vc1_h_loop_filter16(dst, s->linesize, pq);
192     }
193 }
194
195 static av_always_inline void vc1_i_v_loop_filter(VC1Context *v, uint8_t *dest,
196                                                  uint32_t flags, uint8_t fieldtx,
197                                                  int block_num)
198 {
199     MpegEncContext *s  = &v->s;
200     int pq = v->pq;
201     uint8_t *dst;
202
203     if ((block_num & 5) == 1)
204         return;
205
206     if (!(flags & TOP_EDGE) || block_num & 2) {
207         if (block_num > 3)
208             dst = dest;
209         else
210             dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
211
212         if (v->fcm == ILACE_FRAME) {
213             if (block_num > 3) {
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);
219             }
220         } else
221             if (block_num > 3)
222                 v->vc1dsp.vc1_v_loop_filter8(dst, s->uvlinesize, pq);
223             else
224                 v->vc1dsp.vc1_v_loop_filter16(dst, s->linesize, pq);
225     }
226 }
227
228 void ff_vc1_i_loop_filter(VC1Context *v)
229 {
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;
234     uint32_t flags = 0;
235     int i;
236
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;
248         if (s->mb_x) {
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);
252         }
253         if (s->mb_x == s->mb_width - 1) {
254             dest += 16;
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);
258         }
259     }
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;
263         if (s->mb_x) {
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);
267         }
268         if (s->mb_x == s->mb_width - 1) {
269             dest += 16;
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);
273         }
274     }
275
276     if (s->mb_y >= s->start_mb_y + 2) {
277         dest = s->dest[0] - 32 * s->linesize - 16;
278         if (s->mb_x) {
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);
282         }
283         if (s->mb_x == s->mb_width - 1) {
284             dest += 16;
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);
288         }
289     }
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;
293             if (s->mb_x) {
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);
297             }
298             if (s->mb_x == s->mb_width - 1) {
299                 flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
300                 dest += 16;
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);
303             }
304         }
305         dest = s->dest[0] - 16;
306         if (s->mb_x) {
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);
310         }
311         if (s->mb_x == s->mb_width - 1) {
312             dest += 16;
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);
316         }
317     }
318 }
319
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)
323 {
324     MpegEncContext *s  = &v->s;
325     int pq = v->pq;
326     uint32_t left_cbp = cbp[0] >> (block_num * 4), right_cbp;
327     uint8_t left_is_intra, right_is_intra;
328     int tt;
329     int idx, linesize  = block_num > 3 ? s->uvlinesize : s->linesize;
330     uint8_t *dst;
331
332     if (block_num > 3)
333         dst = dest;
334     else
335         dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
336
337     if (!(flags & RIGHT_EDGE) || !(block_num & 5)) {
338         left_is_intra = is_intra[0] & (1 << block_num);
339
340         if (block_num > 3) {
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);
346         } else {
347             right_is_intra = is_intra[0] & (1 << block_num + 1);
348             right_cbp = cbp[0] >> ((block_num + 1) * 4);
349         }
350
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);
355         else {
356             idx = (left_cbp | (right_cbp >> 1)) & 5;
357             if (idx & 1)
358                 v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize + 8, linesize, pq);
359             if (idx & 4)
360                 v->vc1dsp.vc1_h_loop_filter4(dst + 8, linesize, pq);
361         }
362     }
363
364     tt = ttblk[0] >> (block_num * 4) & 0xf;
365     if (tt == TT_4X4 || tt == TT_4X8) {
366         if (left_cbp & 3)
367             v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
368         if (left_cbp & 12)
369             v->vc1dsp.vc1_h_loop_filter4(dst + 4, linesize, pq);
370     }
371 }
372
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)
376 {
377     MpegEncContext *s  = &v->s;
378     int pq = v->pq;
379     uint32_t top_cbp = cbp[0] >> (block_num * 4), bottom_cbp;
380     uint8_t top_is_intra, bottom_is_intra;
381     int tt;
382     int idx, linesize  = block_num > 3 ? s->uvlinesize : s->linesize;
383     uint8_t *dst;
384
385     if (block_num > 3)
386         dst = dest;
387     else
388         dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
389
390     if(!(flags & BOTTOM_EDGE) || block_num < 2) {
391         top_is_intra = is_intra[0] & (1 << block_num);
392
393         if (block_num > 3) {
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);
399         } else {
400             bottom_is_intra = is_intra[s->mb_stride] & (1 << block_num - 2);
401             bottom_cbp = cbp[s->mb_stride] >> ((block_num - 2) * 4);
402         }
403
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);
409         else {
410             idx = (top_cbp | (bottom_cbp >> 2)) & 3;
411             if (idx & 1)
412                 v->vc1dsp.vc1_v_loop_filter4(dst + 8 * linesize + 4, linesize, pq);
413             if (idx & 2)
414                 v->vc1dsp.vc1_v_loop_filter4(dst + 8 * linesize, linesize, pq);
415         }
416     }
417
418     tt = ttblk[0] >> (block_num * 4) & 0xf;
419     if (tt == TT_4X4 || tt == TT_8X4) {
420         if (top_cbp & 5)
421             v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
422         if (top_cbp & 10)
423             v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize, linesize, pq);
424     }
425 }
426
427 void ff_vc1_p_loop_filter(VC1Context *v)
428 {
429     MpegEncContext *s = &v->s;
430     int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
431     uint8_t *dest;
432     uint32_t *cbp;
433     uint8_t *is_intra;
434     int16_t (*uvmv)[2];
435     int *ttblk;
436     uint32_t flags;
437     int i;
438
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) {
447         if (s->mb_x) {
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,
457                                     cbp,
458                                     is_intra,
459                                     i > 3 ? uvmv :
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],
463                                     ttblk,
464                                     flags,
465                                     i);
466         }
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,
477                                     cbp,
478                                     is_intra,
479                                     i > 3 ? uvmv :
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],
483                                     ttblk,
484                                     flags,
485                                     i);
486         }
487     }
488     if (s->mb_y == s->end_mb_y - 1) {
489         if (s->mb_x) {
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,
500                                         cbp,
501                                         is_intra,
502                                         i > 3 ? uvmv :
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],
506                                         ttblk,
507                                         flags,
508                                         i);
509             }
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,
519                                     cbp,
520                                     is_intra,
521                                     i > 3 ? uvmv :
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],
525                                     ttblk,
526                                     flags,
527                                     i);
528         }
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,
540                                         cbp,
541                                         is_intra,
542                                         i > 3 ? uvmv :
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],
546                                         ttblk,
547                                         flags,
548                                         i);
549             }
550             dest = s->dest[0];
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,
559                                     cbp,
560                                     is_intra,
561                                     i > 3 ? uvmv :
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],
565                                     ttblk,
566                                     flags,
567                                     i);
568         }
569     }
570
571     if (s->mb_y >= s->start_mb_y + 2) {
572         if (s->mb_x >= 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,
582                                     cbp,
583                                     is_intra,
584                                     i > 3 ? uvmv :
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],
588                                     ttblk,
589                                     flags,
590                                     i);
591         }
592         if (s->mb_x == s->mb_width - 1) {
593             if (s->mb_x >= 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,
603                                             cbp,
604                                             is_intra,
605                                             i > 3 ? uvmv :
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],
609                                             ttblk,
610                                             flags,
611                                             i);
612             }
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,
622                                     cbp,
623                                     is_intra,
624                                     i > 3 ? uvmv :
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],
628                                     ttblk,
629                                     flags,
630                                     i);
631         }
632     }
633     if (s->mb_y == s->end_mb_y - 1) {
634         if (s->mb_y >= s->start_mb_y + 1) {
635             if (s->mb_x >= 2) {
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,
645                                         cbp,
646                                         is_intra,
647                                         i > 3 ? uvmv :
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],
651                                         ttblk,
652                                         flags,
653                                         i);
654             }
655             if (s->mb_x == s->mb_width - 1) {
656                 if (s->mb_x >= 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,
666                                                 cbp,
667                                                 is_intra,
668                                                 i > 3 ? uvmv :
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],
672                                                 ttblk,
673                                                 flags,
674                                                 i);
675                 }
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,
685                                         cbp,
686                                         is_intra,
687                                         i > 3 ? uvmv :
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],
691                                         ttblk,
692                                         flags,
693                                         i);
694             }
695         }
696         if (s->mb_x >= 2) {
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,
706                                     cbp,
707                                     is_intra,
708                                     i > 3 ? uvmv :
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],
712                                     ttblk,
713                                     flags,
714                                     i);
715         }
716         if (s->mb_x == s->mb_width - 1) {
717             if (s->mb_x >= 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,
727                                         cbp,
728                                         is_intra,
729                                         i > 3 ? uvmv :
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],
733                                         ttblk,
734                                         flags,
735                                         i);
736             }
737             dest = s->dest[0];
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,
746                                     cbp,
747                                     is_intra,
748                                     i > 3 ? uvmv :
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],
752                                     ttblk,
753                                     flags,
754                                     i);
755         }
756     }
757 }
758
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)
761 {
762     MpegEncContext *s  = &v->s;
763     int pq = v->pq;
764     int tt;
765     int linesize  = block_num > 3 ? s->uvlinesize : s->linesize;
766     uint8_t *dst;
767
768     if (block_num > 3)
769         dst = dest;
770     else
771         dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
772
773     tt = ttblk[0] >> (block_num * 4) & 0xf;
774     if (block_num < 4) {
775         if (fieldtx) {
776             if (block_num < 2) {
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);
781             } else {
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);
786             }
787         } else {
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);
791             }
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);
795             }
796         }
797     } else {
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);
801         }
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);
805         }
806     }
807 }
808
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)
811 {
812     MpegEncContext *s  = &v->s;
813     int pq = v->pq;
814     int tt;
815     int linesize  = block_num > 3 ? s->uvlinesize : s->linesize;
816     uint8_t *dst;
817
818     if (block_num > 3)
819         dst = dest;
820     else
821         dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
822
823     tt = ttblk[0] >> (block_num * 4) & 0xf;
824     if (block_num < 4) {
825         if (fieldtx) {
826             if (block_num < 2) {
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);
831             } else {
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);
836             }
837         } else {
838             if (block_num < 2) {
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);
842                 }
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);
849                 }
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);
852             }
853         }
854     } else {
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);
859             }
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);
862         }
863     }
864 }
865
866 void ff_vc1_p_intfr_loop_filter(VC1Context *v)
867 {
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;
871     uint8_t *dest;
872     int *ttblk;
873     uint32_t flags;
874     uint8_t fieldtx;
875     int i;
876
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
884      * loop. */
885     if (s->mb_x) {
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,
894                                           ttblk,
895                                           flags,
896                                           fieldtx,
897                                           i);
898         }
899     }
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,
909                                           ttblk,
910                                           flags,
911                                           fieldtx,
912                                           i);
913         }
914     }
915     if (s->mb_y == s->end_mb_y - 1) {
916         if (s->mb_x) {
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,
924                                           ttblk,
925                                           flags,
926                                           fieldtx,
927                                           i);
928         }
929         if (s->mb_x == s->mb_width - 1) {
930             dest = s->dest[0];
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,
937                                           ttblk,
938                                           flags,
939                                           fieldtx,
940                                           i);
941         }
942     }
943
944     if (s->mb_y >= s->start_mb_y + 2) {
945         if (s->mb_x >= 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,
953                                           ttblk,
954                                           flags,
955                                           fieldtx,
956                                           i);
957         }
958         if (s->mb_x == s->mb_width - 1) {
959             if (s->mb_x >= 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,
967                                               ttblk,
968                                               flags,
969                                               fieldtx,
970                                               i);
971             }
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,
979                                           ttblk,
980                                           flags,
981                                           fieldtx,
982                                           i);
983         }
984     }
985     if (s->mb_y == s->end_mb_y - 1) {
986         if (s->mb_y >= s->start_mb_y + 1) {
987             if (s->mb_x >= 2) {
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,
995                                               ttblk,
996                                               flags,
997                                               fieldtx,
998                                               i);
999             }
1000             if (s->mb_x == s->mb_width - 1) {
1001                 if (s->mb_x >= 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,
1009                                                   ttblk,
1010                                                   flags,
1011                                                   fieldtx,
1012                                                   i);
1013                 }
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,
1021                                               ttblk,
1022                                               flags,
1023                                               fieldtx,
1024                                               i);
1025             }
1026         }
1027         if (s->mb_x >= 2) {
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,
1035                                           ttblk,
1036                                           flags,
1037                                           fieldtx,
1038                                           i);
1039         }
1040         if (s->mb_x == s->mb_width - 1) {
1041             if (s->mb_x >= 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,
1049                                               ttblk,
1050                                               flags,
1051                                               fieldtx,
1052                                               i);
1053             }
1054             dest = s->dest[0];
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,
1061                                           ttblk,
1062                                           flags,
1063                                           fieldtx,
1064                                           i);
1065         }
1066     }
1067 }
1068
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)
1071 {
1072     MpegEncContext *s  = &v->s;
1073     int pq = v->pq;
1074     uint8_t *dst;
1075     uint32_t block_cbp = cbp[0] >> (block_num * 4);
1076     int tt;
1077     int idx, linesize  = block_num > 3 ? s->uvlinesize : s->linesize;
1078
1079     if (block_num > 3)
1080         dst = dest;
1081     else
1082         dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
1083
1084     if (!(flags & RIGHT_EDGE) || !(block_num & 5)) {
1085         if (block_num > 3)
1086             v->vc1dsp.vc1_h_loop_filter8(dst + 8, linesize, pq);
1087         else
1088             v->vc1dsp.vc1_h_loop_filter8(dst + 8, linesize, pq);
1089     }
1090
1091     tt = ttblk[0] >> (block_num * 4) & 0xf;
1092     if (tt == TT_4X4 || tt == TT_4X8) {
1093         idx = (block_cbp | (block_cbp >> 1)) & 5;
1094         if (idx & 1)
1095             v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
1096         if (idx & 4)
1097             v->vc1dsp.vc1_h_loop_filter4(dst + 4, linesize, pq);
1098     }
1099 }
1100
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)
1103 {
1104     MpegEncContext *s  = &v->s;
1105     int pq = v->pq;
1106     uint8_t *dst;
1107     uint32_t block_cbp = cbp[0] >> (block_num * 4);
1108     int tt;
1109     int idx, linesize  = block_num > 3 ? s->uvlinesize : s->linesize;
1110
1111     if (block_num > 3)
1112         dst = dest;
1113     else
1114         dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
1115
1116     if(!(flags & BOTTOM_EDGE) || block_num < 2)
1117         v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, linesize, pq);
1118
1119     tt = ttblk[0] >> (block_num * 4) & 0xf;
1120     if (tt == TT_4X4 || tt == TT_8X4) {
1121         idx = (block_cbp | (block_cbp >> 2)) & 3;
1122         if (idx & 1)
1123             v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
1124         if (idx & 2)
1125             v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize, linesize, pq);
1126     }
1127 }
1128
1129 void ff_vc1_b_intfi_loop_filter(VC1Context *v)
1130 {
1131     MpegEncContext *s = &v->s;
1132     int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
1133     uint8_t *dest;
1134     uint32_t *cbp;
1135     int *ttblk;
1136     uint32_t flags = 0;
1137     int i;
1138
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);
1152     }
1153     if (s->mb_y == s->end_mb_y - 1) {
1154         dest = s->dest[0];
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);
1160     }
1161
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];
1166         if (s->mb_x) {
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);
1170         }
1171         if (s->mb_x == s->mb_width - 1) {
1172             dest += 16;
1173             cbp++;
1174             ttblk++;
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);
1178         }
1179     }
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];
1184         if (s->mb_x) {
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);
1188         }
1189         if (s->mb_x == s->mb_width - 1) {
1190             dest += 16;
1191             cbp++;
1192             ttblk++;
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);
1196         }
1197     }
1198 }