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