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