1 /*
2 * Copyright (C) 2009 The Android Open Source Project
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 express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*------------------------------------------------------------------------------
18
19 Table of contents
20
21 1. Include headers
22 2. External compiler flags
23 3. Module defines
24 4. Local function prototypes
25 5. Functions
26 ComparePictures
27 h264bsdReorderRefPicList
28 Mmcop1
29 Mmcop2
30 Mmcop3
31 Mmcop4
32 Mmcop5
33 Mmcop6
34 h264bsdMarkDecRefPic
35 h264bsdGetRefPicData
36 h264bsdAllocateDpbImage
37 SlidingWindowRefPicMarking
38 h264bsdInitDpb
39 h264bsdResetDpb
40 h264bsdInitRefPicList
41 FindDpbPic
42 SetPicNums
43 h264bsdCheckGapsInFrameNum
44 FindSmallestPicOrderCnt
45 OutputPicture
46 h264bsdDpbOutputPicture
47 h264bsdFlushDpb
48 h264bsdFreeDpb
49
50 ------------------------------------------------------------------------------*/
51
52 /*------------------------------------------------------------------------------
53 1. Include headers
54 ------------------------------------------------------------------------------*/
55
56 #include "h264bsd_cfg.h"
57 #include "h264bsd_dpb.h"
58 #include "h264bsd_slice_header.h"
59 #include "h264bsd_image.h"
60 #include "h264bsd_util.h"
61 #include "basetype.h"
62
63 /*------------------------------------------------------------------------------
64 2. External compiler flags
65 --------------------------------------------------------------------------------
66
67 --------------------------------------------------------------------------------
68 3. Module defines
69 ------------------------------------------------------------------------------*/
70
71 /* macros to determine picture status. Note that IS_SHORT_TERM macro returns
72 * true also for non-existing pictures because non-existing pictures are
73 * regarded short term pictures according to H.264 standard */
74 #define IS_REFERENCE(a) ((a).status)
75 #define IS_EXISTING(a) ((a).status > NON_EXISTING)
76 #define IS_SHORT_TERM(a) \
77 ((a).status == NON_EXISTING || (a).status == SHORT_TERM)
78 #define IS_LONG_TERM(a) ((a).status == LONG_TERM)
79
80 /* macro to set a picture unused for reference */
81 #define SET_UNUSED(a) (a).status = UNUSED;
82
83 #define MAX_NUM_REF_IDX_L0_ACTIVE 16
84
85 /*------------------------------------------------------------------------------
86 4. Local function prototypes
87 ------------------------------------------------------------------------------*/
88
89 static i32 ComparePictures(const void *ptr1, const void *ptr2);
90
91 static u32 Mmcop1(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums);
92
93 static u32 Mmcop2(dpbStorage_t *dpb, u32 longTermPicNum);
94
95 static u32 Mmcop3(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums,
96 u32 longTermFrameIdx);
97
98 static u32 Mmcop4(dpbStorage_t *dpb, u32 maxLongTermFrameIdx);
99
100 static u32 Mmcop5(dpbStorage_t *dpb);
101
102 static u32 Mmcop6(dpbStorage_t *dpb, u32 frameNum, i32 picOrderCnt,
103 u32 longTermFrameIdx);
104
105 static u32 SlidingWindowRefPicMarking(dpbStorage_t *dpb);
106
107 static i32 FindDpbPic(dpbStorage_t *dpb, i32 picNum, u32 isShortTerm);
108
109 static void SetPicNums(dpbStorage_t *dpb, u32 currFrameNum);
110
111 static dpbPicture_t* FindSmallestPicOrderCnt(dpbStorage_t *dpb);
112
113 static u32 OutputPicture(dpbStorage_t *dpb);
114
115 static void ShellSort(dpbPicture_t *pPic, u32 num);
116
117 /*------------------------------------------------------------------------------
118
119 Function: ComparePictures
120
121 Functional description:
122 Function to compare dpb pictures, used by the ShellSort() function.
123 Order of the pictures after sorting shall be as follows:
124 1) short term reference pictures starting with the largest
125 picNum
126 2) long term reference pictures starting with the smallest
127 longTermPicNum
128 3) pictures unused for reference but needed for display
129 4) other pictures
130
131 Returns:
132 -1 pic 1 is greater than pic 2
133 0 equal from comparison point of view
134 1 pic 2 is greater then pic 1
135
136 ------------------------------------------------------------------------------*/
137
ComparePictures(const void * ptr1,const void * ptr2)138 static i32 ComparePictures(const void *ptr1, const void *ptr2)
139 {
140
141 /* Variables */
142
143 dpbPicture_t *pic1, *pic2;
144
145 /* Code */
146
147 ASSERT(ptr1);
148 ASSERT(ptr2);
149
150 pic1 = (dpbPicture_t*)ptr1;
151 pic2 = (dpbPicture_t*)ptr2;
152
153 /* both are non-reference pictures, check if needed for display */
154 if (!IS_REFERENCE(*pic1) && !IS_REFERENCE(*pic2))
155 {
156 if (pic1->toBeDisplayed && !pic2->toBeDisplayed)
157 return(-1);
158 else if (!pic1->toBeDisplayed && pic2->toBeDisplayed)
159 return(1);
160 else
161 return(0);
162 }
163 /* only pic 1 needed for reference -> greater */
164 else if (!IS_REFERENCE(*pic2))
165 return(-1);
166 /* only pic 2 needed for reference -> greater */
167 else if (!IS_REFERENCE(*pic1))
168 return(1);
169 /* both are short term reference pictures -> check picNum */
170 else if (IS_SHORT_TERM(*pic1) && IS_SHORT_TERM(*pic2))
171 {
172 if (pic1->picNum > pic2->picNum)
173 return(-1);
174 else if (pic1->picNum < pic2->picNum)
175 return(1);
176 else
177 return(0);
178 }
179 /* only pic 1 is short term -> greater */
180 else if (IS_SHORT_TERM(*pic1))
181 return(-1);
182 /* only pic 2 is short term -> greater */
183 else if (IS_SHORT_TERM(*pic2))
184 return(1);
185 /* both are long term reference pictures -> check picNum (contains the
186 * longTermPicNum */
187 else
188 {
189 if (pic1->picNum > pic2->picNum)
190 return(1);
191 else if (pic1->picNum < pic2->picNum)
192 return(-1);
193 else
194 return(0);
195 }
196 }
197
198 /*------------------------------------------------------------------------------
199
200 Function: h264bsdReorderRefPicList
201
202 Functional description:
203 Function to perform reference picture list reordering based on
204 reordering commands received in the slice header. See details
205 of the process in the H.264 standard.
206
207 Inputs:
208 dpb pointer to dpb storage structure
209 order pointer to reordering commands
210 currFrameNum current frame number
211 numRefIdxActive number of active reference indices for current
212 picture
213
214 Outputs:
215 dpb 'list' field of the structure reordered
216
217 Returns:
218 HANTRO_OK success
219 HANTRO_NOK if non-existing pictures referred to in the
220 reordering commands
221
222 ------------------------------------------------------------------------------*/
223
h264bsdReorderRefPicList(dpbStorage_t * dpb,refPicListReordering_t * order,u32 currFrameNum,u32 numRefIdxActive)224 u32 h264bsdReorderRefPicList(
225 dpbStorage_t *dpb,
226 refPicListReordering_t *order,
227 u32 currFrameNum,
228 u32 numRefIdxActive)
229 {
230
231 /* Variables */
232
233 u32 i, j, k, picNumPred, refIdx;
234 i32 picNum, picNumNoWrap, index;
235 u32 isShortTerm;
236
237 /* Code */
238
239 ASSERT(order);
240 ASSERT(currFrameNum <= dpb->maxFrameNum);
241 ASSERT(numRefIdxActive <= MAX_NUM_REF_IDX_L0_ACTIVE);
242
243 /* set dpb picture numbers for sorting */
244 SetPicNums(dpb, currFrameNum);
245
246 if (!order->refPicListReorderingFlagL0)
247 return(HANTRO_OK);
248
249 refIdx = 0;
250 picNumPred = currFrameNum;
251
252 i = 0;
253 while (order->command[i].reorderingOfPicNumsIdc < 3)
254 {
255 /* short term */
256 if (order->command[i].reorderingOfPicNumsIdc < 2)
257 {
258 if (order->command[i].reorderingOfPicNumsIdc == 0)
259 {
260 picNumNoWrap =
261 (i32)picNumPred - (i32)order->command[i].absDiffPicNum;
262 if (picNumNoWrap < 0)
263 picNumNoWrap += (i32)dpb->maxFrameNum;
264 }
265 else
266 {
267 picNumNoWrap =
268 (i32)(picNumPred + order->command[i].absDiffPicNum);
269 if (picNumNoWrap >= (i32)dpb->maxFrameNum)
270 picNumNoWrap -= (i32)dpb->maxFrameNum;
271 }
272 picNumPred = (u32)picNumNoWrap;
273 picNum = picNumNoWrap;
274 if ((u32)picNumNoWrap > currFrameNum)
275 picNum -= (i32)dpb->maxFrameNum;
276 isShortTerm = HANTRO_TRUE;
277 }
278 /* long term */
279 else
280 {
281 picNum = (i32)order->command[i].longTermPicNum;
282 isShortTerm = HANTRO_FALSE;
283
284 }
285 /* find corresponding picture from dpb */
286 index = FindDpbPic(dpb, picNum, isShortTerm);
287 if (index < 0 || !IS_EXISTING(dpb->buffer[index]))
288 return(HANTRO_NOK);
289
290 /* shift pictures */
291 for (j = numRefIdxActive; j > refIdx; j--)
292 dpb->list[j] = dpb->list[j-1];
293 /* put picture into the list */
294 dpb->list[refIdx++] = &dpb->buffer[index];
295 /* remove later references to the same picture */
296 for (j = k = refIdx; j <= numRefIdxActive; j++)
297 if(dpb->list[j] != &dpb->buffer[index])
298 dpb->list[k++] = dpb->list[j];
299
300 i++;
301 }
302
303 return(HANTRO_OK);
304
305 }
306
307 /*------------------------------------------------------------------------------
308
309 Function: Mmcop1
310
311 Functional description:
312 Function to mark a short-term reference picture unused for
313 reference, memory_management_control_operation equal to 1
314
315 Returns:
316 HANTRO_OK success
317 HANTRO_NOK failure, picture does not exist in the buffer
318
319 ------------------------------------------------------------------------------*/
320
Mmcop1(dpbStorage_t * dpb,u32 currPicNum,u32 differenceOfPicNums)321 static u32 Mmcop1(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums)
322 {
323
324 /* Variables */
325
326 i32 index, picNum;
327
328 /* Code */
329
330 ASSERT(currPicNum < dpb->maxFrameNum);
331
332 picNum = (i32)currPicNum - (i32)differenceOfPicNums;
333
334 index = FindDpbPic(dpb, picNum, HANTRO_TRUE);
335 if (index < 0)
336 return(HANTRO_NOK);
337
338 SET_UNUSED(dpb->buffer[index]);
339 dpb->numRefFrames--;
340 if (!dpb->buffer[index].toBeDisplayed)
341 dpb->fullness--;
342
343 return(HANTRO_OK);
344
345 }
346
347 /*------------------------------------------------------------------------------
348
349 Function: Mmcop2
350
351 Functional description:
352 Function to mark a long-term reference picture unused for
353 reference, memory_management_control_operation equal to 2
354
355 Returns:
356 HANTRO_OK success
357 HANTRO_NOK failure, picture does not exist in the buffer
358
359 ------------------------------------------------------------------------------*/
360
Mmcop2(dpbStorage_t * dpb,u32 longTermPicNum)361 static u32 Mmcop2(dpbStorage_t *dpb, u32 longTermPicNum)
362 {
363
364 /* Variables */
365
366 i32 index;
367
368 /* Code */
369
370 index = FindDpbPic(dpb, (i32)longTermPicNum, HANTRO_FALSE);
371 if (index < 0)
372 return(HANTRO_NOK);
373
374 SET_UNUSED(dpb->buffer[index]);
375 dpb->numRefFrames--;
376 if (!dpb->buffer[index].toBeDisplayed)
377 dpb->fullness--;
378
379 return(HANTRO_OK);
380
381 }
382
383 /*------------------------------------------------------------------------------
384
385 Function: Mmcop3
386
387 Functional description:
388 Function to assing a longTermFrameIdx to a short-term reference
389 frame (i.e. to change it to a long-term reference picture),
390 memory_management_control_operation equal to 3
391
392 Returns:
393 HANTRO_OK success
394 HANTRO_NOK failure, short-term picture does not exist in the
395 buffer or is a non-existing picture, or invalid
396 longTermFrameIdx given
397
398 ------------------------------------------------------------------------------*/
399
Mmcop3(dpbStorage_t * dpb,u32 currPicNum,u32 differenceOfPicNums,u32 longTermFrameIdx)400 static u32 Mmcop3(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums,
401 u32 longTermFrameIdx)
402 {
403
404 /* Variables */
405
406 i32 index, picNum;
407 u32 i;
408
409 /* Code */
410
411 ASSERT(dpb);
412 ASSERT(currPicNum < dpb->maxFrameNum);
413
414 if ( (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ||
415 (longTermFrameIdx > dpb->maxLongTermFrameIdx) )
416 return(HANTRO_NOK);
417
418 /* check if a long term picture with the same longTermFrameIdx already
419 * exist and remove it if necessary */
420 for (i = 0; i < dpb->maxRefFrames; i++)
421 if (IS_LONG_TERM(dpb->buffer[i]) &&
422 (u32)dpb->buffer[i].picNum == longTermFrameIdx)
423 {
424 SET_UNUSED(dpb->buffer[i]);
425 dpb->numRefFrames--;
426 if (!dpb->buffer[i].toBeDisplayed)
427 dpb->fullness--;
428 break;
429 }
430
431 picNum = (i32)currPicNum - (i32)differenceOfPicNums;
432
433 index = FindDpbPic(dpb, picNum, HANTRO_TRUE);
434 if (index < 0)
435 return(HANTRO_NOK);
436 if (!IS_EXISTING(dpb->buffer[index]))
437 return(HANTRO_NOK);
438
439 dpb->buffer[index].status = LONG_TERM;
440 dpb->buffer[index].picNum = (i32)longTermFrameIdx;
441
442 return(HANTRO_OK);
443
444 }
445
446 /*------------------------------------------------------------------------------
447
448 Function: Mmcop4
449
450 Functional description:
451 Function to set maxLongTermFrameIdx,
452 memory_management_control_operation equal to 4
453
454 Returns:
455 HANTRO_OK success
456
457 ------------------------------------------------------------------------------*/
458
Mmcop4(dpbStorage_t * dpb,u32 maxLongTermFrameIdx)459 static u32 Mmcop4(dpbStorage_t *dpb, u32 maxLongTermFrameIdx)
460 {
461
462 /* Variables */
463
464 u32 i;
465
466 /* Code */
467
468 dpb->maxLongTermFrameIdx = maxLongTermFrameIdx;
469
470 for (i = 0; i < dpb->maxRefFrames; i++)
471 if (IS_LONG_TERM(dpb->buffer[i]) &&
472 ( ((u32)dpb->buffer[i].picNum > maxLongTermFrameIdx) ||
473 (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ) )
474 {
475 SET_UNUSED(dpb->buffer[i]);
476 dpb->numRefFrames--;
477 if (!dpb->buffer[i].toBeDisplayed)
478 dpb->fullness--;
479 }
480
481 return(HANTRO_OK);
482
483 }
484
485 /*------------------------------------------------------------------------------
486
487 Function: Mmcop5
488
489 Functional description:
490 Function to mark all reference pictures unused for reference and
491 set maxLongTermFrameIdx to NO_LONG_TERM_FRAME_INDICES,
492 memory_management_control_operation equal to 5. Function flushes
493 the buffer and places all pictures that are needed for display into
494 the output buffer.
495
496 Returns:
497 HANTRO_OK success
498
499 ------------------------------------------------------------------------------*/
500
Mmcop5(dpbStorage_t * dpb)501 static u32 Mmcop5(dpbStorage_t *dpb)
502 {
503
504 /* Variables */
505
506 u32 i;
507
508 /* Code */
509
510 for (i = 0; i < 16; i++)
511 {
512 if (IS_REFERENCE(dpb->buffer[i]))
513 {
514 SET_UNUSED(dpb->buffer[i]);
515 if (!dpb->buffer[i].toBeDisplayed)
516 dpb->fullness--;
517 }
518 }
519
520 /* output all pictures */
521 while (OutputPicture(dpb) == HANTRO_OK)
522 ;
523 dpb->numRefFrames = 0;
524 dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
525 dpb->prevRefFrameNum = 0;
526
527 return(HANTRO_OK);
528
529 }
530
531 /*------------------------------------------------------------------------------
532
533 Function: Mmcop6
534
535 Functional description:
536 Function to assign longTermFrameIdx to the current picture,
537 memory_management_control_operation equal to 6
538
539 Returns:
540 HANTRO_OK success
541 HANTRO_NOK invalid longTermFrameIdx or no room for current
542 picture in the buffer
543
544 ------------------------------------------------------------------------------*/
545
Mmcop6(dpbStorage_t * dpb,u32 frameNum,i32 picOrderCnt,u32 longTermFrameIdx)546 static u32 Mmcop6(dpbStorage_t *dpb, u32 frameNum, i32 picOrderCnt,
547 u32 longTermFrameIdx)
548 {
549
550 /* Variables */
551
552 u32 i;
553
554 /* Code */
555
556 ASSERT(frameNum < dpb->maxFrameNum);
557
558 if ( (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ||
559 (longTermFrameIdx > dpb->maxLongTermFrameIdx) )
560 return(HANTRO_NOK);
561
562 /* check if a long term picture with the same longTermFrameIdx already
563 * exist and remove it if necessary */
564 for (i = 0; i < dpb->maxRefFrames; i++)
565 if (IS_LONG_TERM(dpb->buffer[i]) &&
566 (u32)dpb->buffer[i].picNum == longTermFrameIdx)
567 {
568 SET_UNUSED(dpb->buffer[i]);
569 dpb->numRefFrames--;
570 if (!dpb->buffer[i].toBeDisplayed)
571 dpb->fullness--;
572 break;
573 }
574
575 if (dpb->numRefFrames < dpb->maxRefFrames)
576 {
577 dpb->currentOut->frameNum = frameNum;
578 dpb->currentOut->picNum = (i32)longTermFrameIdx;
579 dpb->currentOut->picOrderCnt = picOrderCnt;
580 dpb->currentOut->status = LONG_TERM;
581 if (dpb->noReordering)
582 dpb->currentOut->toBeDisplayed = HANTRO_FALSE;
583 else
584 dpb->currentOut->toBeDisplayed = HANTRO_TRUE;
585 dpb->numRefFrames++;
586 dpb->fullness++;
587 return(HANTRO_OK);
588 }
589 /* if there is no room, return an error */
590 else
591 return(HANTRO_NOK);
592
593 }
594
595 /*------------------------------------------------------------------------------
596
597 Function: h264bsdMarkDecRefPic
598
599 Functional description:
600 Function to perform reference picture marking process. This
601 function should be called both for reference and non-reference
602 pictures. Non-reference pictures shall have mark pointer set to
603 NULL.
604
605 Inputs:
606 dpb pointer to the DPB data structure
607 mark pointer to reference picture marking commands
608 image pointer to current picture to be placed in the buffer
609 frameNum frame number of the current picture
610 picOrderCnt picture order count for the current picture
611 isIdr flag to indicate if the current picture is an
612 IDR picture
613 currentPicId identifier for the current picture, from the
614 application, stored along with the picture
615 numErrMbs number of concealed macroblocks in the current
616 picture, stored along with the picture
617
618 Outputs:
619 dpb 'buffer' modified, possible output frames placed into
620 'outBuf'
621
622 Returns:
623 HANTRO_OK success
624 HANTRO_NOK failure
625
626 ------------------------------------------------------------------------------*/
627
h264bsdMarkDecRefPic(dpbStorage_t * dpb,decRefPicMarking_t * mark,image_t * image,u32 frameNum,i32 picOrderCnt,u32 isIdr,u32 currentPicId,u32 numErrMbs)628 u32 h264bsdMarkDecRefPic(
629 dpbStorage_t *dpb,
630 decRefPicMarking_t *mark,
631 image_t *image,
632 u32 frameNum,
633 i32 picOrderCnt,
634 u32 isIdr,
635 u32 currentPicId,
636 u32 numErrMbs)
637 {
638
639 /* Variables */
640
641 u32 i, status;
642 u32 markedAsLongTerm;
643 u32 toBeDisplayed;
644
645 /* Code */
646
647 ASSERT(dpb);
648 ASSERT(mark || !isIdr);
649 ASSERT(!isIdr || (frameNum == 0 && picOrderCnt == 0));
650 ASSERT(frameNum < dpb->maxFrameNum);
651
652 if (image->data != dpb->currentOut->data)
653 {
654 EPRINT("TRYING TO MARK NON-ALLOCATED IMAGE");
655 return(HANTRO_NOK);
656 }
657
658 dpb->lastContainsMmco5 = HANTRO_FALSE;
659 status = HANTRO_OK;
660
661 toBeDisplayed = dpb->noReordering ? HANTRO_FALSE : HANTRO_TRUE;
662
663 /* non-reference picture, stored for display reordering purposes */
664 if (mark == NULL)
665 {
666 dpb->currentOut->status = UNUSED;
667 dpb->currentOut->frameNum = frameNum;
668 dpb->currentOut->picNum = (i32)frameNum;
669 dpb->currentOut->picOrderCnt = picOrderCnt;
670 dpb->currentOut->toBeDisplayed = toBeDisplayed;
671 if (!dpb->noReordering)
672 dpb->fullness++;
673 }
674 /* IDR picture */
675 else if (isIdr)
676 {
677
678 /* h264bsdCheckGapsInFrameNum not called for IDR pictures -> have to
679 * reset numOut and outIndex here */
680 dpb->numOut = dpb->outIndex = 0;
681
682 /* flush the buffer */
683 Mmcop5(dpb);
684 /* if noOutputOfPriorPicsFlag was set -> the pictures preceding the
685 * IDR picture shall not be output -> set output buffer empty */
686 if (mark->noOutputOfPriorPicsFlag || dpb->noReordering)
687 {
688 dpb->numOut = 0;
689 dpb->outIndex = 0;
690 }
691
692 if (mark->longTermReferenceFlag)
693 {
694 dpb->currentOut->status = LONG_TERM;
695 dpb->maxLongTermFrameIdx = 0;
696 }
697 else
698 {
699 dpb->currentOut->status = SHORT_TERM;
700 dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
701 }
702 dpb->currentOut->frameNum = 0;
703 dpb->currentOut->picNum = 0;
704 dpb->currentOut->picOrderCnt = 0;
705 dpb->currentOut->toBeDisplayed = toBeDisplayed;
706 dpb->fullness = 1;
707 dpb->numRefFrames = 1;
708 }
709 /* reference picture */
710 else
711 {
712 markedAsLongTerm = HANTRO_FALSE;
713 if (mark->adaptiveRefPicMarkingModeFlag)
714 {
715 i = 0;
716 while (mark->operation[i].memoryManagementControlOperation)
717 {
718 switch (mark->operation[i].memoryManagementControlOperation)
719 {
720 case 1:
721 status = Mmcop1(
722 dpb,
723 frameNum,
724 mark->operation[i].differenceOfPicNums);
725 break;
726
727 case 2:
728 status = Mmcop2(dpb, mark->operation[i].longTermPicNum);
729 break;
730
731 case 3:
732 status = Mmcop3(
733 dpb,
734 frameNum,
735 mark->operation[i].differenceOfPicNums,
736 mark->operation[i].longTermFrameIdx);
737 break;
738
739 case 4:
740 status = Mmcop4(
741 dpb,
742 mark->operation[i].maxLongTermFrameIdx);
743 break;
744
745 case 5:
746 status = Mmcop5(dpb);
747 dpb->lastContainsMmco5 = HANTRO_TRUE;
748 frameNum = 0;
749 break;
750
751 case 6:
752 status = Mmcop6(
753 dpb,
754 frameNum,
755 picOrderCnt,
756 mark->operation[i].longTermFrameIdx);
757 if (status == HANTRO_OK)
758 markedAsLongTerm = HANTRO_TRUE;
759 break;
760
761 default: /* invalid memory management control operation */
762 status = HANTRO_NOK;
763 break;
764 }
765 if (status != HANTRO_OK)
766 {
767 break;
768 }
769 i++;
770 }
771 }
772 else
773 {
774 status = SlidingWindowRefPicMarking(dpb);
775 }
776 /* if current picture was not marked as long-term reference by
777 * memory management control operation 6 -> mark current as short
778 * term and insert it into dpb (if there is room) */
779 if (!markedAsLongTerm)
780 {
781 if (dpb->numRefFrames < dpb->maxRefFrames)
782 {
783 dpb->currentOut->frameNum = frameNum;
784 dpb->currentOut->picNum = (i32)frameNum;
785 dpb->currentOut->picOrderCnt = picOrderCnt;
786 dpb->currentOut->status = SHORT_TERM;
787 dpb->currentOut->toBeDisplayed = toBeDisplayed;
788 dpb->fullness++;
789 dpb->numRefFrames++;
790 }
791 /* no room */
792 else
793 {
794 status = HANTRO_NOK;
795 }
796 }
797 }
798
799 dpb->currentOut->isIdr = isIdr;
800 dpb->currentOut->picId = currentPicId;
801 dpb->currentOut->numErrMbs = numErrMbs;
802
803 /* dpb was initialized to not to reorder the pictures -> output current
804 * picture immediately */
805 if (dpb->noReordering)
806 {
807 ASSERT(dpb->numOut == 0);
808 ASSERT(dpb->outIndex == 0);
809 dpb->outBuf[dpb->numOut].data = dpb->currentOut->data;
810 dpb->outBuf[dpb->numOut].isIdr = dpb->currentOut->isIdr;
811 dpb->outBuf[dpb->numOut].picId = dpb->currentOut->picId;
812 dpb->outBuf[dpb->numOut].numErrMbs = dpb->currentOut->numErrMbs;
813 dpb->numOut++;
814 }
815 else
816 {
817 /* output pictures if buffer full */
818 while (dpb->fullness > dpb->dpbSize)
819 {
820 i = OutputPicture(dpb);
821 ASSERT(i == HANTRO_OK);
822 }
823 }
824
825 /* sort dpb */
826 ShellSort(dpb->buffer, dpb->dpbSize+1);
827
828 return(status);
829
830 }
831
832 /*------------------------------------------------------------------------------
833
834 Function: h264bsdGetRefPicData
835
836 Functional description:
837 Function to get reference picture data from the reference picture
838 list
839
840 Returns:
841 pointer to desired reference picture data
842 NULL if invalid index or non-existing picture referred
843
844 ------------------------------------------------------------------------------*/
845
h264bsdGetRefPicData(dpbStorage_t * dpb,u32 index)846 u8* h264bsdGetRefPicData(dpbStorage_t *dpb, u32 index)
847 {
848
849 /* Variables */
850
851 /* Code */
852
853 if(index > 16 || dpb->list[index] == NULL)
854 return(NULL);
855 else if(!IS_EXISTING(*dpb->list[index]))
856 return(NULL);
857 else
858 return(dpb->list[index]->data);
859
860 }
861
862 /*------------------------------------------------------------------------------
863
864 Function: h264bsdAllocateDpbImage
865
866 Functional description:
867 function to allocate memory for a image. This function does not
868 really allocate any memory but reserves one of the buffer
869 positions for decoding of current picture
870
871 Returns:
872 pointer to memory area for the image
873
874
875 ------------------------------------------------------------------------------*/
876
h264bsdAllocateDpbImage(dpbStorage_t * dpb)877 u8* h264bsdAllocateDpbImage(dpbStorage_t *dpb)
878 {
879
880 /* Variables */
881
882 /* Code */
883
884 ASSERT( !dpb->buffer[dpb->dpbSize].toBeDisplayed &&
885 !IS_REFERENCE(dpb->buffer[dpb->dpbSize]) );
886 ASSERT(dpb->fullness <= dpb->dpbSize);
887
888 dpb->currentOut = dpb->buffer + dpb->dpbSize;
889
890 return(dpb->currentOut->data);
891
892 }
893
894 /*------------------------------------------------------------------------------
895
896 Function: SlidingWindowRefPicMarking
897
898 Functional description:
899 Function to perform sliding window refence picture marking process.
900
901 Outputs:
902 HANTRO_OK success
903 HANTRO_NOK failure, no short-term reference frame found that
904 could be marked unused
905
906
907 ------------------------------------------------------------------------------*/
908
SlidingWindowRefPicMarking(dpbStorage_t * dpb)909 static u32 SlidingWindowRefPicMarking(dpbStorage_t *dpb)
910 {
911
912 /* Variables */
913
914 i32 index, picNum;
915 u32 i;
916
917 /* Code */
918
919 if (dpb->numRefFrames < dpb->maxRefFrames)
920 {
921 return(HANTRO_OK);
922 }
923 else
924 {
925 index = -1;
926 picNum = 0;
927 /* find the oldest short term picture */
928 for (i = 0; i < dpb->numRefFrames; i++)
929 if (IS_SHORT_TERM(dpb->buffer[i]))
930 if (dpb->buffer[i].picNum < picNum || index == -1)
931 {
932 index = (i32)i;
933 picNum = dpb->buffer[i].picNum;
934 }
935 if (index >= 0)
936 {
937 SET_UNUSED(dpb->buffer[index]);
938 dpb->numRefFrames--;
939 if (!dpb->buffer[index].toBeDisplayed)
940 dpb->fullness--;
941
942 return(HANTRO_OK);
943 }
944 }
945
946 return(HANTRO_NOK);
947
948 }
949
950 /*------------------------------------------------------------------------------
951
952 Function: h264bsdInitDpb
953
954 Functional description:
955 Function to initialize DPB. Reserves memories for the buffer,
956 reference picture list and output buffer. dpbSize indicates
957 the maximum DPB size indicated by the levelIdc in the stream.
958 If noReordering flag is FALSE the DPB stores dpbSize pictures
959 for display reordering purposes. On the other hand, if the
960 flag is TRUE the DPB only stores maxRefFrames reference pictures
961 and outputs all the pictures immediately.
962
963 Inputs:
964 picSizeInMbs picture size in macroblocks
965 dpbSize size of the DPB (number of pictures)
966 maxRefFrames max number of reference frames
967 maxFrameNum max frame number
968 noReordering flag to indicate that DPB does not have to
969 prepare to reorder frames for display
970
971 Outputs:
972 dpb pointer to dpb data storage
973
974 Returns:
975 HANTRO_OK success
976 MEMORY_ALLOCATION_ERROR if memory allocation failed
977
978 ------------------------------------------------------------------------------*/
979
h264bsdInitDpb(dpbStorage_t * dpb,u32 picSizeInMbs,u32 dpbSize,u32 maxRefFrames,u32 maxFrameNum,u32 noReordering)980 u32 h264bsdInitDpb(
981 dpbStorage_t *dpb,
982 u32 picSizeInMbs,
983 u32 dpbSize,
984 u32 maxRefFrames,
985 u32 maxFrameNum,
986 u32 noReordering)
987 {
988
989 /* Variables */
990
991 u32 i;
992
993 /* Code */
994
995 ASSERT(picSizeInMbs);
996 ASSERT(maxRefFrames <= MAX_NUM_REF_PICS);
997 ASSERT(maxRefFrames <= dpbSize);
998 ASSERT(maxFrameNum);
999 ASSERT(dpbSize);
1000
1001 dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
1002 dpb->maxRefFrames = MAX(maxRefFrames, 1);
1003 if (noReordering)
1004 dpb->dpbSize = dpb->maxRefFrames;
1005 else
1006 dpb->dpbSize = dpbSize;
1007 dpb->maxFrameNum = maxFrameNum;
1008 dpb->noReordering = noReordering;
1009 dpb->fullness = 0;
1010 dpb->numRefFrames = 0;
1011 dpb->prevRefFrameNum = 0;
1012
1013 ALLOCATE(dpb->buffer, MAX_NUM_REF_IDX_L0_ACTIVE + 1, dpbPicture_t);
1014 if (dpb->buffer == NULL)
1015 return(MEMORY_ALLOCATION_ERROR);
1016 H264SwDecMemset(dpb->buffer, 0,
1017 (MAX_NUM_REF_IDX_L0_ACTIVE + 1)*sizeof(dpbPicture_t));
1018 for (i = 0; i < dpb->dpbSize + 1; i++)
1019 {
1020 /* Allocate needed amount of memory, which is:
1021 * image size + 32 + 15, where 32 cames from the fact that in ARM OpenMax
1022 * DL implementation Functions may read beyond the end of an array,
1023 * by a maximum of 32 bytes. And +15 cames for the need to align memory
1024 * to 16-byte boundary */
1025 ALLOCATE(dpb->buffer[i].pAllocatedData, (picSizeInMbs*384 + 32+15), u8);
1026 if (dpb->buffer[i].pAllocatedData == NULL)
1027 return(MEMORY_ALLOCATION_ERROR);
1028
1029 dpb->buffer[i].data = ALIGN(dpb->buffer[i].pAllocatedData, 16);
1030 }
1031
1032 ALLOCATE(dpb->list, MAX_NUM_REF_IDX_L0_ACTIVE + 1, dpbPicture_t*);
1033 ALLOCATE(dpb->outBuf, dpb->dpbSize+1, dpbOutPicture_t);
1034
1035 if (dpb->list == NULL || dpb->outBuf == NULL)
1036 return(MEMORY_ALLOCATION_ERROR);
1037
1038 H264SwDecMemset(dpb->list, 0,
1039 ((MAX_NUM_REF_IDX_L0_ACTIVE + 1) * sizeof(dpbPicture_t*)) );
1040
1041 dpb->numOut = dpb->outIndex = 0;
1042
1043 return(HANTRO_OK);
1044
1045 }
1046
1047 /*------------------------------------------------------------------------------
1048
1049 Function: h264bsdResetDpb
1050
1051 Functional description:
1052 Function to reset DPB. This function should be called when an IDR
1053 slice (other than the first) activates new sequence parameter set.
1054 Function calls h264bsdFreeDpb to free old allocated memories and
1055 h264bsdInitDpb to re-initialize the DPB. Same inputs, outputs and
1056 returns as for h264bsdInitDpb.
1057
1058 ------------------------------------------------------------------------------*/
1059
h264bsdResetDpb(dpbStorage_t * dpb,u32 picSizeInMbs,u32 dpbSize,u32 maxRefFrames,u32 maxFrameNum,u32 noReordering)1060 u32 h264bsdResetDpb(
1061 dpbStorage_t *dpb,
1062 u32 picSizeInMbs,
1063 u32 dpbSize,
1064 u32 maxRefFrames,
1065 u32 maxFrameNum,
1066 u32 noReordering)
1067 {
1068
1069 /* Code */
1070
1071 ASSERT(picSizeInMbs);
1072 ASSERT(maxRefFrames <= MAX_NUM_REF_PICS);
1073 ASSERT(maxRefFrames <= dpbSize);
1074 ASSERT(maxFrameNum);
1075 ASSERT(dpbSize);
1076
1077 h264bsdFreeDpb(dpb);
1078
1079 return h264bsdInitDpb(dpb, picSizeInMbs, dpbSize, maxRefFrames,
1080 maxFrameNum, noReordering);
1081 }
1082
1083 /*------------------------------------------------------------------------------
1084
1085 Function: h264bsdInitRefPicList
1086
1087 Functional description:
1088 Function to initialize reference picture list. Function just
1089 sets pointers in the list according to pictures in the buffer.
1090 The buffer is assumed to contain pictures sorted according to
1091 what the H.264 standard says about initial reference picture list.
1092
1093 Inputs:
1094 dpb pointer to dpb data structure
1095
1096 Outputs:
1097 dpb 'list' field initialized
1098
1099 Returns:
1100 none
1101
1102 ------------------------------------------------------------------------------*/
1103
h264bsdInitRefPicList(dpbStorage_t * dpb)1104 void h264bsdInitRefPicList(dpbStorage_t *dpb)
1105 {
1106
1107 /* Variables */
1108
1109 u32 i;
1110
1111 /* Code */
1112
1113 for (i = 0; i < dpb->numRefFrames; i++)
1114 dpb->list[i] = &dpb->buffer[i];
1115
1116 }
1117
1118 /*------------------------------------------------------------------------------
1119
1120 Function: FindDpbPic
1121
1122 Functional description:
1123 Function to find a reference picture from the buffer. The picture
1124 to be found is identified by picNum and isShortTerm flag.
1125
1126 Returns:
1127 index of the picture in the buffer
1128 -1 if the specified picture was not found in the buffer
1129
1130 ------------------------------------------------------------------------------*/
1131
FindDpbPic(dpbStorage_t * dpb,i32 picNum,u32 isShortTerm)1132 static i32 FindDpbPic(dpbStorage_t *dpb, i32 picNum, u32 isShortTerm)
1133 {
1134
1135 /* Variables */
1136
1137 u32 i = 0;
1138 u32 found = HANTRO_FALSE;
1139
1140 /* Code */
1141
1142 if (isShortTerm)
1143 {
1144 while (i < dpb->maxRefFrames && !found)
1145 {
1146 if (IS_SHORT_TERM(dpb->buffer[i]) &&
1147 dpb->buffer[i].picNum == picNum)
1148 found = HANTRO_TRUE;
1149 else
1150 i++;
1151 }
1152 }
1153 else
1154 {
1155 ASSERT(picNum >= 0);
1156 while (i < dpb->maxRefFrames && !found)
1157 {
1158 if (IS_LONG_TERM(dpb->buffer[i]) &&
1159 dpb->buffer[i].picNum == picNum)
1160 found = HANTRO_TRUE;
1161 else
1162 i++;
1163 }
1164 }
1165
1166 if (found)
1167 return((i32)i);
1168 else
1169 return(-1);
1170
1171 }
1172
1173 /*------------------------------------------------------------------------------
1174
1175 Function: SetPicNums
1176
1177 Functional description:
1178 Function to set picNum values for short-term pictures in the
1179 buffer. Numbering of pictures is based on frame numbers and as
1180 frame numbers are modulo maxFrameNum -> frame numbers of older
1181 pictures in the buffer may be bigger than the currFrameNum.
1182 picNums will be set so that current frame has the largest picNum
1183 and all the short-term frames in the buffer will get smaller picNum
1184 representing their "distance" from the current frame. This
1185 function kind of maps the modulo arithmetic back to normal.
1186
1187 ------------------------------------------------------------------------------*/
1188
SetPicNums(dpbStorage_t * dpb,u32 currFrameNum)1189 static void SetPicNums(dpbStorage_t *dpb, u32 currFrameNum)
1190 {
1191
1192 /* Variables */
1193
1194 u32 i;
1195 i32 frameNumWrap;
1196
1197 /* Code */
1198
1199 ASSERT(dpb);
1200 ASSERT(currFrameNum < dpb->maxFrameNum);
1201
1202 for (i = 0; i < dpb->numRefFrames; i++)
1203 if (IS_SHORT_TERM(dpb->buffer[i]))
1204 {
1205 if (dpb->buffer[i].frameNum > currFrameNum)
1206 frameNumWrap =
1207 (i32)dpb->buffer[i].frameNum - (i32)dpb->maxFrameNum;
1208 else
1209 frameNumWrap = (i32)dpb->buffer[i].frameNum;
1210 dpb->buffer[i].picNum = frameNumWrap;
1211 }
1212
1213 }
1214
1215 /*------------------------------------------------------------------------------
1216
1217 Function: h264bsdCheckGapsInFrameNum
1218
1219 Functional description:
1220 Function to check gaps in frame_num and generate non-existing
1221 (short term) reference pictures if necessary. This function should
1222 be called only for non-IDR pictures.
1223
1224 Inputs:
1225 dpb pointer to dpb data structure
1226 frameNum frame number of the current picture
1227 isRefPic flag to indicate if current picture is a reference or
1228 non-reference picture
1229 gapsAllowed Flag which indicates active SPS stance on whether
1230 to allow gaps
1231
1232 Outputs:
1233 dpb 'buffer' possibly modified by inserting non-existing
1234 pictures with sliding window marking process
1235
1236 Returns:
1237 HANTRO_OK success
1238 HANTRO_NOK error in sliding window reference picture marking or
1239 frameNum equal to previous reference frame used for
1240 a reference picture
1241
1242 ------------------------------------------------------------------------------*/
1243
h264bsdCheckGapsInFrameNum(dpbStorage_t * dpb,u32 frameNum,u32 isRefPic,u32 gapsAllowed)1244 u32 h264bsdCheckGapsInFrameNum(dpbStorage_t *dpb, u32 frameNum, u32 isRefPic,
1245 u32 gapsAllowed)
1246 {
1247
1248 /* Variables */
1249
1250 u32 unUsedShortTermFrameNum;
1251 u8 *tmp;
1252
1253 /* Code */
1254
1255 ASSERT(dpb);
1256 ASSERT(dpb->fullness <= dpb->dpbSize);
1257 ASSERT(frameNum < dpb->maxFrameNum);
1258
1259 dpb->numOut = 0;
1260 dpb->outIndex = 0;
1261
1262 if(!gapsAllowed)
1263 return(HANTRO_OK);
1264
1265 if ( (frameNum != dpb->prevRefFrameNum) &&
1266 (frameNum != ((dpb->prevRefFrameNum + 1) % dpb->maxFrameNum)))
1267 {
1268
1269 unUsedShortTermFrameNum = (dpb->prevRefFrameNum + 1) % dpb->maxFrameNum;
1270
1271 /* store data pointer of last buffer position to be used as next
1272 * "allocated" data pointer if last buffer position after this process
1273 * contains data pointer located in outBuf (buffer placed in the output
1274 * shall not be overwritten by the current picture) */
1275 tmp = dpb->buffer[dpb->dpbSize].data;
1276 do
1277 {
1278 SetPicNums(dpb, unUsedShortTermFrameNum);
1279
1280 if (SlidingWindowRefPicMarking(dpb) != HANTRO_OK)
1281 {
1282 return(HANTRO_NOK);
1283 }
1284
1285 /* output pictures if buffer full */
1286 while (dpb->fullness >= dpb->dpbSize)
1287 {
1288 #ifdef _ASSERT_USED
1289 ASSERT(!dpb->noReordering);
1290 ASSERT(OutputPicture(dpb) == HANTRO_OK);
1291 #else
1292 OutputPicture(dpb);
1293 #endif
1294 }
1295
1296 /* add to end of list */
1297 ASSERT( !dpb->buffer[dpb->dpbSize].toBeDisplayed &&
1298 !IS_REFERENCE(dpb->buffer[dpb->dpbSize]) );
1299 dpb->buffer[dpb->dpbSize].status = NON_EXISTING;
1300 dpb->buffer[dpb->dpbSize].frameNum = unUsedShortTermFrameNum;
1301 dpb->buffer[dpb->dpbSize].picNum = (i32)unUsedShortTermFrameNum;
1302 dpb->buffer[dpb->dpbSize].picOrderCnt = 0;
1303 dpb->buffer[dpb->dpbSize].toBeDisplayed = HANTRO_FALSE;
1304 dpb->fullness++;
1305 dpb->numRefFrames++;
1306
1307 /* sort the buffer */
1308 ShellSort(dpb->buffer, dpb->dpbSize+1);
1309
1310 unUsedShortTermFrameNum = (unUsedShortTermFrameNum + 1) %
1311 dpb->maxFrameNum;
1312
1313 } while (unUsedShortTermFrameNum != frameNum);
1314
1315 /* pictures placed in output buffer -> check that 'data' in
1316 * buffer position dpbSize is not in the output buffer (this will be
1317 * "allocated" by h264bsdAllocateDpbImage). If it is -> exchange data
1318 * pointer with the one stored in the beginning */
1319 if (dpb->numOut)
1320 {
1321 u32 i;
1322
1323 for (i = 0; i < dpb->numOut; i++)
1324 {
1325 if (dpb->outBuf[i].data == dpb->buffer[dpb->dpbSize].data)
1326 {
1327 /* find buffer position containing data pointer stored in
1328 * tmp */
1329 for (i = 0; i < dpb->dpbSize; i++)
1330 {
1331 if (dpb->buffer[i].data == tmp)
1332 {
1333 dpb->buffer[i].data =
1334 dpb->buffer[dpb->dpbSize].data;
1335 dpb->buffer[dpb->dpbSize].data = tmp;
1336 break;
1337 }
1338 }
1339 ASSERT(i < dpb->dpbSize);
1340 break;
1341 }
1342 }
1343 }
1344 }
1345 /* frameNum for reference pictures shall not be the same as for previous
1346 * reference picture, otherwise accesses to pictures in the buffer cannot
1347 * be solved unambiguously */
1348 else if (isRefPic && frameNum == dpb->prevRefFrameNum)
1349 {
1350 return(HANTRO_NOK);
1351 }
1352
1353 /* save current frame_num in prevRefFrameNum. For non-reference frame
1354 * prevFrameNum is set to frame number of last non-existing frame above */
1355 if (isRefPic)
1356 dpb->prevRefFrameNum = frameNum;
1357 else if (frameNum != dpb->prevRefFrameNum)
1358 {
1359 dpb->prevRefFrameNum =
1360 (frameNum + dpb->maxFrameNum - 1) % dpb->maxFrameNum;
1361 }
1362
1363 return(HANTRO_OK);
1364
1365 }
1366
1367 /*------------------------------------------------------------------------------
1368
1369 Function: FindSmallestPicOrderCnt
1370
1371 Functional description:
1372 Function to find picture with smallest picture order count. This
1373 will be the next picture in display order.
1374
1375 Returns:
1376 pointer to the picture, NULL if no pictures to be displayed
1377
1378 ------------------------------------------------------------------------------*/
1379
FindSmallestPicOrderCnt(dpbStorage_t * dpb)1380 dpbPicture_t* FindSmallestPicOrderCnt(dpbStorage_t *dpb)
1381 {
1382
1383 /* Variables */
1384
1385 u32 i;
1386 i32 picOrderCnt;
1387 dpbPicture_t *tmp;
1388
1389 /* Code */
1390
1391 ASSERT(dpb);
1392
1393 picOrderCnt = 0x7FFFFFFF;
1394 tmp = NULL;
1395
1396 for (i = 0; i <= dpb->dpbSize; i++)
1397 {
1398 if (dpb->buffer[i].toBeDisplayed &&
1399 (dpb->buffer[i].picOrderCnt < picOrderCnt))
1400 {
1401 tmp = dpb->buffer + i;
1402 picOrderCnt = dpb->buffer[i].picOrderCnt;
1403 }
1404 }
1405
1406 return(tmp);
1407
1408 }
1409
1410 /*------------------------------------------------------------------------------
1411
1412 Function: OutputPicture
1413
1414 Functional description:
1415 Function to put next display order picture into the output buffer.
1416
1417 Returns:
1418 HANTRO_OK success
1419 HANTRO_NOK no pictures to display
1420
1421 ------------------------------------------------------------------------------*/
1422
OutputPicture(dpbStorage_t * dpb)1423 u32 OutputPicture(dpbStorage_t *dpb)
1424 {
1425
1426 /* Variables */
1427
1428 dpbPicture_t *tmp;
1429
1430 /* Code */
1431
1432 ASSERT(dpb);
1433
1434 if (dpb->noReordering)
1435 return(HANTRO_NOK);
1436
1437 tmp = FindSmallestPicOrderCnt(dpb);
1438
1439 /* no pictures to be displayed */
1440 if (tmp == NULL)
1441 return(HANTRO_NOK);
1442
1443 dpb->outBuf[dpb->numOut].data = tmp->data;
1444 dpb->outBuf[dpb->numOut].isIdr = tmp->isIdr;
1445 dpb->outBuf[dpb->numOut].picId = tmp->picId;
1446 dpb->outBuf[dpb->numOut].numErrMbs = tmp->numErrMbs;
1447 dpb->numOut++;
1448
1449 tmp->toBeDisplayed = HANTRO_FALSE;
1450 if (!IS_REFERENCE(*tmp))
1451 {
1452 dpb->fullness--;
1453 }
1454
1455 return(HANTRO_OK);
1456
1457 }
1458
1459 /*------------------------------------------------------------------------------
1460
1461 Function: h264bsdDpbOutputPicture
1462
1463 Functional description:
1464 Function to get next display order picture from the output buffer.
1465
1466 Return:
1467 pointer to output picture structure, NULL if no pictures to
1468 display
1469
1470 ------------------------------------------------------------------------------*/
1471
h264bsdDpbOutputPicture(dpbStorage_t * dpb)1472 dpbOutPicture_t* h264bsdDpbOutputPicture(dpbStorage_t *dpb)
1473 {
1474
1475 /* Variables */
1476
1477 /* Code */
1478
1479 ASSERT(dpb);
1480
1481 if (dpb->outIndex < dpb->numOut)
1482 return(dpb->outBuf + dpb->outIndex++);
1483 else
1484 return(NULL);
1485
1486 }
1487
1488 /*------------------------------------------------------------------------------
1489
1490 Function: h264bsdFlushDpb
1491
1492 Functional description:
1493 Function to flush the DPB. Function puts all pictures needed for
1494 display into the output buffer. This function shall be called in
1495 the end of the stream to obtain pictures buffered for display
1496 re-ordering purposes.
1497
1498 ------------------------------------------------------------------------------*/
1499
h264bsdFlushDpb(dpbStorage_t * dpb)1500 void h264bsdFlushDpb(dpbStorage_t *dpb)
1501 {
1502
1503 /* don't do anything if buffer not reserved */
1504 if (dpb->buffer)
1505 {
1506 dpb->flushed = 1;
1507 /* output all pictures */
1508 while (OutputPicture(dpb) == HANTRO_OK)
1509 ;
1510 }
1511
1512 }
1513
1514 /*------------------------------------------------------------------------------
1515
1516 Function: h264bsdFreeDpb
1517
1518 Functional description:
1519 Function to free memories reserved for the DPB.
1520
1521 ------------------------------------------------------------------------------*/
1522
h264bsdFreeDpb(dpbStorage_t * dpb)1523 void h264bsdFreeDpb(dpbStorage_t *dpb)
1524 {
1525
1526 /* Variables */
1527
1528 u32 i;
1529
1530 /* Code */
1531
1532 ASSERT(dpb);
1533
1534 if (dpb->buffer)
1535 {
1536 for (i = 0; i < dpb->dpbSize+1; i++)
1537 {
1538 FREE(dpb->buffer[i].pAllocatedData);
1539 }
1540 }
1541 FREE(dpb->buffer);
1542 FREE(dpb->list);
1543 FREE(dpb->outBuf);
1544
1545 }
1546
1547 /*------------------------------------------------------------------------------
1548
1549 Function: ShellSort
1550
1551 Functional description:
1552 Sort pictures in the buffer. Function implements Shell's method,
1553 i.e. diminishing increment sort. See e.g. "Numerical Recipes in C"
1554 for more information.
1555
1556 ------------------------------------------------------------------------------*/
1557
ShellSort(dpbPicture_t * pPic,u32 num)1558 static void ShellSort(dpbPicture_t *pPic, u32 num)
1559 {
1560
1561 u32 i, j;
1562 u32 step;
1563 dpbPicture_t tmpPic;
1564
1565 step = 7;
1566
1567 while (step)
1568 {
1569 for (i = step; i < num; i++)
1570 {
1571 tmpPic = pPic[i];
1572 j = i;
1573 while (j >= step && ComparePictures(pPic + j - step, &tmpPic) > 0)
1574 {
1575 pPic[j] = pPic[j-step];
1576 j -= step;
1577 }
1578 pPic[j] = tmpPic;
1579 }
1580 step >>= 1;
1581 }
1582
1583 }
1584
1585