/****************************************************************************** * * Copyright (C) 2015 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 : mpeg2dec_api_utils.c */ /* */ /* */ /* Description : This file defines the API interface for MPEG2 Decoder*/ /* */ /* List of Functions : */ /* */ /* Issues / Problems : None */ /* */ /* Revision History : */ /* */ /* DD MM YYYY Author(s) Changes (Describe the changes made) */ /* 17 09 2007 Rajendra C Y Creation */ /* */ /*****************************************************************************/ /*****************************************************************************/ /* File Includes */ /*****************************************************************************/ /* System include files */ #include #include #include /* User include files */ #include "iv_datatypedef.h" #include "iv.h" #include "ivd.h" #include "ithread.h" #include "impeg2_job_queue.h" #include "impeg2_macros.h" #include "impeg2_buf_mgr.h" #include "impeg2_disp_mgr.h" #include "impeg2_defs.h" #include "impeg2_platform_macros.h" #include "impeg2_inter_pred.h" #include "impeg2_idct.h" #include "impeg2_format_conv.h" #include "impeg2_mem_func.h" #include "impeg2d.h" #include "impeg2d_api.h" #include "impeg2d_bitstream.h" #include "impeg2d_debug.h" #include "impeg2d_structs.h" #include "impeg2d_mc.h" #include "impeg2d_pic_proc.h" #include "impeg2d_dec_hdr.h" void impeg2d_next_start_code(dec_state_t *ps_dec); void impeg2d_next_code(dec_state_t *ps_dec, UWORD32 u4_start_code_val); /*****************************************************************************/ /* */ /* Function Name : impeg2d_dec_hdr */ /* */ /* Description : */ /* Inputs : */ /* Globals : */ /* Processing : */ /* Outputs : */ /* Returns : */ /* */ /* Issues : */ /* */ /* Revision History: */ /* */ /* DD MM YYYY Author(s) Changes (Describe the changes made) */ /* 17 09 2007 Rajendra C Y Draft */ /* */ /*****************************************************************************/ void impeg2d_dec_hdr(void *pv_dec,impeg2d_video_decode_ip_t *ps_ip, impeg2d_video_decode_op_t *ps_op) { UWORD32 u4_bits_read; dec_state_t *ps_dec; UWORD32 u4_size = ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes; ps_dec = (dec_state_t *)pv_dec; ps_op->s_ivd_video_decode_op_t.u4_error_code = 0; if (u4_size > MAX_BITSTREAM_BUFFER_SIZE) { u4_size = MAX_BITSTREAM_BUFFER_SIZE; } memcpy(ps_dec->pu1_input_buffer, ps_ip->s_ivd_video_decode_ip_t.pv_stream_buffer, u4_size); impeg2d_bit_stream_init(&(ps_dec->s_bit_stream), ps_dec->pu1_input_buffer, u4_size); { { IMPEG2D_ERROR_CODES_T e_error; e_error = impeg2d_process_video_header(ps_dec); if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error) { ps_op->s_ivd_video_decode_op_t.u4_error_code = e_error; u4_bits_read = impeg2d_bit_stream_num_bits_read(&ps_dec->s_bit_stream); ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = u4_bits_read>> 3; if(ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed > ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes) { ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes; } if(ps_op->s_ivd_video_decode_op_t.u4_error_code == 0) ps_op->s_ivd_video_decode_op_t.u4_error_code = e_error; if (IMPEG2D_UNSUPPORTED_DIMENSIONS == e_error) { ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = 0; ps_dec->u2_header_done = 0; ps_op->s_ivd_video_decode_op_t.u4_pic_ht = ps_dec->u2_reinit_max_height; ps_op->s_ivd_video_decode_op_t.u4_pic_wd = ps_dec->u2_reinit_max_width; } impeg2d_next_code(ps_dec, SEQUENCE_HEADER_CODE); return; } } ps_op->s_ivd_video_decode_op_t.u4_pic_ht = ps_dec->u2_vertical_size; ps_op->s_ivd_video_decode_op_t.u4_pic_wd = ps_dec->u2_horizontal_size; ps_op->s_ivd_video_decode_op_t.e_pic_type = IV_NA_FRAME; ps_op->s_ivd_video_decode_op_t.u4_error_code = IV_SUCCESS; u4_bits_read = impeg2d_bit_stream_num_bits_read(&ps_dec->s_bit_stream); ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = u4_bits_read>> 3; if(ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed > ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes) { ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes; } ps_op->s_ivd_video_decode_op_t.u4_frame_decoded_flag = 0; /* Set the stride */ if (0 == ps_dec->u4_frm_buf_stride) { ps_dec->u4_frm_buf_stride = ps_dec->u2_horizontal_size; } /* MOD */ ps_dec->u2_header_done = 1; } } /*****************************************************************************/ /* */ /* Function Name : impeg2d_dec_frm */ /* */ /* Description : */ /* Inputs : */ /* Globals : */ /* Processing : */ /* Outputs : */ /* Returns : */ /* */ /* Issues : */ /* */ /* Revision History: */ /* */ /* DD MM YYYY Author(s) Changes (Describe the changes made) */ /* 17 09 2007 Rajendra C Y Draft */ /* */ /*****************************************************************************/ void impeg2d_dec_frm(void *pv_dec,impeg2d_video_decode_ip_t *ps_ip, impeg2d_video_decode_op_t *ps_op) { stream_t *ps_stream; UWORD32 u4_size = ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes; dec_state_t *ps_dec; ps_dec = (dec_state_t *)pv_dec; ps_op->s_ivd_video_decode_op_t.u4_error_code = 0; ps_dec->i4_bytes_consumed = 0; ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = 0; IMPEG2D_FRM_NUM_SET(); if (u4_size > MAX_BITSTREAM_BUFFER_SIZE) { u4_size = MAX_BITSTREAM_BUFFER_SIZE; } memcpy(ps_dec->pu1_input_buffer, ps_ip->s_ivd_video_decode_ip_t.pv_stream_buffer, u4_size); ps_dec->pu1_inp_bits_buf = ps_dec->pu1_input_buffer; ps_dec->u4_num_inp_bytes = u4_size; ps_stream = &ps_dec->s_bit_stream; impeg2d_bit_stream_init(ps_stream, ps_dec->pu1_input_buffer, u4_size); /* @ */ /* Updating the bufferID */ ps_dec->u4_xdmBufID = ps_ip->s_ivd_video_decode_ip_t.u4_ts; { IMPEG2D_ERROR_CODES_T e_error; /* Process the Bitstream */ e_error = impeg2d_process_video_bit_stream(ps_dec); if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error) { ps_op->s_ivd_video_decode_op_t.u4_error_code = e_error; if ((IMPEG2D_ERROR_CODES_T) IVD_RES_CHANGED == e_error) { ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = ps_dec->i4_bytes_consumed; ps_dec->u2_header_done = 0; } else if (IMPEG2D_UNSUPPORTED_DIMENSIONS == e_error) { ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = 0; ps_dec->u2_header_done = 0; ps_op->s_ivd_video_decode_op_t.u4_pic_ht = ps_dec->u2_reinit_max_height; ps_op->s_ivd_video_decode_op_t.u4_pic_wd = ps_dec->u2_reinit_max_width; } else { if(ps_dec->i4_num_cores > 1 && 0 != ps_dec->i4_bytes_consumed) { /* If the number of bytes consumed has been updated by * get_slice_pos function, then use that. Else, the bytes consumed is * calculated from the offset. The bytes consumed for multi-thread runs * is updated only into ps_dec->i4_bytes_consumed if the get_slice_pos * function has been called. If that function has not run, then we have * encountered an error but still have to consume the bytes in header * decode, etc. */ ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = ps_dec->i4_bytes_consumed; } else { ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = (ps_dec->s_bit_stream.u4_offset + 7) >> 3; ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed -= ((size_t)ps_dec->s_bit_stream.pv_bs_buf & 3); } if(ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed > ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes) { ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes; } impeg2d_next_start_code(ps_dec); } if(ps_op->s_ivd_video_decode_op_t.u4_error_code == 0) { ps_op->s_ivd_video_decode_op_t.u4_error_code = e_error; } return; } } /**************************************************************************/ /* Remove the bytes left till next start code is encountered */ /**************************************************************************/ ps_op->s_ivd_video_decode_op_t.u4_error_code = IV_SUCCESS; if(ps_dec->i4_num_cores > 1 && 0 != ps_dec->i4_bytes_consumed) { /* If the number of bytes consumed has been updated by * get_slice_pos function, then use that. Else, the bytes consumed is * calculated from the offset. The bytes consumed for multi-thread runs * is updated only into ps_dec->i4_bytes_consumed if the get_slice_pos * function has been called. If that function has not run, then we have * encountered an error but still have to consume the bytes in header * decode, etc. */ ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = ps_dec->i4_bytes_consumed; } else { ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = (ps_dec->s_bit_stream.u4_offset + 7) >> 3; ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed -= ((size_t)ps_dec->s_bit_stream.pv_bs_buf & 3); } if(ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed > ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes) { ps_op->s_ivd_video_decode_op_t.u4_num_bytes_consumed = ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes; } ps_op->s_ivd_video_decode_op_t.u4_pic_ht = ps_dec->u2_vertical_size; ps_op->s_ivd_video_decode_op_t.u4_pic_wd = ps_dec->u2_horizontal_size; switch(ps_dec->e_pic_type) { case I_PIC : ps_op->s_ivd_video_decode_op_t.e_pic_type = IV_I_FRAME; break; case P_PIC: ps_op->s_ivd_video_decode_op_t.e_pic_type = IV_P_FRAME; break; case B_PIC: ps_op->s_ivd_video_decode_op_t.e_pic_type = IV_B_FRAME; break; case D_PIC: ps_op->s_ivd_video_decode_op_t.e_pic_type = IV_I_FRAME; break; default : ps_op->s_ivd_video_decode_op_t.e_pic_type = IV_FRAMETYPE_DEFAULT; break; } ps_op->s_ivd_video_decode_op_t.u4_frame_decoded_flag = ps_dec->i4_frame_decoded; ps_op->s_ivd_video_decode_op_t.u4_new_seq = 0; ps_op->s_ivd_video_decode_op_t.u4_error_code = ps_dec->u4_error_code; }