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 "avclib_common.h" 19 20 #define DPB_MEM_ATTR 0 21 22 AVCStatus InitDPB(AVCHandle *avcHandle, AVCCommonObj *video, int FrameHeightInMbs, int PicWidthInMbs, bool padding) 23 { 24 AVCDecPicBuffer *dpb = video->decPicBuf; 25 int level, framesize, num_fs; 26 void *userData = avcHandle->userData; 27 #ifndef PV_MEMORY_POOL 28 uint32 addr; 29 #endif 30 uint16 refIdx = 0; 31 level = video->currSeqParams->level_idc; 32 33 for (num_fs = 0; num_fs < MAX_FS; num_fs++) 34 { 35 dpb->fs[num_fs] = NULL; 36 } 37 38 framesize = (int)(((FrameHeightInMbs * PicWidthInMbs) << 7) * 3); 39 if (padding) 40 { 41 video->padded_size = (int)((((FrameHeightInMbs + 2) * (PicWidthInMbs + 2)) << 7) * 3) - framesize; 42 } 43 else 44 { 45 video->padded_size = 0; 46 } 47 48 #ifndef PV_MEMORY_POOL 49 if (dpb->decoded_picture_buffer) 50 { 51 avcHandle->CBAVC_Free(userData, (int)dpb->decoded_picture_buffer); 52 dpb->decoded_picture_buffer = NULL; 53 } 54 #endif 55 /* need to allocate one extra frame for current frame, DPB only defines for reference frames */ 56 57 dpb->num_fs = (uint32)(MaxDPBX2[mapLev2Idx[level]] << 2) / (3 * FrameHeightInMbs * PicWidthInMbs) + 1; 58 if (dpb->num_fs > MAX_FS) 59 { 60 dpb->num_fs = MAX_FS; 61 } 62 63 if (video->currSeqParams->num_ref_frames + 1 > (uint32)dpb->num_fs) 64 { 65 dpb->num_fs = video->currSeqParams->num_ref_frames + 1; 66 } 67 68 dpb->dpb_size = dpb->num_fs * (framesize + video->padded_size); 69 // dpb->dpb_size = (uint32)MaxDPBX2[mapLev2Idx[level]]*512 + framesize; 70 71 #ifndef PV_MEMORY_POOL 72 dpb->decoded_picture_buffer = (uint8*) avcHandle->CBAVC_Malloc(userData, dpb->dpb_size, 100/*DPB_MEM_ATTR*/); 73 74 if (dpb->decoded_picture_buffer == NULL || dpb->decoded_picture_buffer&0x3) // not word aligned 75 return AVC_MEMORY_FAIL; 76 #endif 77 dpb->used_size = 0; 78 num_fs = 0; 79 80 while (num_fs < dpb->num_fs) 81 { 82 /* fs is an array pointers to AVCDecPicture */ 83 dpb->fs[num_fs] = (AVCFrameStore*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCFrameStore), 101/*DEFAULT_ATTR*/); 84 if (dpb->fs[num_fs] == NULL) 85 { 86 return AVC_MEMORY_FAIL; 87 } 88 #ifndef PV_MEMORY_POOL 89 /* assign the actual memory for Sl, Scb, Scr */ 90 dpb->fs[num_fs]->base_dpb = dpb->decoded_picture_buffer + dpb->used_size; 91 #endif 92 dpb->fs[num_fs]->IsReference = 0; 93 dpb->fs[num_fs]->IsLongTerm = 0; 94 dpb->fs[num_fs]->IsOutputted = 3; 95 dpb->fs[num_fs]->frame.RefIdx = refIdx++; /* this value will remain unchanged through out the encoding session */ 96 dpb->fs[num_fs]->frame.picType = AVC_FRAME; 97 dpb->fs[num_fs]->frame.isLongTerm = 0; 98 dpb->fs[num_fs]->frame.isReference = 0; 99 video->RefPicList0[num_fs] = &(dpb->fs[num_fs]->frame); 100 dpb->fs[num_fs]->frame.padded = 0; 101 dpb->used_size += (framesize + video->padded_size); 102 num_fs++; 103 } 104 105 return AVC_SUCCESS; 106 } 107 108 OSCL_EXPORT_REF AVCStatus AVCConfigureSequence(AVCHandle *avcHandle, AVCCommonObj *video, bool padding) 109 { 110 void *userData = avcHandle->userData; 111 AVCDecPicBuffer *dpb = video->decPicBuf; 112 int framesize, ii; /* size of one frame */ 113 uint PicWidthInMbs, PicHeightInMapUnits, FrameHeightInMbs, PicSizeInMapUnits; 114 uint num_fs; 115 /* derived variables from SPS */ 116 PicWidthInMbs = video->currSeqParams->pic_width_in_mbs_minus1 + 1; 117 PicHeightInMapUnits = video->currSeqParams->pic_height_in_map_units_minus1 + 1 ; 118 FrameHeightInMbs = (2 - video->currSeqParams->frame_mbs_only_flag) * PicHeightInMapUnits ; 119 PicSizeInMapUnits = PicWidthInMbs * PicHeightInMapUnits ; 120 121 if (video->PicSizeInMapUnits != PicSizeInMapUnits || video->currSeqParams->level_idc != video->level_idc) 122 { 123 /* make sure you mark all the frames as unused for reference for flushing*/ 124 for (ii = 0; ii < dpb->num_fs; ii++) 125 { 126 dpb->fs[ii]->IsReference = 0; 127 dpb->fs[ii]->IsOutputted |= 0x02; 128 } 129 130 num_fs = (uint32)(MaxDPBX2[(uint32)mapLev2Idx[video->currSeqParams->level_idc]] << 2) / (3 * PicSizeInMapUnits) + 1; 131 if (num_fs >= MAX_FS) 132 { 133 num_fs = MAX_FS; 134 } 135 #ifdef PV_MEMORY_POOL 136 if (padding) 137 { 138 avcHandle->CBAVC_DPBAlloc(avcHandle->userData, 139 PicSizeInMapUnits + ((PicWidthInMbs + 2) << 1) + (PicHeightInMapUnits << 1), num_fs); 140 } 141 else 142 { 143 avcHandle->CBAVC_DPBAlloc(avcHandle->userData, PicSizeInMapUnits, num_fs); 144 } 145 #endif 146 CleanUpDPB(avcHandle, video); 147 if (InitDPB(avcHandle, video, FrameHeightInMbs, PicWidthInMbs, padding) != AVC_SUCCESS) 148 { 149 return AVC_FAIL; 150 } 151 /* Allocate video->mblock upto PicSizeInMbs and populate the structure such as the neighboring MB pointers. */ 152 framesize = (FrameHeightInMbs * PicWidthInMbs); 153 if (video->mblock) 154 { 155 avcHandle->CBAVC_Free(userData, (uint32)video->mblock); 156 video->mblock = NULL; 157 } 158 video->mblock = (AVCMacroblock*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCMacroblock) * framesize, DEFAULT_ATTR); 159 if (video->mblock == NULL) 160 { 161 return AVC_FAIL; 162 } 163 for (ii = 0; ii < framesize; ii++) 164 { 165 video->mblock[ii].slice_id = -1; 166 } 167 /* Allocate memory for intra prediction */ 168 #ifdef MB_BASED_DEBLOCK 169 video->intra_pred_top = (uint8*) avcHandle->CBAVC_Malloc(userData, PicWidthInMbs << 4, FAST_MEM_ATTR); 170 if (video->intra_pred_top == NULL) 171 { 172 return AVC_FAIL; 173 } 174 video->intra_pred_top_cb = (uint8*) avcHandle->CBAVC_Malloc(userData, PicWidthInMbs << 3, FAST_MEM_ATTR); 175 if (video->intra_pred_top_cb == NULL) 176 { 177 return AVC_FAIL; 178 } 179 video->intra_pred_top_cr = (uint8*) avcHandle->CBAVC_Malloc(userData, PicWidthInMbs << 3, FAST_MEM_ATTR); 180 if (video->intra_pred_top_cr == NULL) 181 { 182 return AVC_FAIL; 183 } 184 185 #endif 186 /* Allocate slice group MAP map */ 187 188 if (video->MbToSliceGroupMap) 189 { 190 avcHandle->CBAVC_Free(userData, (uint32)video->MbToSliceGroupMap); 191 video->MbToSliceGroupMap = NULL; 192 } 193 video->MbToSliceGroupMap = (int*) avcHandle->CBAVC_Malloc(userData, sizeof(uint) * PicSizeInMapUnits * 2, 7/*DEFAULT_ATTR*/); 194 if (video->MbToSliceGroupMap == NULL) 195 { 196 return AVC_FAIL; 197 } 198 video->PicSizeInMapUnits = PicSizeInMapUnits; 199 video->level_idc = video->currSeqParams->level_idc; 200 201 } 202 return AVC_SUCCESS; 203 } 204 205 OSCL_EXPORT_REF AVCStatus CleanUpDPB(AVCHandle *avcHandle, AVCCommonObj *video) 206 { 207 AVCDecPicBuffer *dpb = video->decPicBuf; 208 int ii; 209 void *userData = avcHandle->userData; 210 211 for (ii = 0; ii < MAX_FS; ii++) 212 { 213 if (dpb->fs[ii] != NULL) 214 { 215 avcHandle->CBAVC_Free(userData, (int)dpb->fs[ii]); 216 dpb->fs[ii] = NULL; 217 } 218 } 219 #ifndef PV_MEMORY_POOL 220 if (dpb->decoded_picture_buffer) 221 { 222 avcHandle->CBAVC_Free(userData, (int)dpb->decoded_picture_buffer); 223 dpb->decoded_picture_buffer = NULL; 224 } 225 #endif 226 dpb->used_size = 0; 227 dpb->dpb_size = 0; 228 229 return AVC_SUCCESS; 230 } 231 232 OSCL_EXPORT_REF AVCStatus DPBInitBuffer(AVCHandle *avcHandle, AVCCommonObj *video) 233 { 234 AVCDecPicBuffer *dpb = video->decPicBuf; 235 int ii, status; 236 237 /* Before doing any decoding, check if there's a frame memory available */ 238 /* look for next unused dpb->fs, or complementary field pair */ 239 /* video->currPic is assigned to this */ 240 241 /* There's also restriction on the frame_num, see page 59 of JVT-I1010.doc. */ 242 243 for (ii = 0; ii < dpb->num_fs; ii++) 244 { 245 /* looking for the one not used or not reference and has been outputted */ 246 if (dpb->fs[ii]->IsReference == 0 && dpb->fs[ii]->IsOutputted == 3) 247 { 248 video->currFS = dpb->fs[ii]; 249 #ifdef PV_MEMORY_POOL 250 status = avcHandle->CBAVC_FrameBind(avcHandle->userData, ii, &(video->currFS->base_dpb)); 251 if (status == AVC_FAIL) 252 { 253 return AVC_NO_BUFFER; /* this should not happen */ 254 } 255 #endif 256 break; 257 } 258 } 259 if (ii == dpb->num_fs) 260 { 261 return AVC_PICTURE_OUTPUT_READY; /* no empty frame available */ 262 } 263 return AVC_SUCCESS; 264 } 265 266 OSCL_EXPORT_REF void DPBInitPic(AVCCommonObj *video, int CurrPicNum) 267 { 268 int offset = 0; 269 int offsetc = 0; 270 int luma_framesize; 271 /* this part has to be set here, assuming that slice header and POC have been decoded. */ 272 /* used in GetOutput API */ 273 video->currFS->PicOrderCnt = video->PicOrderCnt; 274 video->currFS->FrameNum = video->sliceHdr->frame_num; 275 video->currFS->FrameNumWrap = CurrPicNum; // MC_FIX 276 /* initialize everything to zero */ 277 video->currFS->IsOutputted = 0; 278 video->currFS->IsReference = 0; 279 video->currFS->IsLongTerm = 0; 280 video->currFS->frame.isReference = FALSE; 281 video->currFS->frame.isLongTerm = FALSE; 282 283 /* initialize the pixel pointer to NULL */ 284 video->currFS->frame.Sl = video->currFS->frame.Scb = video->currFS->frame.Scr = NULL; 285 286 /* determine video->currPic */ 287 /* assign dbp->base_dpb to fs[i]->frame.Sl, Scb, Scr .*/ 288 /* For PicSizeInMbs, see DecodeSliceHeader() */ 289 290 video->currPic = &(video->currFS->frame); 291 292 video->currPic->padded = 0; // reset this flag to not-padded 293 294 if (video->padded_size) 295 { 296 offset = ((video->PicWidthInSamplesL + 32) << 4) + 16; // offset to the origin 297 offsetc = (offset >> 2) + 4; 298 luma_framesize = (int)((((video->FrameHeightInMbs + 2) * (video->PicWidthInMbs + 2)) << 8)); 299 } 300 else 301 luma_framesize = video->PicSizeInMbs << 8; 302 303 304 video->currPic->Sl = video->currFS->base_dpb + offset; 305 video->currPic->Scb = video->currFS->base_dpb + luma_framesize + offsetc; 306 video->currPic->Scr = video->currPic->Scb + (luma_framesize >> 2); 307 video->currPic->pitch = video->PicWidthInSamplesL + (video->padded_size == 0 ? 0 : 32); 308 309 310 video->currPic->height = video->PicHeightInSamplesL; 311 video->currPic->width = video->PicWidthInSamplesL; 312 video->currPic->PicNum = CurrPicNum; 313 } 314 315 /* to release skipped frame after encoding */ 316 OSCL_EXPORT_REF void DPBReleaseCurrentFrame(AVCHandle *avcHandle, AVCCommonObj *video) 317 { 318 AVCDecPicBuffer *dpb = video->decPicBuf; 319 int ii; 320 321 video->currFS->IsOutputted = 3; // return this buffer. 322 323 #ifdef PV_MEMORY_POOL /* for non-memory pool, no need to do anything */ 324 325 /* search for current frame index */ 326 ii = dpb->num_fs; 327 while (ii--) 328 { 329 if (dpb->fs[ii] == video->currFS) 330 { 331 avcHandle->CBAVC_FrameUnbind(avcHandle->userData, ii); 332 break; 333 } 334 } 335 #endif 336 337 return ; 338 } 339 340 /* see subclause 8.2.5.1 */ 341 OSCL_EXPORT_REF AVCStatus StorePictureInDPB(AVCHandle *avcHandle, AVCCommonObj *video) 342 { 343 AVCStatus status; 344 AVCDecPicBuffer *dpb = video->decPicBuf; 345 AVCSliceHeader *sliceHdr = video->sliceHdr; 346 int ii, num_ref; 347 348 /* number 1 of 8.2.5.1, we handle gaps in frame_num differently without using the memory */ 349 /* to be done!!!! */ 350 351 /* number 3 of 8.2.5.1 */ 352 if (video->nal_unit_type == AVC_NALTYPE_IDR) 353 { 354 for (ii = 0; ii < dpb->num_fs; ii++) 355 { 356 if (dpb->fs[ii] != video->currFS) /* not current frame */ 357 { 358 dpb->fs[ii]->IsReference = 0; /* mark as unused for reference */ 359 dpb->fs[ii]->IsLongTerm = 0; /* but still used until output */ 360 dpb->fs[ii]->IsOutputted |= 0x02; 361 #ifdef PV_MEMORY_POOL 362 if (dpb->fs[ii]->IsOutputted == 3) 363 { 364 avcHandle->CBAVC_FrameUnbind(avcHandle->userData, ii); 365 } 366 #endif 367 } 368 } 369 370 video->currPic->isReference = TRUE; 371 video->currFS->IsReference = 3; 372 373 if (sliceHdr->long_term_reference_flag == 0) 374 { 375 video->currPic->isLongTerm = FALSE; 376 video->currFS->IsLongTerm = 0; 377 video->MaxLongTermFrameIdx = -1; 378 } 379 else 380 { 381 video->currPic->isLongTerm = TRUE; 382 video->currFS->IsLongTerm = 3; 383 video->currFS->LongTermFrameIdx = 0; 384 video->MaxLongTermFrameIdx = 0; 385 } 386 if (sliceHdr->no_output_of_prior_pics_flag) 387 { 388 for (ii = 0; ii < dpb->num_fs; ii++) 389 { 390 if (dpb->fs[ii] != video->currFS) /* not current frame */ 391 { 392 dpb->fs[ii]->IsOutputted = 3; 393 #ifdef PV_MEMORY_POOL 394 avcHandle->CBAVC_FrameUnbind(avcHandle->userData, ii); 395 #endif 396 } 397 } 398 } 399 video->mem_mgr_ctrl_eq_5 = TRUE; /* flush reference frames MC_FIX */ 400 } 401 else 402 { 403 if (video->currPic->isReference == TRUE) 404 { 405 if (sliceHdr->adaptive_ref_pic_marking_mode_flag == 0) 406 { 407 status = sliding_window_process(avcHandle, video, dpb); /* we may have to do this after adaptive_memory_marking */ 408 } 409 else 410 { 411 status = adaptive_memory_marking(avcHandle, video, dpb, sliceHdr); 412 } 413 if (status != AVC_SUCCESS) 414 { 415 return status; 416 } 417 } 418 } 419 /* number 4 of 8.2.5.1 */ 420 /* This basically says every frame must be at least used for short-term ref. */ 421 /* Need to be revisited!!! */ 422 /* look at insert_picture_in_dpb() */ 423 424 425 426 if (video->nal_unit_type != AVC_NALTYPE_IDR && video->currPic->isLongTerm == FALSE) 427 { 428 if (video->currPic->isReference) 429 { 430 video->currFS->IsReference = 3; 431 } 432 else 433 { 434 video->currFS->IsReference = 0; 435 } 436 video->currFS->IsLongTerm = 0; 437 } 438 439 /* check if number of reference frames doesn't exceed num_ref_frames */ 440 num_ref = 0; 441 for (ii = 0; ii < dpb->num_fs; ii++) 442 { 443 if (dpb->fs[ii]->IsReference) 444 { 445 num_ref++; 446 } 447 } 448 449 if (num_ref > (int)video->currSeqParams->num_ref_frames) 450 { 451 return AVC_FAIL; /* out of range */ 452 } 453 454 return AVC_SUCCESS; 455 } 456 457 458 AVCStatus sliding_window_process(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb) 459 { 460 int ii, numShortTerm, numLongTerm; 461 int32 MinFrameNumWrap; 462 int MinIdx; 463 464 465 numShortTerm = 0; 466 numLongTerm = 0; 467 for (ii = 0; ii < dpb->num_fs; ii++) 468 { 469 if (dpb->fs[ii] != video->currFS) /* do not count the current frame */ 470 { 471 if (dpb->fs[ii]->IsLongTerm) 472 { 473 numLongTerm++; 474 } 475 else if (dpb->fs[ii]->IsReference) 476 { 477 numShortTerm++; 478 } 479 } 480 } 481 482 while (numShortTerm + numLongTerm >= (int)video->currSeqParams->num_ref_frames) 483 { 484 /* get short-term ref frame with smallest PicOrderCnt */ 485 /* this doesn't work for all I-slice clip since PicOrderCnt will not be initialized */ 486 487 MinFrameNumWrap = 0x7FFFFFFF; 488 MinIdx = -1; 489 for (ii = 0; ii < dpb->num_fs; ii++) 490 { 491 if (dpb->fs[ii]->IsReference && !dpb->fs[ii]->IsLongTerm) 492 { 493 if (dpb->fs[ii]->FrameNumWrap < MinFrameNumWrap) 494 { 495 MinFrameNumWrap = dpb->fs[ii]->FrameNumWrap; 496 MinIdx = ii; 497 } 498 } 499 } 500 if (MinIdx < 0) /* something wrong, impossible */ 501 { 502 return AVC_FAIL; 503 } 504 505 /* mark the frame with smallest PicOrderCnt to be unused for reference */ 506 dpb->fs[MinIdx]->IsReference = 0; 507 dpb->fs[MinIdx]->IsLongTerm = 0; 508 dpb->fs[MinIdx]->frame.isReference = FALSE; 509 dpb->fs[MinIdx]->frame.isLongTerm = FALSE; 510 dpb->fs[MinIdx]->IsOutputted |= 0x02; 511 #ifdef PV_MEMORY_POOL 512 if (dpb->fs[MinIdx]->IsOutputted == 3) 513 { 514 avcHandle->CBAVC_FrameUnbind(avcHandle->userData, MinIdx); 515 } 516 #endif 517 numShortTerm--; 518 } 519 return AVC_SUCCESS; 520 } 521 522 /* see subclause 8.2.5.4 */ 523 AVCStatus adaptive_memory_marking(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, AVCSliceHeader *sliceHdr) 524 { 525 int ii; 526 527 ii = 0; 528 while (ii < MAX_DEC_REF_PIC_MARKING && sliceHdr->memory_management_control_operation[ii] != 0) 529 { 530 switch (sliceHdr->memory_management_control_operation[ii]) 531 { 532 case 1: 533 MemMgrCtrlOp1(avcHandle, video, dpb, sliceHdr->difference_of_pic_nums_minus1[ii]); 534 // update_ref_list(dpb); 535 break; 536 case 2: 537 MemMgrCtrlOp2(avcHandle, dpb, sliceHdr->long_term_pic_num[ii]); 538 break; 539 case 3: 540 MemMgrCtrlOp3(avcHandle, video, dpb, sliceHdr->difference_of_pic_nums_minus1[ii], sliceHdr->long_term_frame_idx[ii]); 541 break; 542 case 4: 543 MemMgrCtrlOp4(avcHandle, video, dpb, sliceHdr->max_long_term_frame_idx_plus1[ii]); 544 break; 545 case 5: 546 MemMgrCtrlOp5(avcHandle, video, dpb); 547 video->currFS->FrameNum = 0; // 548 video->currFS->PicOrderCnt = 0; 549 break; 550 case 6: 551 MemMgrCtrlOp6(avcHandle, video, dpb, sliceHdr->long_term_frame_idx[ii]); 552 break; 553 } 554 ii++; 555 } 556 557 if (ii == MAX_DEC_REF_PIC_MARKING) 558 { 559 return AVC_FAIL; /* exceed the limit */ 560 } 561 562 return AVC_SUCCESS; 563 } 564 565 566 /* see subclause 8.2.5.4.1, mark short-term picture as "unused for reference" */ 567 void MemMgrCtrlOp1(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, int difference_of_pic_nums_minus1) 568 { 569 int picNumX, ii; 570 571 picNumX = video->CurrPicNum - (difference_of_pic_nums_minus1 + 1); 572 573 for (ii = 0; ii < dpb->num_fs; ii++) 574 { 575 if (dpb->fs[ii]->IsReference == 3 && dpb->fs[ii]->IsLongTerm == 0) 576 { 577 if (dpb->fs[ii]->frame.PicNum == picNumX) 578 { 579 unmark_for_reference(avcHandle, dpb, ii); 580 return ; 581 } 582 } 583 } 584 585 return ; 586 } 587 588 /* see subclause 8.2.5.4.2 mark long-term picture as "unused for reference" */ 589 void MemMgrCtrlOp2(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, int long_term_pic_num) 590 { 591 int ii; 592 593 for (ii = 0; ii < dpb->num_fs; ii++) 594 { 595 if (dpb->fs[ii]->IsLongTerm == 3) 596 { 597 if (dpb->fs[ii]->frame.LongTermPicNum == long_term_pic_num) 598 { 599 unmark_for_reference(avcHandle, dpb, ii); 600 } 601 } 602 } 603 } 604 605 /* see subclause 8.2.5.4.3 assign LongTermFrameIdx to a short-term ref picture */ 606 void MemMgrCtrlOp3(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint difference_of_pic_nums_minus1, 607 uint long_term_frame_idx) 608 { 609 int picNumX, ii; 610 611 picNumX = video->CurrPicNum - (difference_of_pic_nums_minus1 + 1); 612 613 /* look for fs[i] with long_term_frame_idx */ 614 615 unmark_long_term_frame_for_reference_by_frame_idx(avcHandle, dpb, long_term_frame_idx); 616 617 618 /* now mark the picture with picNumX to long term frame idx */ 619 620 for (ii = 0; ii < dpb->num_fs; ii++) 621 { 622 if (dpb->fs[ii]->IsReference == 3) 623 { 624 if ((dpb->fs[ii]->frame.isLongTerm == FALSE) && (dpb->fs[ii]->frame.PicNum == picNumX)) 625 { 626 dpb->fs[ii]->LongTermFrameIdx = long_term_frame_idx; 627 dpb->fs[ii]->frame.LongTermPicNum = long_term_frame_idx; 628 629 dpb->fs[ii]->frame.isLongTerm = TRUE; 630 631 dpb->fs[ii]->IsLongTerm = 3; 632 return; 633 } 634 } 635 } 636 637 } 638 639 /* see subclause 8.2.5.4.4, MaxLongTermFrameIdx */ 640 void MemMgrCtrlOp4(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint max_long_term_frame_idx_plus1) 641 { 642 int ii; 643 644 video->MaxLongTermFrameIdx = max_long_term_frame_idx_plus1 - 1; 645 646 /* then mark long term frame with exceeding LongTermFrameIdx to unused for reference. */ 647 for (ii = 0; ii < dpb->num_fs; ii++) 648 { 649 if (dpb->fs[ii]->IsLongTerm && dpb->fs[ii] != video->currFS) 650 { 651 if (dpb->fs[ii]->LongTermFrameIdx > video->MaxLongTermFrameIdx) 652 { 653 unmark_for_reference(avcHandle, dpb, ii); 654 } 655 } 656 } 657 } 658 659 /* see subclause 8.2.5.4.5 mark all reference picture as "unused for reference" and setting 660 MaxLongTermFrameIdx to "no long-term frame indices" */ 661 void MemMgrCtrlOp5(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb) 662 { 663 int ii; 664 665 video->MaxLongTermFrameIdx = -1; 666 for (ii = 0; ii < dpb->num_fs; ii++) /* including the current frame ??????*/ 667 { 668 if (dpb->fs[ii] != video->currFS) // MC_FIX 669 { 670 unmark_for_reference(avcHandle, dpb, ii); 671 } 672 } 673 674 video->mem_mgr_ctrl_eq_5 = TRUE; 675 } 676 677 /* see subclause 8.2.5.4.6 assing long-term frame index to the current picture */ 678 void MemMgrCtrlOp6(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint long_term_frame_idx) 679 { 680 681 unmark_long_term_frame_for_reference_by_frame_idx(avcHandle, dpb, long_term_frame_idx); 682 video->currFS->IsLongTerm = 3; 683 video->currFS->IsReference = 3; 684 685 video->currPic->isLongTerm = TRUE; 686 video->currPic->isReference = TRUE; 687 video->currFS->LongTermFrameIdx = long_term_frame_idx; 688 } 689 690 691 void unmark_for_reference(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, uint idx) 692 { 693 694 AVCFrameStore *fs = dpb->fs[idx]; 695 fs->frame.isReference = FALSE; 696 fs->frame.isLongTerm = FALSE; 697 698 fs->IsLongTerm = 0; 699 fs->IsReference = 0; 700 fs->IsOutputted |= 0x02; 701 #ifdef PV_MEMORY_POOL 702 if (fs->IsOutputted == 3) 703 { 704 avcHandle->CBAVC_FrameUnbind(avcHandle->userData, idx); 705 } 706 #endif 707 return ; 708 } 709 710 void unmark_long_term_frame_for_reference_by_frame_idx(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, uint long_term_frame_idx) 711 { 712 int ii; 713 for (ii = 0; ii < dpb->num_fs; ii++) 714 { 715 716 if (dpb->fs[ii]->IsLongTerm && (dpb->fs[ii]->LongTermFrameIdx == (int)long_term_frame_idx)) 717 { 718 unmark_for_reference(avcHandle, dpb, ii); 719 } 720 721 } 722 } 723 724 725