FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vc1_loopfilter.c
Go to the documentation of this file.
1 /*
2  * VC-1 and WMV3 decoder
3  * Copyright (c) 2011 Mashiat Sarker Shakkhar
4  * Copyright (c) 2006-2007 Konstantin Shishkov
5  * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 /**
25  * @file
26  * VC-1 and WMV3 loopfilter
27  */
28 
29 #include "avcodec.h"
30 #include "mpegvideo.h"
31 #include "vc1.h"
32 #include "vc1dsp.h"
33 
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 & 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 & 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 
65 {
66  MpegEncContext *s = &v->s;
67  int j;
68 
69  /* The loopfilter runs 1 row and 1 column behind the overlap filter, which
70  * means it runs two rows/cols behind the decoding loop. */
71  if (!s->first_slice_line) {
72  if (s->mb_x) {
73  if (s->mb_y >= s->start_mb_y + 2) {
74  v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 16 * s->linesize - 16, s->linesize, pq);
75 
76  if (s->mb_x >= 2)
77  v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize - 16, s->linesize, pq);
78  v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize - 8, s->linesize, pq);
79  if (!CONFIG_GRAY || !(s->avctx->flags & CODEC_FLAG_GRAY))
80  for (j = 0; j < 2; j++) {
81  v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize - 8, s->uvlinesize, pq);
82  if (s->mb_x >= 2) {
83  v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 16 * s->uvlinesize - 8, s->uvlinesize, pq);
84  }
85  }
86  }
87  v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize - 16, s->linesize, pq);
88  }
89 
90  if (s->mb_x == s->mb_width - 1) {
91  if (s->mb_y >= s->start_mb_y + 2) {
92  v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 16 * s->linesize, s->linesize, pq);
93 
94  if (s->mb_x)
95  v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize, s->linesize, pq);
96  v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize + 8, s->linesize, pq);
97  if (!CONFIG_GRAY || !(s->avctx->flags & CODEC_FLAG_GRAY))
98  for (j = 0; j < 2; j++) {
99  v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq);
100  if (s->mb_x >= 2) {
101  v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 16 * s->uvlinesize, s->uvlinesize, pq);
102  }
103  }
104  }
105  v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize, s->linesize, pq);
106  }
107 
108  if (s->mb_y == s->end_mb_y) {
109  if (s->mb_x) {
110  if (s->mb_x >= 2)
111  v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize - 16, s->linesize, pq);
112  v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize - 8, s->linesize, pq);
113  if (s->mb_x >= 2 && (!CONFIG_GRAY || !(s->avctx->flags & CODEC_FLAG_GRAY))) {
114  for (j = 0; j < 2; j++) {
115  v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize - 8, s->uvlinesize, pq);
116  }
117  }
118  }
119 
120  if (s->mb_x == s->mb_width - 1) {
121  if (s->mb_x)
122  v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize, s->linesize, pq);
123  v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize + 8, s->linesize, pq);
124  if (s->mb_x && (!CONFIG_GRAY || !(s->avctx->flags & CODEC_FLAG_GRAY))) {
125  for (j = 0; j < 2; j++) {
126  v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq);
127  }
128  }
129  }
130  }
131  }
132 }
133 
135 {
136  MpegEncContext *s = &v->s;
137  int mb_pos;
138 
139  if (v->condover == CONDOVER_NONE)
140  return;
141 
142  mb_pos = s->mb_x + s->mb_y * s->mb_stride;
143 
144  /* Within a MB, the horizontal overlap always runs before the vertical.
145  * To accomplish that, we run the H on left and internal borders of the
146  * currently decoded MB. Then, we wait for the next overlap iteration
147  * to do H overlap on the right edge of this MB, before moving over and
148  * running the V overlap. Therefore, the V overlap makes us trail by one
149  * MB col and the H overlap filter makes us trail by one MB row. This
150  * is reflected in the time at which we run the put_pixels loop. */
151  if (v->condover == CONDOVER_ALL || v->pq >= 9 || v->over_flags_plane[mb_pos]) {
152  if (s->mb_x && (v->condover == CONDOVER_ALL || v->pq >= 9 ||
153  v->over_flags_plane[mb_pos - 1])) {
155  v->block[v->cur_blk_idx][0]);
157  v->block[v->cur_blk_idx][2]);
158  if (!CONFIG_GRAY || !(s->avctx->flags & CODEC_FLAG_GRAY)) {
160  v->block[v->cur_blk_idx][4]);
162  v->block[v->cur_blk_idx][5]);
163  }
164  }
166  v->block[v->cur_blk_idx][1]);
168  v->block[v->cur_blk_idx][3]);
169 
170  if (s->mb_x == s->mb_width - 1) {
171  if (!s->first_slice_line && (v->condover == CONDOVER_ALL || v->pq >= 9 ||
172  v->over_flags_plane[mb_pos - s->mb_stride])) {
174  v->block[v->cur_blk_idx][0]);
176  v->block[v->cur_blk_idx][1]);
177  if (!CONFIG_GRAY || !(s->avctx->flags & CODEC_FLAG_GRAY)) {
179  v->block[v->cur_blk_idx][4]);
181  v->block[v->cur_blk_idx][5]);
182  }
183  }
185  v->block[v->cur_blk_idx][2]);
187  v->block[v->cur_blk_idx][3]);
188  }
189  }
190  if (s->mb_x && (v->condover == CONDOVER_ALL || v->over_flags_plane[mb_pos - 1])) {
191  if (!s->first_slice_line && (v->condover == CONDOVER_ALL || v->pq >= 9 ||
192  v->over_flags_plane[mb_pos - s->mb_stride - 1])) {
194  v->block[v->left_blk_idx][0]);
196  v->block[v->left_blk_idx][1]);
197  if (!CONFIG_GRAY || !(s->avctx->flags & CODEC_FLAG_GRAY)) {
199  v->block[v->left_blk_idx][4]);
201  v->block[v->left_blk_idx][5]);
202  }
203  }
205  v->block[v->left_blk_idx][2]);
207  v->block[v->left_blk_idx][3]);
208  }
209 }
210 
212 {
213  MpegEncContext *s = &v->s;
214  int mb_cbp = v->cbp[s->mb_x - s->mb_stride],
215  block_cbp = mb_cbp >> (block_num * 4), bottom_cbp,
216  mb_is_intra = v->is_intra[s->mb_x - s->mb_stride],
217  block_is_intra = mb_is_intra >> block_num, bottom_is_intra;
218  int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize, ttblk;
219  uint8_t *dst;
220 
221  if (block_num > 3) {
222  dst = s->dest[block_num - 3];
223  } else {
224  dst = s->dest[0] + (block_num & 1) * 8 + ((block_num & 2) * 4 - 8) * linesize;
225  }
226  if (s->mb_y != s->end_mb_y || block_num < 2) {
227  int16_t (*mv)[2];
228  int mv_stride;
229 
230  if (block_num > 3) {
231  bottom_cbp = v->cbp[s->mb_x] >> (block_num * 4);
232  bottom_is_intra = v->is_intra[s->mb_x] >> block_num;
233  mv = &v->luma_mv[s->mb_x - s->mb_stride];
234  mv_stride = s->mb_stride;
235  } else {
236  bottom_cbp = (block_num < 2) ? (mb_cbp >> ((block_num + 2) * 4))
237  : (v->cbp[s->mb_x] >> ((block_num - 2) * 4));
238  bottom_is_intra = (block_num < 2) ? (mb_is_intra >> (block_num + 2))
239  : (v->is_intra[s->mb_x] >> (block_num - 2));
240  mv_stride = s->b8_stride;
241  mv = &s->current_picture.motion_val[0][s->block_index[block_num] - 2 * mv_stride];
242  }
243 
244  if (bottom_is_intra & 1 || block_is_intra & 1 ||
245  mv[0][0] != mv[mv_stride][0] || mv[0][1] != mv[mv_stride][1]) {
246  v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq);
247  } else {
248  idx = ((bottom_cbp >> 2) | block_cbp) & 3;
249  if (idx == 3) {
250  v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq);
251  } else if (idx) {
252  if (idx == 1)
253  v->vc1dsp.vc1_v_loop_filter4(dst + 4, linesize, v->pq);
254  else
255  v->vc1dsp.vc1_v_loop_filter4(dst, linesize, v->pq);
256  }
257  }
258  }
259 
260  dst -= 4 * linesize;
261  ttblk = (v->ttblk[s->mb_x - s->mb_stride] >> (block_num * 4)) & 0xF;
262  if (ttblk == TT_4X4 || ttblk == TT_8X4) {
263  idx = (block_cbp | (block_cbp >> 2)) & 3;
264  if (idx == 3) {
265  v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq);
266  } else if (idx) {
267  if (idx == 1)
268  v->vc1dsp.vc1_v_loop_filter4(dst + 4, linesize, v->pq);
269  else
270  v->vc1dsp.vc1_v_loop_filter4(dst, linesize, v->pq);
271  }
272  }
273 }
274 
276 {
277  MpegEncContext *s = &v->s;
278  int mb_cbp = v->cbp[s->mb_x - 1 - s->mb_stride],
279  block_cbp = mb_cbp >> (block_num * 4), right_cbp,
280  mb_is_intra = v->is_intra[s->mb_x - 1 - s->mb_stride],
281  block_is_intra = mb_is_intra >> block_num, right_is_intra;
282  int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize, ttblk;
283  uint8_t *dst;
284 
285  if (block_num > 3) {
286  dst = s->dest[block_num - 3] - 8 * linesize;
287  } else {
288  dst = s->dest[0] + (block_num & 1) * 8 + ((block_num & 2) * 4 - 16) * linesize - 8;
289  }
290 
291  if (s->mb_x != s->mb_width || !(block_num & 5)) {
292  int16_t (*mv)[2];
293 
294  if (block_num > 3) {
295  right_cbp = v->cbp[s->mb_x - s->mb_stride] >> (block_num * 4);
296  right_is_intra = v->is_intra[s->mb_x - s->mb_stride] >> block_num;
297  mv = &v->luma_mv[s->mb_x - s->mb_stride - 1];
298  } else {
299  right_cbp = (block_num & 1) ? (v->cbp[s->mb_x - s->mb_stride] >> ((block_num - 1) * 4))
300  : (mb_cbp >> ((block_num + 1) * 4));
301  right_is_intra = (block_num & 1) ? (v->is_intra[s->mb_x - s->mb_stride] >> (block_num - 1))
302  : (mb_is_intra >> (block_num + 1));
303  mv = &s->current_picture.motion_val[0][s->block_index[block_num] - s->b8_stride * 2 - 2];
304  }
305  if (block_is_intra & 1 || right_is_intra & 1 || mv[0][0] != mv[1][0] || mv[0][1] != mv[1][1]) {
306  v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq);
307  } else {
308  idx = ((right_cbp >> 1) | block_cbp) & 5; // FIXME check
309  if (idx == 5) {
310  v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq);
311  } else if (idx) {
312  if (idx == 1)
313  v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize, linesize, v->pq);
314  else
315  v->vc1dsp.vc1_h_loop_filter4(dst, linesize, v->pq);
316  }
317  }
318  }
319 
320  dst -= 4;
321  ttblk = (v->ttblk[s->mb_x - s->mb_stride - 1] >> (block_num * 4)) & 0xf;
322  if (ttblk == TT_4X4 || ttblk == TT_4X8) {
323  idx = (block_cbp | (block_cbp >> 1)) & 5;
324  if (idx == 5) {
325  v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq);
326  } else if (idx) {
327  if (idx == 1)
328  v->vc1dsp.vc1_h_loop_filter4(dst + linesize * 4, linesize, v->pq);
329  else
330  v->vc1dsp.vc1_h_loop_filter4(dst, linesize, v->pq);
331  }
332  }
333 }
334 
336 {
337  MpegEncContext *s = &v->s;
338  int i;
339  int block_count = CONFIG_GRAY && (s->avctx->flags & CODEC_FLAG_GRAY) ? 4 : 6;
340 
341  for (i = 0; i < block_count; i++) {
343  }
344 
345  /* V always precedes H, therefore we run H one MB before V;
346  * at the end of a row, we catch up to complete the row */
347  if (s->mb_x) {
348  for (i = 0; i < block_count; i++) {
350  }
351  if (s->mb_x == s->mb_width - 1) {
352  s->mb_x++;
354  for (i = 0; i < block_count; i++) {
356  }
357  }
358  }
359 }
int topleft_blk_idx
Definition: vc1.h:385
VC-1 and WMV3 decoder.
float v
const char * s
Definition: avisynth_c.h:631
void ff_vc1_apply_p_loop_filter(VC1Context *v)
The VC1 Context.
Definition: vc1.h:173
int start_mb_y
start mb_y of this thread (so current thread should process start_mb_y <= row < end_mb_y) ...
Definition: mpegvideo.h:222
int end_mb_y
end mb_y of this thread (so current thread should process start_mb_y <= row < end_mb_y) ...
Definition: mpegvideo.h:223
void ff_vc1_loop_filter_iblk(VC1Context *v, int pq)
mpegvideo header.
int top_blk_idx
Definition: vc1.h:385
void(* vc1_v_loop_filter8)(uint8_t *src, int stride, int pq)
Definition: vc1dsp.h:52
if()
Definition: avfilter.c:975
uint8_t
void(* vc1_v_loop_filter4)(uint8_t *src, int stride, int pq)
Definition: vc1dsp.h:50
int left_blk_idx
Definition: vc1.h:385
Picture current_picture
copy of the current picture structure.
Definition: mpegvideo.h:249
int16_t((* luma_mv)[2]
Definition: vc1.h:388
void(* vc1_h_loop_filter8)(uint8_t *src, int stride, int pq)
Definition: vc1dsp.h:53
uint8_t * over_flags_plane
Overflags bitplane.
Definition: vc1.h:323
static void ff_update_block_index(MpegEncContext *s)
Definition: mpegvideo.h:759
Definition: vc1.h:119
int16_t(* block)[6][64]
Definition: vc1.h:384
static av_always_inline void vc1_apply_p_h_loop_filter(VC1Context *v, int block_num)
int flags
CODEC_FLAG_*.
Definition: avcodec.h:1335
void(* vc1_v_loop_filter16)(uint8_t *src, int stride, int pq)
Definition: vc1dsp.h:54
Libavcodec external API header.
int16_t(*[2] motion_val)[2]
Definition: mpegvideo.h:97
uint32_t * cbp
Definition: vc1.h:386
int block_index[6]
index to current MB in block based arrays with edges
Definition: mpegvideo.h:360
static const int8_t mv[256][2]
Definition: 4xm.c:77
int first_slice_line
used in mpeg4 too to handle resync markers
Definition: mpegvideo.h:497
void(* vc1_h_loop_filter4)(uint8_t *src, int stride, int pq)
Definition: vc1dsp.h:51
ptrdiff_t linesize
line size, in bytes, may be different from width
Definition: mpegvideo.h:203
uint8_t * is_intra
Definition: vc1.h:387
static av_always_inline void vc1_apply_p_v_loop_filter(VC1Context *v, int block_num)
Definition: vc1.h:115
ptrdiff_t uvlinesize
line size, for chroma in bytes, may be different from width
Definition: mpegvideo.h:204
int b8_stride
2*mb_width+1 used for some 8x8 block arrays to allow simple addressing
Definition: mpegvideo.h:200
MpegEncContext s
Definition: vc1.h:174
MpegEncContext.
Definition: mpegvideo.h:150
struct AVCodecContext * avctx
Definition: mpegvideo.h:167
int cur_blk_idx
Definition: vc1.h:385
uint8_t pq
Definition: vc1.h:238
int mb_stride
mb_width+1 used for some arrays to allow simple addressing of left & top MBs without sig11 ...
Definition: mpegvideo.h:199
#define CODEC_FLAG_GRAY
Only decode/encode grayscale.
Definition: avcodec.h:738
uint8_t * dest[3]
Definition: mpegvideo.h:362
void ff_vc1_smooth_overlap_filter_iblk(VC1Context *v)
int * ttblk
Transform type at the block level.
Definition: vc1.h:259
void(* vc1_v_s_overlap)(int16_t *top, int16_t *bottom)
Definition: vc1dsp.h:48
void ff_vc1_loop_filter_iblk_delayed(VC1Context *v, int pq)
uint8_t condover
Definition: vc1.h:325
Definition: vc1.h:118
#define av_always_inline
Definition: attributes.h:37
void(* vc1_h_s_overlap)(int16_t *left, int16_t *right)
Definition: vc1dsp.h:49
VC1DSPContext vc1dsp
Definition: vc1.h:177
void(* vc1_h_loop_filter16)(uint8_t *src, int stride, int pq)
Definition: vc1dsp.h:55