/****************************************************************************** * * Copyright (C) 2021 The Android Open Source Project * * 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. * ***************************************************************************** * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore */ /*****************************************************************************/ /* */ /* File Name : imvcd_api_utils.c */ /* */ /* Description : Utility functions used by 'imvcd_api.c' */ /* */ /*****************************************************************************/ #include #include "ih264_typedefs.h" #include "iv.h" #include "imvcd.h" #include "ih264_disp_mgr.h" #include "ih264d_structs.h" #include "ih264d_tables.h" #include "ih264d_utils.h" #include "imvcd_structs.h" #include "imvcd_utils.h" IV_API_CALL_STATUS_T imvcd_check_dec_handle(iv_obj_t *ps_handle) { if(ps_handle == NULL) { return IV_FAIL; } if(ps_handle->pv_codec_handle == NULL) { return IV_FAIL; } return IV_SUCCESS; } IV_API_CALL_STATUS_T imvcd_check_create_structs(imvcd_create_ip_t *ps_ip, imvcd_create_op_t *ps_op) { if(NULL == ps_ip) { return IV_FAIL; } if(NULL == ps_op) { return IV_FAIL; } if(ps_ip->s_ivd_ip.e_output_format != IV_YUV_420P) { return IV_FAIL; } if(NULL == ps_ip->s_ivd_ip.pf_aligned_alloc) { return IV_FAIL; } if(NULL == ps_ip->s_ivd_ip.pf_aligned_free) { return IV_FAIL; } if(0 != ps_ip->s_ivd_ip.u4_share_disp_buf) { return IV_FAIL; } return IV_SUCCESS; } IV_API_CALL_STATUS_T imvcd_check_ctl_structs(void *pv_ip, void *pv_op) { ivd_ctl_set_config_ip_t *ps_ip = (ivd_ctl_set_config_ip_t *) pv_ip; ivd_ctl_set_config_op_t *ps_op = (ivd_ctl_set_config_op_t *) pv_op; WORD32 i4_sub_cmd = ps_ip->e_sub_cmd; if(NULL == ps_ip) { return IV_FAIL; } if(NULL == ps_op) { return IV_FAIL; } switch(i4_sub_cmd) { case IVD_CMD_CTL_SETPARAMS: { if((ps_ip->u4_size != sizeof(ivd_ctl_set_config_ip_t)) || (ps_op->u4_size != sizeof(ivd_ctl_set_config_op_t))) { return IV_FAIL; } else { return IV_SUCCESS; } } case IMVCD_CTL_SET_NUM_CORES: { if((ps_ip->u4_size != sizeof(imvcd_set_num_cores_ip_t)) || (ps_op->u4_size != sizeof(imvcd_set_num_cores_op_t))) { return IV_FAIL; } else { return IV_SUCCESS; } } case IMVCD_CTL_SET_PROCESSOR: { if((ps_ip->u4_size != sizeof(imvcd_set_arch_ip_t)) || (ps_op->u4_size != sizeof(imvcd_set_arch_op_t))) { return IV_FAIL; } else { return IV_SUCCESS; } } case IMVCD_CTL_DEGRADE: { if((ps_ip->u4_size != sizeof(imvcd_set_degrade_mode_ip_t)) || (ps_op->u4_size != sizeof(imvcd_set_degrade_mode_op_t))) { return IV_FAIL; } else { return IV_SUCCESS; } } case IVD_CMD_CTL_FLUSH: { if((ps_ip->u4_size != sizeof(ivd_ctl_flush_ip_t)) || (ps_op->u4_size != sizeof(ivd_ctl_flush_op_t))) { return IV_FAIL; } else { return IV_SUCCESS; } } case IVD_CMD_CTL_GETBUFINFO: { if((ps_ip->u4_size != sizeof(ivd_ctl_getbufinfo_ip_t)) || (ps_op->u4_size != sizeof(ivd_ctl_getbufinfo_op_t))) { return IV_FAIL; } else { return IV_SUCCESS; } } case IMVCD_CTL_GET_VUI_PARAMS: { if((ps_ip->u4_size != sizeof(imvcd_get_vui_ip_t)) || (ps_op->u4_size != sizeof(imvcd_get_vui_op_t))) { return IV_FAIL; } else { return IV_SUCCESS; } } default: { return IV_FAIL; } } } IV_API_CALL_STATUS_T imvcd_check_decode_structs(iv_obj_t *ps_dec_hdl, imvcd_video_decode_ip_t *ps_ip, imvcd_video_decode_op_t *ps_op) { WORD32 i, j; mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; UWORD16 u2_num_views = 1; if(NULL == ps_ip) { return IV_FAIL; } if(NULL == ps_op) { return IV_FAIL; } if(!ps_mvcd_ctxt->b_flush_enabled && !ps_mvcd_ctxt->b_header_only_decode) { if(NULL == ps_ip->s_ivd_ip.pv_stream_buffer) { return IV_FAIL; } for(i = 0; i < u2_num_views; i++) { for(j = 0; j < NUM_COMPONENTS; j++) { if(NULL == ps_ip->s_ivd_ip.s_out_buffer.pu1_bufs[i * NUM_COMPONENTS + j]) { return IV_FAIL; } } } if(0 == ps_ip->s_ivd_ip.u4_num_Bytes) { return IV_FAIL; } } return IV_SUCCESS; } static void imvcd_convert_app_out_buf(mvc_dec_ctxt_t *ps_mvcd_ctxt, ivd_out_bufdesc_t *ps_app_buffer) { if(!ps_mvcd_ctxt->b_header_only_decode) { WORD32 i, j; subset_sps_t *ps_subset_sps = imvcd_get_valid_subset_sps(ps_mvcd_ctxt); dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; UWORD16 u2_num_views = (NULL == ps_subset_sps) ? 1 : ps_subset_sps->s_sps_mvc_ext.u2_num_views; for(i = 0; i < u2_num_views; i++) { yuv_buf_props_t *ps_view_buf = &ps_mvcd_ctxt->s_out_buffer.as_view_buf_props[i]; ps_view_buf->u1_bit_depth = 8; ps_view_buf->u2_height = ps_view_ctxt->u2_disp_height; ps_view_buf->u2_width = ps_view_ctxt->u2_disp_width; for(j = 0; j < NUM_COMPONENTS; j++) { buffer_container_t *ps_component_buf = &ps_view_buf->as_component_bufs[j]; bool b_is_chroma = (((COMPONENT_TYPES_T) j) != Y); ps_component_buf->pv_data = ps_app_buffer->pu1_bufs[i * NUM_COMPONENTS + j]; ps_component_buf->i4_data_stride = ps_view_buf->u2_width >> b_is_chroma; } } } } void imvcd_convert_to_app_disp_buf(mvc_dec_ctxt_t *ps_mvcd_ctxt, iv_yuv_buf_t *ps_view_disp_bufs) { WORD32 i; UWORD16 u2_num_views = ps_mvcd_ctxt->u2_num_views; for(i = 0; i < u2_num_views; i++) { yuv_buf_props_t *ps_view_buf = &ps_mvcd_ctxt->s_out_buffer.as_view_buf_props[i]; ps_view_disp_bufs[i].u4_size = sizeof(ps_view_disp_bufs[i]); ps_view_disp_bufs[i].pv_y_buf = ps_view_buf->as_component_bufs[Y].pv_data; ps_view_disp_bufs[i].u4_y_strd = ps_view_buf->as_component_bufs[Y].i4_data_stride; ps_view_disp_bufs[i].u4_y_wd = ps_view_buf->u2_width; ps_view_disp_bufs[i].u4_y_ht = ps_view_buf->u2_height; ps_view_disp_bufs[i].pv_u_buf = ps_view_buf->as_component_bufs[U].pv_data; ps_view_disp_bufs[i].u4_u_strd = ps_view_buf->as_component_bufs[U].i4_data_stride; ps_view_disp_bufs[i].u4_u_wd = ps_view_buf->u2_width / 2; ps_view_disp_bufs[i].u4_u_ht = ps_view_buf->u2_height / 2; ps_view_disp_bufs[i].pv_v_buf = ps_view_buf->as_component_bufs[V].pv_data; ps_view_disp_bufs[i].u4_v_strd = ps_view_buf->as_component_bufs[V].i4_data_stride; ps_view_disp_bufs[i].u4_v_wd = ps_view_buf->u2_width / 2; ps_view_disp_bufs[i].u4_v_ht = ps_view_buf->u2_height / 2; } } void imvcd_au_init(iv_obj_t *ps_dec_hdl, imvcd_video_decode_ip_t *ps_ip, imvcd_video_decode_op_t *ps_op) { subset_sps_t *ps_subset_sps; mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; ps_mvcd_ctxt->u2_num_views_decoded = 0; ps_subset_sps = imvcd_get_valid_subset_sps(ps_mvcd_ctxt); ps_mvcd_ctxt->u2_num_views = (NULL == ps_subset_sps) ? 1 : ps_subset_sps->s_sps_mvc_ext.u2_num_views; imvcd_convert_app_out_buf(ps_mvcd_ctxt, &ps_ip->s_ivd_ip.s_out_buffer); ps_op->s_ivd_op.u4_num_bytes_consumed = 0; ps_op->s_ivd_op.u4_output_present = 0; ps_op->s_ivd_op.u4_error_code = 0; ps_op->s_ivd_op.e_pic_type = IV_FRAMETYPE_DEFAULT; ps_op->s_ivd_op.u4_frame_decoded_flag = 0; ps_op->s_ivd_op.u4_new_seq = 0; ps_op->s_ivd_op.u4_progressive_frame_flag = 1; ps_op->s_ivd_op.u4_is_ref_flag = 1; ps_op->s_ivd_op.e4_fld_type = IV_NA_FLD; ps_view_ctxt->u4_fmt_conv_cur_row = 0; ps_view_ctxt->u4_output_present = 0; ps_view_ctxt->u4_fmt_conv_num_rows = FMT_CONV_NUM_ROWS; ps_view_ctxt->u4_ts = ps_ip->s_ivd_ip.u4_ts; ps_view_ctxt->i4_frametype = IV_NA_FRAME; ps_view_ctxt->i4_content_type = IV_CONTENTTYPE_NA; /* Mimicking the hack in lines '2005' in 'ih264d_api.c' and '1323' in * 'ih264d_parse_headers.c */ ps_view_ctxt->u4_sps_cnt_in_process = 0; memset(ps_mvcd_ctxt->as_nalu_mvc_ext, 0, sizeof(ps_mvcd_ctxt->as_nalu_mvc_ext)); } void imvcd_view_init(mvc_dec_ctxt_t *ps_mvcd_ctxt) { dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; ps_view_ctxt->u4_num_fld_in_frm = 0; ps_view_ctxt->u4_slice_start_code_found = 0; ps_view_ctxt->u2_cur_mb_addr = 0; ps_view_ctxt->u2_total_mbs_coded = 0; ps_view_ctxt->u2_cur_slice_num = 0; ps_view_ctxt->cur_dec_mb_num = 0; ps_view_ctxt->cur_recon_mb_num = 0; ps_view_ctxt->u4_first_slice_in_pic = 1; ps_view_ctxt->u1_slice_header_done = 0; ps_view_ctxt->u1_dangling_field = 0; ps_view_ctxt->u4_dec_thread_created = 0; ps_view_ctxt->u4_bs_deblk_thread_created = 0; ps_view_ctxt->u4_cur_bs_mb_num = 0; ps_view_ctxt->u4_start_recon_deblk = 0; ps_view_ctxt->u4_pic_buf_got = 0; ps_view_ctxt->pu1_inv_scan = (UWORD8 *) gau1_ih264d_inv_scan; ps_view_ctxt->u1_pic_decode_done = 0; ps_view_ctxt->pu1_init_dpb_base = NULL; ps_view_ctxt->ps_dpb_mgr = NULL; } IV_API_CALL_STATUS_T imvcd_bitstream_buf_alloc(dec_struct_t *ps_view_ctxt, UWORD16 u2_num_views) { UWORD32 u4_size; u4_size = MAX(MIN_BITSTREAMS_BUF_SIZE, ((ps_view_ctxt->u2_pic_wd * ps_view_ctxt->u2_pic_ht * 3 / 2) + EXTRA_BS_OFFSET) * u2_num_views * sizeof(ps_view_ctxt->pu1_bits_buf_dynamic[0])); ps_view_ctxt->pu1_bits_buf_dynamic = ps_view_ctxt->pf_aligned_alloc(ps_view_ctxt->pv_mem_ctxt, 128, u4_size); RETURN_IF((NULL == ps_view_ctxt->pu1_bits_buf_dynamic), IV_FAIL); memset(ps_view_ctxt->pu1_bits_buf_dynamic, 0, u4_size); ps_view_ctxt->u4_dynamic_bits_buf_size = u4_size; return IV_SUCCESS; } void imvcd_bitsteam_buf_free(dec_struct_t *ps_view_ctxt) { PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu1_bits_buf_dynamic); } IV_API_CALL_STATUS_T imvcd_bitstream_buf_realloc(dec_struct_t *ps_view_ctxt, UWORD32 u4_size) { imvcd_bitsteam_buf_free(ps_view_ctxt); u4_size = MAX(MIN_BITSTREAMS_BUF_SIZE, u4_size); ps_view_ctxt->pu1_bits_buf_dynamic = ps_view_ctxt->pf_aligned_alloc(ps_view_ctxt->pv_mem_ctxt, 128, u4_size); RETURN_IF((NULL == ps_view_ctxt->pu1_bits_buf_dynamic), IV_FAIL); memset(ps_view_ctxt->pu1_bits_buf_dynamic, 0, u4_size); ps_view_ctxt->u4_dynamic_bits_buf_size = u4_size; return IV_SUCCESS; }