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 
InitDPB(AVCHandle * avcHandle,AVCCommonObj * video,int FrameHeightInMbs,int PicWidthInMbs,bool padding)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 
AVCConfigureSequence(AVCHandle * avcHandle,AVCCommonObj * video,bool padding)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, 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, 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 
CleanUpDPB(AVCHandle * avcHandle,AVCCommonObj * video)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, 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, 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 
DPBInitBuffer(AVCHandle * avcHandle,AVCCommonObj * video)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 
DPBInitPic(AVCCommonObj * video,int CurrPicNum)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 */
DPBReleaseCurrentFrame(AVCHandle * avcHandle,AVCCommonObj * video)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 */
StorePictureInDPB(AVCHandle * avcHandle,AVCCommonObj * video)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 
sliding_window_process(AVCHandle * avcHandle,AVCCommonObj * video,AVCDecPicBuffer * dpb)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 */
adaptive_memory_marking(AVCHandle * avcHandle,AVCCommonObj * video,AVCDecPicBuffer * dpb,AVCSliceHeader * sliceHdr)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" */
MemMgrCtrlOp1(AVCHandle * avcHandle,AVCCommonObj * video,AVCDecPicBuffer * dpb,int difference_of_pic_nums_minus1)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" */
MemMgrCtrlOp2(AVCHandle * avcHandle,AVCDecPicBuffer * dpb,int long_term_pic_num)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 */
MemMgrCtrlOp3(AVCHandle * avcHandle,AVCCommonObj * video,AVCDecPicBuffer * dpb,uint difference_of_pic_nums_minus1,uint long_term_frame_idx)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 */
MemMgrCtrlOp4(AVCHandle * avcHandle,AVCCommonObj * video,AVCDecPicBuffer * dpb,uint max_long_term_frame_idx_plus1)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" */
MemMgrCtrlOp5(AVCHandle * avcHandle,AVCCommonObj * video,AVCDecPicBuffer * dpb)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 */
MemMgrCtrlOp6(AVCHandle * avcHandle,AVCCommonObj * video,AVCDecPicBuffer * dpb,uint long_term_frame_idx)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 
unmark_for_reference(AVCHandle * avcHandle,AVCDecPicBuffer * dpb,uint idx)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 
unmark_long_term_frame_for_reference_by_frame_idx(AVCHandle * avcHandle,AVCDecPicBuffer * dpb,uint long_term_frame_idx)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