1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 #include <string.h> 19 20 #include "avclib_common.h" 21 22 OSCL_EXPORT_REF void InitNeighborAvailability(AVCCommonObj *video, int mbNum) 23 { 24 int PicWidthInMbs = video->PicWidthInMbs; 25 26 // do frame-only and postpone intraAvail calculattion 27 video->mbAddrA = mbNum - 1; 28 video->mbAddrB = mbNum - PicWidthInMbs; 29 video->mbAddrC = mbNum - PicWidthInMbs + 1; 30 video->mbAddrD = mbNum - PicWidthInMbs - 1; 31 32 video->mbAvailA = video->mbAvailB = video->mbAvailC = video->mbAvailD = 0; 33 if (video->mb_x) 34 { 35 video->mbAvailA = (video->mblock[video->mbAddrA].slice_id == video->currMB->slice_id); 36 if (video->mb_y) 37 { 38 video->mbAvailD = (video->mblock[video->mbAddrD].slice_id == video->currMB->slice_id); 39 } 40 } 41 42 if (video->mb_y) 43 { 44 video->mbAvailB = (video->mblock[video->mbAddrB].slice_id == video->currMB->slice_id); 45 if (video->mb_x < (PicWidthInMbs - 1)) 46 { 47 video->mbAvailC = (video->mblock[video->mbAddrC].slice_id == video->currMB->slice_id); 48 } 49 } 50 return ; 51 } 52 53 bool mb_is_available(AVCMacroblock *mblock, uint PicSizeInMbs, int mbAddr, int currMbAddr) 54 { 55 if (mbAddr < 0 || mbAddr >= (int)PicSizeInMbs) 56 { 57 return FALSE; 58 } 59 60 if (mblock[mbAddr].slice_id != mblock[currMbAddr].slice_id) 61 { 62 return FALSE; 63 } 64 65 return TRUE; 66 } 67 68 OSCL_EXPORT_REF int predict_nnz(AVCCommonObj *video, int i, int j) 69 { 70 int pred_nnz = 0; 71 int cnt = 1; 72 AVCMacroblock *tempMB; 73 74 /* left block */ 75 /*getLuma4x4Neighbour(video, mb_nr, i, j, -1, 0, &pix); 76 leftMB = video->mblock + pix.mb_addr; */ 77 /* replace the above with below (won't work for field decoding), 1/19/04 */ 78 79 if (i) 80 { 81 pred_nnz = video->currMB->nz_coeff[(j<<2)+i-1]; 82 } 83 else 84 { 85 if (video->mbAvailA) 86 { 87 tempMB = video->mblock + video->mbAddrA; 88 pred_nnz = tempMB->nz_coeff[(j<<2)+3]; 89 } 90 else 91 { 92 cnt = 0; 93 } 94 } 95 96 97 /* top block */ 98 /*getLuma4x4Neighbour(video, mb_nr, i, j, 0, -1, &pix); 99 topMB = video->mblock + pix.mb_addr;*/ 100 /* replace the above with below (won't work for field decoding), 1/19/04 */ 101 102 if (j) 103 { 104 pred_nnz += video->currMB->nz_coeff[((j-1)<<2)+i]; 105 cnt++; 106 } 107 else 108 { 109 if (video->mbAvailB) 110 { 111 tempMB = video->mblock + video->mbAddrB; 112 pred_nnz += tempMB->nz_coeff[12+i]; 113 cnt++; 114 } 115 } 116 117 118 if (cnt == 2) 119 { 120 pred_nnz = (pred_nnz + 1) >> 1; 121 } 122 123 return pred_nnz; 124 125 } 126 127 128 OSCL_EXPORT_REF int predict_nnz_chroma(AVCCommonObj *video, int i, int j) 129 { 130 int pred_nnz = 0; 131 int cnt = 1; 132 AVCMacroblock *tempMB; 133 134 /* left block */ 135 /*getChroma4x4Neighbour(video, mb_nr, i%2, j-4, -1, 0, &pix); 136 leftMB = video->mblock + pix.mb_addr;*/ 137 /* replace the above with below (won't work for field decoding), 1/19/04 */ 138 if (i&1) 139 { 140 pred_nnz = video->currMB->nz_coeff[(j<<2)+i-1]; 141 142 } 143 else 144 { 145 if (video->mbAvailA) 146 { 147 tempMB = video->mblock + video->mbAddrA; 148 pred_nnz = tempMB->nz_coeff[(j<<2)+i+1]; 149 } 150 else 151 { 152 cnt = 0; 153 } 154 } 155 156 157 /* top block */ 158 /*getChroma4x4Neighbour(video, mb_nr, i%2, j-4, 0, -1, &pix); 159 topMB = video->mblock + pix.mb_addr;*/ 160 /* replace the above with below (won't work for field decoding), 1/19/04 */ 161 162 if (j&1) 163 { 164 pred_nnz += video->currMB->nz_coeff[((j-1)<<2)+i]; 165 cnt++; 166 } 167 else 168 { 169 if (video->mbAvailB) 170 { 171 tempMB = video->mblock + video->mbAddrB; 172 pred_nnz += tempMB->nz_coeff[20+i]; 173 cnt++; 174 } 175 176 } 177 178 if (cnt == 2) 179 { 180 pred_nnz = (pred_nnz + 1) >> 1; 181 } 182 183 return pred_nnz; 184 } 185 186 OSCL_EXPORT_REF void GetMotionVectorPredictor(AVCCommonObj *video, int encFlag) 187 { 188 AVCMacroblock *currMB = video->currMB; 189 AVCMacroblock *MB_A, *MB_B, *MB_C, *MB_D; 190 int block_x, block_y, block_x_1, block_y_1, new_block_x; 191 int mbPartIdx, subMbPartIdx, offset_indx; 192 int16 *mv, pmv_x, pmv_y; 193 int nmSubMbHeight, nmSubMbWidth, mbPartIdx_X, mbPartIdx_Y; 194 int avail_a, avail_b, avail_c; 195 const static uint32 C = 0x5750; 196 int i, j, offset_MbPart_indx, refIdxLXA, refIdxLXB, refIdxLXC = 0, curr_ref_idx; 197 int pmv_A_x, pmv_B_x, pmv_C_x = 0, pmv_A_y, pmv_B_y, pmv_C_y = 0; 198 199 /* we have to take care of Intra/skip blocks somewhere, i.e. set MV to 0 and set ref to -1! */ 200 /* we have to populate refIdx as well */ 201 202 203 MB_A = &video->mblock[video->mbAddrA]; 204 MB_B = &video->mblock[video->mbAddrB]; 205 206 207 if (currMB->mbMode == AVC_SKIP /* && !encFlag */) /* only for decoder */ 208 { 209 currMB->ref_idx_L0[0] = currMB->ref_idx_L0[1] = currMB->ref_idx_L0[2] = currMB->ref_idx_L0[3] = 0; 210 if (video->mbAvailA && video->mbAvailB) 211 { 212 if ((MB_A->ref_idx_L0[1] == 0 && MB_A->mvL0[3] == 0) || 213 (MB_B->ref_idx_L0[2] == 0 && MB_B->mvL0[12] == 0)) 214 { 215 memset(currMB->mvL0, 0, sizeof(int32)*16); 216 return; 217 } 218 } 219 else 220 { 221 memset(currMB->mvL0, 0, sizeof(int32)*16); 222 return; 223 } 224 video->mvd_l0[0][0][0] = 0; 225 video->mvd_l0[0][0][1] = 0; 226 } 227 228 MB_C = &video->mblock[video->mbAddrC]; 229 MB_D = &video->mblock[video->mbAddrD]; 230 231 offset_MbPart_indx = 0; 232 for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++) 233 { 234 offset_indx = 0; 235 nmSubMbHeight = currMB->SubMbPartHeight[mbPartIdx] >> 2; 236 nmSubMbWidth = currMB->SubMbPartWidth[mbPartIdx] >> 2; 237 mbPartIdx_X = ((mbPartIdx + offset_MbPart_indx) & 1) << 1; 238 mbPartIdx_Y = (mbPartIdx + offset_MbPart_indx) & 2; 239 240 for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++) 241 { 242 block_x = mbPartIdx_X + ((subMbPartIdx + offset_indx) & 1); 243 block_y = mbPartIdx_Y + (((subMbPartIdx + offset_indx) >> 1) & 1); 244 245 block_x_1 = block_x - 1; 246 block_y_1 = block_y - 1; 247 refIdxLXA = refIdxLXB = refIdxLXC = -1; 248 pmv_A_x = pmv_A_y = pmv_B_x = pmv_B_y = pmv_C_x = pmv_C_y = 0; 249 250 if (block_x) 251 { 252 avail_a = 1; 253 refIdxLXA = currMB->ref_idx_L0[(block_y & 2) + (block_x_1 >> 1)]; 254 mv = (int16*)(currMB->mvL0 + (block_y << 2) + block_x_1); 255 pmv_A_x = *mv++; 256 pmv_A_y = *mv; 257 } 258 else 259 { 260 avail_a = video->mbAvailA; 261 if (avail_a) 262 { 263 refIdxLXA = MB_A->ref_idx_L0[(block_y & 2) + 1]; 264 mv = (int16*)(MB_A->mvL0 + (block_y << 2) + 3); 265 pmv_A_x = *mv++; 266 pmv_A_y = *mv; 267 } 268 } 269 270 if (block_y) 271 { 272 avail_b = 1; 273 refIdxLXB = currMB->ref_idx_L0[(block_y_1 & 2) + (block_x >> 1)]; 274 mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + block_x); 275 pmv_B_x = *mv++; 276 pmv_B_y = *mv; 277 } 278 279 else 280 { 281 avail_b = video->mbAvailB; 282 if (avail_b) 283 { 284 refIdxLXB = MB_B->ref_idx_L0[2 + (block_x >> 1)]; 285 mv = (int16*)(MB_B->mvL0 + 12 + block_x); 286 pmv_B_x = *mv++; 287 pmv_B_y = *mv; 288 } 289 } 290 291 new_block_x = block_x + (currMB->SubMbPartWidth[mbPartIdx] >> 2) - 1; 292 avail_c = (C >> ((block_y << 2) + new_block_x)) & 0x1; 293 294 if (avail_c) 295 { 296 /* it guaranteed that block_y > 0 && new_block_x<3 ) */ 297 refIdxLXC = currMB->ref_idx_L0[(block_y_1 & 2) + ((new_block_x+1) >> 1)]; 298 mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + (new_block_x + 1)); 299 pmv_C_x = *mv++; 300 pmv_C_y = *mv; 301 } 302 else 303 { 304 if (block_y == 0 && new_block_x < 3) 305 { 306 avail_c = video->mbAvailB; 307 if (avail_c) 308 { 309 refIdxLXC = MB_B->ref_idx_L0[2 + ((new_block_x+1)>>1)]; 310 mv = (int16*)(MB_B->mvL0 + 12 + (new_block_x + 1)); 311 pmv_C_x = *mv++; 312 pmv_C_y = *mv; 313 } 314 } 315 else if (block_y == 0 && new_block_x == 3) 316 { 317 avail_c = video->mbAvailC; 318 if (avail_c) 319 { 320 refIdxLXC = MB_C->ref_idx_L0[2]; 321 mv = (int16*)(MB_C->mvL0 + 12); 322 pmv_C_x = *mv++; 323 pmv_C_y = *mv; 324 } 325 } 326 327 if (avail_c == 0) 328 { /* check D */ 329 if (block_x && block_y) 330 { 331 avail_c = 1; 332 refIdxLXC = currMB->ref_idx_L0[(block_y_1 & 2) + (block_x_1 >> 1)]; 333 mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + block_x_1); 334 pmv_C_x = *mv++; 335 pmv_C_y = *mv; 336 } 337 else if (block_y) 338 { 339 avail_c = video->mbAvailA; 340 if (avail_c) 341 { 342 refIdxLXC = MB_A->ref_idx_L0[(block_y_1 & 2) + 1]; 343 mv = (int16*)(MB_A->mvL0 + (block_y_1 << 2) + 3); 344 pmv_C_x = *mv++; 345 pmv_C_y = *mv; 346 } 347 } 348 else if (block_x) 349 { 350 avail_c = video->mbAvailB; 351 if (avail_c) 352 { 353 refIdxLXC = MB_B->ref_idx_L0[2 + (block_x_1 >> 1)]; 354 mv = (int16*)(MB_B->mvL0 + 12 + block_x_1); 355 pmv_C_x = *mv++; 356 pmv_C_y = *mv; 357 } 358 } 359 else 360 { 361 avail_c = video->mbAvailD; 362 if (avail_c) 363 { 364 refIdxLXC = MB_D->ref_idx_L0[3]; 365 mv = (int16*)(MB_D->mvL0 + 15); 366 pmv_C_x = *mv++; 367 pmv_C_y = *mv; 368 } 369 } 370 } 371 } 372 373 offset_indx = currMB->SubMbPartWidth[mbPartIdx] >> 3; 374 375 curr_ref_idx = currMB->ref_idx_L0[(block_y & 2) + (block_x >> 1)]; 376 377 if (avail_a && !(avail_b || avail_c)) 378 { 379 pmv_x = pmv_A_x; 380 pmv_y = pmv_A_y; 381 } 382 else if (((curr_ref_idx == refIdxLXA) + (curr_ref_idx == refIdxLXB) + (curr_ref_idx == refIdxLXC)) == 1) 383 { 384 if (curr_ref_idx == refIdxLXA) 385 { 386 pmv_x = pmv_A_x; 387 pmv_y = pmv_A_y; 388 } 389 else if (curr_ref_idx == refIdxLXB) 390 { 391 pmv_x = pmv_B_x; 392 pmv_y = pmv_B_y; 393 } 394 else 395 { 396 pmv_x = pmv_C_x; 397 pmv_y = pmv_C_y; 398 } 399 } 400 else 401 { 402 pmv_x = AVC_MEDIAN(pmv_A_x, pmv_B_x, pmv_C_x); 403 pmv_y = AVC_MEDIAN(pmv_A_y, pmv_B_y, pmv_C_y); 404 } 405 406 /* overwrite if special case */ 407 if (currMB->NumMbPart == 2) 408 { 409 if (currMB->MbPartWidth == 16) 410 { 411 if (mbPartIdx == 0) 412 { 413 if (refIdxLXB == curr_ref_idx) 414 { 415 pmv_x = pmv_B_x; 416 pmv_y = pmv_B_y; 417 } 418 } 419 else if (refIdxLXA == curr_ref_idx) 420 { 421 pmv_x = pmv_A_x; 422 pmv_y = pmv_A_y; 423 } 424 } 425 else 426 { 427 if (mbPartIdx == 0) 428 { 429 if (refIdxLXA == curr_ref_idx) 430 { 431 pmv_x = pmv_A_x; 432 pmv_y = pmv_A_y; 433 } 434 } 435 else if (refIdxLXC == curr_ref_idx) 436 { 437 pmv_x = pmv_C_x; 438 pmv_y = pmv_C_y; 439 } 440 } 441 } 442 443 mv = (int16*)(currMB->mvL0 + block_x + (block_y << 2)); 444 445 if (encFlag) /* calculate residual MV video->mvd_l0 */ 446 { 447 video->mvd_l0[mbPartIdx][subMbPartIdx][0] = *mv++ - pmv_x; 448 video->mvd_l0[mbPartIdx][subMbPartIdx][1] = *mv++ - pmv_y; 449 } 450 else /* calculate original MV currMB->mvL0 */ 451 { 452 pmv_x += video->mvd_l0[mbPartIdx][subMbPartIdx][0]; 453 pmv_y += video->mvd_l0[mbPartIdx][subMbPartIdx][1]; 454 455 for (i = 0; i < nmSubMbHeight; i++) 456 { 457 for (j = 0; j < nmSubMbWidth; j++) 458 { 459 *mv++ = pmv_x; 460 *mv++ = pmv_y; 461 } 462 mv += (8 - (j << 1)); 463 } 464 } 465 } 466 offset_MbPart_indx = currMB->MbPartWidth >> 4; 467 468 } 469 } 470 471 472