Home | History | Annotate | Download | only in src
      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