diff options
Diffstat (limited to 'decoder/ihevcd_utils.c')
-rw-r--r-- | decoder/ihevcd_utils.c | 1318 |
1 files changed, 1318 insertions, 0 deletions
diff --git a/decoder/ihevcd_utils.c b/decoder/ihevcd_utils.c new file mode 100644 index 0000000..36399a7 --- /dev/null +++ b/decoder/ihevcd_utils.c @@ -0,0 +1,1318 @@ +/****************************************************************************** +* +* Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +******************************************************************************/ +/** +******************************************************************************* +* @file +* ihevcd_utils.c +* +* @brief +* Contains miscellaneous utility functions such as init() etc +* +* @author +* Harish +* +* @par List of Functions: +* +* @remarks +* None +* +******************************************************************************* +*/ +/*****************************************************************************/ +/* File Includes */ +/*****************************************************************************/ +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "ihevc_typedefs.h" +#include "iv.h" +#include "ivd.h" +#include "ihevcd_cxa.h" +#include "ithread.h" + +#include "ihevc_defs.h" +#include "ihevc_debug.h" +#include "ihevc_defs.h" +#include "ihevc_error.h" +#include "ihevc_structs.h" +#include "ihevc_buf_mgr.h" +#include "ihevc_dpb_mgr.h" +#include "ihevc_macros.h" +#include "ihevc_platform_macros.h" + +#include "ihevc_common_tables.h" +#include "ihevc_buf_mgr.h" +#include "ihevc_disp_mgr.h" +#include "ihevc_cabac_tables.h" + +#include "ihevcd_defs.h" + +#include "ihevcd_function_selector.h" +#include "ihevcd_structs.h" +#include "ihevcd_error.h" +#include "ihevcd_nal.h" +#include "ihevcd_bitstream.h" +#include "ihevcd_utils.h" +#include "ihevcd_trace.h" +#include "ihevcd_process_slice.h" +#include "ihevcd_job_queue.h" +#ifdef GPU_BUILD +#include "ihevcd_opencl_mc_interface.h" +#endif +#define MAX_DPB_PIC_BUF 6 + +/* Function declarations */ +mv_buf_t* ihevcd_mv_mgr_get_poc(buf_mgr_t *ps_mv_buf_mgr, UWORD32 abs_poc); + +/** +******************************************************************************* +* +* @brief +* Used to get level index for a given level +* +* @par Description: +* Converts from level_idc (which is multiplied by 30) to an index that can be +* used as a lookup. Also used to ignore invalid levels like 2.2 , 3.2 etc +* +* @param[in] level +* Level of the stream +* +* @returns Level index for a given level +* +* @remarks +* +* +******************************************************************************* +*/ +WORD32 ihevcd_get_lvl_idx(WORD32 level) +{ + WORD32 lvl_idx = 0; + + if(level < IHEVC_LEVEL_20) + { + lvl_idx = 0; + } + else if(level >= IHEVC_LEVEL_20 && level < IHEVC_LEVEL_21) + { + lvl_idx = 1; + } + else if(level >= IHEVC_LEVEL_21 && level < IHEVC_LEVEL_30) + { + lvl_idx = 2; + } + else if(level >= IHEVC_LEVEL_30 && level < IHEVC_LEVEL_31) + { + lvl_idx = 3; + } + else if(level >= IHEVC_LEVEL_31 && level < IHEVC_LEVEL_40) + { + lvl_idx = 4; + } + else if(level >= IHEVC_LEVEL_40 && level < IHEVC_LEVEL_41) + { + lvl_idx = 5; + } + else if(level >= IHEVC_LEVEL_41 && level < IHEVC_LEVEL_50) + { + lvl_idx = 6; + } + else if(level >= IHEVC_LEVEL_50 && level < IHEVC_LEVEL_51) + { + lvl_idx = 7; + } + else if(level >= IHEVC_LEVEL_51 && level < IHEVC_LEVEL_52) + { + lvl_idx = 8; + } + else if(level >= IHEVC_LEVEL_52 && level < IHEVC_LEVEL_60) + { + lvl_idx = 9; + } + else if(level >= IHEVC_LEVEL_60 && level < IHEVC_LEVEL_61) + { + lvl_idx = 10; + } + else if(level >= IHEVC_LEVEL_61 && level < IHEVC_LEVEL_62) + { + lvl_idx = 11; + } + else if(level >= IHEVC_LEVEL_62) + { + lvl_idx = 12; + } + + return (lvl_idx); +} + +/** +******************************************************************************* +* +* @brief +* Used to get DPB size for a given level, and number of luma samples +* +* @par Description: +* For given width, height and level number of max_dpb_size is computed as per +* Annex A.4.1 +* +* @param[in] level +* Level of the stream +* +* @param[in] pic_size +* Width * Height +* +* @returns Number of buffers in DPB +* +* @remarks +* +* +******************************************************************************* +*/ +WORD32 ihevcd_get_dpb_size(WORD32 level, WORD32 pic_size) +{ + + WORD32 max_luma_samples; + + WORD32 max_dpb_size; + WORD32 lvl_idx = ihevcd_get_lvl_idx(level); + max_luma_samples = gai4_ihevc_max_luma_pic_size[lvl_idx]; + + + + if(pic_size <= (max_luma_samples >> 2)) + { + max_dpb_size = MIN(4 * MAX_DPB_PIC_BUF, 16); + } + else if(pic_size <= (max_luma_samples >> 1)) + { + max_dpb_size = MIN(2 * MAX_DPB_PIC_BUF, 16); + } + else if(pic_size <= ((3 * max_luma_samples) >> 2)) + { + max_dpb_size = MIN((4 * MAX_DPB_PIC_BUF) / 3, 16); + } + else + { + max_dpb_size = MAX_DPB_PIC_BUF; + } + + return max_dpb_size; +} +/** +******************************************************************************* +* +* @brief +* Used to get reference picture buffer size for a given level and +* and padding used +* +* @par Description: +* Used to get reference picture buffer size for a given level and padding used +* Each picture is padded on all four sides +* +* @param[in] pic_size +* Mumber of luma samples (Width * Height) +* +* @param[in] level +* Level +* +* @param[in] horz_pad +* Total padding used in horizontal direction +* +* @param[in] vert_pad +* Total padding used in vertical direction +* +* @returns Total picture buffer size +* +* @remarks +* +* +******************************************************************************* +*/ +WORD32 ihevcd_get_total_pic_buf_size(WORD32 pic_size, + WORD32 level, + WORD32 horz_pad, + WORD32 vert_pad, + WORD32 num_ref_frames, + WORD32 num_reorder_frames) +{ + WORD32 size; + WORD32 num_luma_samples; + WORD32 lvl_idx; + WORD32 max_wd; + WORD32 max_dpb_size; + WORD32 num_samples; + WORD32 max_num_bufs; + WORD32 pad = MAX(horz_pad, vert_pad); + + + /* Get maximum number of buffers for the current picture size */ + max_dpb_size = ihevcd_get_dpb_size(level, pic_size); + + + max_num_bufs = (2 * max_dpb_size + 1); + /* If num_ref_frames and num_reorder_frmaes is specified + * Use minimum value + */ + max_num_bufs = MIN(max_num_bufs, (num_ref_frames + num_reorder_frames + 1)); + + /* Get level index */ + lvl_idx = ihevcd_get_lvl_idx(level); + + /* Maximum number of luma samples in a picture at given level */ + num_luma_samples = gai4_ihevc_max_luma_pic_size[lvl_idx]; + + /* Account for chroma */ + num_samples = num_luma_samples * 3 / 2; + + /* Maximum width of luma samples in a picture at given level */ + max_wd = gai4_ihevc_max_wd_ht[lvl_idx]; + + + /* Allocation is required for + * (Wd + horz_pad) * (Ht + vert_pad) * (2 * max_dpb_size + 1) + * + * Above expanded as + * ((Wd * Ht) + (horz_pad * vert_pad) + Wd * vert_pad + Ht * horz_pad) * (2 * max_dpb_size + 1) + * (Wd * Ht) * (2 * max_dpb_size + 1) + ((horz_pad * vert_pad) + Wd * vert_pad + Ht * horz_pad) * (2 * max_dpb_size + 1) + * Now max_dpb_size increases with smaller Wd and Ht, but Wd * ht * max_dpb_size will still be lesser or equal to max_wd * max_ht * dpb_size + * + * In the above equation (Wd * Ht) * (2 * max_dpb_size + 1) is accounted by using num_samples * (2 * max_dpb_size + 1) below + * + * For the padded area use MAX(horz_pad, vert_pad) as pad + * ((pad * pad) + pad * (Wd + Ht)) * (2 * max_dpb_size + 1) has to accounted from the above for padding + * + * Since Width and Height can change worst Wd + Ht is when One of the dimensions is max and other is min + * So use max_wd and min_ht + */ + + /* Number of bytes in reference pictures */ + size = num_samples * max_num_bufs; + + /* Account for padding area */ + size += ((pad * pad) + pad * (max_wd + max_wd)) * max_num_bufs; + + return size; +} +/** +******************************************************************************* +* +* @brief +* Used to get MV bank size for a given number of luma samples +* +* @par Description: +* For given number of luma samples one MV bank size is computed +* Each MV bank includes pu_map and pu_t for all the min PUs(4x4) in a picture +* +* @param[in] num_luma_samples +* Max number of luma pixels in the frame +* +* @returns Total MV Bank size +* +* @remarks +* +* +******************************************************************************* +*/ +WORD32 ihevcd_get_pic_mv_bank_size(WORD32 num_luma_samples) +{ + WORD32 size; + + WORD32 pic_size; + + WORD32 mv_bank_size; + WORD32 num_pu; + WORD32 num_ctb; + pic_size = num_luma_samples; + + + num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE); + num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE); + + mv_bank_size = 0; + + /* Size for storing pu_t start index each CTB */ + /* One extra entry is needed to compute number of PUs in the last CTB */ + mv_bank_size += (num_ctb + 1) * sizeof(WORD32); + + /* Size for pu_map */ + mv_bank_size += num_pu; + + /* Size for storing pu_t for each PU */ + mv_bank_size += num_pu * sizeof(pu_t); + + + size = mv_bank_size; + return size; +} +/** +******************************************************************************* +* +* @brief +* Used to get TU data size for a given number luma samples +* +* @par Description: +* For a given number of luma samples TU data size is computed +* Each TU data includes tu_map and tu_t and coeff data for all +* the min TUs(4x4) in given CTB +* +* @param[in] num_luma_samples +* Number of 64 x 64 CTBs for which TU data has to be allocated. +* +* @returns Total TU data size +* +* @remarks Assumption is num_luma_samples will be at least +* 64 x 64 to handle CTB of size 64 x 64. Can be frame size as well +* +******************************************************************************* +*/ +WORD32 ihevcd_get_tu_data_size(WORD32 num_luma_samples) +{ + + + WORD32 tu_data_size; + WORD32 num_ctb; + WORD32 num_luma_tu, num_chroma_tu, num_tu; + num_ctb = num_luma_samples / (MIN_CTB_SIZE * MIN_CTB_SIZE); + + num_luma_tu = num_luma_samples / (MIN_TU_SIZE * MIN_TU_SIZE); + num_chroma_tu = num_luma_tu >> 1; + + num_tu = num_luma_tu + num_chroma_tu; + tu_data_size = 0; + + /* Size for storing tu_t start index each CTB */ + /* One extra entry is needed to compute number of TUs in the last CTB */ + tu_data_size += (num_ctb + 1) * sizeof(WORD32); + + /* Size for storing tu map */ + tu_data_size += num_luma_tu * sizeof(UWORD8); + + /* Size for storing tu_t for each TU */ + tu_data_size += num_tu * sizeof(tu_t); + + /* Size for storing number of coded subblocks and scan_idx for each TU */ + tu_data_size += num_tu * (sizeof(WORD8) + sizeof(WORD8)); + + /* Size for storing coeff data for each TU */ + tu_data_size += num_tu * sizeof(tu_sblk_coeff_data_t); + + + return tu_data_size; +} + + +WORD32 ihevcd_nctb_cnt(codec_t *ps_codec, sps_t *ps_sps) +{ + WORD32 nctb = 1; + UNUSED(ps_codec); + //TODO: Currently set to 1 + /* If CTB size is less than 32 x 32 then set nCTB as 4 */ + if(ps_sps->i1_log2_ctb_size < 5) + nctb = 1; + + return nctb; +} + +IHEVCD_ERROR_T ihevcd_get_tile_pos(pps_t *ps_pps, + sps_t *ps_sps, + WORD32 ctb_x, + WORD32 ctb_y, + WORD32 *pi4_ctb_tile_x, + WORD32 *pi4_ctb_tile_y, + WORD32 *pi4_tile_idx) +{ + + tile_t *ps_tile_tmp; + WORD32 i; + WORD32 tile_row, tile_col; + + if(ctb_x < 0 || ctb_y < 0) + { + *pi4_ctb_tile_x = 0; + *pi4_ctb_tile_y = 0; + *pi4_tile_idx = 0; + + return (IHEVCD_ERROR_T)IHEVCD_SUCCESS; + } + + tile_row = 0; + tile_col = 0; + ps_tile_tmp = ps_pps->ps_tile; + if(0 == ps_pps->i1_tiles_enabled_flag) + { + *pi4_ctb_tile_x = ctb_x; + *pi4_ctb_tile_y = ctb_y; + *pi4_tile_idx = 0; + } + else + { + for(i = 0; i < ps_pps->i1_num_tile_columns; i++) + { + WORD16 next_tile_ctb_x; + ps_tile_tmp = ps_pps->ps_tile + i; //* ps_pps->i1_num_tile_rows; + if((ps_pps->i1_num_tile_columns - 1) == i) + { + next_tile_ctb_x = ps_sps->i2_pic_wd_in_ctb; + } + else + { + tile_t *ps_tile_next_tmp; + ps_tile_next_tmp = ps_pps->ps_tile + i + 1; + next_tile_ctb_x = ps_tile_next_tmp->u1_pos_x; + } + if((ctb_x >= ps_tile_tmp->u1_pos_x) && (ctb_x < next_tile_ctb_x)) + { + tile_col = i; + break; + } + } + *pi4_ctb_tile_x = ctb_x - ps_tile_tmp->u1_pos_x; + + for(i = 0; i < ps_pps->i1_num_tile_rows; i++) + { + WORD16 next_tile_ctb_y; + ps_tile_tmp = ps_pps->ps_tile + i * ps_pps->i1_num_tile_columns; + if((ps_pps->i1_num_tile_rows - 1) == i) + { + next_tile_ctb_y = ps_sps->i2_pic_ht_in_ctb; + } + else + { + tile_t *ps_tile_next_tmp; + ps_tile_next_tmp = ps_pps->ps_tile + ((i + 1) * ps_pps->i1_num_tile_columns); + next_tile_ctb_y = ps_tile_next_tmp->u1_pos_y; + } + if((ctb_y >= ps_tile_tmp->u1_pos_y) && (ctb_y < next_tile_ctb_y)) + { + tile_row = i; + break; + } + + } + *pi4_ctb_tile_y = ctb_y - ps_tile_tmp->u1_pos_y; + *pi4_tile_idx = tile_row * ps_pps->i1_num_tile_columns + + tile_col; + } + return (IHEVCD_ERROR_T)IHEVCD_SUCCESS; +} +/** +******************************************************************************* +* +* @brief +* Function to initialize ps_pic_buf structs add pic buffers to +* buffer manager in case of non-shared mode +* +* @par Description: +* Function to initialize ps_pic_buf structs add pic buffers to +* buffer manager in case of non-shared mode +* To be called once per stream or for every reset +* +* @param[in] ps_codec +* Pointer to codec context +* +* @returns Error from IHEVCD_ERROR_T +* +* @remarks +* +* +******************************************************************************* +*/ +IHEVCD_ERROR_T ihevcd_pic_buf_mgr_add_bufs(codec_t *ps_codec) +{ + IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS; + WORD32 i; + WORD32 max_dpb_size; + sps_t *ps_sps; + UWORD8 *pu1_buf; + pic_buf_t *ps_pic_buf; + WORD32 pic_buf_size_allocated; + + WORD32 max_num_bufs; + WORD32 pic_size; + WORD32 level; + + + /* Initialize MV Bank buffer manager */ + ps_sps = ps_codec->s_parse.ps_sps; + + pic_size = ps_sps->i2_pic_width_in_luma_samples * + ps_sps->i2_pic_height_in_luma_samples; + + + /* Compute the number of MB Bank buffers needed */ + level = ps_codec->i4_init_level; + max_dpb_size = ihevcd_get_dpb_size(level, pic_size); + /* Allocate twice dpb size to handle worst case reorder without returning more + * than one output per call + */ + max_dpb_size *= 2; + /* Allocate one extra picture to handle current frame + * In case of asynchronous parsing and processing, number of buffers should increase here + * based on when parsing and processing threads are synchronized + */ + max_dpb_size++; + + /* If num_ref_frames and num_reorder_frmaes is specified + * Use minimum value + */ + max_num_bufs = MIN(max_dpb_size, (ps_codec->i4_init_num_ref + ps_codec->i4_init_num_reorder + 1)); + + + pu1_buf = (UWORD8 *)ps_codec->ps_pic_buf; + + ps_pic_buf = (pic_buf_t *)ps_codec->ps_pic_buf; + + pu1_buf += BUF_MGR_MAX_CNT * sizeof(pic_buf_t); + + /* In case of non-shared mode, add picture buffers to buffer manager + * In case of shared mode buffers are added in the run-time + */ + if(0 == ps_codec->i4_share_disp_buf) + { + WORD32 buf_ret; + WORD32 luma_samples; + WORD32 chroma_samples; + pic_buf_size_allocated = ps_codec->i4_total_pic_buf_size - + BUF_MGR_MAX_CNT * sizeof(pic_buf_t); + + luma_samples = (ps_codec->i4_strd) * + (ps_sps->i2_pic_height_in_luma_samples + PAD_HT); + + chroma_samples = luma_samples / 2; + + /* Try to add as many buffers as possible since memory is already allocated */ + /* If the number of buffers that can be added is less than max_num_bufs + * return with an error. + */ + for(i = 0; i < (2 * MAX_DPB_SIZE) + 1; i++) + { + pic_buf_size_allocated -= (luma_samples + chroma_samples); + + if(pic_buf_size_allocated < 0) + { + if(i < max_num_bufs) + { + ps_codec->s_parse.i4_error_code = IHEVCD_INSUFFICIENT_MEM_PICBUF; + return IHEVCD_INSUFFICIENT_MEM_PICBUF; + } + break; + } + + ps_pic_buf->pu1_luma = pu1_buf + ps_codec->i4_strd * PAD_TOP + PAD_LEFT; + pu1_buf += luma_samples; + + ps_pic_buf->pu1_chroma = pu1_buf + ps_codec->i4_strd * (PAD_TOP / 2) + PAD_LEFT; + pu1_buf += chroma_samples; + + buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, ps_pic_buf, i); + + if(0 != buf_ret) + { + ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR; + return IHEVCD_BUF_MGR_ERROR; + } + ps_pic_buf++; + } + } + + return ret; +} +/** +******************************************************************************* +* +* @brief +* Function to add buffers to MV Bank buffer manager +* +* @par Description: +* Function to add buffers to MV Bank buffer manager +* To be called once per stream or for every reset +* +* @param[in] ps_codec +* Pointer to codec context +* +* @returns Error from IHEVCD_ERROR_T +* +* @remarks +* +* +******************************************************************************* +*/ +IHEVCD_ERROR_T ihevcd_mv_buf_mgr_add_bufs(codec_t *ps_codec) +{ + IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS; + WORD32 i; + WORD32 max_dpb_size; + WORD32 mv_bank_size_allocated; + WORD32 pic_mv_bank_size; + WORD32 level; + sps_t *ps_sps; + UWORD8 *pu1_buf; + mv_buf_t *ps_mv_buf; + + + /* Initialize MV Bank buffer manager */ + ps_sps = ps_codec->s_parse.ps_sps; + + + /* Compute the number of MB Bank buffers needed */ + level = ps_codec->i4_init_level; + max_dpb_size = ihevcd_get_dpb_size(level, + ps_sps->i2_pic_width_in_luma_samples * + ps_sps->i2_pic_height_in_luma_samples); + + /* Allocate one extra MV Bank to handle current frame + * In case of asynchronous parsing and processing, number of buffers should increase here + * based on when parsing and processing threads are synchronized + */ + max_dpb_size++; + + pu1_buf = (UWORD8 *)ps_codec->pv_mv_bank_buf_base; + + ps_mv_buf = (mv_buf_t *)pu1_buf; + pu1_buf += BUF_MGR_MAX_CNT * sizeof(mv_buf_t); + ps_codec->ps_mv_buf = ps_mv_buf; + mv_bank_size_allocated = ps_codec->i4_total_mv_bank_size - BUF_MGR_MAX_CNT * sizeof(mv_buf_t); + + /* Compute MV bank size per picture */ + pic_mv_bank_size = ihevcd_get_pic_mv_bank_size(ps_sps->i2_pic_width_in_luma_samples * + ps_sps->i2_pic_height_in_luma_samples); + + for(i = 0; i < max_dpb_size; i++) + { + WORD32 buf_ret; + WORD32 num_pu; + WORD32 num_ctb; + WORD32 pic_size; + pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) * + ALIGN64(ps_sps->i2_pic_height_in_luma_samples); + + + num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE); + num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE); + + + mv_bank_size_allocated -= pic_mv_bank_size; + + if(mv_bank_size_allocated < 0) + { + ps_codec->s_parse.i4_error_code = IHEVCD_INSUFFICIENT_MEM_MVBANK; + return IHEVCD_INSUFFICIENT_MEM_MVBANK; + } + + ps_mv_buf->pu4_pic_pu_idx = (UWORD32 *)pu1_buf; + pu1_buf += (num_ctb + 1) * sizeof(WORD32); + + ps_mv_buf->pu1_pic_pu_map = pu1_buf; + pu1_buf += num_pu; + + ps_mv_buf->pu1_pic_slice_map = (UWORD16 *)pu1_buf; + pu1_buf += num_ctb * sizeof(UWORD16); + + ps_mv_buf->ps_pic_pu = (pu_t *)pu1_buf; + + buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_mv_buf_mgr, ps_mv_buf, i); + + if(0 != buf_ret) + { + ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR; + return IHEVCD_BUF_MGR_ERROR; + } + pu1_buf += pic_mv_bank_size; + ps_mv_buf++; + + } + return ret; +} +/** +******************************************************************************* +* +* @brief +* Picture level initializations required during parsing +* +* @par Description: +* Initialize picture level context variables during parsing Initialize mv +* bank buffer manager in the first init call +* +* @param[in] ps_codec +* Pointer to codec context +* +* @returns Error from IHEVCD_ERROR_T +* +* @remarks +* +* +******************************************************************************* +*/ +IHEVCD_ERROR_T ihevcd_parse_pic_init(codec_t *ps_codec) +{ + IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS; + mv_buf_t *ps_mv_buf; + sps_t *ps_sps; + WORD32 num_min_cu; + WORD32 cur_pic_buf_id; + WORD32 cur_mv_bank_buf_id; + pic_buf_t *ps_cur_pic; + slice_header_t *ps_slice_hdr; + UWORD8 *pu1_cur_pic_luma, *pu1_cur_pic_chroma; + WORD32 i; + + ps_codec->s_parse.i4_error_code = IHEVCD_SUCCESS; + ps_sps = ps_codec->s_parse.ps_sps; +#ifdef GPU_BUILD + //TODO GPU : Later define it for ARM only version as well + ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr_base + (ps_codec->s_parse.i4_cur_slice_idx & (MAX_SLICE_HDR_CNT - 1)); +#else + ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr; +#endif + /* If parse_pic_init is called, then slice data is present in the input bitstrea stream */ + ps_codec->i4_pic_present = 1; + + /* Memset picture level intra map and transquant bypass map to zero */ +#ifdef GPU_BUILD + ps_codec->s_parse.pu1_pic_intra_flag = ps_codec->apu1_pic_intra_flag[ps_codec->u4_parsing_view]; + ps_codec->s_parse.pu1_pic_no_loop_filter_flag = ps_codec->apu1_pic_no_loop_filter_flag[ps_codec->u4_parsing_view]; +#endif + num_min_cu = ((ps_sps->i2_pic_height_in_luma_samples + 7) / 8) * ((ps_sps->i2_pic_width_in_luma_samples + 63) / 64); + memset(ps_codec->s_parse.pu1_pic_intra_flag, 0, num_min_cu); + memset(ps_codec->s_parse.pu1_pic_no_loop_filter_flag, 0, num_min_cu); + + + + if(0 == ps_codec->s_parse.i4_first_pic_init) + { + ret = ihevcd_mv_buf_mgr_add_bufs(ps_codec); + RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret); + + ret = ihevcd_pic_buf_mgr_add_bufs(ps_codec); + RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret); + + ps_codec->s_parse.i4_first_pic_init = 1; + } + + /* Initialize all the slice headers' slice addresses to zero */ + { + WORD32 slice_idx; + WORD32 slice_start_idx; + + slice_start_idx = ps_codec->i4_slice_error ? 2 : 1; + + for(slice_idx = slice_start_idx; slice_idx < MAX_SLICE_HDR_CNT; slice_idx++) + { +#ifdef GPU_BUILD + slice_header_t *ps_slice_hdr_tmp = ps_codec->aps_slice_hdr_base[0] + slice_idx; + ps_slice_hdr_tmp->i2_ctb_x = -1; + ps_slice_hdr_tmp->i2_ctb_y = -1; + ps_slice_hdr_tmp = ps_codec->aps_slice_hdr_base[1] + slice_idx; + ps_slice_hdr_tmp->i2_ctb_x = -1; + ps_slice_hdr_tmp->i2_ctb_y = -1; +#else + slice_header_t *ps_slice_hdr_tmp = ps_codec->ps_slice_hdr_base + slice_idx; + ps_slice_hdr_tmp->i2_ctb_x = -1; + ps_slice_hdr_tmp->i2_ctb_y = -1; +#endif + + } + } + + /* Get free MV Bank to hold current picture's motion vector data */ + { + 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); + + /* If there are no free buffers then return with an error code. + * If the buffer is to be freed by another thread , change the + * following to call thread yield and wait for buffer to be freed + */ + if(NULL == ps_mv_buf) + { + ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_MVBANK; + ps_codec->i4_error_code = IHEVCD_NO_FREE_MVBANK; + return IHEVCD_NO_FREE_MVBANK; + } + + ps_codec->s_parse.ps_cur_mv_buf = ps_mv_buf; + /* Set current ABS poc to ps_mv_buf, so that while freeing a reference buffer + * corresponding mv buffer can be found by looping through ps_codec->ps_mv_buf array + * and getting a buffer id to free + */ + ps_mv_buf->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt; + } + + /* Get free picture buffer to hold current picture recon data */ + /* TODO: For asynchronous api the following initializations related to picture + * buffer should be moved to processing side + */ + { + + UWORD8 *pu1_buf; + 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); + + /* If there are no free buffers then return with an error code. + * TODO: If the buffer is to be freed by another thread , change the + * following to call thread yield and wait for buffer to be freed + */ + if(NULL == ps_cur_pic) + { + ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_PICBUF; + ps_codec->i4_error_code = IHEVCD_NO_FREE_PICBUF; + return IHEVCD_NO_FREE_PICBUF; + } + + /* Store input timestamp sent with input buffer */ + ps_cur_pic->u4_ts = ps_codec->u4_ts; + ps_cur_pic->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt; + ps_cur_pic->i4_poc_lsb = ps_slice_hdr->i4_pic_order_cnt_lsb; + pu1_buf = ps_cur_pic->pu1_luma; + pu1_cur_pic_luma = pu1_buf; + + pu1_buf = ps_cur_pic->pu1_chroma; + + pu1_cur_pic_chroma = pu1_buf; + } + + if(0 == ps_codec->u4_pic_cnt) + { + 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); + 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); + } + + /* Fill the remaining entries of the reference lists with the nearest POC + * This is done to handle cases where there is a corruption in the reference index */ + { + pic_buf_t *ps_pic_buf_ref; + mv_buf_t *ps_mv_buf_ref; + WORD32 r_idx; + dpb_mgr_t *ps_dpb_mgr = (dpb_mgr_t *)ps_codec->pv_dpb_mgr; + buf_mgr_t *ps_mv_buf_mgr = (buf_mgr_t *)ps_codec->pv_mv_buf_mgr; + + ps_pic_buf_ref = ihevc_dpb_mgr_get_ref_by_nearest_poc(ps_dpb_mgr, ps_slice_hdr->i4_abs_pic_order_cnt); + if(NULL == ps_pic_buf_ref) + { + ps_pic_buf_ref = ps_cur_pic; + ps_mv_buf_ref = ps_mv_buf; + } + else + { + ps_mv_buf_ref = ihevcd_mv_mgr_get_poc(ps_mv_buf_mgr, ps_pic_buf_ref->i4_abs_poc); + } + + for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx++) + { + if(NULL == ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf) + { + ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref; + ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref; + } + } + + for(r_idx = ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx < MAX_DPB_SIZE; r_idx++) + { + ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref; + ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref; + } + + for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx++) + { + if(NULL == ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf) + { + ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref; + ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref; + } + } + + for(r_idx = ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx < MAX_DPB_SIZE; r_idx++) + { + ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref; + ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref; + } + } + + + /* Reset the jobq to start of the jobq buffer */ + ihevcd_jobq_reset((jobq_t *)ps_codec->pv_proc_jobq); + + ps_codec->s_parse.i4_pic_pu_idx = 0; + ps_codec->s_parse.i4_pic_tu_idx = 0; + + ps_codec->s_parse.pu1_pic_pu_map = ps_mv_buf->pu1_pic_pu_map; + ps_codec->s_parse.ps_pic_pu = ps_mv_buf->ps_pic_pu; + ps_codec->s_parse.pu4_pic_pu_idx = ps_mv_buf->pu4_pic_pu_idx; + ps_codec->s_parse.pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map; +#ifndef GPU_BUILD + for(i = 0; i < MAX_PROCESS_THREADS; i++) + { + ps_codec->as_process[i].pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map; + } +#endif + ps_codec->s_parse.pu1_pu_map = ps_codec->s_parse.pu1_pic_pu_map; + ps_codec->s_parse.ps_pu = ps_codec->s_parse.ps_pic_pu; + + { + UWORD8 *pu1_buf; + WORD32 ctb_luma_min_tu_cnt, ctb_chroma_min_tu_cnt, ctb_min_tu_cnt; + WORD32 pic_size; + WORD32 num_ctb; + + pic_size = ps_sps->i2_pic_width_in_luma_samples * + ps_sps->i2_pic_height_in_luma_samples; + + ctb_luma_min_tu_cnt = pic_size / (MIN_TU_SIZE * MIN_TU_SIZE); + + ctb_chroma_min_tu_cnt = ctb_luma_min_tu_cnt >> 1; + + ctb_min_tu_cnt = ctb_luma_min_tu_cnt + ctb_chroma_min_tu_cnt; + + num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE); +#ifdef GPU_BUILD + pu1_buf = (UWORD8 *)ps_codec->apv_tu_data[ps_codec->u4_parsing_view]; +#else + pu1_buf = (UWORD8 *)ps_codec->pv_tu_data; +#endif + ps_codec->s_parse.pu4_pic_tu_idx = (UWORD32 *)pu1_buf; + pu1_buf += (num_ctb + 1) * sizeof(WORD32); + + ps_codec->s_parse.pu1_pic_tu_map = pu1_buf; + pu1_buf += ctb_min_tu_cnt; + + ps_codec->s_parse.ps_pic_tu = (tu_t *)pu1_buf; + pu1_buf += ctb_min_tu_cnt * sizeof(tu_t); + + ps_codec->s_parse.pv_pic_tu_coeff_data = pu1_buf; + + ps_codec->s_parse.pu1_tu_map = ps_codec->s_parse.pu1_pic_tu_map; + ps_codec->s_parse.ps_tu = ps_codec->s_parse.ps_pic_tu; + ps_codec->s_parse.pv_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data; + } + + ps_codec->s_parse.s_bs_ctxt.ps_pic_pu = ps_codec->s_parse.ps_pic_pu; + ps_codec->s_parse.s_bs_ctxt.pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx; + ps_codec->s_parse.s_bs_ctxt.pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx; + + + /* Set number of CTBs to be processed simultaneously */ + ps_codec->i4_proc_nctb = ihevcd_nctb_cnt(ps_codec, ps_sps); + + /* Memset Parse Map and process map at the start of frame */ + //TODO: In case of asynchronous API proc_map can not be set to zero here + { + WORD32 num_ctb; + + num_ctb = ps_sps->i4_pic_size_in_ctb; + + memset(ps_codec->pu1_parse_map, 0, num_ctb); + +#ifndef GPU_BUILD + memset(ps_codec->pu1_proc_map, 0, num_ctb); +#endif + } + + + + /* Initialize disp buf id to -1, this will be updated at the end of frame if there is + * buffer to be displayed + */ + ps_codec->i4_disp_buf_id = -1; + ps_codec->ps_disp_buf = NULL; + + ps_codec->i4_disable_deblk_pic = 0; + ps_codec->i4_disable_sao_pic = 0; + ps_codec->i4_fullpel_inter_pred = 0; + ps_codec->i4_mv_frac_mask = 0x7FFFFFFF; + + /* If degrade is enabled, set the degrade flags appropriately */ + if(ps_codec->i4_degrade_type && ps_codec->i4_degrade_pics) + { + WORD32 degrade_pic; + ps_codec->i4_degrade_pic_cnt++; + degrade_pic = 0; + + /* If degrade is to be done in all frames, then do not check further */ + switch(ps_codec->i4_degrade_pics) + { + case 4: + { + degrade_pic = 1; + break; + } + case 3: + { + if(ps_slice_hdr->i1_slice_type != ISLICE) + degrade_pic = 1; + + break; + } + case 2: + { + + /* If pic count hits non-degrade interval or it is an islice, then do not degrade */ + if((ps_slice_hdr->i1_slice_type != ISLICE) && + (ps_codec->i4_degrade_pic_cnt != ps_codec->i4_nondegrade_interval)) + degrade_pic = 1; + + break; + } + case 1: + { + /* Check if the current picture is non-ref */ + if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) && + (ps_slice_hdr->i1_nal_unit_type % 2 == 0)) + { + degrade_pic = 1; + } + break; + } + + + } + if(degrade_pic) + { + if(ps_codec->i4_degrade_type & 0x1) + ps_codec->i4_disable_sao_pic = 1; + + if(ps_codec->i4_degrade_type & 0x2) + ps_codec->i4_disable_deblk_pic = 1; + + /* MC degrading is done only for non-ref pictures */ + if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) && + (ps_slice_hdr->i1_nal_unit_type % 2 == 0)) + { + if(ps_codec->i4_degrade_type & 0x4) + ps_codec->i4_mv_frac_mask = 0; + + if(ps_codec->i4_degrade_type & 0x8) + ps_codec->i4_mv_frac_mask = 0; + } + } + else + ps_codec->i4_degrade_pic_cnt = 0; + } + + + { + WORD32 i; +#ifdef GPU_BUILD + gpu_ctxt_t *ps_gpu = &ps_codec->s_gpu_ctxt; + ps_gpu->i4_curr_grain_ctb_cnt = 0; + ps_codec->s_parse.s_bs_ctxt.pu4_pic_vert_bs = ps_codec->apu4_pic_vert_bs[ps_codec->u4_parsing_view]; + ps_codec->s_parse.s_bs_ctxt.pu4_pic_horz_bs = ps_codec->apu4_pic_horz_bs[ps_codec->u4_parsing_view]; + ps_codec->s_parse.s_bs_ctxt.pu1_pic_qp = ps_codec->apu1_pic_qp[ps_codec->u4_parsing_view]; + ps_codec->s_parse.s_bs_ctxt.pu1_pic_qp_const_in_ctb = ps_codec->apu1_pic_qp_const_in_ctb[ps_codec->u4_parsing_view]; + + ps_codec->s_parse.s_deblk_ctxt.s_bs_ctxt.pu4_pic_vert_bs = (UWORD32 *)ps_codec->s_parse.s_bs_ctxt.pu4_pic_vert_bs; + ps_codec->s_parse.s_deblk_ctxt.s_bs_ctxt.pu4_pic_horz_bs = (UWORD32 *)ps_codec->s_parse.s_bs_ctxt.pu4_pic_horz_bs; + ps_codec->s_parse.s_deblk_ctxt.s_bs_ctxt.pu1_pic_qp = (UWORD8 *)ps_codec->s_parse.s_bs_ctxt.pu1_pic_qp; + ps_codec->s_parse.s_deblk_ctxt.s_bs_ctxt.pu1_pic_qp_const_in_ctb = (UWORD8 *)ps_codec->s_parse.s_bs_ctxt.pu1_pic_qp_const_in_ctb; + + ps_codec->s_parse.s_deblk_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->apu1_pic_no_loop_filter_flag[ps_codec->u4_parsing_view]; + ps_codec->s_parse.s_sao_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->apu1_pic_no_loop_filter_flag[ps_codec->u4_parsing_view]; + + ps_codec->s_parse.s_deblk_ctxt.ps_slice_hdr_base = ps_codec->s_parse.ps_slice_hdr_base; + + ps_codec->s_parse.ps_pic_sao = (sao_t *)ps_codec->aps_pic_sao[ps_codec->u4_parsing_view]; + ps_codec->s_parse.s_sao_ctxt.ps_pic_sao = (sao_t *)ps_codec->aps_pic_sao[ps_codec->u4_parsing_view]; +#endif + for(i = 0; i < MAX_PROCESS_THREADS; i++) + { + ps_codec->as_process[i].pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx; + ps_codec->as_process[i].ps_pic_pu = ps_codec->s_parse.ps_pic_pu; + ps_codec->as_process[i].pu1_pic_pu_map = ps_codec->s_parse.pu1_pic_pu_map; + ps_codec->as_process[i].pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx; + ps_codec->as_process[i].ps_pic_tu = ps_codec->s_parse.ps_pic_tu; + ps_codec->as_process[i].pu1_pic_tu_map = ps_codec->s_parse.pu1_pic_tu_map; + ps_codec->as_process[i].pv_pic_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data; + ps_codec->as_process[i].i4_cur_mv_bank_buf_id = cur_mv_bank_buf_id; + ps_codec->as_process[i].s_sao_ctxt.pu1_slice_idx = ps_codec->as_process[i].pu1_slice_idx; + ps_codec->as_process[i].s_sao_ctxt.pu1_tile_idx = ps_codec->as_process[i].pu1_tile_idx; + + /* TODO: For asynchronous api the following initializations related to picture + * buffer should be moved to processing side + */ + ps_codec->as_process[i].pu1_cur_pic_luma = pu1_cur_pic_luma; + ps_codec->as_process[i].pu1_cur_pic_chroma = pu1_cur_pic_chroma; + ps_codec->as_process[i].ps_cur_pic = ps_cur_pic; + ps_codec->as_process[i].i4_cur_pic_buf_id = cur_pic_buf_id; + + ps_codec->as_process[i].ps_out_buffer = ps_codec->ps_out_buffer; + if(1 < ps_codec->i4_num_cores) + { + ps_codec->as_process[i].i4_check_parse_status = 1; + ps_codec->as_process[i].i4_check_proc_status = 1; + } + else + { + ps_codec->as_process[i].i4_check_parse_status = 0; + ps_codec->as_process[i].i4_check_proc_status = 0; + } + ps_codec->as_process[i].pu1_pic_intra_flag = ps_codec->s_parse.pu1_pic_intra_flag; + ps_codec->as_process[i].pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag; + ps_codec->as_process[i].i4_init_done = 0; + + ps_codec->as_process[i].s_bs_ctxt.pu4_pic_tu_idx = ps_codec->as_process[i].pu4_pic_tu_idx; + ps_codec->as_process[i].s_bs_ctxt.pu4_pic_pu_idx = ps_codec->as_process[i].pu4_pic_pu_idx; + ps_codec->as_process[i].s_bs_ctxt.ps_pic_pu = ps_codec->as_process[i].ps_pic_pu; +#ifdef GPU_BUILD + ps_codec->as_process[i].u4_gpu_inter_flag = ps_codec->u4_gpu_enabled; + ps_codec->as_process[i].s_bs_ctxt.pu4_pic_vert_bs = (UWORD32 *)ps_codec->s_parse.s_bs_ctxt.pu4_pic_vert_bs; + ps_codec->as_process[i].s_bs_ctxt.pu4_pic_horz_bs = (UWORD32 *)ps_codec->s_parse.s_bs_ctxt.pu4_pic_horz_bs; + ps_codec->as_process[i].s_bs_ctxt.pu1_pic_qp = (UWORD8 *)ps_codec->s_parse.s_bs_ctxt.pu1_pic_qp; + ps_codec->as_process[i].s_bs_ctxt.pu1_pic_qp_const_in_ctb = (UWORD8 *)ps_codec->s_parse.s_bs_ctxt.pu1_pic_qp_const_in_ctb; + + ps_codec->as_process[i].s_deblk_ctxt.s_bs_ctxt.pu4_pic_vert_bs = (UWORD32 *)ps_codec->s_parse.s_bs_ctxt.pu4_pic_vert_bs; + ps_codec->as_process[i].s_deblk_ctxt.s_bs_ctxt.pu4_pic_horz_bs = (UWORD32 *)ps_codec->s_parse.s_bs_ctxt.pu4_pic_horz_bs; + ps_codec->as_process[i].s_deblk_ctxt.s_bs_ctxt.pu1_pic_qp = (UWORD8 *)ps_codec->s_parse.s_bs_ctxt.pu1_pic_qp; + ps_codec->as_process[i].s_deblk_ctxt.s_bs_ctxt.pu1_pic_qp_const_in_ctb = (UWORD8 *)ps_codec->s_parse.s_bs_ctxt.pu1_pic_qp_const_in_ctb; + ps_codec->as_process[i].pu1_proc_map = ps_codec->apu1_proc_map[ps_codec->u4_parsing_view]; + + ps_codec->as_process[i].pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map; + +#else +#ifdef GPU_BUILD + //TODO GPU : Later define it for ARM only version as well + ps_codec->as_process[i].pu1_proc_map = ps_codec->pu1_proc_map; +#endif +#endif + ps_codec->as_process[i].s_deblk_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag; + ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma; + ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma; +#ifdef GPU_BUILD + //TODO GPU : Later define it for ARM only version as well + ps_codec->as_process[i].s_deblk_ctxt.ps_slice_hdr_base = ps_codec->s_parse.ps_slice_hdr_base; +#endif + ps_codec->as_process[i].s_sao_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag; + ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma; + ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma; +#ifdef GPU_BUILD + //TODO GPU : Later define it for ARM only version as well + ps_codec->as_process[i].s_sao_ctxt.ps_slice_hdr_base = ps_codec->s_parse.ps_slice_hdr_base; + ps_codec->as_process[i].ps_slice_hdr_base = ps_codec->s_parse.ps_slice_hdr_base; + + ps_codec->as_process[i].s_sao_ctxt.ps_pic_sao = ps_codec->s_parse.ps_pic_sao; +#endif + if(i < (ps_codec->i4_num_cores - 1)) + { + ithread_create(ps_codec->apv_process_thread_handle[i], NULL, + (void *)ihevcd_process_thread, + (void *)&ps_codec->as_process[i]); + ps_codec->ai4_process_thread_created[i] = 1; + } + else + { + ps_codec->ai4_process_thread_created[i] = 0; + } + + } +#ifdef GPU_BUILD + memset(ps_codec->apu1_proc_map[ps_codec->u4_parsing_view], 0, ps_sps->i4_pic_size_in_ctb); +#else +#ifdef GPU_BUILD + //TODO GPU : Later define it for ARM only version as well + // and remove from above. + memset(ps_codec->pu1_proc_map, 0, ps_sps->i4_pic_size_in_ctb); +#endif +#endif + ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma; + ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma; + + ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma; + ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma; + } + /* Since any input bitstream buffer that contains slice data will be sent to output(even in + * case of error, this buffer is added to display queue and next buffer in the display queue + * will be returned as the display buffer. + * Note: If format conversion (or frame copy) is used and is scheduled + * in a different thread then it has to check if the processing for the current row is complete before + * it copies/converts a given row. In case of low delay or in case of B pictures, current frame being decoded has to be + * returned, which requires a status check to ensure that the current row is reconstructed before copying. + */ + /* Add current picture to display manager */ +#ifndef GPU_BUILD + { + WORD32 abs_poc; + slice_header_t *ps_slice_hdr; + ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr; + abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt; + ihevc_disp_mgr_add((disp_mgr_t *)ps_codec->pv_disp_buf_mgr, + ps_codec->as_process[0].i4_cur_pic_buf_id, + abs_poc, + ps_codec->as_process[0].ps_cur_pic); + } +#endif + ps_codec->ps_disp_buf = NULL; + /* Get picture to be displayed if number of pictures decoded is more than max allowed reorder */ + /* Since the current will be decoded, check is fore >= instead of > */ +#ifdef GPU_BUILD + //TODO OPENCL delay this by one frame + //TODO GPU : Should it be just +1 + 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]+2)) || +#else + 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]) || +#endif + ((WORD32)(ps_codec->u4_pic_cnt - ps_codec->u4_disp_cnt) >= ps_codec->i4_init_num_reorder)) + + { + 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); + ps_codec->u4_disp_cnt++; + } + + ps_codec->s_fmt_conv.i4_cur_row = 0; + /* Set number of rows to be processed at a time */ + ps_codec->s_fmt_conv.i4_num_rows = 4; + + if(ps_codec->u4_enable_fmt_conv_ahead && (ps_codec->i4_num_cores > 1)) + { + process_ctxt_t *ps_proc; + + /* i4_num_cores - 1 contexts are currently being used by other threads */ + ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1]; + + /* If the frame being decoded and displayed are different, schedule format conversion jobs + * this will keep the proc threads busy and lets parse thread decode few CTBs ahead + * If the frame being decoded and displayed are same, then format conversion is scheduled later. + */ + if((ps_codec->ps_disp_buf) && (ps_codec->i4_disp_buf_id != ps_proc->i4_cur_pic_buf_id) && + ((0 == ps_codec->i4_share_disp_buf) || (IV_YUV_420P == ps_codec->e_chroma_fmt))) + { + + for(i = 0; i < ps_sps->i2_pic_ht_in_ctb; i++) + { + proc_job_t s_job; + IHEVCD_ERROR_T ret; + s_job.i4_cmd = CMD_FMTCONV; + s_job.i2_ctb_cnt = 0; + s_job.i2_ctb_x = 0; + s_job.i2_ctb_y = i; + s_job.i2_slice_idx = 0; + s_job.i4_tu_coeff_data_ofst = 0; + ret = ihevcd_jobq_queue((jobq_t *)ps_codec->s_parse.pv_proc_jobq, + &s_job, sizeof(proc_job_t), 1); + if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS) + return ret; + } + } + } + +#ifdef GPU_BUILD + /* Pic init for Opencl device */ + ihevcd_gpu_mc_pic_init(ps_codec); +#endif + + return ret; +} + + |