Mercurial > cgi-bin > hgwebdir.cgi > PR > Applications > VSs > VSs__H264__App
comparison 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 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:8c7262284de3 |
|---|---|
| 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 */ | |
| 21 | |
| 22 /** | |
| 23 * @file | |
| 24 * H.264 / AVC / MPEG4 part10 direct mb/block decoding. | |
| 25 * @author Michael Niedermayer <michaelni@gmx.at> | |
| 26 */ | |
| 27 | |
| 28 #include "dsputil.h" | |
| 29 #include "avcodec.h" | |
| 30 #include "h264_data.h" | |
| 31 #include "h264.h" | |
| 32 #include "rectangle.h" | |
| 33 | |
| 34 //#undef NDEBUG | |
| 35 #include <assert.h> | |
| 36 | |
| 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 }; | |
| 43 | |
| 44 | |
| 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 // } | |
| 54 | |
| 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 // } | |
| 64 | |
| 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; | |
| 70 | |
| 71 mrs->top_type = mrs->mb_type_top[mb_x ]; | |
| 72 mrs->left_type = mrs->mb_type [mb_x-1]; | |
| 73 | |
| 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]; | |
| 78 | |
| 79 int type_mask= s->pps.constrained_intra_pred ? 1 : -1; | |
| 80 | |
| 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]); | |
| 87 | |
| 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 } | |
| 94 | |
| 95 if(IS_INTRA(mb_type)){ | |
| 96 // memset(mrc->intra4x4_pred_mode_cache, 0, sizeof(mrc->intra4x4_pred_mode_cache)); | |
| 97 | |
| 98 mrs->topleft_samples_available= | |
| 99 mrs->top_samples_available= | |
| 100 mrs->left_samples_available= 0xFFFF; | |
| 101 mrs->topright_samples_available= 0xEEEA; | |
| 102 | |
| 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 } | |
| 108 | |
| 109 if(!(left_type & type_mask)){ | |
| 110 mrs->topleft_samples_available&= 0xDF5F; | |
| 111 mrs->left_samples_available&= 0x5F5F; | |
| 112 } | |
| 113 | |
| 114 if(!(topleft_type & type_mask)) | |
| 115 mrs->topleft_samples_available&= 0x7FFF; | |
| 116 | |
| 117 if(!(topright_type & type_mask)) | |
| 118 mrs->topright_samples_available&= 0xFBFF; | |
| 119 | |
| 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 } | |
| 129 | |
| 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 } | |
| 151 | |
| 152 if(IS_INTER(mb_type) ||(IS_DIRECT(mb_type) && s->direct_spatial_mv_pred)){ | |
| 153 int list; | |
| 154 | |
| 155 // memset(mrs->mv_cache, 0, sizeof(mrs->mv_cache)); | |
| 156 // memset(mrs->ref_cache, 0, sizeof(mrs->ref_cache)); | |
| 157 | |
| 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; | |
| 160 | |
| 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)); | |
| 166 | |
| 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 } | |
| 178 | |
| 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 } | |
| 207 | |
| 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 } | |
| 228 | |
| 229 if((mb_type&(MB_TYPE_SKIP|MB_TYPE_DIRECT2))) | |
| 230 continue; | |
| 231 | |
| 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 } | |
| 241 | |
| 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; | |
| 247 | |
| 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); | |
| 250 | |
| 251 for(list=0; list<s->list_count; list++){ | |
| 252 int y; | |
| 253 int16_t (*mv_dst)[2]; | |
| 254 int16_t (*mv_src)[2]; | |
| 255 | |
| 256 if(!USES_LIST(mb_type, list)) | |
| 257 continue; | |
| 258 | |
| 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 } | |
| 264 | |
| 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 } | |
| 274 | |
| 275 | |
| 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; | |
| 283 | |
| 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 } | |
| 295 | |
| 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 } | |
| 312 | |
| 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}; | |
| 319 | |
| 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 } | |
| 324 | |
| 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 } | |
| 332 | |
| 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 } | |
| 345 | |
| 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); | |
| 354 | |
| 355 if(min<0) return DC_PRED; | |
| 356 else return min; | |
| 357 } | |
| 358 | |
| 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]; | |
| 361 | |
| 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 } | |
| 380 | |
| 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; | |
| 393 | |
| 394 //assert(h->ref_list[1][0].reference&3); | |
| 395 | |
| 396 #define MB_TYPE_16x16_OR_INTRA (MB_TYPE_16x16|MB_TYPE_INTRA4x4|MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM) | |
| 397 | |
| 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 ]; | |
| 413 | |
| 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 } | |
| 437 | |
| 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 } | |
| 444 | |
| 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 } | |
| 453 | |
| 454 mb_type_col[0] = | |
| 455 mb_type_col[1] = mrs->list1_mb_type[mb_x]; | |
| 456 | |
| 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 } | |
| 470 | |
| 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 // } | |
| 483 | |
| 484 if(IS_16X16(*mb_type)){ | |
| 485 int a,b; | |
| 486 | |
| 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; | |
| 508 | |
| 509 if(is_b8x8 && !IS_DIRECT(m->sub_mb_type[i8])) | |
| 510 continue; | |
| 511 m->sub_mb_type[i8] = sub_mb_type; | |
| 512 | |
| 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); | |
| 517 | |
| 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 } | |
| 554 | |
| 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; | |
| 566 | |
| 567 mb_type_col[0] = | |
| 568 mb_type_col[1] = mrs->list1_mb_type[mb_x]; | |
| 569 | |
| 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 } | |
| 583 | |
| 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]; | |
| 588 | |
| 589 /* one-to-one mv scaling */ | |
| 590 if(IS_16X16(*mb_type)){ | |
| 591 int ref, mv0, mv1; | |
| 592 | |
| 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; | |
| 617 | |
| 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 } | |
| 628 | |
| 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]; | |
| 637 | |
| 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 } | |
| 657 | |
| 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 } | |
| 665 | |
| 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 ]; | |
| 668 | |
| 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 } | |
| 677 | |
| 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; | |
| 693 | |
| 694 assert(part_width==1 || part_width==2 || part_width==4); | |
| 695 | |
| 696 /* mv_cache | |
| 697 B . . A T T T T | |
| 698 U . . L . . , . | |
| 699 U . . L . . . . | |
| 700 U . . L . . , . | |
| 701 . . . L . . . . | |
| 702 */ | |
| 703 | |
| 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); | |
| 706 | |
| 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 } | |
| 730 | |
| 731 } | |
| 732 | |
| 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 ]; | |
| 743 | |
| 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 ]; | |
| 752 | |
| 753 if(left_ref == ref){ | |
| 754 *mx= A[0]; | |
| 755 *my= A[1]; | |
| 756 return; | |
| 757 } | |
| 758 } | |
| 759 | |
| 760 //RARE | |
| 761 pred_motion(mrc, mrs, s, n, 4, list, ref, mx, my); | |
| 762 } | |
| 763 | |
| 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 ]; | |
| 774 | |
| 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; | |
| 783 | |
| 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 } | |
| 791 | |
| 792 //RARE | |
| 793 pred_motion(mrc, mrs, s, n, 2, list, ref, mx, my); | |
| 794 } | |
| 795 | |
| 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 ]; | |
| 799 | |
| 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 ]))){ | |
| 803 | |
| 804 *mx = *my = 0; | |
| 805 return; | |
| 806 } | |
| 807 | |
| 808 pred_motion(mrc, mrs, s, 0, 4, 0, 0, mx, my); | |
| 809 | |
| 810 return; | |
| 811 } | |
| 812 | |
| 813 #define ADD_MVD(list) \ | |
| 814 { \ | |
| 815 mx += m->mvd[list][mp][0]; \ | |
| 816 my += m->mvd[list][mp][1]; \ | |
| 817 mp++; \ | |
| 818 } | |
| 819 | |
| 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; | |
| 824 | |
| 825 // mrc->m =m; | |
| 826 | |
| 827 fill_decode_caches_rec(mrc, mrs, s, m, mb_type); | |
| 828 if (IS_SKIP(mb_type)){ | |
| 829 mb_type=0; | |
| 830 | |
| 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; | |
| 839 | |
| 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 } | |
| 845 | |
| 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 } | |
| 850 | |
| 851 | |
| 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; | |
| 858 | |
| 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]; | |
| 864 | |
| 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 } | |
| 882 | |
| 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; | |
| 887 | |
| 888 } | |
| 889 else if (IS_8X8(mb_type)){ | |
| 890 int i, j, list; | |
| 891 | |
| 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 } | |
| 902 | |
| 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]; | |
| 911 | |
| 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; | |
| 915 | |
| 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); | |
| 922 | |
| 923 ADD_MVD(list) | |
| 924 | |
| 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; | |
| 957 | |
| 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); | |
| 974 | |
| 975 pred_16x8_motion(mrc, mrs, s, 8*i, list, mrs->ref_cache[list][scan8[0] + 16*i], &mx, &my); | |
| 976 ADD_MVD(list) | |
| 977 | |
| 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 } | |
| 985 | |
| 986 }else{ | |
| 987 assert(IS_8X16(mb_type)); | |
| 988 | |
| 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); | |
| 1002 } | |
| 1003 } | |
| 1004 } | |
| 1005 } | |
| 1006 } | |
| 1007 | |
| 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; | |
| 1011 | |
| 1012 return 0; | |
| 1013 } |
