Home | History | Annotate | Download | only in common
      1 /******************************************************************************
      2  *
      3  * Copyright (C) 2015 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at:
      8  *
      9  * http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  *****************************************************************************
     18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
     19 */
     20 /**
     21  *******************************************************************************
     22  * @file
     23  *  ih264_dpb_mgr.c
     24  *
     25  * @brief
     26  *  Function definitions used for decoded picture buffer management
     27  *
     28  * @author
     29  *  Srinivas T
     30  *
     31  * @par List of Functions:
     32  *   - ih264_dpb_mgr_init()
     33  *   - ih264_dpb_mgr_sort_short_term_fields_by_frame_num()
     34  *   - ih264_dpb_mgr_sort_short_term_fields_by_poc_l0()
     35  *   - ih264_dpb_mgr_sort_short_term_fields_by_poc_l1()
     36  *   - ih264_dpb_mgr_sort_long_term_fields_by_frame_idx()
     37  *   - ih264_dpb_mgr_alternate_ref_fields()
     38  *   - ih264_dpb_mgr_insert_ref_field()
     39  *   - ih264_dpb_mgr_insert_ref_frame()
     40  *   - ih264_dpb_mgr_count_ref_frames()
     41  *   - ih264_dpb_mgr_delete_ref_frame()
     42  *   - ih264_dpb_mgr_delete_long_ref_fields_max_frame_idx()
     43  *   - ih264_dpb_mgr_delete_short_ref_frame()
     44  *   - ih264_dpb_mgr_delete_all_ref_frames()
     45  *   - ih264_dpb_mgr_reset()
     46  *   - ih264_dpb_mgr_release_pics()
     47  *
     48  * @remarks
     49  *  None
     50  *
     51  *******************************************************************************
     52  */
     53 
     54 #include <stdio.h>
     55 #include <stdlib.h>
     56 #include <assert.h>
     57 
     58 #include "ih264_typedefs.h"
     59 #include "ih264_defs.h"
     60 #include "ih264_macros.h"
     61 #include "ih264_error.h"
     62 #include "ih264_structs.h"
     63 #include "ih264_buf_mgr.h"
     64 #include "ih264_dpb_mgr.h"
     65 #include "ih264_debug.h"
     66 
     67 /**
     68  *******************************************************************************
     69  *
     70  * @brief
     71  *  DPB manager initializer
     72  *
     73  * @par Description:
     74  *  Initialises the DPB manager structure
     75  *
     76  * @param[in] ps_dpb_mgr
     77  *  Pointer to the DPB manager structure
     78  *
     79  * @returns
     80  *
     81  * @remarks
     82  *
     83  *
     84  *******************************************************************************
     85  */
     86 
     87 void ih264_dpb_mgr_init(dpb_mgr_t *ps_dpb_mgr)
     88 {
     89     UWORD32 i;
     90     dpb_info_t *ps_dpb_info = ps_dpb_mgr->as_dpb_info;
     91     for(i = 0; i < MAX_DPB_BUFS; i++)
     92     {
     93         ps_dpb_info[i].ps_prev_dpb = NULL;
     94         ps_dpb_info[i].ps_pic_buf = NULL;
     95         ps_dpb_mgr->as_top_field_pics[i].i4_used_as_ref    = INVALID;
     96         ps_dpb_mgr->as_bottom_field_pics[i].i4_used_as_ref = INVALID;
     97         ps_dpb_mgr->as_top_field_pics[i].i1_field_type     = INVALID;
     98         ps_dpb_mgr->as_bottom_field_pics[i].i1_field_type  = INVALID;
     99         ps_dpb_mgr->as_top_field_pics[i].i4_long_term_frame_idx    = -1;
    100         ps_dpb_mgr->as_bottom_field_pics[i].i4_long_term_frame_idx = -1;
    101     }
    102 
    103     ps_dpb_mgr->u1_num_short_term_ref_bufs = 0;
    104     ps_dpb_mgr->u1_num_long_term_ref_bufs = 0;
    105     ps_dpb_mgr->ps_dpb_short_term_head = NULL;
    106     ps_dpb_mgr->ps_dpb_long_term_head = NULL;
    107 }
    108 
    109 /**
    110  *******************************************************************************
    111  *
    112  * @brief
    113  *  Function to sort sort term pics by frame_num.
    114  *
    115  * @par Description:
    116  *  Sorts short term fields by frame_num. For 2 fields having same frame_num,
    117  *  orders them based on requested first field type.
    118  *
    119  * @param[in] ps_dpb_mgr
    120  *  Pointer to the DPB manager structure
    121  *
    122  * @param[in] curr_frame_num
    123  *  frame_num of the current pic
    124  *
    125  * @param[in] first_field_type
    126  *  For complementary fields, required first field
    127  *
    128  * @param[in] max_frame_num
    129  *  Maximum frame_num allowed
    130  *
    131  * @returns
    132  *
    133  * @remarks
    134  *
    135  *
    136  *******************************************************************************
    137  */
    138 WORD32 ih264_dpb_mgr_sort_short_term_fields_by_frame_num(dpb_mgr_t *ps_dpb_mgr,
    139                                                          WORD32 curr_frame_num,
    140                                                          WORD32 first_field_type,
    141                                                          WORD32 max_frame_num)
    142 {
    143     dpb_info_t *ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head;
    144     dpb_info_t *ps_dpb_node2;
    145     WORD32 frame_num_node1;
    146     WORD32 frame_num_node2;
    147     pic_buf_t *ps_pic_buf;
    148 
    149     if(ps_dpb_node1 == NULL)
    150         return -1;
    151 
    152     for (; ps_dpb_node1 != NULL; ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb)
    153     {
    154         for (ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; ps_dpb_node2 != NULL; ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb)
    155         {
    156             frame_num_node1 = ps_dpb_node1->ps_pic_buf->i4_frame_num;
    157             frame_num_node2 = ps_dpb_node2->ps_pic_buf->i4_frame_num;
    158 
    159             if(frame_num_node1 > curr_frame_num)
    160                 frame_num_node1 = frame_num_node1 - max_frame_num;
    161             if(frame_num_node2 > curr_frame_num)
    162                 frame_num_node2 = frame_num_node2 - max_frame_num;
    163 
    164             if(frame_num_node1 < frame_num_node2)
    165             {
    166                 ps_pic_buf = ps_dpb_node1->ps_pic_buf;
    167                 ps_dpb_node1->ps_pic_buf = ps_dpb_node2->ps_pic_buf;
    168                 ps_dpb_node2->ps_pic_buf = ps_pic_buf;
    169             }
    170         }
    171     }
    172 
    173     /**
    174      * For frames and complementary field pairs,
    175      * ensure first_field_type appears first in the list
    176      */
    177     ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head;
    178     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
    179     while(ps_dpb_node2 != NULL)
    180     {
    181         pic_buf_t *ps_pic_node1 = ps_dpb_node1->ps_pic_buf;
    182         pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf;
    183         frame_num_node1 = ps_pic_node1->i4_frame_num;
    184         frame_num_node2 = ps_pic_node2->i4_frame_num;
    185         if(frame_num_node1 == frame_num_node2)
    186         {
    187             ASSERT(ps_pic_node1->i1_field_type != ps_pic_node2->i1_field_type);
    188             if(ps_pic_node1->i1_field_type != first_field_type)
    189             {
    190                 ps_dpb_node1->ps_pic_buf = ps_pic_node2;
    191                 ps_dpb_node2->ps_pic_buf = ps_pic_node1;
    192             }
    193         }
    194         ps_dpb_node1 = ps_dpb_node2;
    195         ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb;
    196     }
    197     return 0;
    198 
    199 }
    200 
    201 /**
    202  *******************************************************************************
    203  *
    204  * @brief
    205  *  Function to sort sort term pics by poc for list 0.
    206  *
    207  * @par Description:
    208  *  Orders all the pocs less than current poc in the descending order.
    209  *  Then orders all the pocs greater than current poc in the ascending order.
    210  *
    211  * @param[in] ps_dpb_mgr
    212  *  Pointer to the DPB manager structure
    213  *
    214  * @param[in] curr_poc
    215  *  Poc of the current pic
    216  *
    217  * @param[in] first_field_type
    218  *  For complementary fields, required first field
    219  *
    220  * @returns
    221  *
    222  * @remarks
    223  *
    224  *
    225  *******************************************************************************
    226  */
    227 WORD32 ih264_dpb_mgr_sort_short_term_fields_by_poc_l0(dpb_mgr_t *ps_dpb_mgr,
    228                                                       WORD32 curr_poc,
    229                                                       WORD32 first_field_type)
    230 {
    231     dpb_info_t *ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head;
    232     dpb_info_t *ps_dpb_node2;
    233     WORD32 poc_node1;
    234     WORD32 poc_node2;
    235     WORD32 frame_num_node1;
    236     WORD32 frame_num_node2;
    237     pic_buf_t *ps_pic_buf;
    238 
    239     if(ps_dpb_node1 == NULL)
    240         return -1;
    241 
    242     /**
    243      * Sort the fields by poc.
    244      * All POCs less than current poc are first placed in the descending order.
    245      * Then all POCs greater than current poc are placed in the ascending order.
    246      */
    247     for (; ps_dpb_node1 != NULL; ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb)
    248     {
    249         for (ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; ps_dpb_node2 != NULL; ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb)
    250         {
    251             poc_node1 = ps_dpb_node1->ps_pic_buf->i4_abs_poc;
    252             poc_node2 = ps_dpb_node2->ps_pic_buf->i4_abs_poc;
    253             ASSERT(poc_node1 != curr_poc);
    254             ASSERT(poc_node2 != curr_poc);
    255             if(((poc_node1 < curr_poc) && (poc_node2 > curr_poc)) ||
    256                     ((poc_node1 < curr_poc) && (poc_node2 < curr_poc) && (poc_node1 > poc_node2)) ||
    257                     ((poc_node1 > curr_poc) && (poc_node2 > curr_poc) && (poc_node1 < poc_node2)))
    258                     continue;
    259 
    260             ps_pic_buf = ps_dpb_node1->ps_pic_buf;
    261             ps_dpb_node1->ps_pic_buf = ps_dpb_node2->ps_pic_buf;
    262             ps_dpb_node2->ps_pic_buf = ps_pic_buf;
    263         }
    264     }
    265 
    266     ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head;
    267     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
    268     while(ps_dpb_node2 != NULL)
    269     {
    270         pic_buf_t *ps_pic_node1 = ps_dpb_node1->ps_pic_buf;
    271         pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf;
    272         frame_num_node1 = ps_pic_node1->i4_frame_num;
    273         frame_num_node2 = ps_pic_node2->i4_frame_num;
    274         if(frame_num_node1 == frame_num_node2)
    275         {
    276             ASSERT(ps_pic_node1->i1_field_type != ps_pic_node2->i1_field_type);
    277             if(ps_pic_node1->i1_field_type != first_field_type)
    278             {
    279                 ps_dpb_node1->ps_pic_buf = ps_pic_node2;
    280                 ps_dpb_node2->ps_pic_buf = ps_pic_node1;
    281             }
    282         }
    283         ps_dpb_node1 = ps_dpb_node2;
    284         ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb;
    285     }
    286     return 0;
    287 
    288 }
    289 
    290 /**
    291  *******************************************************************************
    292  *
    293  * @brief
    294  *  Function to sort sort term pics by poc for list 1.
    295  *
    296  * @par Description:
    297  *  Orders all the pocs greater than current poc in the ascending order.
    298  *  Then rrders all the pocs less than current poc in the descending order.
    299  *
    300  * @param[in] ps_dpb_mgr
    301  *  Pointer to the DPB manager structure
    302  *
    303  * @param[in] curr_poc
    304  *  Poc of the current pic
    305  *
    306  * @param[in] first_field_type
    307  *  For complementary fields, required first field
    308  *
    309  * @returns
    310  *
    311  * @remarks
    312  *
    313  *
    314  *******************************************************************************
    315  */
    316 WORD32 ih264_dpb_mgr_sort_short_term_fields_by_poc_l1(dpb_mgr_t *ps_dpb_mgr,
    317                                                       WORD32 curr_poc,
    318                                                       WORD32 first_field_type)
    319 {
    320     dpb_info_t *ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head;
    321     dpb_info_t *ps_dpb_node2;
    322     WORD32 poc_node1;
    323     WORD32 poc_node2;
    324     WORD32 frame_num_node1;
    325     WORD32 frame_num_node2;
    326     pic_buf_t *ps_pic_buf;
    327 
    328     if(ps_dpb_node1 == NULL)
    329         return -1;
    330 
    331     /**
    332      * Sort the fields by poc.
    333      * All POCs greater than current poc are first placed in the ascending order.
    334      * Then all POCs less than current poc are placed in the decending order.
    335      */
    336     for (; ps_dpb_node1 != NULL; ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb)
    337     {
    338         for (ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; ps_dpb_node2 != NULL; ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb)
    339         {
    340             poc_node1 = ps_dpb_node1->ps_pic_buf->i4_abs_poc;
    341             poc_node2 = ps_dpb_node2->ps_pic_buf->i4_abs_poc;
    342             ASSERT(poc_node1 != curr_poc);
    343             ASSERT(poc_node2 != curr_poc);
    344             if(((poc_node1 > curr_poc) && (poc_node2 < curr_poc)) ||
    345                     ((poc_node1 < curr_poc) && (poc_node2 < curr_poc) && (poc_node1 > poc_node2)) ||
    346                     ((poc_node1 > curr_poc) && (poc_node2 > curr_poc) && (poc_node1 < poc_node2)))
    347                     continue;
    348 
    349             ps_pic_buf = ps_dpb_node1->ps_pic_buf;
    350             ps_dpb_node1->ps_pic_buf = ps_dpb_node2->ps_pic_buf;
    351             ps_dpb_node2->ps_pic_buf = ps_pic_buf;
    352         }
    353     }
    354 
    355     ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head;
    356     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
    357     while(ps_dpb_node2 != NULL)
    358     {
    359         pic_buf_t *ps_pic_node1 = ps_dpb_node1->ps_pic_buf;
    360         pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf;
    361         frame_num_node1 = ps_pic_node1->i4_frame_num;
    362         frame_num_node2 = ps_pic_node2->i4_frame_num;
    363         if(frame_num_node1 == frame_num_node2)
    364         {
    365             ASSERT(ps_pic_node1->i1_field_type != ps_pic_node2->i1_field_type);
    366             if(ps_pic_node1->i1_field_type != first_field_type)
    367             {
    368                 ps_dpb_node1->ps_pic_buf = ps_pic_node2;
    369                 ps_dpb_node2->ps_pic_buf = ps_pic_node1;
    370             }
    371         }
    372         ps_dpb_node1 = ps_dpb_node2;
    373         ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb;
    374     }
    375     return 0;
    376 }
    377 /**
    378  *******************************************************************************
    379  *
    380  * @brief
    381  *  Function to sort long term pics by long term frame idx.
    382  *
    383  * @par Description:
    384  *  Sorts long term fields by long term frame idx. For 2 fields
    385  *  having same frame_num, orders them based on requested first field type.
    386  *
    387  * @param[in] ps_dpb_mgr
    388  *  Pointer to the DPB manager structure
    389  *
    390  * @param[in] first_field_type
    391  *  For complementary fields, required first field
    392  *
    393  * @returns
    394  *
    395  * @remarks
    396  *
    397  *
    398  *******************************************************************************
    399  */
    400 WORD32 ih264_dpb_mgr_sort_long_term_fields_by_frame_idx(dpb_mgr_t *ps_dpb_mgr,
    401                                                         WORD32 first_field_type)
    402 {
    403     dpb_info_t *ps_dpb_node1 = ps_dpb_mgr->ps_dpb_long_term_head;
    404     dpb_info_t *ps_dpb_node2;
    405     WORD32 frame_idx_node1;
    406     WORD32 frame_idx_node2;
    407     pic_buf_t *ps_pic_buf;
    408 
    409     if(ps_dpb_node1 == NULL)
    410         return -1;
    411 
    412     /* Sort the fields by frame idx */
    413     for (; ps_dpb_node1 != NULL; ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb)
    414     {
    415         for (ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; ps_dpb_node2 != NULL; ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb)
    416         {
    417             frame_idx_node1 = ps_dpb_node1->ps_pic_buf->i4_long_term_frame_idx;
    418             frame_idx_node2 = ps_dpb_node2->ps_pic_buf->i4_long_term_frame_idx;
    419 
    420             if(frame_idx_node1 > frame_idx_node2)
    421             {
    422                 ps_pic_buf = ps_dpb_node1->ps_pic_buf;
    423                 ps_dpb_node1->ps_pic_buf = ps_dpb_node2->ps_pic_buf;
    424                 ps_dpb_node2->ps_pic_buf = ps_pic_buf;
    425             }
    426         }
    427     }
    428 
    429     /**
    430      * For frames and complementary field pairs,
    431      * ensure first_field_type appears first in the list
    432      */
    433     ps_dpb_node1 = ps_dpb_mgr->ps_dpb_long_term_head;
    434     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
    435     while(ps_dpb_node2 != NULL)
    436     {
    437         pic_buf_t *ps_pic_node1 = ps_dpb_node1->ps_pic_buf;
    438         pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf;
    439         frame_idx_node1 = ps_pic_node1->i4_long_term_frame_idx;
    440         frame_idx_node2 = ps_pic_node2->i4_long_term_frame_idx;
    441         if(frame_idx_node1 == frame_idx_node2)
    442         {
    443             ASSERT(ps_pic_node1->i1_field_type != ps_pic_node2->i1_field_type);
    444             if(ps_pic_node1->i1_field_type != first_field_type)
    445             {
    446                 ps_dpb_node1->ps_pic_buf = ps_pic_node2;
    447                 ps_dpb_node2->ps_pic_buf = ps_pic_node1;
    448             }
    449         }
    450         ps_dpb_node1 = ps_dpb_node2;
    451         ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb;
    452     }
    453     return 0;
    454 }
    455 
    456 /**
    457  *******************************************************************************
    458  *
    459  * @brief
    460  *  Function to alternate fields.
    461  *
    462  * @par Description:
    463  *  In the ordered list of fields, alternate fields starting with
    464  *  first_field_type
    465  *
    466  * @param[in] ps_dpb_mgr
    467  *  Pointer to the DPB manager structure
    468  *
    469  * @param[in] reference_type
    470  *  This is used to select between short-term and long-term linked list.
    471  *
    472  * @param[in] first_field_type
    473  *  For complementary fields, required first field
    474  *
    475  * @returns
    476  *
    477  * @remarks
    478  *
    479  *
    480  *******************************************************************************
    481  */
    482 WORD32 ih264_dpb_mgr_alternate_ref_fields(dpb_mgr_t *ps_dpb_mgr,
    483                                           WORD32 reference_type,
    484                                           WORD32 first_field_type)
    485 {
    486     dpb_info_t s_dpb_head;
    487     dpb_info_t *ps_dpb_head;
    488     dpb_info_t *ps_dpb_node1;
    489     dpb_info_t *ps_dpb_node2;
    490     dpb_info_t *ps_dpb_node3;
    491     dpb_info_t *ps_dpb_node4;
    492     WORD32 expected_field;
    493 
    494     expected_field = first_field_type;
    495 
    496     ps_dpb_head = &s_dpb_head;
    497 
    498     ps_dpb_head->ps_prev_dpb = (reference_type == SHORT_TERM_REF) ?
    499             ps_dpb_mgr->ps_dpb_short_term_head:
    500             ps_dpb_mgr->ps_dpb_long_term_head;
    501 
    502     ps_dpb_node1 = ps_dpb_head;
    503     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
    504     while(ps_dpb_node2 != NULL)
    505     {
    506         pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf;
    507         if(ps_pic_node2->i1_field_type != expected_field)
    508         {
    509             /*
    510              * If it is not expected field, loop over the node till
    511              * the expected field.
    512              */
    513             ps_dpb_node3 = ps_dpb_node2;
    514             ps_dpb_node4 = ps_dpb_node2->ps_prev_dpb;
    515             while((ps_dpb_node4 != NULL) &&
    516                     (ps_dpb_node4->ps_pic_buf->i1_field_type != expected_field))
    517             {
    518                 ps_dpb_node3 = ps_dpb_node4;
    519                 ps_dpb_node4 = ps_dpb_node4->ps_prev_dpb;
    520             }
    521             if(ps_dpb_node4 != NULL)
    522             {
    523                 ps_dpb_node1->ps_prev_dpb = ps_dpb_node4;
    524                 ps_dpb_node3->ps_prev_dpb = ps_dpb_node4->ps_prev_dpb;
    525                 ps_dpb_node4->ps_prev_dpb = ps_dpb_node2;
    526             }
    527             else
    528             {
    529                 /* node4 null means we have reached the end */
    530                 break;
    531             }
    532         }
    533         ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb;
    534         ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
    535         expected_field = (ps_dpb_node1->ps_pic_buf->i1_field_type == TOP_FIELD)?
    536                             BOTTOM_FIELD:TOP_FIELD;
    537     }
    538 
    539     if(reference_type == SHORT_TERM_REF)
    540     {
    541         ps_dpb_mgr->ps_dpb_short_term_head = ps_dpb_head->ps_prev_dpb;
    542     }
    543     else
    544     {
    545         ps_dpb_mgr->ps_dpb_long_term_head = ps_dpb_head->ps_prev_dpb;
    546     }
    547 
    548     return 0;
    549 }
    550 
    551 /**
    552  *******************************************************************************
    553  *
    554  * @brief
    555  *  Add a ref field to short-term or long-term linked list.
    556  *
    557  * @par Description:
    558  *  This function adds a ref field to either short-term or long-term linked
    559  *  list. It picks up memory for the link from the array of dpb_info in
    560  *  dpb_mgr. The field is added to the beginning of the linked list and the
    561  *  head is set the the field.
    562  *
    563  * @param[in] ps_dpb_mgr
    564  *  Pointer to the DPB manager structure
    565  *
    566  * @param[in] ps_pic_buf
    567  *  Pic buf structure for the field being added.
    568  *
    569  * @param[in] reference_type
    570  *  This is used to select between short-term and long-term linked list.
    571  *
    572  * @param[in] frame_num
    573  *  frame_num for the field.
    574  *
    575  * @param[in] long_term_frame_idx
    576  *  If the ref being added is long-term, long_term_frame_idx of the field.
    577  *  Otherwise invalid.
    578  *
    579  * @returns
    580  *
    581  * @remarks
    582  *
    583  *
    584  *******************************************************************************
    585  */
    586 WORD32 ih264_dpb_mgr_insert_ref_field(dpb_mgr_t *ps_dpb_mgr,
    587                                     pic_buf_t *ps_pic_buf,
    588                                     WORD32 reference_type,
    589                                     UWORD32 frame_num,
    590                                     WORD32 long_term_frame_idx)
    591 {
    592     WORD32 i;
    593     dpb_info_t *ps_dpb_info;
    594     dpb_info_t *ps_dpb_head;
    595 
    596     ps_dpb_info = ps_dpb_mgr->as_dpb_info;
    597 
    598     /* Return error if buffer is already present in the DPB */
    599     for(i = 0; i < MAX_DPB_BUFS; i++)
    600     {
    601         if( (ps_dpb_info[i].ps_pic_buf == ps_pic_buf)
    602                         && (ps_dpb_info[i].ps_pic_buf->i4_used_as_ref == reference_type) )
    603         {
    604             return (-1);
    605         }
    606     }
    607 
    608     /* Find an unused DPB location */
    609     for(i = 0; i < MAX_DPB_BUFS; i++)
    610     {
    611         if(NULL == ps_dpb_info[i].ps_pic_buf)
    612         {
    613             break;
    614         }
    615     }
    616     if(i == MAX_DPB_BUFS)
    617     {
    618         return (-1);
    619     }
    620 
    621     ps_dpb_head = (reference_type == SHORT_TERM_REF)
    622                     ?ps_dpb_mgr->ps_dpb_short_term_head
    623                     :ps_dpb_mgr->ps_dpb_long_term_head;
    624 
    625     if(reference_type == SHORT_TERM_REF)
    626         long_term_frame_idx = -1;
    627 
    628     /* Create DPB info */
    629     ps_dpb_info[i].ps_pic_buf = ps_pic_buf;
    630     ps_dpb_info[i].ps_prev_dpb = ps_dpb_head;
    631     ps_dpb_info[i].ps_pic_buf->i4_used_as_ref = reference_type;
    632     ps_dpb_info[i].ps_pic_buf->i4_frame_num = frame_num;
    633     ps_dpb_info[i].ps_pic_buf->i4_long_term_frame_idx = long_term_frame_idx;
    634 
    635     /* update the head node of linked list to point to the current picture */
    636     if(reference_type == SHORT_TERM_REF)
    637     {
    638         ps_dpb_mgr->ps_dpb_short_term_head = ps_dpb_info + i;
    639 
    640         /* Increment Short term buffer count */
    641         ps_dpb_mgr->u1_num_short_term_ref_bufs++;
    642 
    643     }
    644     else
    645     {
    646         ps_dpb_mgr->ps_dpb_long_term_head = ps_dpb_info + i;
    647 
    648         /* Increment Long term buffer count */
    649         ps_dpb_mgr->u1_num_long_term_ref_bufs++;
    650     }
    651 
    652     return 0;
    653 }
    654 
    655 /**
    656  *******************************************************************************
    657  *
    658  * @brief
    659  *  Add a ref frame to short-term or long-term linked list.
    660  *
    661  * @par Description:
    662  *  This function adds a ref frame to either short-term or long-term linked
    663  *  list. Internally it calls add ref field twice to add top and bottom field.
    664  *
    665  * @param[in] ps_dpb_mgr
    666  *  Pointer to the DPB manager structure
    667  *
    668  * @param[in] ps_pic_buf
    669  *  Pic buf structure for the field being added.
    670  *
    671  * @param[in] reference_type
    672  *  This is used to select between short-term and long-term linked list.
    673  *
    674  * @param[in] frame_num
    675  *  frame_num for the field.
    676  *
    677  * @param[in] long_term_frame_idx
    678  *  If the ref being added is long-term, long_term_frame_idx of the field.
    679  *  Otherwise invalid.
    680  *
    681  * @returns
    682  *
    683  * @remarks
    684  *
    685  *
    686  *******************************************************************************
    687  */
    688 WORD32 ih264_dpb_mgr_insert_ref_frame(dpb_mgr_t *ps_dpb_mgr,
    689                                       pic_buf_t *ps_pic_buf,
    690                                       WORD32 reference_type,
    691                                       UWORD32 frame_num,
    692                                       WORD32 long_term_frame_idx)
    693 {
    694     WORD32 buf_id;
    695     pic_buf_t *ps_pic_top;
    696     pic_buf_t *ps_pic_bottom;
    697     WORD32 ret;
    698 
    699     /*
    700      * For a frame, since the ps_pic_buf passed to this function is that of top field
    701      * obtain bottom field using buf_id.
    702      */
    703     ps_pic_top = ps_pic_buf;
    704     buf_id = ps_pic_top->i4_buf_id;
    705     ps_pic_bottom = &ps_dpb_mgr->as_bottom_field_pics[buf_id];
    706 
    707     /* Insert top field */
    708     ret = ih264_dpb_mgr_insert_ref_field(ps_dpb_mgr,
    709                                        ps_pic_top,
    710                                        reference_type,
    711                                        frame_num,
    712                                        long_term_frame_idx);
    713 
    714     if(ret != 0)
    715         return ret;
    716 
    717     /* Insert bottom field */
    718     ret = ih264_dpb_mgr_insert_ref_field(ps_dpb_mgr,
    719                                        ps_pic_bottom,
    720                                        reference_type,
    721                                        frame_num,
    722                                        long_term_frame_idx);
    723 
    724     if(ret != 0)
    725         return ret;
    726 
    727     return ret;
    728 }
    729 
    730 /**
    731  *******************************************************************************
    732  *
    733  * @brief
    734  *  Returns the number of ref frames in both the linked list.
    735  *
    736  * @par Description:
    737  *  Returns the count of number of frames, number of complementary field pairs
    738  *  and number of unpaired fields.
    739  *
    740  * @param[in] ps_dpb_mgr
    741  *  Pointer to the DPB manager structure
    742  *
    743  * @param[in] curr_frame_num
    744  *  frame_num for the field.
    745  *
    746  * @param[in] max_frame_num
    747  *  Maximum frame_num allowed
    748  *
    749  * @returns
    750  *
    751  * @remarks
    752  *
    753  *
    754  *******************************************************************************
    755  */
    756 WORD32 ih264_dpb_mgr_count_ref_frames(dpb_mgr_t *ps_dpb_mgr,
    757                                       WORD32 curr_frame_num,
    758                                       WORD32 max_frame_num)
    759 {
    760     WORD32 numShortTerm = 0;
    761     WORD32 numLongTerm = 0;
    762     dpb_info_t *ps_dpb_node;
    763     WORD32 frame_num;
    764     WORD32 prev_frame_num;
    765 
    766     /*
    767      * Compute the number of short-term frames/complementary field pairs/
    768      * unpaired fields
    769      */
    770     if(ps_dpb_mgr->ps_dpb_short_term_head != NULL)
    771     {
    772         /* Sort the short-term list by frame_num */
    773         ih264_dpb_mgr_sort_short_term_fields_by_frame_num(ps_dpb_mgr,
    774                                                         curr_frame_num,
    775                                                         TOP_FIELD,
    776                                                         max_frame_num);
    777 
    778         ps_dpb_node = ps_dpb_mgr->ps_dpb_short_term_head;
    779         if(ps_dpb_node != NULL)
    780         {
    781             numShortTerm++;
    782             prev_frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num;
    783             ps_dpb_node = ps_dpb_node->ps_prev_dpb;
    784         }
    785 
    786         while(ps_dpb_node != NULL)
    787         {
    788             frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num;
    789             if(frame_num != prev_frame_num)
    790                 numShortTerm++;
    791             prev_frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num;
    792             ps_dpb_node = ps_dpb_node->ps_prev_dpb;
    793         }
    794     }
    795 
    796     /*
    797      * Compute the number of long-term frames/complementary field pairs/
    798      * unpaired fields
    799      */
    800     if(ps_dpb_mgr->ps_dpb_long_term_head != NULL)
    801     {
    802         ih264_dpb_mgr_sort_long_term_fields_by_frame_idx(ps_dpb_mgr,
    803                                                         TOP_FIELD);
    804 
    805         ps_dpb_node = ps_dpb_mgr->ps_dpb_long_term_head;
    806         if(ps_dpb_node != NULL)
    807         {
    808             numLongTerm++;
    809             prev_frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num;
    810             ps_dpb_node = ps_dpb_node->ps_prev_dpb;
    811         }
    812 
    813         while(ps_dpb_node != NULL)
    814         {
    815             frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num;
    816             if(frame_num != prev_frame_num)
    817                 numLongTerm++;
    818             prev_frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num;
    819             ps_dpb_node = ps_dpb_node->ps_prev_dpb;
    820         }
    821     }
    822     return (numShortTerm + numLongTerm);
    823 }
    824 
    825 /**
    826  *******************************************************************************
    827  *
    828  * @brief
    829  *  Deletes the ref frame at the end of the linked list.
    830  *
    831  * @par Description:
    832  *  Deletes the ref frame at the end of the linked list. For unpaired fields,
    833  *  it deletes just the last node. For frame or complementary field pair, it
    834  *  deletes the last two nodes.
    835  *
    836  * @param[in] ps_dpb_mgr
    837  *  Pointer to the DPB manager structure
    838  *
    839  * @param[in] reference_type
    840  *  This is used to select between short-term and long-term linked list.
    841  *
    842  * @returns
    843  *
    844  * @remarks
    845  *
    846  *
    847  *******************************************************************************
    848  */
    849 WORD32 ih264_dpb_mgr_delete_ref_frame(dpb_mgr_t *ps_dpb_mgr,
    850                                       WORD32 reference_type)
    851 {
    852     dpb_info_t *ps_dpb_node1;
    853     dpb_info_t *ps_dpb_node2;
    854     dpb_info_t *ps_dpb_node3;
    855 
    856     /*
    857      * Assumption: The nodes sorted for frame num.
    858      */
    859 
    860 
    861     /* Select bw short-term and long-term list. */
    862     ps_dpb_node1 = (reference_type == SHORT_TERM_REF)
    863                     ?ps_dpb_mgr->ps_dpb_short_term_head
    864                     :ps_dpb_mgr->ps_dpb_long_term_head;
    865     /* If null, no entries in the list. Hence return. */
    866     if(ps_dpb_node1 == NULL)
    867         return 0;
    868 
    869     /* If only one node in the list, set as unsed for refer and return. */
    870     if(ps_dpb_node1->ps_prev_dpb == NULL)
    871     {
    872         /* Set the picture as unused for reference */
    873         ps_dpb_node1->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
    874         ps_dpb_node1->ps_pic_buf = NULL;
    875 
    876         if(reference_type == SHORT_TERM_REF)
    877         {
    878             ps_dpb_mgr->ps_dpb_short_term_head = NULL;
    879 
    880             /* Increment Short term buffer count */
    881             ps_dpb_mgr->u1_num_short_term_ref_bufs = 0;
    882 
    883         }
    884         else
    885         {
    886             ps_dpb_mgr->ps_dpb_long_term_head = NULL;
    887 
    888             /* Increment Long term buffer count */
    889             ps_dpb_mgr->u1_num_long_term_ref_bufs = 0;
    890 
    891         }
    892         return 0;
    893     }
    894 
    895     /**
    896      * If there are only 2 nodes in the list, set second node as unused for reference.
    897      * If the frame_num of second node and first node is same, set first node also as
    898      * unused for reference and set the corresponding head to NULL.
    899      */
    900     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
    901     if(ps_dpb_node2->ps_prev_dpb == NULL)
    902     {
    903         /* Set the picture as unused for reference */
    904         if(ps_dpb_node2->ps_pic_buf->i4_frame_num == ps_dpb_node1->ps_pic_buf->i4_frame_num)
    905         {
    906             /* Set the picture as unused for reference */
    907             ps_dpb_node1->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
    908             ps_dpb_node1->ps_pic_buf = NULL;
    909             if(reference_type == SHORT_TERM_REF)
    910             {
    911                 ps_dpb_mgr->ps_dpb_short_term_head = NULL;
    912 
    913                 /* Increment Short term buffer count */
    914                 ps_dpb_mgr->u1_num_short_term_ref_bufs = 0;
    915 
    916             }
    917             else
    918             {
    919                 ps_dpb_mgr->ps_dpb_long_term_head = NULL;
    920 
    921                 /* Increment Long term buffer count */
    922                 ps_dpb_mgr->u1_num_long_term_ref_bufs = 0;
    923 
    924             }
    925 
    926         }
    927         ps_dpb_node2->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
    928         ps_dpb_node2->ps_pic_buf = NULL;
    929         ps_dpb_node1->ps_prev_dpb = NULL;
    930         return 0;
    931     }
    932     /*
    933      * If there are more than 2 nodes, run a loop to get the last 3 nodes.
    934      */
    935     ps_dpb_node3 = ps_dpb_node2->ps_prev_dpb;
    936     while(ps_dpb_node3->ps_prev_dpb != NULL)
    937     {
    938         ps_dpb_node1 = ps_dpb_node2;
    939         ps_dpb_node2 = ps_dpb_node3;
    940         ps_dpb_node3 = ps_dpb_node3->ps_prev_dpb;
    941     }
    942     /*
    943      * If node 2 and node 3 frame_nums are same, set node 2 also as unsed for
    944      * reference and del reference from node1.
    945      */
    946     if(ps_dpb_node2->ps_pic_buf->i4_frame_num == ps_dpb_node3->ps_pic_buf->i4_frame_num)
    947     {
    948         ps_dpb_node2->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
    949         ps_dpb_node2->ps_pic_buf = NULL;
    950         ps_dpb_node1->ps_prev_dpb = NULL;
    951 
    952     }
    953     /* Set the third node as unused for reference */
    954     ps_dpb_node3->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
    955     ps_dpb_node3->ps_pic_buf = NULL;
    956     ps_dpb_node2->ps_prev_dpb = NULL;
    957 
    958     return 0;
    959 }
    960 /**
    961  *******************************************************************************
    962  *
    963  * @brief
    964  *  Delete long-term ref fields above max frame idx.
    965  *
    966  * @par Description:
    967  *  Deletes all the long-term ref fields having idx greater than max_frame_idx
    968  *
    969  * @param[in] ps_dpb_mgr
    970  *  Pointer to the DPB manager structure
    971  *
    972  * @param[in] max_frame_idx
    973  *  Max long-term frame idx allowed.
    974  *
    975  * @returns
    976  *
    977  * @remarks
    978  *
    979  *
    980  *******************************************************************************
    981  */
    982 WORD32 ih264_dpb_mgr_delete_long_ref_fields_max_frame_idx(dpb_mgr_t *ps_dpb_mgr,
    983                                                           WORD32 max_frame_idx)
    984 {
    985     dpb_info_t *ps_dpb_node1;
    986     dpb_info_t *ps_dpb_node2;
    987     /*
    988      * Loop until there is node which isn't to be deleted is encountered.
    989      */
    990     while(ps_dpb_mgr->ps_dpb_long_term_head != NULL)
    991     {
    992         if(ps_dpb_mgr->ps_dpb_long_term_head->ps_pic_buf->i4_long_term_frame_idx
    993                         <= max_frame_idx)
    994         {
    995             break;
    996         }
    997         ps_dpb_mgr->ps_dpb_long_term_head->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
    998         ps_dpb_mgr->ps_dpb_long_term_head->ps_pic_buf = NULL;
    999         ps_dpb_mgr->ps_dpb_long_term_head = ps_dpb_mgr->ps_dpb_long_term_head->ps_prev_dpb;
   1000     }
   1001 
   1002     ps_dpb_node1 = ps_dpb_mgr->ps_dpb_long_term_head;
   1003     if(ps_dpb_node1 == NULL)
   1004         return 0;
   1005     /*
   1006      * With the node that isn't to be deleted as head, loop until the end.
   1007      */
   1008     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
   1009     while(ps_dpb_node2 != NULL)
   1010     {
   1011         if(ps_dpb_node2->ps_pic_buf->i4_long_term_frame_idx > max_frame_idx)
   1012         {
   1013             ps_dpb_node2->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
   1014             ps_dpb_node2->ps_pic_buf = NULL;
   1015             ps_dpb_node1->ps_prev_dpb = ps_dpb_node2->ps_prev_dpb;
   1016         }
   1017         ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb;
   1018         if(ps_dpb_node1 == NULL)
   1019             break;
   1020         ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
   1021     }
   1022     return 0;
   1023 }
   1024 
   1025 /**
   1026  *******************************************************************************
   1027  *
   1028  * @brief
   1029  *  Deletes the short-term with least frame_num
   1030  *
   1031  * @par Description:
   1032  *  Deletes the short-term with least frame_num. It sorts the function the
   1033  *  short-term linked list by frame-num and the function that deletes the last
   1034  *  frame in the linked list.
   1035  *
   1036  * @param[in] ps_dpb_mgr
   1037  *  Pointer to the DPB manager structure
   1038  *
   1039  * @param[in] curr_frame_num
   1040  *  frame_num of the current pic
   1041  *
   1042  * @param[in] max_frame_num
   1043  *  Maximum frame_num allowed
   1044  *
   1045  * @returns
   1046  *
   1047  * @remarks
   1048  *
   1049  *
   1050  *******************************************************************************
   1051  */
   1052 WORD32 ih264_dpb_mgr_delete_short_ref_frame(dpb_mgr_t *ps_dpb_mgr,
   1053                                             WORD32 curr_frame_num,
   1054                                             WORD32 max_frame_num)
   1055 {
   1056     WORD32 ret;
   1057     /* Sort the short-term list by frame_num */
   1058     ret = ih264_dpb_mgr_sort_short_term_fields_by_frame_num(ps_dpb_mgr,
   1059                                                           curr_frame_num,
   1060                                                           TOP_FIELD,
   1061                                                           max_frame_num);
   1062 
   1063     /* Delete the last reference frame or field */
   1064     ret = ih264_dpb_mgr_delete_ref_frame(ps_dpb_mgr,SHORT_TERM_REF);
   1065 
   1066     if(ret != 0)
   1067     {
   1068         ASSERT(0);
   1069     }
   1070 
   1071     return ret;
   1072 }
   1073 /**
   1074  *******************************************************************************
   1075  *
   1076  * @brief
   1077  *  Deletes all the ref frames.
   1078  *
   1079  * @par Description:
   1080  *  Deletes all of the ref frames/fields in the short-term and long-term linked
   1081  *  list.
   1082  *
   1083  * @param[in] ps_dpb_mgr
   1084  *  Pointer to the DPB manager structure
   1085  *
   1086  * @returns
   1087  *
   1088  * @remarks
   1089  *
   1090  *
   1091  *******************************************************************************
   1092  */
   1093 WORD32 ih264_dpb_mgr_delete_all_ref_frames(dpb_mgr_t *ps_dpb_mgr)
   1094 {
   1095     /* Loop over short-term linked list. */
   1096     while(ps_dpb_mgr->ps_dpb_short_term_head != NULL)
   1097     {
   1098         ih264_dpb_mgr_delete_ref_frame(ps_dpb_mgr,SHORT_TERM_REF);
   1099     }
   1100 
   1101     /* Loop over long-term linked list. */
   1102     while(ps_dpb_mgr->ps_dpb_long_term_head != NULL)
   1103     {
   1104         ih264_dpb_mgr_delete_ref_frame(ps_dpb_mgr,LONG_TERM_REF);
   1105     }
   1106     return 0;
   1107 }
   1108 
   1109 
   1110 void ih264_dpb_mgr_reset(dpb_mgr_t *ps_dpb_mgr, buf_mgr_t *ps_buf_mgr)
   1111 {
   1112     WORD32 i;
   1113     dpb_info_t *ps_dpb_info;
   1114     ASSERT(0);
   1115 
   1116 
   1117     ps_dpb_info = ps_dpb_mgr->as_dpb_info;
   1118 
   1119     for(i = 0; i < MAX_DPB_BUFS; i++)
   1120     {
   1121         if(ps_dpb_info[i].ps_pic_buf->i4_used_as_ref)
   1122         {
   1123             ps_dpb_info[i].ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
   1124             ps_dpb_info[i].ps_prev_dpb = NULL;
   1125             //Release physical buffer
   1126             ih264_buf_mgr_release(ps_buf_mgr, ps_dpb_info[i].ps_pic_buf->i4_buf_id,
   1127                                   BUF_MGR_REF);
   1128 
   1129             ps_dpb_info[i].ps_pic_buf = NULL;
   1130         }
   1131     }
   1132     ps_dpb_mgr->u1_num_short_term_ref_bufs = 0;
   1133     ps_dpb_mgr->u1_num_long_term_ref_bufs  = 0;
   1134     ps_dpb_mgr->ps_dpb_short_term_head = NULL;
   1135     ps_dpb_mgr->ps_dpb_long_term_head  = NULL;
   1136 
   1137 }
   1138 
   1139 /**
   1140  *******************************************************************************
   1141  *
   1142  * @brief
   1143  *  deletes all pictures from DPB
   1144  *
   1145  * @par Description:
   1146  *  Deletes all pictures present in the DPB manager
   1147  *
   1148  * @param[in] ps_buf_mgr
   1149  *  Pointer to buffer manager structure
   1150  *
   1151  * @param[in] u1_disp_bufs
   1152  *  Number of buffers to be deleted
   1153  *
   1154  * @returns
   1155  *
   1156  * @remarks
   1157  *
   1158  *
   1159  *******************************************************************************
   1160  */
   1161 
   1162 void ih264_dpb_mgr_release_pics(buf_mgr_t *ps_buf_mgr, UWORD8 u1_disp_bufs)
   1163 {
   1164     WORD8 i;
   1165     UWORD32 buf_status;
   1166     ASSERT(0);
   1167 
   1168     for(i = 0; i < u1_disp_bufs; i++)
   1169     {
   1170         buf_status = ih264_buf_mgr_get_status(ps_buf_mgr, i);
   1171         if(0 != buf_status)
   1172         {
   1173             ih264_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, i, BUF_MGR_REF);
   1174         }
   1175     }
   1176 }
   1177