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             buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, ps_pic_buf, i);
    522 
    523 
    524             if(0 != buf_ret)
    525             {
    526                 ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR;
    527                 return IHEVCD_BUF_MGR_ERROR;
    528             }
    529             ps_pic_buf++;
    530         }
    531     }
    532     else
    533     {
    534         /* In case of shared mode, buffers are added without adjusting for padding.
    535            Update luma and chroma pointers here to account for padding as per stride.
    536            In some cases stride might not be available when set_display_frame is called.
    537            Hence updated luma and chroma pointers here */
    538 
    539         for(i = 0; i < BUF_MGR_MAX_CNT; i++)
    540         {
    541             ps_pic_buf = ihevc_buf_mgr_get_buf((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, i);
    542             if((NULL == ps_pic_buf) ||
    543                (NULL == ps_pic_buf->pu1_luma) ||
    544                (NULL == ps_pic_buf->pu1_chroma))
    545             {
    546                 break;
    547             }
    548             ps_pic_buf->pu1_luma += ps_codec->i4_strd * PAD_TOP + PAD_LEFT;
    549             ps_pic_buf->pu1_chroma += ps_codec->i4_strd * (PAD_TOP / 2) + PAD_LEFT;
    550         }
    551     }
    552 
    553     return ret;
    554 }
    555 /**
    556 *******************************************************************************
    557 *
    558 * @brief
    559 *  Function to add buffers to MV Bank buffer manager
    560 *
    561 * @par Description:
    562 *  Function to add buffers to MV Bank buffer manager
    563 *  To be called once per stream or for every reset
    564 *
    565 * @param[in] ps_codec
    566 *  Pointer to codec context
    567 *
    568 * @returns  Error from IHEVCD_ERROR_T
    569 *
    570 * @remarks
    571 *
    572 *
    573 *******************************************************************************
    574 */
    575 IHEVCD_ERROR_T ihevcd_mv_buf_mgr_add_bufs(codec_t *ps_codec)
    576 {
    577     IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    578     WORD32 i;
    579     WORD32 max_dpb_size;
    580     WORD32 mv_bank_size_allocated;
    581     WORD32 pic_mv_bank_size;
    582 
    583     sps_t *ps_sps;
    584     UWORD8 *pu1_buf;
    585     mv_buf_t *ps_mv_buf;
    586 
    587 
    588     /* Initialize MV Bank buffer manager */
    589     ps_sps = ps_codec->s_parse.ps_sps;
    590 
    591 
    592     /* Compute the number of MV Bank buffers needed */
    593     max_dpb_size = ps_sps->ai1_sps_max_dec_pic_buffering[ps_sps->i1_sps_max_sub_layers - 1];
    594 
    595     /* Allocate one extra MV Bank to handle current frame
    596      * In case of asynchronous parsing and processing, number of buffers should increase here
    597      * based on when parsing and processing threads are synchronized
    598      */
    599     max_dpb_size++;
    600 
    601     pu1_buf = (UWORD8 *)ps_codec->pv_mv_bank_buf_base;
    602 
    603     ps_mv_buf = (mv_buf_t *)pu1_buf;
    604     pu1_buf += max_dpb_size * sizeof(mv_buf_t);
    605     ps_codec->ps_mv_buf = ps_mv_buf;
    606     mv_bank_size_allocated = ps_codec->i4_total_mv_bank_size - max_dpb_size  * sizeof(mv_buf_t);
    607 
    608     /* Compute MV bank size per picture */
    609     pic_mv_bank_size = ihevcd_get_pic_mv_bank_size(ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
    610                                                    ALIGN64(ps_sps->i2_pic_height_in_luma_samples));
    611 
    612     for(i = 0; i < max_dpb_size; i++)
    613     {
    614         WORD32 buf_ret;
    615         WORD32 num_pu;
    616         WORD32 num_ctb;
    617         WORD32 pic_size;
    618         pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
    619                         ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
    620 
    621 
    622         num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
    623         num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
    624 
    625 
    626         mv_bank_size_allocated -= pic_mv_bank_size;
    627 
    628         if(mv_bank_size_allocated < 0)
    629         {
    630             ps_codec->s_parse.i4_error_code = IHEVCD_INSUFFICIENT_MEM_MVBANK;
    631             return IHEVCD_INSUFFICIENT_MEM_MVBANK;
    632         }
    633 
    634         ps_mv_buf->pu4_pic_pu_idx = (UWORD32 *)pu1_buf;
    635         pu1_buf += (num_ctb + 1) * sizeof(WORD32);
    636 
    637         ps_mv_buf->pu1_pic_pu_map = pu1_buf;
    638         pu1_buf += num_pu;
    639 
    640         ps_mv_buf->pu1_pic_slice_map = (UWORD16 *)pu1_buf;
    641         pu1_buf += ALIGN4(num_ctb * sizeof(UWORD16));
    642 
    643         ps_mv_buf->ps_pic_pu = (pu_t *)pu1_buf;
    644         pu1_buf += num_pu * sizeof(pu_t);
    645 
    646         buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_mv_buf_mgr, ps_mv_buf, i);
    647 
    648         if(0 != buf_ret)
    649         {
    650             ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR;
    651             return IHEVCD_BUF_MGR_ERROR;
    652         }
    653 
    654         ps_mv_buf++;
    655 
    656     }
    657     return ret;
    658 }
    659 /**
    660 *******************************************************************************
    661 *
    662 * @brief
    663 *  Picture level initializations required during parsing
    664 *
    665 * @par Description:
    666 *  Initialize picture level context variables during parsing Initialize mv
    667 * bank buffer manager in the first init call
    668 *
    669 * @param[in] ps_codec
    670 *  Pointer to codec context
    671 *
    672 * @returns  Error from IHEVCD_ERROR_T
    673 *
    674 * @remarks
    675 *
    676 *
    677 *******************************************************************************
    678 */
    679 IHEVCD_ERROR_T ihevcd_parse_pic_init(codec_t *ps_codec)
    680 {
    681     IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
    682     mv_buf_t *ps_mv_buf;
    683     sps_t *ps_sps;
    684     WORD32 num_min_cu;
    685     WORD32 cur_pic_buf_id;
    686     WORD32 cur_mv_bank_buf_id;
    687     pic_buf_t *ps_cur_pic;
    688     slice_header_t *ps_slice_hdr;
    689     UWORD8 *pu1_cur_pic_luma, *pu1_cur_pic_chroma;
    690     WORD32 i;
    691 
    692     ps_codec->s_parse.i4_error_code = IHEVCD_SUCCESS;
    693     ps_sps = ps_codec->s_parse.ps_sps;
    694     ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;
    695     /* If parse_pic_init is called, then slice data is present in the input bitstrea stream */
    696     ps_codec->i4_pic_present = 1;
    697 
    698     /* Memset picture level intra map and transquant bypass map to zero */
    699     num_min_cu = ((ps_sps->i2_pic_height_in_luma_samples + 7) / 8) * ((ps_sps->i2_pic_width_in_luma_samples + 63) / 64);
    700     memset(ps_codec->s_parse.pu1_pic_intra_flag, 0, num_min_cu);
    701     memset(ps_codec->s_parse.pu1_pic_no_loop_filter_flag, 0, num_min_cu);
    702 
    703 
    704 
    705     if(0 == ps_codec->s_parse.i4_first_pic_init)
    706     {
    707         ret = ihevcd_mv_buf_mgr_add_bufs(ps_codec);
    708         RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
    709 
    710         ret = ihevcd_pic_buf_mgr_add_bufs(ps_codec);
    711         RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
    712 
    713         ps_codec->s_parse.i4_first_pic_init = 1;
    714     }
    715 
    716     /* Initialize all the slice headers' slice addresses to zero */
    717     {
    718         WORD32 slice_idx;
    719         WORD32 slice_start_idx;
    720 
    721         slice_start_idx = ps_codec->i4_slice_error ? 2 : 1;
    722 
    723         for(slice_idx = slice_start_idx; slice_idx < MAX_SLICE_HDR_CNT; slice_idx++)
    724         {
    725             slice_header_t *ps_slice_hdr_tmp = ps_codec->ps_slice_hdr_base + slice_idx;
    726             ps_slice_hdr_tmp->i2_ctb_x = -1;
    727             ps_slice_hdr_tmp->i2_ctb_y = -1;
    728 
    729         }
    730     }
    731 
    732     /* Get free MV Bank to hold current picture's motion vector data */
    733     {
    734         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);
    735 
    736         /* If there are no free buffers then return with an error code.
    737          * If the buffer is to be freed by another thread , change the
    738          * following to call thread yield and wait for buffer to be freed
    739          */
    740         if(NULL == ps_mv_buf)
    741         {
    742             ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_MVBANK;
    743             ps_codec->i4_error_code = IHEVCD_NO_FREE_MVBANK;
    744             return IHEVCD_NO_FREE_MVBANK;
    745         }
    746 
    747         ps_codec->s_parse.ps_cur_mv_buf = ps_mv_buf;
    748         /* Set current ABS poc to ps_mv_buf, so that while freeing a reference buffer
    749          * corresponding mv buffer can be found by looping through ps_codec->ps_mv_buf array
    750          * and getting a buffer id to free
    751          */
    752         ps_mv_buf->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
    753     }
    754 
    755     /* Get free picture buffer to hold current picture recon data */
    756     /* TODO: For asynchronous api the following initializations related to picture
    757      * buffer should be moved to processing side
    758      */
    759     {
    760 
    761         UWORD8 *pu1_buf;
    762         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);
    763 
    764         /* If there are no free buffers then return with an error code.
    765          * TODO: If the buffer is to be freed by another thread , change the
    766          * following to call thread yield and wait for buffer to be freed
    767          */
    768         if(NULL == ps_cur_pic)
    769         {
    770             ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_PICBUF;
    771             ps_codec->i4_error_code = IHEVCD_NO_FREE_PICBUF;
    772             return IHEVCD_NO_FREE_PICBUF;
    773         }
    774 
    775         /* Store input timestamp sent with input buffer */
    776         ps_cur_pic->u4_ts = ps_codec->u4_ts;
    777         ps_cur_pic->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
    778         ps_cur_pic->i4_poc_lsb = ps_slice_hdr->i4_pic_order_cnt_lsb;
    779         pu1_buf = ps_cur_pic->pu1_luma;
    780         pu1_cur_pic_luma = pu1_buf;
    781 
    782         pu1_buf = ps_cur_pic->pu1_chroma;
    783 
    784         pu1_cur_pic_chroma = pu1_buf;
    785     }
    786 
    787     if(0 == ps_codec->u4_pic_cnt)
    788     {
    789         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);
    790         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);
    791     }
    792 
    793     /* Fill the remaining entries of the reference lists with the nearest POC
    794      * This is done to handle cases where there is a corruption in the reference index */
    795     {
    796         pic_buf_t *ps_pic_buf_ref;
    797         mv_buf_t *ps_mv_buf_ref;
    798         WORD32 r_idx;
    799         dpb_mgr_t *ps_dpb_mgr = (dpb_mgr_t *)ps_codec->pv_dpb_mgr;
    800         buf_mgr_t *ps_mv_buf_mgr = (buf_mgr_t *)ps_codec->pv_mv_buf_mgr;
    801 
    802         ps_pic_buf_ref = ihevc_dpb_mgr_get_ref_by_nearest_poc(ps_dpb_mgr, ps_slice_hdr->i4_abs_pic_order_cnt);
    803         if(NULL == ps_pic_buf_ref)
    804         {
    805             WORD32 size;
    806 
    807             WORD32 num_pu;
    808             WORD32 num_ctb;
    809             WORD32 pic_size;
    810             /* In case current mv buffer itself is being used as reference mv buffer for colocated
    811              * calculations, then memset all the buffers to zero.
    812              */
    813             pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
    814                             ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
    815 
    816             num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
    817             num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
    818 
    819             memset(ps_mv_buf->ai4_l0_collocated_poc, 0, sizeof(ps_mv_buf->ai4_l0_collocated_poc));
    820             memset(ps_mv_buf->ai1_l0_collocated_poc_lt, 0, sizeof(ps_mv_buf->ai1_l0_collocated_poc_lt));
    821             memset(ps_mv_buf->ai4_l1_collocated_poc, 0, sizeof(ps_mv_buf->ai4_l1_collocated_poc));
    822             memset(ps_mv_buf->ai1_l1_collocated_poc_lt, 0, sizeof(ps_mv_buf->ai1_l1_collocated_poc_lt));
    823 
    824             size = (num_ctb + 1) * sizeof(WORD32);
    825             memset(ps_mv_buf->pu4_pic_pu_idx, 0, size);
    826 
    827             size = num_pu;
    828             memset(ps_mv_buf->pu1_pic_pu_map, 0, size);
    829             size = ALIGN4(num_ctb * sizeof(UWORD16));
    830             memset(ps_mv_buf->pu1_pic_slice_map, 0, size);
    831             size = num_pu * sizeof(pu_t);
    832             memset(ps_mv_buf->ps_pic_pu, 0, size);
    833 
    834             ps_pic_buf_ref = ps_cur_pic;
    835             ps_mv_buf_ref = ps_mv_buf;
    836         }
    837         else
    838         {
    839             ps_mv_buf_ref = ihevcd_mv_mgr_get_poc(ps_mv_buf_mgr, ps_pic_buf_ref->i4_abs_poc);
    840         }
    841 
    842         for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx++)
    843         {
    844             if(NULL == ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf)
    845             {
    846                 ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
    847                 ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
    848             }
    849         }
    850 
    851         for(r_idx = ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx < MAX_DPB_SIZE; r_idx++)
    852         {
    853             ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
    854             ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
    855         }
    856 
    857         for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx++)
    858         {
    859             if(NULL == ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf)
    860             {
    861                 ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
    862                 ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
    863             }
    864         }
    865 
    866         for(r_idx = ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx < MAX_DPB_SIZE; r_idx++)
    867         {
    868             ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
    869             ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
    870         }
    871     }
    872 
    873 
    874     /* Reset the jobq to start of the jobq buffer */
    875     ihevcd_jobq_reset((jobq_t *)ps_codec->pv_proc_jobq);
    876 
    877     ps_codec->s_parse.i4_pic_pu_idx = 0;
    878     ps_codec->s_parse.i4_pic_tu_idx = 0;
    879 
    880     ps_codec->s_parse.pu1_pic_pu_map = ps_mv_buf->pu1_pic_pu_map;
    881     ps_codec->s_parse.ps_pic_pu      = ps_mv_buf->ps_pic_pu;
    882     ps_codec->s_parse.pu4_pic_pu_idx = ps_mv_buf->pu4_pic_pu_idx;
    883     ps_codec->s_parse.pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map;
    884     for(i = 0; i < MAX_PROCESS_THREADS; i++)
    885     {
    886         ps_codec->as_process[i].pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map;
    887     }
    888     ps_codec->s_parse.pu1_pu_map = ps_codec->s_parse.pu1_pic_pu_map;
    889     ps_codec->s_parse.ps_pu = ps_codec->s_parse.ps_pic_pu;
    890 
    891     {
    892         UWORD8 *pu1_buf;
    893         WORD32 ctb_luma_min_tu_cnt, ctb_chroma_min_tu_cnt, ctb_min_tu_cnt;
    894         WORD32 pic_size;
    895         WORD32 num_ctb;
    896 
    897         pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
    898                         ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
    899 
    900         ctb_luma_min_tu_cnt = pic_size / (MIN_TU_SIZE * MIN_TU_SIZE);
    901 
    902         ctb_chroma_min_tu_cnt = ctb_luma_min_tu_cnt >> 1;
    903 
    904         ctb_min_tu_cnt = ctb_luma_min_tu_cnt + ctb_chroma_min_tu_cnt;
    905 
    906         num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
    907         pu1_buf  = (UWORD8 *)ps_codec->pv_tu_data;
    908         ps_codec->s_parse.pu4_pic_tu_idx = (UWORD32 *)pu1_buf;
    909         pu1_buf += (num_ctb + 1) * sizeof(WORD32);
    910 
    911         ps_codec->s_parse.pu1_pic_tu_map = pu1_buf;
    912         pu1_buf += ctb_min_tu_cnt;
    913 
    914         ps_codec->s_parse.ps_pic_tu = (tu_t *)pu1_buf;
    915         pu1_buf += ctb_min_tu_cnt * sizeof(tu_t);
    916 
    917         ps_codec->s_parse.pv_pic_tu_coeff_data = pu1_buf;
    918 
    919         ps_codec->s_parse.pu1_tu_map = ps_codec->s_parse.pu1_pic_tu_map;
    920         ps_codec->s_parse.ps_tu = ps_codec->s_parse.ps_pic_tu;
    921         ps_codec->s_parse.pv_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data;
    922     }
    923 
    924     ps_codec->s_parse.s_bs_ctxt.ps_pic_pu = ps_codec->s_parse.ps_pic_pu;
    925     ps_codec->s_parse.s_bs_ctxt.pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx;
    926     ps_codec->s_parse.s_bs_ctxt.pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx;
    927 
    928 
    929     /* Set number of CTBs to be processed simultaneously */
    930     ps_codec->i4_proc_nctb = ihevcd_nctb_cnt(ps_codec, ps_sps);
    931 
    932     /* Memset Parse Map and process map at the start of frame */
    933     //TODO: In case of asynchronous API proc_map can not be set to zero here
    934     {
    935         WORD32 num_ctb;
    936 
    937         num_ctb = ps_sps->i4_pic_size_in_ctb;
    938 
    939         memset(ps_codec->pu1_parse_map, 0, num_ctb);
    940 
    941         memset(ps_codec->pu1_proc_map, 0, num_ctb);
    942     }
    943 
    944 
    945 
    946     /* Initialize disp buf id to -1, this will be updated at the end of frame if there is
    947      * buffer to be displayed
    948      */
    949     ps_codec->i4_disp_buf_id = -1;
    950     ps_codec->ps_disp_buf = NULL;
    951 
    952     ps_codec->i4_disable_deblk_pic  = 0;
    953     ps_codec->i4_disable_sao_pic    = 0;
    954     ps_codec->i4_fullpel_inter_pred = 0;
    955     ps_codec->i4_mv_frac_mask       = 0x7FFFFFFF;
    956 
    957     /* If degrade is enabled, set the degrade flags appropriately */
    958     if(ps_codec->i4_degrade_type && ps_codec->i4_degrade_pics)
    959     {
    960         WORD32 degrade_pic;
    961         ps_codec->i4_degrade_pic_cnt++;
    962         degrade_pic = 0;
    963 
    964         /* If degrade is to be done in all frames, then do not check further */
    965         switch(ps_codec->i4_degrade_pics)
    966         {
    967             case 4:
    968             {
    969                 degrade_pic = 1;
    970                 break;
    971             }
    972             case 3:
    973             {
    974                 if(ps_slice_hdr->i1_slice_type != ISLICE)
    975                     degrade_pic = 1;
    976 
    977                 break;
    978             }
    979             case 2:
    980             {
    981 
    982                 /* If pic count hits non-degrade interval or it is an islice, then do not degrade */
    983                 if((ps_slice_hdr->i1_slice_type != ISLICE) &&
    984                    (ps_codec->i4_degrade_pic_cnt != ps_codec->i4_nondegrade_interval))
    985                     degrade_pic = 1;
    986 
    987                 break;
    988             }
    989             case 1:
    990             {
    991                 /* Check if the current picture is non-ref */
    992                 if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) &&
    993                    (ps_slice_hdr->i1_nal_unit_type % 2 == 0))
    994                 {
    995                     degrade_pic = 1;
    996                 }
    997                 break;
    998             }
    999 
   1000 
   1001         }
   1002         if(degrade_pic)
   1003         {
   1004             if(ps_codec->i4_degrade_type & 0x1)
   1005                 ps_codec->i4_disable_sao_pic = 1;
   1006 
   1007             if(ps_codec->i4_degrade_type & 0x2)
   1008                 ps_codec->i4_disable_deblk_pic = 1;
   1009 
   1010             /* MC degrading is done only for non-ref pictures */
   1011             if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) &&
   1012                (ps_slice_hdr->i1_nal_unit_type % 2 == 0))
   1013             {
   1014                 if(ps_codec->i4_degrade_type & 0x4)
   1015                     ps_codec->i4_mv_frac_mask = 0;
   1016 
   1017                 if(ps_codec->i4_degrade_type & 0x8)
   1018                     ps_codec->i4_mv_frac_mask = 0;
   1019             }
   1020         }
   1021         else
   1022             ps_codec->i4_degrade_pic_cnt = 0;
   1023     }
   1024 
   1025 
   1026     {
   1027         WORD32 i;
   1028         for(i = 0; i < MAX_PROCESS_THREADS; i++)
   1029         {
   1030             ps_codec->as_process[i].pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx;
   1031             ps_codec->as_process[i].ps_pic_pu = ps_codec->s_parse.ps_pic_pu;
   1032             ps_codec->as_process[i].pu1_pic_pu_map = ps_codec->s_parse.pu1_pic_pu_map;
   1033             ps_codec->as_process[i].pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx;
   1034             ps_codec->as_process[i].ps_pic_tu = ps_codec->s_parse.ps_pic_tu;
   1035             ps_codec->as_process[i].pu1_pic_tu_map = ps_codec->s_parse.pu1_pic_tu_map;
   1036             ps_codec->as_process[i].pv_pic_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data;
   1037             ps_codec->as_process[i].i4_cur_mv_bank_buf_id = cur_mv_bank_buf_id;
   1038             ps_codec->as_process[i].s_sao_ctxt.pu1_slice_idx = ps_codec->as_process[i].pu1_slice_idx;
   1039             ps_codec->as_process[i].s_sao_ctxt.pu1_tile_idx = ps_codec->as_process[i].pu1_tile_idx;
   1040 
   1041             /* TODO: For asynchronous api the following initializations related to picture
   1042              * buffer should be moved to processing side
   1043              */
   1044             ps_codec->as_process[i].pu1_cur_pic_luma = pu1_cur_pic_luma;
   1045             ps_codec->as_process[i].pu1_cur_pic_chroma = pu1_cur_pic_chroma;
   1046             ps_codec->as_process[i].ps_cur_pic = ps_cur_pic;
   1047             ps_codec->as_process[i].i4_cur_pic_buf_id = cur_pic_buf_id;
   1048 
   1049             ps_codec->as_process[i].ps_out_buffer = ps_codec->ps_out_buffer;
   1050             if(1 < ps_codec->i4_num_cores)
   1051             {
   1052                 ps_codec->as_process[i].i4_check_parse_status = 1;
   1053                 ps_codec->as_process[i].i4_check_proc_status = 1;
   1054             }
   1055             else
   1056             {
   1057                 ps_codec->as_process[i].i4_check_parse_status = 0;
   1058                 ps_codec->as_process[i].i4_check_proc_status = 0;
   1059             }
   1060             ps_codec->as_process[i].pu1_pic_intra_flag = ps_codec->s_parse.pu1_pic_intra_flag;
   1061             ps_codec->as_process[i].pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
   1062             ps_codec->as_process[i].i4_init_done = 0;
   1063 
   1064             ps_codec->as_process[i].s_bs_ctxt.pu4_pic_tu_idx = ps_codec->as_process[i].pu4_pic_tu_idx;
   1065             ps_codec->as_process[i].s_bs_ctxt.pu4_pic_pu_idx = ps_codec->as_process[i].pu4_pic_pu_idx;
   1066             ps_codec->as_process[i].s_bs_ctxt.ps_pic_pu = ps_codec->as_process[i].ps_pic_pu;
   1067             ps_codec->as_process[i].s_deblk_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
   1068             ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
   1069             ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
   1070             ps_codec->as_process[i].s_sao_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
   1071             ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
   1072             ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
   1073             if(i < (ps_codec->i4_num_cores - 1))
   1074             {
   1075                 ithread_create(ps_codec->apv_process_thread_handle[i], NULL,
   1076                                (void *)ihevcd_process_thread,
   1077                                (void *)&ps_codec->as_process[i]);
   1078                 ps_codec->ai4_process_thread_created[i] = 1;
   1079             }
   1080             else
   1081             {
   1082                 ps_codec->ai4_process_thread_created[i] = 0;
   1083             }
   1084 
   1085         }
   1086         ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
   1087         ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
   1088 
   1089         ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
   1090         ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
   1091     }
   1092     /* Since any input bitstream buffer that contains slice data will be sent to output(even in
   1093      * case of error, this buffer is added to display queue and next buffer in the display queue
   1094      * will be returned as the display buffer.
   1095      * Note: If format conversion (or frame copy) is used and is scheduled
   1096      * in a different thread then it has to check if the processing for the current row is complete before
   1097      * it copies/converts a given row. In case of low delay or in case of B pictures, current frame being decoded has to be
   1098      * returned, which requires a status check to ensure that the current row is reconstructed before copying.
   1099      */
   1100     /* Add current picture to display manager */
   1101     {
   1102         WORD32 abs_poc;
   1103         slice_header_t *ps_slice_hdr;
   1104         ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;
   1105         abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
   1106         ihevc_disp_mgr_add((disp_mgr_t *)ps_codec->pv_disp_buf_mgr,
   1107                            ps_codec->as_process[0].i4_cur_pic_buf_id,
   1108                            abs_poc,
   1109                            ps_codec->as_process[0].ps_cur_pic);
   1110     }
   1111     ps_codec->ps_disp_buf = NULL;
   1112     /* Get picture to be displayed if number of pictures decoded is more than max allowed reorder */
   1113     /* Since the current will be decoded, check is fore >= instead of > */
   1114     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]) ||
   1115        (ps_codec->e_frm_out_mode == IVD_DECODE_FRAME_OUT))
   1116 
   1117     {
   1118         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);
   1119         ps_codec->u4_disp_cnt++;
   1120     }
   1121 
   1122     ps_codec->s_fmt_conv.i4_cur_row = 0;
   1123     /* Set number of rows to be processed at a time */
   1124     ps_codec->s_fmt_conv.i4_num_rows = 4;
   1125 
   1126     if(ps_codec->u4_enable_fmt_conv_ahead && (ps_codec->i4_num_cores > 1))
   1127     {
   1128         process_ctxt_t *ps_proc;
   1129 
   1130         /* i4_num_cores - 1 contexts are currently being used by other threads */
   1131         ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1];
   1132 
   1133         /* If the frame being decoded and displayed are different, schedule format conversion jobs
   1134          * this will keep the proc threads busy and lets parse thread decode few CTBs ahead
   1135          * If the frame being decoded and displayed are same, then format conversion is scheduled later.
   1136          */
   1137         if((ps_codec->ps_disp_buf) && (ps_codec->i4_disp_buf_id != ps_proc->i4_cur_pic_buf_id) &&
   1138            ((0 == ps_codec->i4_share_disp_buf) || (IV_YUV_420P == ps_codec->e_chroma_fmt)))
   1139         {
   1140 
   1141             for(i = 0; i < ps_sps->i2_pic_ht_in_ctb; i++)
   1142             {
   1143                 proc_job_t s_job;
   1144                 IHEVCD_ERROR_T ret;
   1145                 s_job.i4_cmd = CMD_FMTCONV;
   1146                 s_job.i2_ctb_cnt = 0;
   1147                 s_job.i2_ctb_x = 0;
   1148                 s_job.i2_ctb_y = i;
   1149                 s_job.i2_slice_idx = 0;
   1150                 s_job.i4_tu_coeff_data_ofst = 0;
   1151                 ret = ihevcd_jobq_queue((jobq_t *)ps_codec->s_parse.pv_proc_jobq,
   1152                                         &s_job, sizeof(proc_job_t), 1);
   1153                 if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
   1154                     return ret;
   1155             }
   1156         }
   1157     }
   1158 
   1159 
   1160     return ret;
   1161 }
   1162 
   1163 
   1164