view libavcodec/h264_pred_mode.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/... direct mb/block decoding
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 direct mb/block decoding.
25 * @author Michael Niedermayer <michaelni@gmx.at>
26 */
28 #include "dsputil.h"
29 #include "avcodec.h"
30 #include "h264_data.h"
31 #include "h264.h"
32 #include "rectangle.h"
34 //#undef NDEBUG
35 #include <assert.h>
37 static const uint8_t left_block_options[4][16]={
38 {0,1,2,3,7,10,8,11,7+0*8, 7+1*8, 7+2*8, 7+3*8, 2+0*8, 2+3*8, 2+1*8, 2+2*8},
39 {2,2,3,3,8,11,8,11,7+2*8, 7+2*8, 7+3*8, 7+3*8, 2+1*8, 2+2*8, 2+1*8, 2+2*8},
40 {0,0,1,1,7,10,7,10,7+0*8, 7+0*8, 7+1*8, 7+1*8, 2+0*8, 2+3*8, 2+0*8, 2+3*8},
41 {0,2,0,2,7,10,7,10,7+0*8, 7+2*8, 7+0*8, 7+2*8, 2+0*8, 2+3*8, 2+0*8, 2+3*8}
42 };
45 // static void check_cache_copy(MBRecContext *mrc, H264Slice *s, H264Mb *m){
46 // for (int list=0; list<2; list++){
47 // for (int i=0; i<40; i++){
48 // assert (m->ref_cache[list][i] == m->ref_cache_copy[list][i]);
49 // assert (mrs->mv_cache[list][i][0] == mrs->mv_cache_copy[list][i][0]);
50 // assert (mrs->mv_cache[list][i][1] == mrs->mv_cache_copy[list][i][1]);
51 // }
52 // }
53 // }
55 // static void check_cache_copy2(MBRecContext *mrc, H264Slice *s, H264Mb *m){
56 // for (int list=0; list<2; list++){
57 // for (int i=0; i<40; i++){
58 // assert (m->ref_cache[list][i] == m->ref_cache_copy2[list][i]);
59 // assert (mrs->mv_cache[list][i][0] == mrs->mv_cache_copy2[list][i][0]);
60 // assert (mrs->mv_cache[list][i][1] == mrs->mv_cache_copy2[list][i][1]);
61 // }
62 // }
63 // }
65 static void fill_decode_caches_rec(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int mb_type){
66 int topleft_type, top_type, topright_type, left_type;
67 const uint8_t * left_block= left_block_options[0];
68 const int mb_x = m->mb_x;
69 int i;
71 mrs->top_type = mrs->mb_type_top[mb_x ];
72 mrs->left_type = mrs->mb_type [mb_x-1];
74 topleft_type = mrs->mb_type_top[mb_x-1];
75 top_type = mrs->mb_type_top[mb_x ];
76 topright_type= mrs->mb_type_top[mb_x+1];
77 left_type = mrs->mb_type [mb_x-1];
79 int type_mask= s->pps.constrained_intra_pred ? 1 : -1;
81 if(!IS_SKIP(mb_type)){
82 // memset(mrc->non_zero_count_cache, 0, sizeof(mrc->non_zero_count_cache));
83 AV_COPY32(&mrs->non_zero_count_cache[4+8*1], &m->non_zero_count[ 0]);
84 AV_COPY32(&mrs->non_zero_count_cache[4+8*2], &m->non_zero_count[ 4]);
85 AV_COPY32(&mrs->non_zero_count_cache[4+8*3], &m->non_zero_count[ 8]);
86 AV_COPY32(&mrs->non_zero_count_cache[4+8*4], &m->non_zero_count[12]);
88 for (int i=0; i<2; i++) {
89 mrs->non_zero_count_cache[8*1 + 8*i + 1] = m->non_zero_count[16 + i*2 ];
90 mrs->non_zero_count_cache[8*1 + 8*i + 2] = m->non_zero_count[16 + i*2 +1];
91 mrs->non_zero_count_cache[8*4 + 8*i + 1] = m->non_zero_count[20 + i*2 ];
92 mrs->non_zero_count_cache[8*4 + 8*i + 2] = m->non_zero_count[20 + i*2 +1];
93 }
95 if(IS_INTRA(mb_type)){
96 // memset(mrc->intra4x4_pred_mode_cache, 0, sizeof(mrc->intra4x4_pred_mode_cache));
98 mrs->topleft_samples_available=
99 mrs->top_samples_available=
100 mrs->left_samples_available= 0xFFFF;
101 mrs->topright_samples_available= 0xEEEA;
103 if(!(top_type & type_mask)){
104 mrs->topleft_samples_available= 0xB3FF;
105 mrs->top_samples_available= 0x33FF;
106 mrs->topright_samples_available= 0x26EA;
107 }
109 if(!(left_type & type_mask)){
110 mrs->topleft_samples_available&= 0xDF5F;
111 mrs->left_samples_available&= 0x5F5F;
112 }
114 if(!(topleft_type & type_mask))
115 mrs->topleft_samples_available&= 0x7FFF;
117 if(!(topright_type & type_mask))
118 mrs->topright_samples_available&= 0xFBFF;
120 if(IS_INTRA4x4(mb_type)){
121 if(IS_INTRA4x4(top_type)){
122 AV_COPY32(mrs->intra4x4_pred_mode_cache+4+8*0, &mrs->intra4x4_pred_mode_top[4*mb_x]);
123 }else{
124 mrs->intra4x4_pred_mode_cache[4+8*0]=
125 mrs->intra4x4_pred_mode_cache[5+8*0]=
126 mrs->intra4x4_pred_mode_cache[6+8*0]=
127 mrs->intra4x4_pred_mode_cache[7+8*0]= 2 - 3*!(top_type & type_mask);
128 }
130 if(IS_INTRA4x4(left_type)){
131 #if OMPSS
132 mrs->intra4x4_pred_mode_cache[3+8*1]= m->intra4x4_pred_mode_left[0];
133 mrs->intra4x4_pred_mode_cache[3+8*2]= m->intra4x4_pred_mode_left[1];
134 mrs->intra4x4_pred_mode_cache[3+8*3]= m->intra4x4_pred_mode_left[2];
135 mrs->intra4x4_pred_mode_cache[3+8*4]= m->intra4x4_pred_mode_left[3];
136 #else
137 mrs->intra4x4_pred_mode_cache[3+8*1]= mrs->intra4x4_pred_mode_left[0];
138 mrs->intra4x4_pred_mode_cache[3+8*2]= mrs->intra4x4_pred_mode_left[1];
139 mrs->intra4x4_pred_mode_cache[3+8*3]= mrs->intra4x4_pred_mode_left[2];
140 mrs->intra4x4_pred_mode_cache[3+8*4]= mrs->intra4x4_pred_mode_left[3];
141 #endif
142 }else{
143 mrs->intra4x4_pred_mode_cache[3+8*1]=
144 mrs->intra4x4_pred_mode_cache[3+8*2]=
145 mrs->intra4x4_pred_mode_cache[3+8*3]=
146 mrs->intra4x4_pred_mode_cache[3+8*4]= 2 - 3*!(left_type & type_mask);
147 }
148 }
149 }
150 }
152 if(IS_INTER(mb_type) ||(IS_DIRECT(mb_type) && s->direct_spatial_mv_pred)){
153 int list;
155 // memset(mrs->mv_cache, 0, sizeof(mrs->mv_cache));
156 // memset(mrs->ref_cache, 0, sizeof(mrs->ref_cache));
158 mrs->ref_cache[0][scan8[5 ]+1] = mrs->ref_cache[0][scan8[7 ]+1] = mrs->ref_cache[0][scan8[13]+1] =
159 mrs->ref_cache[1][scan8[5 ]+1] = mrs->ref_cache[1][scan8[7 ]+1] = mrs->ref_cache[1][scan8[13]+1] = PART_NOT_AVAILABLE;
161 for(list=0; list<s->list_count; list++){
162 if(!USES_LIST(mb_type, list)){
163 continue;
164 }
165 assert(!(IS_DIRECT(mb_type) && !s->direct_spatial_mv_pred));
167 if(USES_LIST(top_type, list)){
168 const int b_xy= 4*mb_x + 3*mrc->b_stride;
169 AV_COPY128(mrs->mv_cache[list][scan8[0] + 0 - 1*8], mrs->motion_val_top[list][b_xy + 0]);
170 mrs->ref_cache[list][scan8[0] + 0 - 1*8]=
171 mrs->ref_cache[list][scan8[0] + 1 - 1*8]= mrs->ref_index_top[list][4*mb_x + 2];
172 mrs->ref_cache[list][scan8[0] + 2 - 1*8]=
173 mrs->ref_cache[list][scan8[0] + 3 - 1*8]= mrs->ref_index_top[list][4*mb_x + 3];
174 }else{
175 AV_ZERO128(mrs->mv_cache[list][scan8[0] + 0 - 1*8]);
176 AV_WN32A(&mrs->ref_cache[list][scan8[0] + 0 - 1*8], ((top_type ? LIST_NOT_USED : PART_NOT_AVAILABLE)&0xFF)*0x01010101);
177 }
179 if(mb_type & (MB_TYPE_16x8|MB_TYPE_8x8)){
180 for(i=0; i<2; i++){
181 int cache_idx = scan8[0] - 1 + i*2*8;
182 if(USES_LIST(left_type, list)){
183 const int b_xy= 4*(mb_x-1) + 3;
184 const int b8_x= 4*(mb_x-1) + 1;
185 AV_COPY32(mrs->mv_cache[list][cache_idx ], mrs->motion_val[list][b_xy + mrc->b_stride*left_block[0+i*2]]);
186 AV_COPY32(mrs->mv_cache[list][cache_idx+8], mrs->motion_val[list][b_xy + mrc->b_stride*left_block[1+i*2]]);
187 mrs->ref_cache[list][cache_idx ]= mrs->ref_index[list][b8_x + (left_block[0+i*2]&~1)];
188 mrs->ref_cache[list][cache_idx+8]= mrs->ref_index[list][b8_x + (left_block[1+i*2]&~1)];
189 }else{
190 AV_ZERO32(mrs->mv_cache [list][cache_idx ]);
191 AV_ZERO32(mrs->mv_cache [list][cache_idx+8]);
192 mrs->ref_cache[list][cache_idx ]=
193 mrs->ref_cache[list][cache_idx+8]= (left_type ? LIST_NOT_USED : PART_NOT_AVAILABLE);
194 }
195 }
196 }else{
197 if(USES_LIST(left_type, list)){
198 const int b_x = 4*(mb_x-1) + 3;
199 const int b8_x= 4*(mb_x-1) + 1;
200 AV_COPY32(mrs->mv_cache[list][scan8[0] - 1], mrs->motion_val[list][b_x + mrc->b_stride*left_block[0]]);
201 mrs->ref_cache[list][scan8[0] - 1]= mrs->ref_index[list][b8_x + (left_block[0]&~1)];
202 }else{
203 AV_ZERO32(mrs->mv_cache [list][scan8[0] - 1]);
204 mrs->ref_cache[list][scan8[0] - 1]= left_type ? LIST_NOT_USED : PART_NOT_AVAILABLE;
205 }
206 }
208 if(USES_LIST(topright_type, list)){
209 const int b_xy= 4*(mb_x+1) + 3*mrc->b_stride;
210 AV_COPY32(mrs->mv_cache[list][scan8[0] + 4 - 1*8], mrs->motion_val_top[list][b_xy]);
211 mrs->ref_cache[list][scan8[0] + 4 - 1*8]= mrs->ref_index_top[list][4*(mb_x+1) + 2];
212 }else{
213 AV_ZERO32(mrs->mv_cache [list][scan8[0] + 4 - 1*8]);
214 mrs->ref_cache[list][scan8[0] + 4 - 1*8]= topright_type ? LIST_NOT_USED : PART_NOT_AVAILABLE;
215 }
216 if(mrs->ref_cache[list][scan8[0] + 4 - 1*8] < 0){
217 int topleft_partition= -1;
218 if(USES_LIST(topleft_type, list)){
219 const int b_xy = 4*(mb_x-1) + 3 + mrc->b_stride + (topleft_partition & 2*mrc->b_stride);
220 const int b8_x= 4*(mb_x-1) + 1 + (topleft_partition & 2);
221 AV_COPY32(mrs->mv_cache[list][scan8[0] - 1 - 1*8], mrs->motion_val_top[list][b_xy]);
222 mrs->ref_cache[list][scan8[0] - 1 - 1*8]= mrs->ref_index_top[list][b8_x];
223 }else{
224 AV_ZERO32(mrs->mv_cache[list][scan8[0] - 1 - 1*8]);
225 mrs->ref_cache[list][scan8[0] - 1 - 1*8]= topleft_type ? LIST_NOT_USED : PART_NOT_AVAILABLE;
226 }
227 }
229 if((mb_type&(MB_TYPE_SKIP|MB_TYPE_DIRECT2)))
230 continue;
232 if(!(mb_type&(MB_TYPE_SKIP|MB_TYPE_DIRECT2))) {
233 mrs->ref_cache[list][scan8[4 ]] =
234 mrs->ref_cache[list][scan8[12]] = PART_NOT_AVAILABLE;
235 AV_ZERO32(mrs->mv_cache [list][scan8[4 ]]);
236 AV_ZERO32(mrs->mv_cache [list][scan8[12]]);
237 }
238 }
239 }
240 }
242 static inline void write_back_motion_rec(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int mb_type){
243 const int b_stride = mrc->b_stride;
244 const int b_x = 4*m->mb_x; //try mb2b(8)_xy
245 const int b8_x= 4*m->mb_x;
246 int list;
248 if(!USES_LIST(mb_type, 0))
249 fill_rectangle(&mrs->ref_index[0][b8_x], 2, 2, 2, (uint8_t)LIST_NOT_USED, 1);
251 for(list=0; list<s->list_count; list++){
252 int y;
253 int16_t (*mv_dst)[2];
254 int16_t (*mv_src)[2];
256 if(!USES_LIST(mb_type, list))
257 continue;
259 mv_dst = &mrs->motion_val[list][b_x];
260 mv_src = &mrs->mv_cache[list][scan8[0]];
261 for(y=0; y<4; y++){
262 AV_COPY128(mv_dst + y*b_stride, mv_src + 8*y);
263 }
265 {
266 int8_t *ref_index = &mrs->ref_index[list][b8_x];
267 ref_index[0+0*2]= mrs->ref_cache[list][scan8[0]];
268 ref_index[1+0*2]= mrs->ref_cache[list][scan8[4]];
269 ref_index[0+1*2]= mrs->ref_cache[list][scan8[8]];
270 ref_index[1+1*2]= mrs->ref_cache[list][scan8[12]];
271 }
272 }
273 }
276 /**
277 * checks if the top & left blocks are available if needed & changes the dc mode so it only uses the available blocks.
278 */
279 static int check_intra4x4_pred_mode(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m){
280 static const int8_t top [12]= {-1, 0,LEFT_DC_PRED,-1,-1,-1,-1,-1, 0};
281 static const int8_t left[12]= { 0,-1, TOP_DC_PRED, 0,-1,-1,-1, 0,-1,DC_128_PRED};
282 int i;
284 if(!(mrs->top_samples_available&0x8000)){
285 for(i=0; i<4; i++){
286 int status= top[ mrs->intra4x4_pred_mode_cache[scan8[0] + i] ];
287 if(status<0){
288 av_log(AV_LOG_ERROR, "top block unavailable for requested intra4x4 mode %d at %d %d\n", status, m->mb_x, m->mb_y);
289 return -1;
290 } else if(status){
291 mrs->intra4x4_pred_mode_cache[scan8[0] + i]= status;
292 }
293 }
294 }
296 if((mrs->left_samples_available&0x8888)!=0x8888){
297 static const int mask[4]={0x8000,0x2000,0x80,0x20};
298 for(i=0; i<4; i++){
299 if(!(mrs->left_samples_available&mask[i])){
300 int status= left[ mrs->intra4x4_pred_mode_cache[scan8[0] + 8*i] ];
301 if(status<0){
302 av_log(AV_LOG_ERROR, "left block unavailable for requested intra4x4 mode %d at %d %d\n", status, m->mb_x, m->mb_y);
303 return -1;
304 } else if(status){
305 mrs->intra4x4_pred_mode_cache[scan8[0] + 8*i]= status;
306 }
307 }
308 }
309 }
310 return 0;
311 }
313 /**
314 * checks if the top & left blocks are available if needed & changes the dc mode so it only uses the available blocks.
315 */
316 static int check_intra_pred_mode(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int mode){
317 static const int8_t top [7]= {LEFT_DC_PRED8x8, 1,-1,-1};
318 static const int8_t left[7]= { TOP_DC_PRED8x8,-1, 2,-1,DC_128_PRED8x8};
320 if(mode > 6) {
321 av_log(AV_LOG_ERROR, "out of range intra chroma pred mode at %d %d\n", m->mb_x, m->mb_y);
322 return -1;
323 }
325 if(!(mrs->top_samples_available&0x8000)){
326 mode= top[ mode ];
327 if(mode<0){
328 av_log(AV_LOG_ERROR, "top block unavailable for requested intra mode at %d %d\n", m->mb_x, m->mb_y);
329 return -1;
330 }
331 }
333 if((mrs->left_samples_available&0x8080) != 0x8080){
334 mode= left[ mode ];
335 if(mrs->left_samples_available&0x8080){ //mad cow disease mode, aka MBAFF + constrained_intra_pred
336 mode= ALZHEIMER_DC_L0T_PRED8x8 + (!(mrs->left_samples_available&0x8000)) + 2*(mode == DC_128_PRED8x8);
337 }
338 if(mode<0){
339 av_log(AV_LOG_ERROR, "left block unavailable for requested intra mode at %d %d\n", m->mb_x, m->mb_y);
340 return -1;
341 }
342 }
343 return mode;
344 }
346 /**
347 * gets the predicted intra4x4 prediction mode.
348 */
349 static inline int pred_intra_mode(MBRecContext *mrc, MBRecState *mrs, int n){
350 const int index8= scan8[n];
351 const int left= mrs->intra4x4_pred_mode_cache[index8 - 1];
352 const int top = mrs->intra4x4_pred_mode_cache[index8 - 8];
353 const int min= FFMIN(left, top);
355 if(min<0) return DC_PRED;
356 else return min;
357 }
359 static void write_back_intra_pred_mode_rec(MBRecContext *mrc, MBRecState *mrs, H264Mb *m, int mb_x){
360 int8_t *mode= &mrs->intra4x4_pred_mode[4*mb_x];
362 AV_COPY32(mode, mrs->intra4x4_pred_mode_cache + 4 + 8*4);
363 #if OMPSS
364 if (m->mb_x < mrc->mb_width-1){
365 H264Mb *mr= m+1;
366 mode = mr->intra4x4_pred_mode_left;
367 mode[0]= mrs->intra4x4_pred_mode_cache[7+8*1];
368 mode[1]= mrs->intra4x4_pred_mode_cache[7+8*2];
369 mode[2]= mrs->intra4x4_pred_mode_cache[7+8*3];
370 mode[3]= mrs->intra4x4_pred_mode_cache[7+8*4];
371 }
372 #else
373 mode = mrs->intra4x4_pred_mode_left;
374 mode[0]= mrs->intra4x4_pred_mode_cache[7+8*1];
375 mode[1]= mrs->intra4x4_pred_mode_cache[7+8*2];
376 mode[2]= mrs->intra4x4_pred_mode_cache[7+8*3];
377 mode[3]= mrs->intra4x4_pred_mode_cache[7+8*4];
378 #endif
379 }
381 static void pred_spatial_direct_motion_rec(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int *mb_type){
382 int b4_stride = mrc->b_stride;
383 const int mb_x = m->mb_x;
384 int mb_type_col[2];
385 const int16_t (*l1mv0)[2], (*l1mv1)[2];
386 const int8_t *l1ref0, *l1ref1;
387 const int is_b8x8 = IS_8X8(*mb_type);
388 unsigned int sub_mb_type= MB_TYPE_L0L1;
389 int i8, i4;
390 int ref[2];
391 int mv[2];
392 int list;
394 //assert(h->ref_list[1][0].reference&3);
396 #define MB_TYPE_16x16_OR_INTRA (MB_TYPE_16x16|MB_TYPE_INTRA4x4|MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM)
398 /* ref = min(neighbors) */
399 for(list=0; list<2; list++){
400 int left_ref = mrs->ref_cache[list][scan8[0] - 1];
401 int top_ref = mrs->ref_cache[list][scan8[0] - 8];
402 int refc = mrs->ref_cache[list][scan8[0] - 8 + 4];
403 const int16_t *C= mrs->mv_cache[list][ scan8[0] - 8 + 4];
404 if(refc == PART_NOT_AVAILABLE){
405 refc = mrs->ref_cache[list][scan8[0] - 8 - 1];
406 C = mrs->mv_cache[list][scan8[0] - 8 - 1];
407 }
408 ref[list] = FFMIN3((unsigned)left_ref, (unsigned)top_ref, (unsigned)refc);
409 if(ref[list] >= 0){
410 //this is just pred_motion() but with the cases removed that cannot happen for direct blocks
411 const int16_t * const A= mrs->mv_cache[list][ scan8[0] - 1 ];
412 const int16_t * const B= mrs->mv_cache[list][ scan8[0] - 8 ];
414 int match_count= (left_ref==ref[list]) + (top_ref==ref[list]) + (refc==ref[list]);
415 if(match_count > 1){ //most common
416 mv[list]= pack16to32(mid_pred(A[0], B[0], C[0]),
417 mid_pred(A[1], B[1], C[1]) );
418 }else {
419 assert(match_count==1);
420 if(left_ref==ref[list]){
421 mv[list]= AV_RN32A(A);
422 }else if(top_ref==ref[list]){
423 mv[list]= AV_RN32A(B);
424 }else{
425 mv[list]= AV_RN32A(C);
426 }
427 }
428 }else{
429 int mask= ~(MB_TYPE_L0 << (2*list));
430 mv[list] = 0;
431 ref[list] = -1;
432 if(!is_b8x8)
433 *mb_type &= mask;
434 sub_mb_type &= mask;
435 }
436 }
438 if(ref[0] < 0 && ref[1] < 0){
439 ref[0] = ref[1] = 0;
440 if(!is_b8x8)
441 *mb_type |= MB_TYPE_L0L1;
442 sub_mb_type |= MB_TYPE_L0L1;
443 }
445 if(!(is_b8x8|mv[0]|mv[1])){
446 fill_rectangle(&mrs->ref_cache[0][scan8[0]], 4, 4, 8, (uint8_t)ref[0], 1);
447 fill_rectangle(&mrs->ref_cache[1][scan8[0]], 4, 4, 8, (uint8_t)ref[1], 1);
448 fill_rectangle(&mrs->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4);
449 fill_rectangle(&mrs->mv_cache[1][scan8[0]], 4, 4, 8, 0, 4);
450 *mb_type= (*mb_type & ~(MB_TYPE_8x8|MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_P1L0|MB_TYPE_P1L1))|MB_TYPE_16x16|MB_TYPE_DIRECT2;
451 return;
452 }
454 mb_type_col[0] =
455 mb_type_col[1] = mrs->list1_mb_type[mb_x];
457 sub_mb_type |= MB_TYPE_16x16|MB_TYPE_DIRECT2; /* B_SUB_8x8 */
458 if(!is_b8x8 && (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA)){
459 *mb_type |= MB_TYPE_16x16|MB_TYPE_DIRECT2; /* B_16x16 */
460 }else if(!is_b8x8 && (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16))){
461 *mb_type |= MB_TYPE_DIRECT2 | (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16));
462 }else{
463 if(!s->direct_8x8_inference_flag){
464 /* FIXME save sub mb types from previous frames (or derive from MVs)
465 * so we know exactly what block size to use */
466 sub_mb_type += (MB_TYPE_8x8-MB_TYPE_16x16); /* B_SUB_4x4 */
467 }
468 *mb_type |= MB_TYPE_8x8;
469 }
471 l1mv0 = (void *) &mrs->list1_motion_val[0][4*mb_x];
472 l1mv1 = (void *) &mrs->list1_motion_val[1][4*mb_x];
473 l1ref0 = &mrs->list1_ref_index [0][4*mb_x];
474 l1ref1 = &mrs->list1_ref_index [1][4*mb_x];
475 // if(!b8_stride){
476 // if(m->mb_y&1){
477 // l1ref0 += 2;
478 // l1ref1 += 2;
479 // l1mv0 += 2*b4_stride;
480 // l1mv1 += 2*b4_stride;
481 // }
482 // }
484 if(IS_16X16(*mb_type)){
485 int a,b;
487 fill_rectangle(&mrs->ref_cache[0][scan8[0]], 4, 4, 8, (uint8_t)ref[0], 1);
488 fill_rectangle(&mrs->ref_cache[1][scan8[0]], 4, 4, 8, (uint8_t)ref[1], 1);
489 if(!IS_INTRA(mb_type_col[0]) && ( (l1ref0[0] == 0 && FFABS(l1mv0[0][0]) <= 1 && FFABS(l1mv0[0][1]) <= 1)
490 || (l1ref0[0] < 0 && l1ref1[0] == 0 && FFABS(l1mv1[0][0]) <= 1 && FFABS(l1mv1[0][1]) <= 1
491 ))){
492 a=b=0;
493 if(ref[0] > 0)
494 a= mv[0];
495 if(ref[1] > 0)
496 b= mv[1];
497 }else{
498 a= mv[0];
499 b= mv[1];
500 }
501 fill_rectangle(&mrs->mv_cache[0][scan8[0]], 4, 4, 8, a, 4);
502 fill_rectangle(&mrs->mv_cache[1][scan8[0]], 4, 4, 8, b, 4);
503 }else{
504 int n=0;
505 for(i8=0; i8<4; i8++){
506 const int x8 = i8&1;
507 const int y8 = i8>>1;
509 if(is_b8x8 && !IS_DIRECT(m->sub_mb_type[i8]))
510 continue;
511 m->sub_mb_type[i8] = sub_mb_type;
513 fill_rectangle(&mrs->mv_cache[0][scan8[i8*4]], 2, 2, 8, mv[0], 4);
514 fill_rectangle(&mrs->mv_cache[1][scan8[i8*4]], 2, 2, 8, mv[1], 4);
515 fill_rectangle(&mrs->ref_cache[0][scan8[i8*4]], 2, 2, 8, (uint8_t)ref[0], 1);
516 fill_rectangle(&mrs->ref_cache[1][scan8[i8*4]], 2, 2, 8, (uint8_t)ref[1], 1);
518 /* col_zero_flag */
519 if(!IS_INTRA(mb_type_col[0]) && (l1ref0[i8] == 0 || (l1ref0[i8] < 0 && l1ref1[i8] == 0 ))
520 ){
521 const int16_t (*l1mv)[2]= l1ref0[i8] == 0 ? l1mv0 : l1mv1;
522 if(IS_SUB_8X8(sub_mb_type)){
523 const int16_t *mv_col = l1mv[x8*3 + y8*3*b4_stride];
524 if(FFABS(mv_col[0]) <= 1 && FFABS(mv_col[1]) <= 1){
525 if(ref[0] == 0)
526 fill_rectangle(&mrs->mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4);
527 if(ref[1] == 0)
528 fill_rectangle(&mrs->mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4);
529 n+=4;
530 }
531 }else{
532 int k=0;
533 for(i4=0; i4<4; i4++){
534 const int16_t *mv_col = l1mv[x8*2 + (i4&1) + (y8*2 + (i4>>1))*b4_stride];
535 if(FFABS(mv_col[0]) <= 1 && FFABS(mv_col[1]) <= 1){
536 if(ref[0] == 0)
537 AV_ZERO32(mrs->mv_cache[0][scan8[i8*4+i4]]);
538 if(ref[1] == 0)
539 AV_ZERO32(mrs->mv_cache[1][scan8[i8*4+i4]]);
540 k++;
541 }
542 }
543 if(!(k&3))
544 m->sub_mb_type[i8]+= MB_TYPE_16x16 - MB_TYPE_8x8;
545 n+=k;
546 }
547 }
548 }
549 if(!is_b8x8 && !(n&15)){
550 *mb_type= (*mb_type & ~(MB_TYPE_8x8|MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_P1L0|MB_TYPE_P1L1))|MB_TYPE_16x16|MB_TYPE_DIRECT2;
551 }
552 }
553 }
555 static void pred_temp_direct_motion_rec(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int *mb_type){
556 const int mb_x = m->mb_x;
557 int b4_stride = mrc->b_stride;
558 int mb_type_col[2];
559 const int16_t (*l1mv0)[2], (*l1mv1)[2];
560 const int8_t *l1ref0, *l1ref1;
561 const int is_b8x8 = IS_8X8(*mb_type);
562 unsigned int sub_mb_type;
563 int i8, i4;
564 const int *map_col_to_list0[2] = {s->map_col_to_list0[0], s->map_col_to_list0[1]};
565 const int *dist_scale_factor = s->dist_scale_factor;
567 mb_type_col[0] =
568 mb_type_col[1] = mrs->list1_mb_type[mb_x];
570 sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */
571 if(!is_b8x8 && (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA)){
572 *mb_type |= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_16x16 */
573 }else if(!is_b8x8 && (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16))){
574 *mb_type |= MB_TYPE_L0L1|MB_TYPE_DIRECT2 | (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16));
575 }else{
576 if(!s->direct_8x8_inference_flag){
577 /* FIXME save sub mb types from previous frames (or derive from MVs)
578 * so we know exactly what block size to use */
579 sub_mb_type = MB_TYPE_8x8|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_4x4 */
580 }
581 *mb_type |= MB_TYPE_8x8|MB_TYPE_L0L1;
582 }
584 l1mv0 = (void *) &mrs->list1_motion_val[0][4*mb_x];
585 l1mv1 = (void *) &mrs->list1_motion_val[1][4*mb_x];
586 l1ref0 = &mrs->list1_ref_index [0][4*mb_x];
587 l1ref1 = &mrs->list1_ref_index [1][4*mb_x];
589 /* one-to-one mv scaling */
590 if(IS_16X16(*mb_type)){
591 int ref, mv0, mv1;
593 fill_rectangle(&mrs->ref_cache[1][scan8[0]], 4, 4, 8, 0, 1);
594 if(IS_INTRA(mb_type_col[0])){
595 ref=mv0=mv1=0;
596 }else{
597 const int ref0 = l1ref0[0] >= 0 ? map_col_to_list0[0][l1ref0[0]]
598 : map_col_to_list0[1][l1ref1[0]];
599 const int scale = dist_scale_factor[ref0];
600 const int16_t *mv_col = l1ref0[0] >= 0 ? l1mv0[0] : l1mv1[0];
601 int mv_l0[2];
602 mv_l0[0] = (scale * mv_col[0] + 128) >> 8;
603 mv_l0[1] = (scale * mv_col[1] + 128) >> 8;
604 ref= ref0;
605 mv0= pack16to32(mv_l0[0],mv_l0[1]);
606 mv1= pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]);
607 }
608 fill_rectangle(&mrs->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
609 fill_rectangle(&mrs->mv_cache[0][scan8[0]], 4, 4, 8, mv0, 4);
610 fill_rectangle(&mrs->mv_cache[1][scan8[0]], 4, 4, 8, mv1, 4);
611 }else{
612 for(i8=0; i8<4; i8++){
613 const int x8 = i8&1;
614 const int y8 = i8>>1;
615 int ref0, scale;
616 const int16_t (*l1mv)[2]= l1mv0;
618 if(is_b8x8 && !IS_DIRECT(m->sub_mb_type[i8]))
619 continue;
620 m->sub_mb_type[i8] = sub_mb_type;
621 fill_rectangle(&mrs->ref_cache[1][scan8[i8*4]], 2, 2, 8, 0, 1);
622 if(IS_INTRA(mb_type_col[0])){
623 fill_rectangle(&mrs->ref_cache[0][scan8[i8*4]], 2, 2, 8, 0, 1);
624 fill_rectangle(&mrs->mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4);
625 fill_rectangle(&mrs->mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4);
626 continue;
627 }
629 ref0 = l1ref0[i8];
630 if(ref0 >= 0)
631 ref0 = map_col_to_list0[0][ref0 ];
632 else{
633 ref0 = map_col_to_list0[1][l1ref1[i8]];
634 l1mv= l1mv1;
635 }
636 scale = dist_scale_factor[ref0];
638 fill_rectangle(&mrs->ref_cache[0][scan8[i8*4]], 2, 2, 8, ref0, 1);
639 if(IS_SUB_8X8(sub_mb_type)){
640 const int16_t *mv_col = l1mv[x8*3 + y8*3*b4_stride];
641 int mx = (scale * mv_col[0] + 128) >> 8;
642 int my = (scale * mv_col[1] + 128) >> 8;
643 fill_rectangle(&mrs->mv_cache[0][scan8[i8*4]], 2, 2, 8, pack16to32(mx,my), 4);
644 fill_rectangle(&mrs->mv_cache[1][scan8[i8*4]], 2, 2, 8, pack16to32(mx-mv_col[0],my-mv_col[1]), 4);
645 }else
646 for(i4=0; i4<4; i4++){
647 const int16_t *mv_col = l1mv[x8*2 + (i4&1) + (y8*2 + (i4>>1))*b4_stride];
648 int16_t *mv_l0 = mrs->mv_cache[0][scan8[i8*4+i4]];
649 mv_l0[0] = (scale * mv_col[0] + 128) >> 8;
650 mv_l0[1] = (scale * mv_col[1] + 128) >> 8;
651 AV_WN32A(mrs->mv_cache[1][scan8[i8*4+i4]],
652 pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]));
653 }
654 }
655 }
656 }
658 void ff_h264_pred_direct_motion_rec(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int *mb_type){
659 if(s->direct_spatial_mv_pred){
660 pred_spatial_direct_motion_rec(mrc, mrs, s, m, mb_type);
661 }else{
662 pred_temp_direct_motion_rec(mrc, mrs, s, m, mb_type);
663 }
664 }
666 static inline int fetch_diagonal_mv(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, const int16_t **C, int i, int list, int part_width){
667 const int topright_ref= mrs->ref_cache[list][ i - 8 + part_width ];
669 if(topright_ref != PART_NOT_AVAILABLE){
670 *C= mrs->mv_cache[list][ i - 8 + part_width ];
671 return topright_ref;
672 }else{
673 *C= mrs->mv_cache[list][ i - 8 - 1 ];
674 return mrs->ref_cache[list][ i - 8 - 1 ];
675 }
676 }
678 /**
679 * gets the predicted MV.
680 * @param n the block index
681 * @param part_width the width of the partition (4, 8,16) -> (1, 2, 4)
682 * @param mx the x component of the predicted motion vector
683 * @param my the y component of the predicted motion vector
684 */
685 static inline void pred_motion(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, int n, int part_width, int list, int ref, int * const mx, int * const my){
686 const int index8= scan8[n];
687 const int top_ref= mrs->ref_cache[list][ index8 - 8 ];
688 const int left_ref= mrs->ref_cache[list][ index8 - 1 ];
689 const int16_t * const A= mrs->mv_cache[list][ index8 - 1 ];
690 const int16_t * const B= mrs->mv_cache[list][ index8 - 8 ];
691 const int16_t * C;
692 int diagonal_ref, match_count;
694 assert(part_width==1 || part_width==2 || part_width==4);
696 /* mv_cache
697 B . . A T T T T
698 U . . L . . , .
699 U . . L . . . .
700 U . . L . . , .
701 . . . L . . . .
702 */
704 diagonal_ref= fetch_diagonal_mv(mrc, mrs, s, &C, index8, list, part_width);
705 match_count= (diagonal_ref==ref) + (top_ref==ref) + (left_ref==ref);
707 if(match_count > 1){ //most common
708 *mx= mid_pred(A[0], B[0], C[0]);
709 *my= mid_pred(A[1], B[1], C[1]);
710 }else if(match_count==1){
711 if(left_ref==ref){
712 *mx= A[0];
713 *my= A[1];
714 }else if(top_ref==ref){
715 *mx= B[0];
716 *my= B[1];
717 }else{
718 *mx= C[0];
719 *my= C[1];
720 }
721 }else{
722 if(top_ref == PART_NOT_AVAILABLE && diagonal_ref == PART_NOT_AVAILABLE && left_ref != PART_NOT_AVAILABLE){
723 *mx= A[0];
724 *my= A[1];
725 }else{
726 *mx= mid_pred(A[0], B[0], C[0]);
727 *my= mid_pred(A[1], B[1], C[1]);
728 }
729 }
731 }
733 /**
734 * gets the directionally predicted 16x8 MV.
735 * @param n the block index
736 * @param mx the x component of the predicted motion vector
737 * @param my the y component of the predicted motion vector
738 */
739 static inline void pred_16x8_motion(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, int n, int list, int ref, int * const mx, int * const my){
740 if(n==0){
741 const int top_ref= mrs->ref_cache[list][ scan8[0] - 8 ];
742 const int16_t * const B= mrs->mv_cache[list][ scan8[0] - 8 ];
744 if(top_ref == ref){
745 *mx= B[0];
746 *my= B[1];
747 return;
748 }
749 }else{
750 const int left_ref= mrs->ref_cache[list][ scan8[8] - 1 ];
751 const int16_t * const A= mrs->mv_cache[list][ scan8[8] - 1 ];
753 if(left_ref == ref){
754 *mx= A[0];
755 *my= A[1];
756 return;
757 }
758 }
760 //RARE
761 pred_motion(mrc, mrs, s, n, 4, list, ref, mx, my);
762 }
764 /**
765 * gets the directionally predicted 8x16 MV.
766 * @param n the block index
767 * @param mx the x component of the predicted motion vector
768 * @param my the y component of the predicted motion vector
769 */
770 static inline void pred_8x16_motion(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, int n, int list, int ref, int * const mx, int * const my){
771 if(n==0){
772 const int left_ref= mrs->ref_cache[list][ scan8[0] - 1 ];
773 const int16_t * const A= mrs->mv_cache[list][ scan8[0] - 1 ];
775 if(left_ref == ref){
776 *mx= A[0];
777 *my= A[1];
778 return;
779 }
780 }else{
781 const int16_t * C;
782 int diagonal_ref;
784 diagonal_ref= fetch_diagonal_mv(mrc, mrs, s, &C, scan8[4], list, 2);
785 if(diagonal_ref == ref){
786 *mx= C[0];
787 *my= C[1];
788 return;
789 }
790 }
792 //RARE
793 pred_motion(mrc, mrs, s, n, 2, list, ref, mx, my);
794 }
796 static inline void pred_pskip_motion(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb * m, int * const mx, int * const my){
797 const int top_ref = mrs->ref_cache[0][ scan8[0] - 8 ];
798 const int left_ref= mrs->ref_cache[0][ scan8[0] - 1 ];
800 if(top_ref == PART_NOT_AVAILABLE || left_ref == PART_NOT_AVAILABLE
801 || !( top_ref | AV_RN32A(mrs->mv_cache[0][ scan8[0] - 8 ]))
802 || !(left_ref | AV_RN32A(mrs->mv_cache[0][ scan8[0] - 1 ]))){
804 *mx = *my = 0;
805 return;
806 }
808 pred_motion(mrc, mrs, s, 0, 4, 0, 0, mx, my);
810 return;
811 }
813 #define ADD_MVD(list) \
814 { \
815 mx += m->mvd[list][mp][0]; \
816 my += m->mvd[list][mp][1]; \
817 mp++; \
818 }
820 int pred_motion_mb_rec (MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m){
821 int mp=0;
822 int mb_type = m->mb_type;
823 const int mb_x = m->mb_x;
825 // mrc->m =m;
827 fill_decode_caches_rec(mrc, mrs, s, m, mb_type);
828 if (IS_SKIP(mb_type)){
829 mb_type=0;
831 if( s->slice_type_nos == FF_B_TYPE )
832 {
833 mb_type|= MB_TYPE_L0L1|MB_TYPE_DIRECT2|MB_TYPE_SKIP;
834 ff_h264_pred_direct_motion_rec(mrc, mrs, s, m, &mb_type);
835 }
836 else
837 {
838 int mx, my;
840 mb_type|= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P1L0|MB_TYPE_SKIP; //FIXME check required
841 pred_pskip_motion(mrc, mrs, s, m, &mx, &my);
842 fill_rectangle(&mrs->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1);
843 fill_rectangle(mrs->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mx,my), 4);
844 }
846 write_back_motion_rec(mrc, mrs, s, m, mb_type);
847 m->mb_type = mrs->mb_type[mb_x]= mb_type;
848 return 0;
849 }
852 if (IS_INTRA_PCM(mb_type)){
853 mrs->mb_type[mb_x] = mb_type;
854 return 0;
855 }
856 else if (IS_INTRA(mb_type)){
857 int i, pred_mode;
859 if( IS_INTRA4x4( mb_type ) ) {
860 if ( IS_8x8DCT(mb_type) ) {
861 for( i = 0; i < 16; i+=4 ) {
862 int pred = pred_intra_mode(mrc, mrs, i );
863 int mode = m->intra4x4_pred_mode[i];
865 mode = mode < 0 ? pred : mode + ( mode >= pred );
866 fill_rectangle( &mrs->intra4x4_pred_mode_cache[ scan8[i] ], 2, 2, 8, mode, 1 );
867 }
868 } else {
869 for( i = 0; i < 16; i++ ) {
870 int pred = pred_intra_mode(mrc, mrs, i );
871 int mode = m->intra4x4_pred_mode[i];
872 mode = mode < 0 ? pred : mode + ( mode >= pred );
873 mrs->intra4x4_pred_mode_cache[ scan8[i] ] = mode;
874 }
875 }
876 write_back_intra_pred_mode_rec(mrc, mrs, m, mb_x);
877 if( check_intra4x4_pred_mode(mrc, mrs, s, m) < 0 ) return -1;
878 } else {
879 m->intra16x16_pred_mode= check_intra_pred_mode(mrc, mrs, s, m, m->intra16x16_pred_mode );
880 if( m->intra16x16_pred_mode < 0 ) return -1;
881 }
883 pred_mode = m->chroma_pred_mode;
884 pred_mode= check_intra_pred_mode( mrc, mrs, s, m, pred_mode );
885 if( pred_mode < 0 ) return -1;
886 m->chroma_pred_mode= pred_mode;
888 }
889 else if (IS_8X8(mb_type)){
890 int i, j, list;
892 if( s->slice_type_nos == FF_B_TYPE ) {
893 if( IS_DIRECT(m->sub_mb_type[0] | m->sub_mb_type[1] |
894 m->sub_mb_type[2] | m->sub_mb_type[3]) ) {
895 ff_h264_pred_direct_motion_rec(mrc, mrs, s, m, &mb_type);
896 mrs->ref_cache[0][scan8[4]] =
897 mrs->ref_cache[1][scan8[4]] =
898 mrs->ref_cache[0][scan8[12]] =
899 mrs->ref_cache[1][scan8[12]] = PART_NOT_AVAILABLE;
900 }
901 }
903 for(list=0; list<s->list_count; list++){
904 for(i=0; i<4; i++){
905 if(IS_DIRECT(m->sub_mb_type[i])){
906 mrs->ref_cache[list][ scan8[4*i] ]=mrs->ref_cache[list][ scan8[4*i]+1 ];
907 continue;
908 } else {
909 mrs->ref_cache[list][ scan8[4*i] ]=mrs->ref_cache[list][ scan8[4*i]+1 ]=
910 mrs->ref_cache[list][ scan8[4*i]+8 ]=mrs->ref_cache[list][ scan8[4*i]+9 ]= m->ref_index[list][i];
912 if(IS_DIR(m->sub_mb_type[i], 0, list) ){
913 const int sub_mb_type= m->sub_mb_type[i];
914 const int block_width= (sub_mb_type & (MB_TYPE_16x16|MB_TYPE_16x8)) ? 2 : 1;
916 int sub_partition_count = IS_SUB_8X8(sub_mb_type) ? 1 : (IS_SUB_4X4(sub_mb_type)? 4 :2);
917 for(j=0; j<sub_partition_count; j++){
918 int mx, my;
919 const int index= 4*i + block_width*j;
920 int16_t (* mv_cache)[2]= &mrs->mv_cache[list][ scan8[index]];
921 pred_motion(mrc, mrs, s, index, block_width, list, mrs->ref_cache[list][ scan8[index] ], &mx, &my);
923 ADD_MVD(list)
925 if(IS_SUB_8X8(sub_mb_type)){
926 mv_cache[ 1 ][0]=
927 mv_cache[ 8 ][0]= mv_cache[ 9 ][0]= mx;
928 mv_cache[ 1 ][1]=
929 mv_cache[ 8 ][1]= mv_cache[ 9 ][1]= my;
930 }else if(IS_SUB_8X4(sub_mb_type)){
931 mv_cache[ 1 ][0]= mx;
932 mv_cache[ 1 ][1]= my;
933 }else if(IS_SUB_4X8(sub_mb_type)){
934 mv_cache[ 8 ][0]= mx;
935 mv_cache[ 8 ][1]= my;
936 }
937 mv_cache[ 0 ][0]= mx;
938 mv_cache[ 0 ][1]= my;
939 }
940 }else{
941 fill_rectangle(mrs->mv_cache [list][ scan8[4*i] ], 2, 2, 8, 0, 4);
942 }
943 }
944 }
945 }
946 } else if( IS_DIRECT(mb_type) ) {
947 mb_type &= ~MB_TYPE_16x16; //FIXME not nice
948 ff_h264_pred_direct_motion_rec(mrc, mrs, s, m, &mb_type);
949 }
950 else {
951 int list, i;
952 if(IS_16X16(mb_type)){
953 for(list=0; list<s->list_count; list++){
954 if(IS_DIR(mb_type, 0, list)){
955 int ref;
956 int mx,my;
958 ref = m->ref_index[list][0];
959 fill_rectangle(&mrs->ref_cache[list][ scan8[0] ], 4, 4, 8, ref, 1);
960 pred_motion(mrc, mrs, s, 0, 4, list, mrs->ref_cache[list][ scan8[0] ], &mx, &my);
961 ADD_MVD(list)
962 fill_rectangle(mrs->mv_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx,my), 4);
963 }
964 }
965 }
966 else if(IS_16X8(mb_type)){
967 for(list=0; list<s->list_count; list++){
968 for(i=0; i<2; i++){
969 if(IS_DIR(mb_type, i, list)){
970 int ref;
971 int mx,my;
972 ref = m->ref_index[list][i];
973 fill_rectangle(&mrs->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, ref, 1);
975 pred_16x8_motion(mrc, mrs, s, 8*i, list, mrs->ref_cache[list][scan8[0] + 16*i], &mx, &my);
976 ADD_MVD(list)
978 fill_rectangle(mrs->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack16to32(mx,my), 4);
979 }else{
980 fill_rectangle(&mrs->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, (LIST_NOT_USED&0xFF), 1);
981 fill_rectangle(mrs->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 4);
982 }
983 }
984 }
986 }else{
987 assert(IS_8X16(mb_type));
989 for(list=0; list<s->list_count; list++){
990 for(i=0; i<2; i++){
991 if(IS_DIR(mb_type, i, list)){ //FIXME optimize
992 int ref;
993 int mx,my;
994 ref = m->ref_index[list][i];
995 fill_rectangle(&mrs->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, ref, 1);
996 pred_8x16_motion(mrc, mrs, s, i*4, list, mrs->ref_cache[list][ scan8[0] + 2*i ], &mx, &my);
997 ADD_MVD(list)
998 fill_rectangle(mrs->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack16to32(mx,my), 4);
999 }else{
1000 fill_rectangle(&mrs->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, (LIST_NOT_USED&0xFF), 1);
1001 fill_rectangle(mrs->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 4);
1008 if (IS_INTER(mb_type)||(IS_DIRECT(mb_type)))
1009 write_back_motion_rec(mrc, mrs, s, m, mb_type);
1010 m->mb_type = mrs->mb_type[mb_x]= mb_type;
1012 return 0;