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
89static i32 ComparePictures(const void *ptr1, const void *ptr2);
90
91static u32 Mmcop1(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums);
92
93static u32 Mmcop2(dpbStorage_t *dpb, u32 longTermPicNum);
94
95static u32 Mmcop3(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums,
96    u32 longTermFrameIdx);
97
98static u32 Mmcop4(dpbStorage_t *dpb, u32 maxLongTermFrameIdx);
99
100static u32 Mmcop5(dpbStorage_t *dpb);
101
102static u32 Mmcop6(dpbStorage_t *dpb, u32 frameNum, i32 picOrderCnt,
103    u32 longTermFrameIdx);
104
105static u32 SlidingWindowRefPicMarking(dpbStorage_t *dpb);
106
107static i32 FindDpbPic(dpbStorage_t *dpb, i32 picNum, u32 isShortTerm);
108
109static void SetPicNums(dpbStorage_t *dpb, u32 currFrameNum);
110
111static dpbPicture_t* FindSmallestPicOrderCnt(dpbStorage_t *dpb);
112
113static u32 OutputPicture(dpbStorage_t *dpb);
114
115static 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
138static 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
224u32 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
321static 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
361static 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
400static 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
459static 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
501static 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
546static 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
628u32 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
846u8* 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
877u8* 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
909static 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
980u32 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
1060u32 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
1104void 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
1132static 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
1189static 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
1244u32 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
1380dpbPicture_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
1423u32 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
1472dpbOutPicture_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
1500void 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
1523void 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
1558static 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