annotate libavcodec/h264_pred_mode.c @ 9:ea1ba68cf0ed

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