Mercurial > cgi-bin > hgwebdir.cgi > PR > Applications > VSs > VSs__H264__App
view libavcodec/h264_deblock.c @ 2:897f711a7157
rearrange to work with autoconf
| author | Nina Engelhardt <nengel@mailbox.tu-berlin.de> |
|---|---|
| date | Tue, 25 Sep 2012 15:55:33 +0200 |
| parents | |
| children |
line source
1 /*
2 * H.26L/H.264/AVC/JVT/14496-10/... loop filter
3 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
22 /**
23 * @file
24 * H.264 / AVC / MPEG4 part10 loop filter.
25 * @author Michael Niedermayer <michaelni@gmx.at>
26 */
28 #include "dsputil.h"
29 #include "mathops.h"
30 #include "rectangle.h"
31 #include "h264_types.h"
32 #include "h264_misc.h"
33 #include "h264_data.h"
34 //#undef NDEBUG
35 #include <assert.h>
37 /* Deblocking filter (p153) */
38 static const uint8_t alpha_table[52*3] = {
39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
41 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
42 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44 0, 0, 0, 0, 0, 0, 4, 4, 5, 6,
45 7, 8, 9, 10, 12, 13, 15, 17, 20, 22,
46 25, 28, 32, 36, 40, 45, 50, 56, 63, 71,
47 80, 90,101,113,127,144,162,182,203,226,
48 255,255,
49 255,255,255,255,255,255,255,255,255,255,255,255,255,
50 255,255,255,255,255,255,255,255,255,255,255,255,255,
51 255,255,255,255,255,255,255,255,255,255,255,255,255,
52 255,255,255,255,255,255,255,255,255,255,255,255,255,
53 };
54 static const uint8_t beta_table[52*3] = {
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60 0, 0, 0, 0, 0, 0, 2, 2, 2, 3,
61 3, 3, 3, 4, 4, 4, 6, 6, 7, 7,
62 8, 8, 9, 9, 10, 10, 11, 11, 12, 12,
63 13, 13, 14, 14, 15, 15, 16, 16, 17, 17,
64 18, 18,
65 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
66 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
67 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
68 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
69 };
70 static const uint8_t tc0_table[52*3][4] = {
71 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
72 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
73 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
74 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
75 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
76 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
77 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
78 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
79 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
80 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
81 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
82 {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 1 },
83 {-1, 0, 0, 1 }, {-1, 0, 0, 1 }, {-1, 0, 0, 1 }, {-1, 0, 1, 1 }, {-1, 0, 1, 1 }, {-1, 1, 1, 1 },
84 {-1, 1, 1, 1 }, {-1, 1, 1, 1 }, {-1, 1, 1, 1 }, {-1, 1, 1, 2 }, {-1, 1, 1, 2 }, {-1, 1, 1, 2 },
85 {-1, 1, 1, 2 }, {-1, 1, 2, 3 }, {-1, 1, 2, 3 }, {-1, 2, 2, 3 }, {-1, 2, 2, 4 }, {-1, 2, 3, 4 },
86 {-1, 2, 3, 4 }, {-1, 3, 3, 5 }, {-1, 3, 4, 6 }, {-1, 3, 4, 6 }, {-1, 4, 5, 7 }, {-1, 4, 5, 8 },
87 {-1, 4, 6, 9 }, {-1, 5, 7,10 }, {-1, 6, 8,11 }, {-1, 6, 8,13 }, {-1, 7,10,14 }, {-1, 8,11,16 },
88 {-1, 9,12,18 }, {-1,10,13,20 }, {-1,11,15,23 }, {-1,13,17,25 },
89 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
90 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
91 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
92 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
93 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
94 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
95 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
96 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
97 {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
98 };
100 av_always_inline static void filter_mb_edgev( uint8_t *pix, int stride, int16_t bS[4], unsigned int qp, MBRecContext *mrc, H264Slice *s) {
101 const unsigned int index_a = qp + s->slice_alpha_c0_offset;
102 const int alpha = alpha_table[index_a];
103 const int beta = beta_table[qp + s->slice_beta_offset];
104 if (alpha ==0 || beta == 0) return;
106 if( bS[0] < 4 ) {
107 int8_t tc[4];
108 tc[0] = tc0_table[index_a][bS[0]];
109 tc[1] = tc0_table[index_a][bS[1]];
110 tc[2] = tc0_table[index_a][bS[2]];
111 tc[3] = tc0_table[index_a][bS[3]];
112 mrc->hdsp.h264_h_loop_filter_luma(pix, stride, alpha, beta, tc);
113 } else {
114 mrc->hdsp.h264_h_loop_filter_luma_intra(pix, stride, alpha, beta);
115 }
116 }
118 av_always_inline static void filter_mb_edgecv( uint8_t *pix, int stride, int16_t bS[4], unsigned int qp, MBRecContext *mrc, H264Slice *s ) {
119 const unsigned int index_a = qp + s->slice_alpha_c0_offset;
120 const int alpha = alpha_table[index_a];
121 const int beta = beta_table[qp + s->slice_beta_offset];
122 if (alpha ==0 || beta == 0) return;
124 if( bS[0] < 4 ) {
125 int8_t tc[4];
126 tc[0] = tc0_table[index_a][bS[0]]+1;
127 tc[1] = tc0_table[index_a][bS[1]]+1;
128 tc[2] = tc0_table[index_a][bS[2]]+1;
129 tc[3] = tc0_table[index_a][bS[3]]+1;
130 mrc->hdsp.h264_h_loop_filter_chroma(pix, stride, alpha, beta, tc);
131 } else {
132 mrc->hdsp.h264_h_loop_filter_chroma_intra(pix, stride, alpha, beta);
133 }
134 }
137 av_always_inline static void filter_mb_edgeh( uint8_t *pix, int stride, int16_t bS[4], unsigned int qp, MBRecContext *mrc, H264Slice *s ) {
138 const unsigned int index_a = qp + s->slice_alpha_c0_offset;
139 const int alpha = alpha_table[index_a];
140 const int beta = beta_table[qp + s->slice_beta_offset];
141 if (alpha ==0 || beta == 0) return;
143 if( bS[0] < 4 ) {
144 int8_t tc[4];
145 tc[0] = tc0_table[index_a][bS[0]];
146 tc[1] = tc0_table[index_a][bS[1]];
147 tc[2] = tc0_table[index_a][bS[2]];
148 tc[3] = tc0_table[index_a][bS[3]];
149 mrc->hdsp.h264_v_loop_filter_luma(pix, stride, alpha, beta, tc);
150 } else {
151 mrc->hdsp.h264_v_loop_filter_luma_intra(pix, stride, alpha, beta);
152 }
153 }
155 av_always_inline static void filter_mb_edgech( uint8_t *pix, int stride, int16_t bS[4], unsigned int qp, MBRecContext *mrc, H264Slice *s ) {
156 const unsigned int index_a = qp + s->slice_alpha_c0_offset;
157 const int alpha = alpha_table[index_a];
158 const int beta = beta_table[qp + s->slice_beta_offset];
159 if (alpha ==0 || beta == 0) return;
161 if( bS[0] < 4 ) {
162 int8_t tc[4];
163 tc[0] = tc0_table[index_a][bS[0]]+1;
164 tc[1] = tc0_table[index_a][bS[1]]+1;
165 tc[2] = tc0_table[index_a][bS[2]]+1;
166 tc[3] = tc0_table[index_a][bS[3]]+1;
167 mrc->hdsp.h264_v_loop_filter_chroma(pix, stride, alpha, beta, tc);
168 } else {
169 mrc->hdsp.h264_v_loop_filter_chroma_intra(pix, stride, alpha, beta);
170 }
171 }
173 static av_always_inline void filter_mb_dir(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, int dir) {
174 const int mbm_type = dir == 0 ? mrs->left_type : mrs->top_type;
175 const int qp_xy= m->qscale_mb_xy;
176 const int qp_dir = dir == 0 ? m->qscale_left_mb_xy : m->qscale_top_mb_xy;
177 const int linesize = mrc->linesize;
178 const int uvlinesize = mrc->uvlinesize;
179 const int mb_type = m->mb_type;
180 int edge;
181 const int edges = mrs->edges[dir];
183 if(mbm_type){
184 int16_t* bS=mrs->bS[dir][0];
185 /* Filter edge */
186 // Do not use s->qscale as luma quantizer because it has not the same
187 // value in IPCM macroblocks.
188 if(bS[0]+bS[1]+bS[2]+bS[3]){
189 int qp = ( qp_xy + qp_dir + 1 ) >> 1;
190 if( dir == 0 ) {
191 filter_mb_edgev( &img_y[0], linesize, bS, qp, mrc, s );
192 {
193 int qp= ( get_chroma_qp(s, 0, qp_xy) + get_chroma_qp( s, 0, qp_dir) + 1 ) >> 1;
194 filter_mb_edgecv( &img_cb[0], uvlinesize, bS, qp, mrc, s);
195 filter_mb_edgecv( &img_cr[0], uvlinesize, bS, qp, mrc, s);
196 }
197 } else {
198 filter_mb_edgeh( &img_y[0], linesize, bS, qp, mrc, s );
199 {
200 int qp= ( get_chroma_qp(s, 0, qp_xy) + get_chroma_qp( s, 0, qp_dir) + 1 ) >> 1;
201 filter_mb_edgech( &img_cb[0], uvlinesize, bS, qp, mrc, s);
202 filter_mb_edgech( &img_cr[0], uvlinesize, bS, qp, mrc, s);
203 }
204 }
205 }
206 }
208 for( edge = 1; edge < edges; edge++ ) {
209 int16_t* bS=mrs->bS[dir][edge];
210 int qp = qp_xy;
212 if( IS_8x8DCT(mb_type & (edge<<24)) ) // (edge&1) && IS_8x8DCT(mb_type)
213 continue;
215 if(bS[0]+bS[1]+bS[2]+bS[3] == 0)
216 continue;
218 /* Filter edge */
219 // Do not use s->qscale as luma quantizer because it has not the same
220 // value in IPCM macroblocks.
222 if( dir == 0 ) {
223 filter_mb_edgev( &img_y[4*edge], linesize, bS, qp, mrc, s);
224 if( (edge&1) == 0 ) {
225 filter_mb_edgecv( &img_cb[2*edge], uvlinesize, bS, get_chroma_qp(s, 0, qp_xy), mrc, s);
226 filter_mb_edgecv( &img_cr[2*edge], uvlinesize, bS, get_chroma_qp(s, 1, qp_xy), mrc, s);
227 }
228 } else {
229 filter_mb_edgeh( &img_y[4*edge*linesize], linesize, bS, qp, mrc, s );
230 if( (edge&1) == 0 ) {
231 filter_mb_edgech( &img_cb[2*edge*uvlinesize], uvlinesize, bS, get_chroma_qp(s, 0, qp_xy), mrc, s);
232 filter_mb_edgech( &img_cr[2*edge*uvlinesize], uvlinesize, bS, get_chroma_qp(s, 1, qp_xy), mrc, s);
233 }
234 }
235 }
236 }
238 static int check_mv(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, long b_idx, long bn_idx, int mvy_limit){
239 int v;
240 v= mrs->ref_cache[0][b_idx] != mrs->ref_cache[0][bn_idx];
241 if(!v && mrs->ref_cache[0][b_idx]!=-1)
242 // absolute value >= 7 | ...
243 v= ((unsigned) (mrs->mv_cache[0][b_idx][0] - mrs->mv_cache[0][bn_idx][0] + 3) >= 7U) |
244 ((FFABS( mrs->mv_cache[0][b_idx][1] - mrs->mv_cache[0][bn_idx][1] )) >= mvy_limit);
246 if(s->list_count==2){
247 if(!v)
248 v = (mrs->ref_cache[1][b_idx] != mrs->ref_cache[1][bn_idx]) |
249 ((unsigned) (mrs->mv_cache[1][b_idx][0] - mrs->mv_cache[1][bn_idx][0] + 3) >= 7U) |
250 ((FFABS( mrs->mv_cache[1][b_idx][1] - mrs->mv_cache[1][bn_idx][1] )) >= mvy_limit);
252 if(v){
253 if((mrs->ref_cache[0][b_idx] != mrs->ref_cache[1][bn_idx]) |
254 (mrs->ref_cache[1][b_idx] != mrs->ref_cache[0][bn_idx]))
255 return 1;
256 return
257 ((unsigned) (mrs->mv_cache[0][b_idx][0] - mrs->mv_cache[1][bn_idx][0] + 3) >= 7U) |
258 ((FFABS( mrs->mv_cache[0][b_idx][1] - mrs->mv_cache[1][bn_idx][1] )) >= mvy_limit) |
259 ((unsigned) (mrs->mv_cache[1][b_idx][0] - mrs->mv_cache[0][bn_idx][0] + 3) >= 7U) |
260 ((FFABS( mrs->mv_cache[1][b_idx][1] - mrs->mv_cache[0][bn_idx][1] )) >= mvy_limit);
261 }
262 }
264 return v;
265 }
267 static void calc_bS_values(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int mvy_limit, int dir) {
268 int mb_type = m->mb_type;
269 int edge;
270 const int mbm_type = dir == 0 ? mrs->left_type : mrs->top_type;
272 // how often to recheck mv-based bS when iterating between edges
273 static const uint8_t mask_edge_tab[2][8]={{0,3,3,3,1,1,1,1},
274 {0,3,1,1,3,3,3,3}};
275 const int mask_edge = mask_edge_tab[dir][(mb_type>>3)&7];
276 const int edges = mask_edge== 3 && !(m->cbp&15) ? 1 : 4;
277 // how often to recheck mv-based bS when iterating along each edge
278 const int mask_par0 = mb_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir));
280 mrs->edges[dir]= edges;
282 if(mbm_type){
283 int16_t* bS=mrs->bS[dir][0];
284 if( IS_INTRA(mb_type|mbm_type)) {
285 AV_WN64A(bS, 0x0004000400040004ULL);
286 } else {
287 int i;
288 int mv_done;
289 if( mask_par0 && ((mbm_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)))) ) {
290 int b_idx= 8 + 4;
291 int bn_idx= b_idx - (dir ? 8:1);
293 bS[0] = bS[1] = bS[2] = bS[3] = check_mv(mrc, mrs, s, 8 + 4, bn_idx, mvy_limit);
294 mv_done = 1;
295 }
296 else
297 mv_done = 0;
299 for( i = 0; i < 4; i++ ) {
300 int x = dir == 0 ? 0 : i;
301 int y = dir == 0 ? i : 0;
302 int b_idx= 8 + 4 + x + 8*y;
303 int bn_idx= b_idx - (dir ? 8:1);
305 if( mrs->non_zero_count_cache[b_idx] |
306 mrs->non_zero_count_cache[bn_idx] ) {
307 bS[i] = 2;
308 }
309 else if(!mv_done)
310 {
311 bS[i] = check_mv(mrc, mrs, s, b_idx, bn_idx, mvy_limit);
312 }
313 }
314 }
315 }
317 /* Calculate bS */
318 for( edge = 1; edge < edges; edge++ ) {
319 int16_t* bS=mrs->bS[dir][edge];
321 if( IS_8x8DCT(mb_type & (edge<<24)) ) // (edge&1) && IS_8x8DCT(mb_type)
322 continue;
324 if( IS_INTRA(mb_type)) {
325 AV_WN64A(bS, 0x0003000300030003ULL);
326 } else {
327 int i;
328 int mv_done;
330 if( edge & mask_edge ) {
331 AV_ZERO64(bS);
332 mv_done = 1;
333 }
334 else if( mask_par0 ) {
335 int b_idx= 8 + 4 + edge * (dir ? 8:1);
336 int bn_idx= b_idx - (dir ? 8:1);
338 bS[0] = bS[1] = bS[2] = bS[3] = check_mv(mrc, mrs, s, b_idx, bn_idx, mvy_limit);
339 mv_done = 1;
340 }
341 else
342 mv_done = 0;
344 for( i = 0; i < 4; i++ ) {
345 int x = dir == 0 ? edge : i;
346 int y = dir == 0 ? i : edge;
347 int b_idx= 8 + 4 + x + 8*y;
348 int bn_idx= b_idx - (dir ? 8:1);
350 if( mrs->non_zero_count_cache[b_idx] |
351 mrs->non_zero_count_cache[bn_idx] ) {
352 bS[i] = 2;
353 }
354 else if(!mv_done)
355 {
356 bS[i] = check_mv(mrc, mrs, s, b_idx, bn_idx, mvy_limit);
357 }
358 }
360 if(bS[0]+bS[1]+bS[2]+bS[3] == 0)
361 continue;
362 }
364 }
365 }
368 /**
369 *
370 * @return zero if the loop filter can be skiped
371 */
372 static int fill_filter_caches(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int mb_type){
373 H264Mb *m_top = m - mrc->mb_width;
374 H264Mb *m_left = m - 1;
375 const int mb_x = m->mb_x;
376 const int mb_y = m->mb_y;
377 int top_type, left_type;
378 int qp, top_qp, left_qp;
379 int qp_thresh = s->qp_thresh; //FIXME strictly we should store qp_thresh for each mb of a slice
381 qp = m->qscale_mb_xy ;
382 left_qp = m->qscale_left_mb_xy ;
383 top_qp = m->qscale_top_mb_xy ;
385 //for sufficiently low qp, filtering wouldn't do anything
386 //this is a conservative estimate: could also check beta_offset and more accurate chroma_qp
387 if(qp <= qp_thresh
388 && (!(mb_x+mb_y) || ((qp + left_qp + 1)>>1) <= qp_thresh)
389 && ( mb_y==0 || ((qp + top_qp + 1)>>1) <= qp_thresh)){
390 return 0;
391 }
393 if(IS_INTRA(mb_type)){
394 return 1;
395 }
397 {
398 int list;
399 for(list=0; list<s->list_count; list++){
400 int8_t *ref;
402 if(!USES_LIST(mb_type, list)){
403 fill_rectangle( mrs->mv_cache[list][scan8[0]], 4, 4, 8, pack16to32(0,0), 4);
404 fill_rectangle( mrs->mv_cache[list][scan8[0]], 4, 4, 8, pack16to32(0,0), 4);
405 AV_WN32A(&mrs->ref_cache[list][scan8[ 0]], ((LIST_NOT_USED)&0xFF)*0x01010101u);
406 AV_WN32A(&mrs->ref_cache[list][scan8[ 2]], ((LIST_NOT_USED)&0xFF)*0x01010101u);
407 AV_WN32A(&mrs->ref_cache[list][scan8[ 8]], ((LIST_NOT_USED)&0xFF)*0x01010101u);
408 AV_WN32A(&mrs->ref_cache[list][scan8[10]], ((LIST_NOT_USED)&0xFF)*0x01010101u);
409 continue;
410 }
412 ref = &mrs->ref_index[list][4*mb_x];
413 {
414 int (*ref2frm)[64] =(void *) (s->ref2frm[0] + 2);
415 AV_WN32A(&mrs->ref_cache[list][scan8[ 0]], (pack16to32(ref2frm[list][ref[0]],ref2frm[list][ref[1]])&0x00FF00FF)*0x0101);
416 AV_WN32A(&mrs->ref_cache[list][scan8[ 2]], (pack16to32(ref2frm[list][ref[0]],ref2frm[list][ref[1]])&0x00FF00FF)*0x0101);
417 ref += 2;
419 AV_WN32A(&mrs->ref_cache[list][scan8[ 8]], (pack16to32(ref2frm[list][ref[0]],ref2frm[list][ref[1]])&0x00FF00FF)*0x0101);
420 AV_WN32A(&mrs->ref_cache[list][scan8[10]], (pack16to32(ref2frm[list][ref[0]],ref2frm[list][ref[1]])&0x00FF00FF)*0x0101);
421 }
422 }
423 }
425 /*
426 0 . T T. T T T T
427 1 L . .L . . . .
428 2 L . .L . . . .
429 3 . T TL . . . .
430 4 L . .L . . . .
431 5 L . .. . . . .
432 */
434 if (IS_SKIP(mb_type)){
435 memset(mrs->non_zero_count_cache + 8, 0, 8*5); //FIXME ugly, remove pfui
436 }
438 //FIXME constraint_intra_pred & partitioning & nnz (let us hope this is just a typo in the spec)
439 top_type = mrs->top_type;
440 left_type = mrs->left_type;
441 if(top_type){
442 AV_COPY32(&mrs->non_zero_count_cache[4+8*0], &m_top->non_zero_count[3*4]);
443 }
445 if(left_type){
446 mrs->non_zero_count_cache[3+8*1]= m_left->non_zero_count[3+0*4];
447 mrs->non_zero_count_cache[3+8*2]= m_left->non_zero_count[3+1*4];
448 mrs->non_zero_count_cache[3+8*3]= m_left->non_zero_count[3+2*4];
449 mrs->non_zero_count_cache[3+8*4]= m_left->non_zero_count[3+3*4];
450 }
452 if(IS_INTER(mb_type) || IS_DIRECT(mb_type)){
453 int list;
454 for(list=0; list<s->list_count; list++){
455 if(USES_LIST(top_type, list)){
456 const int b_xy= 4*mb_x + 3*mrc->b_stride;
457 const int b8_x= 4*mb_x + 2;
458 int (*ref2frm)[64] = (void *) (s->ref2frm[0] + 2);
459 AV_COPY128(mrs->mv_cache[list][scan8[0] + 0 - 1*8], mrs->motion_val_top[list][b_xy + 0]);
461 mrs->ref_cache[list][scan8[0] + 0 - 1*8]=
462 mrs->ref_cache[list][scan8[0] + 1 - 1*8]= ref2frm[list][mrs->ref_index_top[list][b8_x + 0]];
463 mrs->ref_cache[list][scan8[0] + 2 - 1*8]=
464 mrs->ref_cache[list][scan8[0] + 3 - 1*8]= ref2frm[list][mrs->ref_index_top[list][b8_x + 1]];
465 }else{
466 AV_ZERO128(mrs->mv_cache[list][scan8[0] + 0 - 1*8]);
467 AV_WN32A(&mrs->ref_cache[list][scan8[0] + 0 - 1*8], ((LIST_NOT_USED)&0xFF)*0x01010101u);
468 }
470 if(USES_LIST(left_type, list)){
471 const int b_x = 4*(mb_x-1) + 3;
472 const int b8_x= 4*(mb_x-1) + 1;
473 int (*ref2frm)[64] = (void *) (s->ref2frm[0] + 2);
474 AV_COPY32(mrs->mv_cache[list][scan8[0] - 1 + 0 ], mrs->motion_val[list][b_x + mrc->b_stride*0]);
475 AV_COPY32(mrs->mv_cache[list][scan8[0] - 1 + 8 ], mrs->motion_val[list][b_x + mrc->b_stride*1]);
476 AV_COPY32(mrs->mv_cache[list][scan8[0] - 1 +16 ], mrs->motion_val[list][b_x + mrc->b_stride*2]);
477 AV_COPY32(mrs->mv_cache[list][scan8[0] - 1 +24 ], mrs->motion_val[list][b_x + mrc->b_stride*3]);
479 mrs->ref_cache[list][scan8[0] - 1 + 0 ]=
480 mrs->ref_cache[list][scan8[0] - 1 + 8 ]= ref2frm[list][mrs->ref_index[list][b8_x + 2*0]];
481 mrs->ref_cache[list][scan8[0] - 1 +16 ]=
482 mrs->ref_cache[list][scan8[0] - 1 +24 ]= ref2frm[list][mrs->ref_index[list][b8_x + 2*1]];
484 }else{
485 AV_ZERO32(mrs->mv_cache [list][scan8[0] - 1 + 0 ]);
486 AV_ZERO32(mrs->mv_cache [list][scan8[0] - 1 + 8 ]);
487 AV_ZERO32(mrs->mv_cache [list][scan8[0] - 1 +16 ]);
488 AV_ZERO32(mrs->mv_cache [list][scan8[0] - 1 +24 ]);
490 mrs->ref_cache[list][scan8[0] - 1 + 0 ]=
491 mrs->ref_cache[list][scan8[0] - 1 + 8 ]=
492 mrs->ref_cache[list][scan8[0] - 1 + 16 ]=
493 mrs->ref_cache[list][scan8[0] - 1 + 24 ]= LIST_NOT_USED;
494 }
495 }
496 }
497 return 1;
498 }
500 void ff_h264_filter_mb(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr) {
501 if (fill_filter_caches(mrc, mrs, s, m, m->mb_type)){
502 calc_bS_values(mrc, mrs, s, m, 4, 0);
503 calc_bS_values(mrc, mrs, s, m, 4, 1);
504 filter_mb_dir(mrc, mrs, s, m, img_y, img_cb, img_cr, 0);
505 filter_mb_dir(mrc, mrs, s, m, img_y, img_cb, img_cr, 1);
506 }
507 }
