Home | History | Annotate | Download | only in decoder
      1 /******************************************************************************
      2 *
      3 * Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
      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 /**
     19 *******************************************************************************
     20 * @file
     21 *  ihevcd_utils.c
     22 *
     23 * @brief
     24 *  Contains miscellaneous utility functions such as init() etc
     25 *
     26 * @author
     27 *  Harish
     28 *
     29 * @par List of Functions:
     30 *
     31 * @remarks
     32 *  None
     33 *
     34 *******************************************************************************
     35 */
     36 /*****************************************************************************/
     37 /* File Includes                                                             */
     38 /*****************************************************************************/
     39 #include <stdio.h>
     40 #include <stddef.h>
     41 #include <stdlib.h>
     42 #include <string.h>
     43 #include <assert.h>
     44 
     45 #include "ihevc_typedefs.h"
     46 #include "iv.h"
     47 #include "ivd.h"
     48 #include "ihevcd_cxa.h"
     49 #include "ithread.h"
     50 
     51 #include "ihevc_defs.h"
     52 #include "ihevc_debug.h"
     53 #include "ihevc_defs.h"
     54 #include "ihevc_error.h"
     55 #include "ihevc_structs.h"
     56 #include "ihevc_buf_mgr.h"
     57 #include "ihevc_dpb_mgr.h"
     58 #include "ihevc_macros.h"
     59 #include "ihevc_platform_macros.h"
     60 
     61 #include "ihevc_common_tables.h"
     62 #include "ihevc_buf_mgr.h"
     63 #include "ihevc_disp_mgr.h"
     64 #include "ihevc_cabac_tables.h"
     65 
     66 #include "ihevcd_defs.h"
     67 
     68 #include "ihevcd_function_selector.h"
     69 #include "ihevcd_structs.h"
     70 #include "ihevcd_error.h"
     71 #include "ihevcd_nal.h"
     72 #include "ihevcd_bitstream.h"
     73 #include "ihevcd_utils.h"
     74 #include "ihevcd_trace.h"
     75 #include "ihevcd_process_slice.h"
     76 #include "ihevcd_job_queue.h"
     77 #define MAX_DPB_PIC_BUF 6
     78 
     79 /* Function declarations */
     80 mv_buf_t* ihevcd_mv_mgr_get_poc(buf_mgr_t *ps_mv_buf_mgr, UWORD32 abs_poc);
     81 
     82 /**
     83 *******************************************************************************
     84 *
     85 * @brief
     86 *  Used to get level index for a given level
     87 *
     88 * @par Description:
     89 *  Converts from level_idc (which is multiplied by 30) to an index that can be
     90 *  used as a lookup. Also used to ignore invalid levels like 2.2 , 3.2 etc
     91 *
     92 * @param[in] level
     93 *  Level of the stream
     94 *
     95 * @returns  Level index for a given level
     96 *
     97 * @remarks
     98 *
     99 *
    100 *******************************************************************************
    101 */
    102 WORD32 ihevcd_get_lvl_idx(WORD32 level)
    103 {
    104     WORD32 lvl_idx = 0;
    105 
    106     if(level < IHEVC_LEVEL_20)
    107     {
    108         lvl_idx = 0;
    109     }
    110     else if(level >= IHEVC_LEVEL_20 && level < IHEVC_LEVEL_21)
    111     {
    112         lvl_idx = 1;
    113     }
    114     else if(level >= IHEVC_LEVEL_21 && level < IHEVC_LEVEL_30)
    115     {
    116         lvl_idx = 2;
    117     }
    118     else if(level >= IHEVC_LEVEL_30 && level < IHEVC_LEVEL_31)
    119     {
    120         lvl_idx = 3;
    121     }
    122     else if(level >= IHEVC_LEVEL_31 && level < IHEVC_LEVEL_40)
    123     {
    124         lvl_idx = 4;
    125     }
    126     else if(level >= IHEVC_LEVEL_40 && level < IHEVC_LEVEL_41)
    127     {
    128         lvl_idx = 5;
    129     }
    130     else if(level >= IHEVC_LEVEL_41 && level < IHEVC_LEVEL_50)
    131     {
    132         lvl_idx = 6;
    133     }
    134     else if(level >= IHEVC_LEVEL_50 && level < IHEVC_LEVEL_51)
    135     {
    136         lvl_idx = 7;
    137     }
    138     else if(level >= IHEVC_LEVEL_51 && level < IHEVC_LEVEL_52)
    139     {
    140         lvl_idx = 8;
    141     }
    142     else if(level >= IHEVC_LEVEL_52 && level < IHEVC_LEVEL_60)
    143     {
    144         lvl_idx = 9;
    145     }
    146     else if(level >= IHEVC_LEVEL_60 && level < IHEVC_LEVEL_61)
    147     {
    148         lvl_idx = 10;
    149     }
    150     else if(level >= IHEVC_LEVEL_61 && level < IHEVC_LEVEL_62)
    151     {
    152         lvl_idx = 11;
    153     }
    154     else if(level >= IHEVC_LEVEL_62)
    155     {
    156         lvl_idx = 12;
    157     }
    158 
    159     return (lvl_idx);
    160 }
    161 
    162 /**
    163 *******************************************************************************
    164 *
    165 * @brief
    166 *  Used to get reference picture buffer size for a given level and
    167 *  and padding used
    168 *
    169 * @par Description:
    170 *  Used to get reference picture buffer size for a given level and padding used
    171 *  Each picture is padded on all four sides
    172 *
    173 * @param[in] pic_size
    174 *  Mumber of luma samples (Width * Height)
    175 *
    176 * @param[in] level
    177 *  Level
    178 *
    179 * @param[in] horz_pad
    180 *  Total padding used in horizontal direction
    181 *
    182 * @param[in] vert_pad
    183 *  Total padding used in vertical direction
    184 *
    185 * @returns  Total picture buffer size
    186 *
    187 * @remarks
    188 *
    189 *
    190 *******************************************************************************
    191 */
    192 WORD32 ihevcd_get_total_pic_buf_size(codec_t *ps_codec,
    193                                      WORD32 wd,
    194                                      WORD32 ht)
    195 {
    196     WORD32 size;
    197     WORD32 num_luma_samples;
    198     WORD32 max_dpb_size;
    199     WORD32 num_samples;
    200 
    201 
    202     sps_t *ps_sps = (ps_codec->s_parse.ps_sps_base + ps_codec->i4_sps_id);
    203 
    204     /* Get maximum number of buffers for the current picture size */
    205     max_dpb_size = ps_sps->ai1_sps_max_dec_pic_buffering[ps_sps->i1_sps_max_sub_layers - 1];
    206 
    207     if(ps_codec->e_frm_out_mode != IVD_DECODE_FRAME_OUT)
    208         max_dpb_size += ps_sps->ai1_sps_max_num_reorder_pics[ps_sps->i1_sps_max_sub_layers - 1];
    209 
    210     max_dpb_size++;
    211     /* Allocation is required for
    212      * (Wd + horz_pad) * (Ht + vert_pad) * (2 * max_dpb_size + 1)
    213      */
    214 
    215     /* Account for padding area */
    216     num_luma_samples = (wd + PAD_WD) * (ht + PAD_HT);
    217 
    218     /* Account for chroma */
    219     num_samples = num_luma_samples * 3 / 2;
    220 
    221     /* Number of bytes in reference pictures */
    222     size = num_samples * max_dpb_size;
    223 
    224 
    225     return size;
    226 }
    227 /**
    228 *******************************************************************************
    229 *
    230 * @brief
    231 *  Used to get MV bank size for a given number of luma samples
    232 *
    233 * @par Description:
    234 *  For given number of luma samples  one MV bank size is computed
    235 *  Each MV bank includes pu_map and pu_t for all the min PUs(4x4) in a picture
    236 *
    237 * @param[in] num_luma_samples
    238 *  Max number of luma pixels in the frame
    239 *
    240 * @returns  Total MV Bank size
    241 *
    242 * @remarks
    243 *
    244 *
    245 *******************************************************************************
    246 */
    247 WORD32 ihevcd_get_pic_mv_bank_size(WORD32 num_luma_samples)
    248 {
    249     WORD32 size;
    250 
    251     WORD32 pic_size;
    252 
    253     WORD32 mv_bank_size;
    254     WORD32 num_pu;
    255     WORD32 num_ctb;
    256     pic_size = num_luma_samples;
    257 
    258 
    259     num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
    260     num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
    261 
    262     mv_bank_size = 0;
    263 
    264     /* Size for storing pu_t start index each CTB */
    265     /* One extra entry is needed to compute number of PUs in the last CTB */
    266     mv_bank_size += (num_ctb + 1) * sizeof(WORD32);
    267 
    268     /* Size for pu_map */
    269     mv_bank_size += num_pu;
    270 
    271     /* Size for storing pu_t for each PU */
    272     mv_bank_size += num_pu * sizeof(pu_t);
    273 
    274     /* Size for storing slice_idx for each CTB */
    275     mv_bank_size += ALIGN4(num_ctb * sizeof(UWORD16));
    276 
    277     size =  mv_bank_size;
    278     return size;
    279 }
    280 /**
    281 *******************************************************************************
    282 *
    283 * @brief
    284 *  Used to get TU data size for a given number luma samples
    285 *
    286 * @par Description:
    287 *  For a given number of luma samples TU data size is computed
    288 *  Each TU data includes tu_map and tu_t and coeff data for all
    289 *  the min TUs(4x4) in given CTB
    290 *
    291 * @param[in] num_luma_samples
    292 *  Number of 64 x 64 CTBs for which TU data has to be allocated.
    293 *
    294 * @returns  Total TU data size
    295 *
    296 * @remarks Assumption is num_luma_samples will be at least
    297 * 64 x 64 to handle CTB of size 64 x 64. Can be frame size as well
    298 *
    299 *******************************************************************************
    300 */
    301 WORD32 ihevcd_get_tu_data_size(WORD32 num_luma_samples)
    302 {
    303 
    304 
    305     WORD32 tu_data_size;
    306     WORD32 num_ctb;
    307     WORD32 num_luma_tu, num_chroma_tu, num_tu;
    308     num_ctb = num_luma_samples / (MIN_CTB_SIZE * MIN_CTB_SIZE);
    309 
    310     num_luma_tu = num_luma_samples / (MIN_TU_SIZE * MIN_TU_SIZE);
    311     num_chroma_tu = num_luma_tu >> 1;
    312 
    313     num_tu = num_luma_tu + num_chroma_tu;
    314     tu_data_size = 0;
    315 
    316     /* Size for storing tu_t start index each CTB */
    317     /* One extra entry is needed to compute number of TUs in the last CTB */
    318     tu_data_size += (num_ctb + 1) * sizeof(WORD32);
    319 
    320     /* Size for storing tu map */
    321     tu_data_size += num_luma_tu * sizeof(UWORD8);
    322 
    323     /* Size for storing tu_t for each TU */
    324     tu_data_size += num_tu * sizeof(tu_t);
    325 
    326     /* Size for storing number of coded subblocks and scan_idx for each TU */
    327     tu_data_size += num_tu * (sizeof(WORD8) + sizeof(WORD8));
    328 
    329     /* Size for storing coeff data for each TU */
    330     tu_data_size += num_tu * sizeof(tu_sblk_coeff_data_t);
    331 
    332 
    333     return tu_data_size;
    334 }
    335 
    336 
    337 WORD32 ihevcd_nctb_cnt(codec_t *ps_codec, sps_t *ps_sps)
    338 {
    339     WORD32 nctb = 1;
    340     UNUSED(ps_codec);
    341     //TODO: Currently set to 1
    342     /* If CTB size is less than 32 x 32 then set nCTB as 4 */
    343     if(ps_sps->i1_log2_ctb_size < 5)
    344         nctb = 1;
    345 
    346     return nctb;
    347 }
    348 
    349 IHEVCD_ERROR_T ihevcd_get_tile_pos(pps_t *ps_pps,
    350                                    sps_t *ps_sps,
    351                                    WORD32 ctb_x,
    352                                    WORD32 ctb_y,
    353                                    WORD32 *pi4_ctb_tile_x,
    354                                    WORD32 *pi4_ctb_tile_y,
    355                                    WORD32 *pi4_tile_idx)
    356 {
    357 
    358     tile_t *ps_tile_tmp;
    359     WORD32 i;
    360     WORD32 tile_row, tile_col;
    361 
    362     if(ctb_x < 0 || ctb_y < 0)
    363     {
    364         *pi4_ctb_tile_x = 0;
    365         *pi4_ctb_tile_y = 0;
    366         *pi4_tile_idx = 0;
    367 
    368         return (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    369     }
    370 
    371     tile_row = 0;
    372     tile_col = 0;
    373     ps_tile_tmp = ps_pps->ps_tile;
    374     if(0 == ps_pps->i1_tiles_enabled_flag)
    375     {
    376         *pi4_ctb_tile_x = ctb_x;
    377         *pi4_ctb_tile_y = ctb_y;
    378         *pi4_tile_idx = 0;
    379     }
    380     else
    381     {
    382         for(i = 0; i < ps_pps->i1_num_tile_columns; i++)
    383         {
    384             WORD16 next_tile_ctb_x;
    385             ps_tile_tmp = ps_pps->ps_tile + i; //* ps_pps->i1_num_tile_rows;
    386             if((ps_pps->i1_num_tile_columns - 1) == i)
    387             {
    388                 next_tile_ctb_x = ps_sps->i2_pic_wd_in_ctb;
    389             }
    390             else
    391             {
    392                 tile_t *ps_tile_next_tmp;
    393                 ps_tile_next_tmp = ps_pps->ps_tile + i + 1;
    394                 next_tile_ctb_x = ps_tile_next_tmp->u1_pos_x;
    395             }
    396             if((ctb_x >= ps_tile_tmp->u1_pos_x) && (ctb_x < next_tile_ctb_x))
    397             {
    398                 tile_col = i;
    399                 break;
    400             }
    401         }
    402         *pi4_ctb_tile_x = ctb_x - ps_tile_tmp->u1_pos_x;
    403 
    404         for(i = 0; i < ps_pps->i1_num_tile_rows; i++)
    405         {
    406             WORD16 next_tile_ctb_y;
    407             ps_tile_tmp = ps_pps->ps_tile + i * ps_pps->i1_num_tile_columns;
    408             if((ps_pps->i1_num_tile_rows - 1) == i)
    409             {
    410                 next_tile_ctb_y = ps_sps->i2_pic_ht_in_ctb;
    411             }
    412             else
    413             {
    414                 tile_t *ps_tile_next_tmp;
    415                 ps_tile_next_tmp = ps_pps->ps_tile + ((i + 1) * ps_pps->i1_num_tile_columns);
    416                 next_tile_ctb_y = ps_tile_next_tmp->u1_pos_y;
    417             }
    418             if((ctb_y >= ps_tile_tmp->u1_pos_y) && (ctb_y < next_tile_ctb_y))
    419             {
    420                 tile_row = i;
    421                 break;
    422             }
    423 
    424         }
    425         *pi4_ctb_tile_y = ctb_y - ps_tile_tmp->u1_pos_y;
    426         *pi4_tile_idx = tile_row * ps_pps->i1_num_tile_columns
    427                         + tile_col;
    428     }
    429     return (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    430 }
    431 /**
    432 *******************************************************************************
    433 *
    434 * @brief
    435 *  Function to initialize ps_pic_buf structs add pic buffers to
    436 *  buffer manager in case of non-shared mode
    437 *
    438 * @par Description:
    439 *  Function to initialize ps_pic_buf structs add pic buffers to
    440 *  buffer manager in case of non-shared mode
    441 *  To be called once per stream or for every reset
    442 *
    443 * @param[in] ps_codec
    444 *  Pointer to codec context
    445 *
    446 * @returns  Error from IHEVCD_ERROR_T
    447 *
    448 * @remarks
    449 *
    450 *
    451 *******************************************************************************
    452 */
    453 IHEVCD_ERROR_T ihevcd_pic_buf_mgr_add_bufs(codec_t *ps_codec)
    454 {
    455     IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    456     WORD32 i;
    457     WORD32 max_dpb_size;
    458     sps_t *ps_sps;
    459     UWORD8 *pu1_buf;
    460     pic_buf_t *ps_pic_buf;
    461     WORD32 pic_buf_size_allocated;
    462 
    463 
    464 
    465 
    466     /* Initialize Pic buffer manager */
    467     ps_sps = ps_codec->s_parse.ps_sps;
    468 
    469     /* Compute the number of Pic buffers needed */
    470     max_dpb_size = ps_sps->ai1_sps_max_dec_pic_buffering[ps_sps->i1_sps_max_sub_layers - 1];
    471 
    472     if(ps_codec->e_frm_out_mode != IVD_DECODE_FRAME_OUT)
    473         max_dpb_size += ps_sps->ai1_sps_max_num_reorder_pics[ps_sps->i1_sps_max_sub_layers - 1];
    474 
    475     /* Allocate one extra picture to handle current frame
    476      * In case of asynchronous parsing and processing, number of buffers should increase here
    477      * based on when parsing and processing threads are synchronized
    478      */
    479     max_dpb_size++;
    480 
    481 
    482     pu1_buf = (UWORD8 *)ps_codec->pu1_ref_pic_buf_base;
    483 
    484     ps_pic_buf = (pic_buf_t *)ps_codec->ps_pic_buf;
    485 
    486     /* In case of non-shared mode, add picture buffers to buffer manager
    487      * In case of shared mode buffers are added in the run-time
    488      */
    489     if(0 == ps_codec->i4_share_disp_buf)
    490     {
    491         WORD32 buf_ret;
    492         WORD32 luma_samples;
    493         WORD32 chroma_samples;
    494         pic_buf_size_allocated = ps_codec->i4_total_pic_buf_size;
    495 
    496         luma_samples = (ps_codec->i4_strd) *
    497                         (ps_sps->i2_pic_height_in_luma_samples + PAD_HT);
    498 
    499         chroma_samples = luma_samples / 2;
    500 
    501         /* Try to add as many buffers as possible since memory is already allocated */
    502         /* If the number of buffers that can be added is less than max_num_bufs
    503          * return with an error.
    504          */
    505         for(i = 0; i < max_dpb_size; i++)
    506         {
    507             pic_buf_size_allocated -= (luma_samples + chroma_samples);
    508 
    509             if(pic_buf_size_allocated < 0)
    510             {
    511                 ps_codec->s_parse.i4_error_code = IHEVCD_INSUFFICIENT_MEM_PICBUF;
    512                 return IHEVCD_INSUFFICIENT_MEM_PICBUF;
    513             }
    514 
    515             ps_pic_buf->pu1_luma = pu1_buf + ps_codec->i4_strd * PAD_TOP + PAD_LEFT;
    516             pu1_buf += luma_samples;
    517 
    518             ps_pic_buf->pu1_chroma = pu1_buf + ps_codec->i4_strd * (PAD_TOP / 2) + PAD_LEFT;
    519             pu1_buf += chroma_samples;
    520 
    521             /* Pad boundary pixels (one pixel on all sides) */
    522             /* This ensures SAO does not read uninitialized pixels */
    523             /* Note these are not used in actual processing */
    524             {
    525                 UWORD8 *pu1_buf;
    526                 WORD32 strd, wd, ht;
    527                 WORD32 i;
    528                 strd = ps_codec->i4_strd;
    529                 wd = ps_codec->i4_wd;
    530                 ht = ps_codec->i4_ht;
    531 
    532                 pu1_buf = ps_pic_buf->pu1_luma;
    533                 for(i = 0; i < ht; i++)
    534                 {
    535                     pu1_buf[-1] = 0;
    536                     pu1_buf[wd] = 0;
    537                     pu1_buf += strd;
    538                 }
    539                 pu1_buf = ps_pic_buf->pu1_luma;
    540                 memset(pu1_buf - strd - 1, 0, wd + 2);
    541 
    542                 pu1_buf += strd * ht;
    543                 memset(pu1_buf - 1, 0, wd + 2);
    544 
    545                 pu1_buf = ps_pic_buf->pu1_chroma;
    546                 ht >>= 1;
    547                 for(i = 0; i < ht; i++)
    548                 {
    549                     pu1_buf[-1] = 0;
    550                     pu1_buf[-2] = 0;
    551                     pu1_buf[wd] = 0;
    552                     pu1_buf[wd + 1] = 0;
    553                     pu1_buf += strd;
    554                 }
    555                 pu1_buf = ps_pic_buf->pu1_chroma;
    556                 memset(pu1_buf - strd - 2, 0, wd + 4);
    557 
    558                 pu1_buf += strd * ht;
    559                 memset(pu1_buf - 2, 0, wd + 4);
    560             }
    561 
    562             buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, ps_pic_buf, i);
    563 
    564 
    565             if(0 != buf_ret)
    566             {
    567                 ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR;
    568                 return IHEVCD_BUF_MGR_ERROR;
    569             }
    570             ps_pic_buf++;
    571         }
    572     }
    573     else
    574     {
    575         /* In case of shared mode, buffers are added without adjusting for padding.
    576            Update luma and chroma pointers here to account for padding as per stride.
    577            In some cases stride might not be available when set_display_frame is called.
    578            Hence updated luma and chroma pointers here */
    579 
    580         for(i = 0; i < BUF_MGR_MAX_CNT; i++)
    581         {
    582             ps_pic_buf = ihevc_buf_mgr_get_buf((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, i);
    583             if((NULL == ps_pic_buf) ||
    584                (NULL == ps_pic_buf->pu1_luma) ||
    585                (NULL == ps_pic_buf->pu1_chroma))
    586             {
    587                 break;
    588             }
    589             ps_pic_buf->pu1_luma += ps_codec->i4_strd * PAD_TOP + PAD_LEFT;
    590             ps_pic_buf->pu1_chroma += ps_codec->i4_strd * (PAD_TOP / 2) + PAD_LEFT;
    591         }
    592     }
    593 
    594     return ret;
    595 }
    596 /**
    597 *******************************************************************************
    598 *
    599 * @brief
    600 *  Function to add buffers to MV Bank buffer manager
    601 *
    602 * @par Description:
    603 *  Function to add buffers to MV Bank buffer manager
    604 *  To be called once per stream or for every reset
    605 *
    606 * @param[in] ps_codec
    607 *  Pointer to codec context
    608 *
    609 * @returns  Error from IHEVCD_ERROR_T
    610 *
    611 * @remarks
    612 *
    613 *
    614 *******************************************************************************
    615 */
    616 IHEVCD_ERROR_T ihevcd_mv_buf_mgr_add_bufs(codec_t *ps_codec)
    617 {
    618     IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    619     WORD32 i;
    620     WORD32 max_dpb_size;
    621     WORD32 mv_bank_size_allocated;
    622     WORD32 pic_mv_bank_size;
    623 
    624     sps_t *ps_sps;
    625     UWORD8 *pu1_buf;
    626     mv_buf_t *ps_mv_buf;
    627 
    628 
    629     /* Initialize MV Bank buffer manager */
    630     ps_sps = ps_codec->s_parse.ps_sps;
    631 
    632 
    633     /* Compute the number of MV Bank buffers needed */
    634     max_dpb_size = ps_sps->ai1_sps_max_dec_pic_buffering[ps_sps->i1_sps_max_sub_layers - 1];
    635 
    636     /* Allocate one extra MV Bank to handle current frame
    637      * In case of asynchronous parsing and processing, number of buffers should increase here
    638      * based on when parsing and processing threads are synchronized
    639      */
    640     max_dpb_size++;
    641 
    642     ps_codec->i4_max_dpb_size = max_dpb_size;
    643 
    644     pu1_buf = (UWORD8 *)ps_codec->pv_mv_bank_buf_base;
    645 
    646     ps_mv_buf = (mv_buf_t *)pu1_buf;
    647     pu1_buf += max_dpb_size * sizeof(mv_buf_t);
    648     ps_codec->ps_mv_buf = ps_mv_buf;
    649     mv_bank_size_allocated = ps_codec->i4_total_mv_bank_size - max_dpb_size  * sizeof(mv_buf_t);
    650 
    651     /* Compute MV bank size per picture */
    652     pic_mv_bank_size = ihevcd_get_pic_mv_bank_size(ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
    653                                                    ALIGN64(ps_sps->i2_pic_height_in_luma_samples));
    654 
    655     for(i = 0; i < max_dpb_size; i++)
    656     {
    657         WORD32 buf_ret;
    658         WORD32 num_pu;
    659         WORD32 num_ctb;
    660         WORD32 pic_size;
    661         pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
    662                         ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
    663 
    664 
    665         num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
    666         num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
    667 
    668 
    669         mv_bank_size_allocated -= pic_mv_bank_size;
    670 
    671         if(mv_bank_size_allocated < 0)
    672         {
    673             ps_codec->s_parse.i4_error_code = IHEVCD_INSUFFICIENT_MEM_MVBANK;
    674             return IHEVCD_INSUFFICIENT_MEM_MVBANK;
    675         }
    676 
    677         ps_mv_buf->pu4_pic_pu_idx = (UWORD32 *)pu1_buf;
    678         pu1_buf += (num_ctb + 1) * sizeof(WORD32);
    679 
    680         ps_mv_buf->pu1_pic_pu_map = pu1_buf;
    681         pu1_buf += num_pu;
    682 
    683         ps_mv_buf->pu1_pic_slice_map = (UWORD16 *)pu1_buf;
    684         pu1_buf += ALIGN4(num_ctb * sizeof(UWORD16));
    685 
    686         ps_mv_buf->ps_pic_pu = (pu_t *)pu1_buf;
    687         pu1_buf += num_pu * sizeof(pu_t);
    688 
    689         buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_mv_buf_mgr, ps_mv_buf, i);
    690 
    691         if(0 != buf_ret)
    692         {
    693             ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR;
    694             return IHEVCD_BUF_MGR_ERROR;
    695         }
    696 
    697         ps_mv_buf++;
    698 
    699     }
    700     return ret;
    701 }
    702 /**
    703 *******************************************************************************
    704 *
    705 * @brief
    706 *  Output buffer check
    707 *
    708 * @par Description:
    709 *  Check for the number of buffers and buffer sizes of output buffer
    710 *
    711 * @param[in] ps_codec
    712 *  Pointer to codec context
    713 *
    714 * @returns  Error from IHEVCD_ERROR_T
    715 *
    716 * @remarks
    717 *
    718 *
    719 *******************************************************************************
    720 */
    721 IHEVCD_ERROR_T ihevcd_check_out_buf_size(codec_t *ps_codec)
    722 {
    723     ivd_out_bufdesc_t *ps_out_buffer = ps_codec->ps_out_buffer;
    724     UWORD32 au4_min_out_buf_size[IVD_VIDDEC_MAX_IO_BUFFERS];
    725     UWORD32 u4_min_num_out_bufs = 0, i;
    726     UWORD32 wd, ht;
    727 
    728     if(0 == ps_codec->i4_share_disp_buf)
    729     {
    730         wd = ps_codec->i4_disp_wd;
    731         ht = ps_codec->i4_disp_ht;
    732     }
    733     else
    734     {
    735         /* In case of shared mode, do not check validity of ps_codec->ps_out_buffer */
    736         return (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    737     }
    738 
    739     if(ps_codec->i4_disp_strd > (WORD32)wd)
    740         wd = ps_codec->i4_disp_strd;
    741 
    742     if(ps_codec->e_chroma_fmt == IV_YUV_420P)
    743         u4_min_num_out_bufs = MIN_OUT_BUFS_420;
    744     else if(ps_codec->e_chroma_fmt == IV_YUV_422ILE)
    745         u4_min_num_out_bufs = MIN_OUT_BUFS_422ILE;
    746     else if(ps_codec->e_chroma_fmt == IV_RGB_565)
    747         u4_min_num_out_bufs = MIN_OUT_BUFS_RGB565;
    748     else if(ps_codec->e_chroma_fmt == IV_RGBA_8888)
    749         u4_min_num_out_bufs = MIN_OUT_BUFS_RGBA8888;
    750     else if((ps_codec->e_chroma_fmt == IV_YUV_420SP_UV)
    751                     || (ps_codec->e_chroma_fmt == IV_YUV_420SP_VU))
    752         u4_min_num_out_bufs = MIN_OUT_BUFS_420SP;
    753 
    754     if(ps_codec->e_chroma_fmt == IV_YUV_420P)
    755     {
    756         au4_min_out_buf_size[0] = (wd * ht);
    757         au4_min_out_buf_size[1] = (wd * ht) >> 2;
    758         au4_min_out_buf_size[2] = (wd * ht) >> 2;
    759     }
    760     else if(ps_codec->e_chroma_fmt == IV_YUV_422ILE)
    761     {
    762         au4_min_out_buf_size[0] = (wd * ht) * 2;
    763         au4_min_out_buf_size[1] =
    764                         au4_min_out_buf_size[2] = 0;
    765     }
    766     else if(ps_codec->e_chroma_fmt == IV_RGB_565)
    767     {
    768         au4_min_out_buf_size[0] = (wd * ht) * 2;
    769         au4_min_out_buf_size[1] =
    770                         au4_min_out_buf_size[2] = 0;
    771     }
    772     else if(ps_codec->e_chroma_fmt == IV_RGBA_8888)
    773     {
    774         au4_min_out_buf_size[0] = (wd * ht) * 4;
    775         au4_min_out_buf_size[1] =
    776                         au4_min_out_buf_size[2] = 0;
    777     }
    778     else if((ps_codec->e_chroma_fmt == IV_YUV_420SP_UV)
    779                     || (ps_codec->e_chroma_fmt == IV_YUV_420SP_VU))
    780     {
    781         au4_min_out_buf_size[0] = (wd * ht);
    782         au4_min_out_buf_size[1] = (wd * ht) >> 1;
    783         au4_min_out_buf_size[2] = 0;
    784     }
    785 
    786     if(ps_out_buffer->u4_num_bufs < u4_min_num_out_bufs)
    787     {
    788         return (IHEVCD_ERROR_T)IV_FAIL;
    789     }
    790 
    791     for (i = 0 ; i < u4_min_num_out_bufs; i++)
    792     {
    793         if(ps_out_buffer->u4_min_out_buf_size[i] < au4_min_out_buf_size[i])
    794         {
    795             return (IHEVCD_ERROR_T)IV_FAIL;
    796         }
    797     }
    798 
    799     return (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    800 }
    801 
    802 /**
    803 *******************************************************************************
    804 *
    805 * @brief
    806 *  Picture level initializations required during parsing
    807 *
    808 * @par Description:
    809 *  Initialize picture level context variables during parsing Initialize mv
    810 * bank buffer manager in the first init call
    811 *
    812 * @param[in] ps_codec
    813 *  Pointer to codec context
    814 *
    815 * @returns  Error from IHEVCD_ERROR_T
    816 *
    817 * @remarks
    818 *
    819 *
    820 *******************************************************************************
    821 */
    822 IHEVCD_ERROR_T ihevcd_parse_pic_init(codec_t *ps_codec)
    823 {
    824     IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    825     mv_buf_t *ps_mv_buf;
    826     sps_t *ps_sps;
    827     WORD32 num_min_cu;
    828     WORD32 cur_pic_buf_id;
    829     WORD32 cur_mv_bank_buf_id;
    830     pic_buf_t *ps_cur_pic;
    831     slice_header_t *ps_slice_hdr;
    832     UWORD8 *pu1_cur_pic_luma, *pu1_cur_pic_chroma;
    833     WORD32 i;
    834 
    835     ps_codec->s_parse.i4_error_code = IHEVCD_SUCCESS;
    836     ps_sps = ps_codec->s_parse.ps_sps;
    837     ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;
    838 
    839     /* Memset picture level intra map and transquant bypass map to zero */
    840     num_min_cu = ((ps_sps->i2_pic_height_in_luma_samples + 7) / 8) * ((ps_sps->i2_pic_width_in_luma_samples + 63) / 64);
    841     memset(ps_codec->s_parse.pu1_pic_intra_flag, 0, num_min_cu);
    842     memset(ps_codec->s_parse.pu1_pic_no_loop_filter_flag, 0, num_min_cu);
    843 
    844 
    845 
    846     if(0 == ps_codec->s_parse.i4_first_pic_init)
    847     {
    848         ret = ihevcd_mv_buf_mgr_add_bufs(ps_codec);
    849         RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
    850 
    851         ret = ihevcd_pic_buf_mgr_add_bufs(ps_codec);
    852         RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
    853 
    854         ps_codec->s_parse.i4_first_pic_init = 1;
    855     }
    856 
    857     /* Output buffer check */
    858     ret = ihevcd_check_out_buf_size(ps_codec);
    859     RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
    860 
    861     /* Initialize all the slice headers' slice addresses to zero */
    862     {
    863         WORD32 slice_idx;
    864         WORD32 slice_start_idx;
    865 
    866         slice_start_idx = ps_codec->i4_slice_error ? 2 : 1;
    867 
    868         for(slice_idx = slice_start_idx; slice_idx < MAX_SLICE_HDR_CNT; slice_idx++)
    869         {
    870             slice_header_t *ps_slice_hdr_tmp = ps_codec->ps_slice_hdr_base + slice_idx;
    871             ps_slice_hdr_tmp->i2_ctb_x = -1;
    872             ps_slice_hdr_tmp->i2_ctb_y = -1;
    873 
    874         }
    875     }
    876 
    877     /* Get free MV Bank to hold current picture's motion vector data */
    878     {
    879         ps_mv_buf = (mv_buf_t *)ihevc_buf_mgr_get_next_free((buf_mgr_t *)ps_codec->pv_mv_buf_mgr, &cur_mv_bank_buf_id);
    880 
    881         /* If there are no free buffers then return with an error code.
    882          * If the buffer is to be freed by another thread , change the
    883          * following to call thread yield and wait for buffer to be freed
    884          */
    885         if(NULL == ps_mv_buf)
    886         {
    887             ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_MVBANK;
    888             ps_codec->i4_error_code = IHEVCD_NO_FREE_MVBANK;
    889             return IHEVCD_NO_FREE_MVBANK;
    890         }
    891 
    892         ps_codec->s_parse.ps_cur_mv_buf = ps_mv_buf;
    893         /* Set current ABS poc to ps_mv_buf, so that while freeing a reference buffer
    894          * corresponding mv buffer can be found by looping through ps_codec->ps_mv_buf array
    895          * and getting a buffer id to free
    896          */
    897         ps_mv_buf->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
    898     }
    899 
    900     /* Get free picture buffer to hold current picture recon data */
    901     /* TODO: For asynchronous api the following initializations related to picture
    902      * buffer should be moved to processing side
    903      */
    904     {
    905 
    906         UWORD8 *pu1_buf;
    907         ps_cur_pic = (pic_buf_t *)ihevc_buf_mgr_get_next_free((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, &cur_pic_buf_id);
    908 
    909         /* If there are no free buffers then return with an error code.
    910          * TODO: If the buffer is to be freed by another thread , change the
    911          * following to call thread yield and wait for buffer to be freed
    912          */
    913         if(NULL == ps_cur_pic)
    914         {
    915             ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_PICBUF;
    916             ps_codec->i4_error_code = IHEVCD_NO_FREE_PICBUF;
    917             return IHEVCD_NO_FREE_PICBUF;
    918         }
    919 
    920         /* Store input timestamp sent with input buffer */
    921         ps_cur_pic->u4_ts = ps_codec->u4_ts;
    922         ps_cur_pic->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
    923         ps_cur_pic->i4_poc_lsb = ps_slice_hdr->i4_pic_order_cnt_lsb;
    924         pu1_buf = ps_cur_pic->pu1_luma;
    925         pu1_cur_pic_luma = pu1_buf;
    926 
    927         pu1_buf = ps_cur_pic->pu1_chroma;
    928 
    929         pu1_cur_pic_chroma = pu1_buf;
    930 
    931         ps_cur_pic->s_sei_params.i1_sei_parameters_present_flag = 0;
    932         if(ps_codec->s_parse.s_sei_params.i1_sei_parameters_present_flag)
    933         {
    934             sei_params_t *ps_sei = &ps_codec->s_parse.s_sei_params;
    935             ps_cur_pic->s_sei_params = ps_codec->s_parse.s_sei_params;
    936 
    937             /* Once sei_params is copied to pic_buf,
    938              * mark sei_params in s_parse as not present,
    939              * this ensures that future frames do not use this data again.
    940              */
    941             ps_sei->i1_sei_parameters_present_flag = 0;
    942             ps_sei->i1_user_data_registered_present_flag = 0;
    943             ps_sei->i1_aud_present_flag = 0;
    944             ps_sei->i1_time_code_present_flag = 0;
    945             ps_sei->i1_buf_period_params_present_flag = 0;
    946             ps_sei->i1_pic_timing_params_present_flag = 0;
    947             ps_sei->i1_recovery_point_params_present_flag = 0;
    948             ps_sei->i1_active_parameter_set = 0;
    949             ps_sei->i4_sei_mastering_disp_colour_vol_params_present_flags = 0;
    950         }
    951     }
    952 
    953     if(0 == ps_codec->u4_pic_cnt)
    954     {
    955         memset(ps_cur_pic->pu1_luma, 128, (ps_sps->i2_pic_width_in_luma_samples + PAD_WD) * ps_sps->i2_pic_height_in_luma_samples);
    956         memset(ps_cur_pic->pu1_chroma, 128, (ps_sps->i2_pic_width_in_luma_samples + PAD_WD) * ps_sps->i2_pic_height_in_luma_samples / 2);
    957     }
    958 
    959     /* Fill the remaining entries of the reference lists with the nearest POC
    960      * This is done to handle cases where there is a corruption in the reference index */
    961     {
    962         pic_buf_t *ps_pic_buf_ref;
    963         mv_buf_t *ps_mv_buf_ref;
    964         WORD32 r_idx;
    965         dpb_mgr_t *ps_dpb_mgr = (dpb_mgr_t *)ps_codec->pv_dpb_mgr;
    966         buf_mgr_t *ps_mv_buf_mgr = (buf_mgr_t *)ps_codec->pv_mv_buf_mgr;
    967 
    968         ps_pic_buf_ref = ihevc_dpb_mgr_get_ref_by_nearest_poc(ps_dpb_mgr, ps_slice_hdr->i4_abs_pic_order_cnt);
    969         if(NULL == ps_pic_buf_ref)
    970         {
    971             WORD32 size;
    972 
    973             WORD32 num_pu;
    974             WORD32 num_ctb;
    975             WORD32 pic_size;
    976             /* In case current mv buffer itself is being used as reference mv buffer for colocated
    977              * calculations, then memset all the buffers to zero.
    978              */
    979             pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
    980                             ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
    981 
    982             num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
    983             num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
    984 
    985             memset(ps_mv_buf->ai4_l0_collocated_poc, 0, sizeof(ps_mv_buf->ai4_l0_collocated_poc));
    986             memset(ps_mv_buf->ai1_l0_collocated_poc_lt, 0, sizeof(ps_mv_buf->ai1_l0_collocated_poc_lt));
    987             memset(ps_mv_buf->ai4_l1_collocated_poc, 0, sizeof(ps_mv_buf->ai4_l1_collocated_poc));
    988             memset(ps_mv_buf->ai1_l1_collocated_poc_lt, 0, sizeof(ps_mv_buf->ai1_l1_collocated_poc_lt));
    989 
    990             size = (num_ctb + 1) * sizeof(WORD32);
    991             memset(ps_mv_buf->pu4_pic_pu_idx, 0, size);
    992 
    993             size = num_pu;
    994             memset(ps_mv_buf->pu1_pic_pu_map, 0, size);
    995             size = ALIGN4(num_ctb * sizeof(UWORD16));
    996             memset(ps_mv_buf->pu1_pic_slice_map, 0, size);
    997             size = num_pu * sizeof(pu_t);
    998             memset(ps_mv_buf->ps_pic_pu, 0, size);
    999 
   1000             ps_pic_buf_ref = ps_cur_pic;
   1001             ps_mv_buf_ref = ps_mv_buf;
   1002         }
   1003         else
   1004         {
   1005             ps_mv_buf_ref = ihevcd_mv_mgr_get_poc(ps_mv_buf_mgr, ps_pic_buf_ref->i4_abs_poc);
   1006         }
   1007 
   1008         for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx++)
   1009         {
   1010             if(NULL == ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf)
   1011             {
   1012                 ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
   1013                 ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
   1014             }
   1015         }
   1016 
   1017         for(r_idx = ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx < MAX_DPB_SIZE; r_idx++)
   1018         {
   1019             ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
   1020             ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
   1021         }
   1022 
   1023         for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx++)
   1024         {
   1025             if(NULL == ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf)
   1026             {
   1027                 ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
   1028                 ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
   1029             }
   1030         }
   1031 
   1032         for(r_idx = ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx < MAX_DPB_SIZE; r_idx++)
   1033         {
   1034             ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
   1035             ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
   1036         }
   1037     }
   1038 
   1039 
   1040     /* Reset the jobq to start of the jobq buffer */
   1041     ihevcd_jobq_reset((jobq_t *)ps_codec->pv_proc_jobq);
   1042 
   1043     ps_codec->s_parse.i4_pic_pu_idx = 0;
   1044     ps_codec->s_parse.i4_pic_tu_idx = 0;
   1045 
   1046     ps_codec->s_parse.pu1_pic_pu_map = ps_mv_buf->pu1_pic_pu_map;
   1047     ps_codec->s_parse.ps_pic_pu      = ps_mv_buf->ps_pic_pu;
   1048     ps_codec->s_parse.pu4_pic_pu_idx = ps_mv_buf->pu4_pic_pu_idx;
   1049     ps_codec->s_parse.pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map;
   1050     for(i = 0; i < MAX_PROCESS_THREADS; i++)
   1051     {
   1052         ps_codec->as_process[i].pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map;
   1053     }
   1054     ps_codec->s_parse.pu1_pu_map = ps_codec->s_parse.pu1_pic_pu_map;
   1055     ps_codec->s_parse.ps_pu = ps_codec->s_parse.ps_pic_pu;
   1056 
   1057     {
   1058         UWORD8 *pu1_buf;
   1059         WORD32 ctb_luma_min_tu_cnt, ctb_chroma_min_tu_cnt, ctb_min_tu_cnt;
   1060         WORD32 pic_size;
   1061         WORD32 num_ctb;
   1062 
   1063         pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
   1064                         ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
   1065 
   1066         ctb_luma_min_tu_cnt = pic_size / (MIN_TU_SIZE * MIN_TU_SIZE);
   1067 
   1068         ctb_chroma_min_tu_cnt = ctb_luma_min_tu_cnt >> 1;
   1069 
   1070         ctb_min_tu_cnt = ctb_luma_min_tu_cnt + ctb_chroma_min_tu_cnt;
   1071 
   1072         num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
   1073         pu1_buf  = (UWORD8 *)ps_codec->pv_tu_data;
   1074         ps_codec->s_parse.pu4_pic_tu_idx = (UWORD32 *)pu1_buf;
   1075         pu1_buf += (num_ctb + 1) * sizeof(WORD32);
   1076 
   1077         ps_codec->s_parse.pu1_pic_tu_map = pu1_buf;
   1078         pu1_buf += ctb_min_tu_cnt;
   1079 
   1080         ps_codec->s_parse.ps_pic_tu = (tu_t *)pu1_buf;
   1081         pu1_buf += ctb_min_tu_cnt * sizeof(tu_t);
   1082 
   1083         ps_codec->s_parse.pv_pic_tu_coeff_data = pu1_buf;
   1084 
   1085         ps_codec->s_parse.pu1_tu_map = ps_codec->s_parse.pu1_pic_tu_map;
   1086         ps_codec->s_parse.ps_tu = ps_codec->s_parse.ps_pic_tu;
   1087         ps_codec->s_parse.pv_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data;
   1088     }
   1089 
   1090     ps_codec->s_parse.s_bs_ctxt.ps_pic_pu = ps_codec->s_parse.ps_pic_pu;
   1091     ps_codec->s_parse.s_bs_ctxt.pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx;
   1092     ps_codec->s_parse.s_bs_ctxt.pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx;
   1093 
   1094 
   1095     /* Set number of CTBs to be processed simultaneously */
   1096     ps_codec->i4_proc_nctb = ihevcd_nctb_cnt(ps_codec, ps_sps);
   1097 
   1098     /* Memset Parse Map and process map at the start of frame */
   1099     //TODO: In case of asynchronous API proc_map can not be set to zero here
   1100     {
   1101         WORD32 num_ctb;
   1102 
   1103         num_ctb = ps_sps->i4_pic_size_in_ctb;
   1104 
   1105         memset(ps_codec->pu1_parse_map, 0, num_ctb);
   1106 
   1107         memset(ps_codec->pu1_proc_map, 0, num_ctb);
   1108     }
   1109 
   1110 
   1111 
   1112     /* Initialize disp buf id to -1, this will be updated at the end of frame if there is
   1113      * buffer to be displayed
   1114      */
   1115     ps_codec->i4_disp_buf_id = -1;
   1116     ps_codec->ps_disp_buf = NULL;
   1117 
   1118     ps_codec->i4_disable_deblk_pic  = 0;
   1119     ps_codec->i4_disable_sao_pic    = 0;
   1120     ps_codec->i4_fullpel_inter_pred = 0;
   1121     ps_codec->i4_mv_frac_mask       = 0x7FFFFFFF;
   1122 
   1123     /* If degrade is enabled, set the degrade flags appropriately */
   1124     if(ps_codec->i4_degrade_type && ps_codec->i4_degrade_pics)
   1125     {
   1126         WORD32 degrade_pic;
   1127         ps_codec->i4_degrade_pic_cnt++;
   1128         degrade_pic = 0;
   1129 
   1130         /* If degrade is to be done in all frames, then do not check further */
   1131         switch(ps_codec->i4_degrade_pics)
   1132         {
   1133             case 4:
   1134             {
   1135                 degrade_pic = 1;
   1136                 break;
   1137             }
   1138             case 3:
   1139             {
   1140                 if(ps_slice_hdr->i1_slice_type != ISLICE)
   1141                     degrade_pic = 1;
   1142 
   1143                 break;
   1144             }
   1145             case 2:
   1146             {
   1147 
   1148                 /* If pic count hits non-degrade interval or it is an islice, then do not degrade */
   1149                 if((ps_slice_hdr->i1_slice_type != ISLICE) &&
   1150                    (ps_codec->i4_degrade_pic_cnt != ps_codec->i4_nondegrade_interval))
   1151                     degrade_pic = 1;
   1152 
   1153                 break;
   1154             }
   1155             case 1:
   1156             {
   1157                 /* Check if the current picture is non-ref */
   1158                 if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) &&
   1159                    (ps_slice_hdr->i1_nal_unit_type % 2 == 0))
   1160                 {
   1161                     degrade_pic = 1;
   1162                 }
   1163                 break;
   1164             }
   1165 
   1166 
   1167         }
   1168         if(degrade_pic)
   1169         {
   1170             if(ps_codec->i4_degrade_type & 0x1)
   1171                 ps_codec->i4_disable_sao_pic = 1;
   1172 
   1173             if(ps_codec->i4_degrade_type & 0x2)
   1174                 ps_codec->i4_disable_deblk_pic = 1;
   1175 
   1176             /* MC degrading is done only for non-ref pictures */
   1177             if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) &&
   1178                (ps_slice_hdr->i1_nal_unit_type % 2 == 0))
   1179             {
   1180                 if(ps_codec->i4_degrade_type & 0x4)
   1181                     ps_codec->i4_mv_frac_mask = 0;
   1182 
   1183                 if(ps_codec->i4_degrade_type & 0x8)
   1184                     ps_codec->i4_mv_frac_mask = 0;
   1185             }
   1186         }
   1187         else
   1188             ps_codec->i4_degrade_pic_cnt = 0;
   1189     }
   1190 
   1191 
   1192     {
   1193         WORD32 i;
   1194         for(i = 0; i < MAX_PROCESS_THREADS; i++)
   1195         {
   1196             ps_codec->as_process[i].pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx;
   1197             ps_codec->as_process[i].ps_pic_pu = ps_codec->s_parse.ps_pic_pu;
   1198             ps_codec->as_process[i].pu1_pic_pu_map = ps_codec->s_parse.pu1_pic_pu_map;
   1199             ps_codec->as_process[i].pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx;
   1200             ps_codec->as_process[i].ps_pic_tu = ps_codec->s_parse.ps_pic_tu;
   1201             ps_codec->as_process[i].pu1_pic_tu_map = ps_codec->s_parse.pu1_pic_tu_map;
   1202             ps_codec->as_process[i].pv_pic_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data;
   1203             ps_codec->as_process[i].i4_cur_mv_bank_buf_id = cur_mv_bank_buf_id;
   1204             ps_codec->as_process[i].s_sao_ctxt.pu1_slice_idx = ps_codec->as_process[i].pu1_slice_idx;
   1205             ps_codec->as_process[i].s_sao_ctxt.pu1_tile_idx = ps_codec->as_process[i].pu1_tile_idx;
   1206 
   1207             /* TODO: For asynchronous api the following initializations related to picture
   1208              * buffer should be moved to processing side
   1209              */
   1210             ps_codec->as_process[i].pu1_cur_pic_luma = pu1_cur_pic_luma;
   1211             ps_codec->as_process[i].pu1_cur_pic_chroma = pu1_cur_pic_chroma;
   1212             ps_codec->as_process[i].ps_cur_pic = ps_cur_pic;
   1213             ps_codec->as_process[i].i4_cur_pic_buf_id = cur_pic_buf_id;
   1214 
   1215             ps_codec->as_process[i].ps_out_buffer = ps_codec->ps_out_buffer;
   1216             if(1 < ps_codec->i4_num_cores)
   1217             {
   1218                 ps_codec->as_process[i].i4_check_parse_status = 1;
   1219                 ps_codec->as_process[i].i4_check_proc_status = 1;
   1220             }
   1221             else
   1222             {
   1223                 ps_codec->as_process[i].i4_check_parse_status = 0;
   1224                 ps_codec->as_process[i].i4_check_proc_status = 0;
   1225             }
   1226             ps_codec->as_process[i].pu1_pic_intra_flag = ps_codec->s_parse.pu1_pic_intra_flag;
   1227             ps_codec->as_process[i].pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
   1228             ps_codec->as_process[i].i4_init_done = 0;
   1229 
   1230             ps_codec->as_process[i].s_bs_ctxt.pu4_pic_tu_idx = ps_codec->as_process[i].pu4_pic_tu_idx;
   1231             ps_codec->as_process[i].s_bs_ctxt.pu4_pic_pu_idx = ps_codec->as_process[i].pu4_pic_pu_idx;
   1232             ps_codec->as_process[i].s_bs_ctxt.ps_pic_pu = ps_codec->as_process[i].ps_pic_pu;
   1233             ps_codec->as_process[i].s_deblk_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
   1234             ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
   1235             ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
   1236             ps_codec->as_process[i].s_sao_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
   1237             ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
   1238             ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
   1239             if(i < (ps_codec->i4_num_cores - 1))
   1240             {
   1241                 ithread_create(ps_codec->apv_process_thread_handle[i], NULL,
   1242                                (void *)ihevcd_process_thread,
   1243                                (void *)&ps_codec->as_process[i]);
   1244                 ps_codec->ai4_process_thread_created[i] = 1;
   1245             }
   1246             else
   1247             {
   1248                 ps_codec->ai4_process_thread_created[i] = 0;
   1249             }
   1250 
   1251         }
   1252         ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
   1253         ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
   1254 
   1255         ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
   1256         ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
   1257     }
   1258     /* Since any input bitstream buffer that contains slice data will be sent to output(even in
   1259      * case of error, this buffer is added to display queue and next buffer in the display queue
   1260      * will be returned as the display buffer.
   1261      * Note: If format conversion (or frame copy) is used and is scheduled
   1262      * in a different thread then it has to check if the processing for the current row is complete before
   1263      * it copies/converts a given row. In case of low delay or in case of B pictures, current frame being decoded has to be
   1264      * returned, which requires a status check to ensure that the current row is reconstructed before copying.
   1265      */
   1266     /* Add current picture to display manager */
   1267     {
   1268         WORD32 abs_poc;
   1269         slice_header_t *ps_slice_hdr;
   1270         ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;
   1271         abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
   1272         ihevc_disp_mgr_add((disp_mgr_t *)ps_codec->pv_disp_buf_mgr,
   1273                            ps_codec->as_process[0].i4_cur_pic_buf_id,
   1274                            abs_poc,
   1275                            ps_codec->as_process[0].ps_cur_pic);
   1276     }
   1277     ps_codec->ps_disp_buf = NULL;
   1278     /* Get picture to be displayed if number of pictures decoded is more than max allowed reorder */
   1279     /* Since the current will be decoded, check is fore >= instead of > */
   1280     if(((WORD32)(ps_codec->u4_pic_cnt - ps_codec->u4_disp_cnt) >= ps_sps->ai1_sps_max_num_reorder_pics[ps_sps->i1_sps_max_sub_layers - 1]) ||
   1281        (ps_codec->e_frm_out_mode == IVD_DECODE_FRAME_OUT))
   1282 
   1283     {
   1284         ps_codec->ps_disp_buf = (pic_buf_t *)ihevc_disp_mgr_get((disp_mgr_t *)ps_codec->pv_disp_buf_mgr, &ps_codec->i4_disp_buf_id);
   1285         ps_codec->u4_disp_cnt++;
   1286     }
   1287 
   1288     ps_codec->s_fmt_conv.i4_cur_row = 0;
   1289     /* Set number of rows to be processed at a time */
   1290     ps_codec->s_fmt_conv.i4_num_rows = 4;
   1291 
   1292     if(ps_codec->u4_enable_fmt_conv_ahead && (ps_codec->i4_num_cores > 1))
   1293     {
   1294         process_ctxt_t *ps_proc;
   1295 
   1296         /* i4_num_cores - 1 contexts are currently being used by other threads */
   1297         ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1];
   1298 
   1299         /* If the frame being decoded and displayed are different, schedule format conversion jobs
   1300          * this will keep the proc threads busy and lets parse thread decode few CTBs ahead
   1301          * If the frame being decoded and displayed are same, then format conversion is scheduled later.
   1302          */
   1303         if((ps_codec->ps_disp_buf) && (ps_codec->i4_disp_buf_id != ps_proc->i4_cur_pic_buf_id) &&
   1304            ((0 == ps_codec->i4_share_disp_buf) || (IV_YUV_420P == ps_codec->e_chroma_fmt)))
   1305         {
   1306 
   1307             for(i = 0; i < ps_sps->i2_pic_ht_in_ctb; i++)
   1308             {
   1309                 proc_job_t s_job;
   1310                 IHEVCD_ERROR_T ret;
   1311                 s_job.i4_cmd = CMD_FMTCONV;
   1312                 s_job.i2_ctb_cnt = 0;
   1313                 s_job.i2_ctb_x = 0;
   1314                 s_job.i2_ctb_y = i;
   1315                 s_job.i2_slice_idx = 0;
   1316                 s_job.i4_tu_coeff_data_ofst = 0;
   1317                 ret = ihevcd_jobq_queue((jobq_t *)ps_codec->s_parse.pv_proc_jobq,
   1318                                         &s_job, sizeof(proc_job_t), 1);
   1319                 if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
   1320                     return ret;
   1321             }
   1322         }
   1323     }
   1324 
   1325     /* If parse_pic_init is called, then slice data is present in the input bitstrea stream */
   1326     ps_codec->i4_pic_present = 1;
   1327 
   1328     return ret;
   1329 }
   1330 
   1331 
   1332