/****************************************************************************** * * 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 */ #include "iv_datatypedef.h" #include "iv.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_globals.h" #include "impeg2_mem_func.h" #include "impeg2_format_conv.h" #include "impeg2_macros.h" #include "ivd.h" #include "impeg2d.h" #include "impeg2d_bitstream.h" #include "impeg2d_structs.h" #include "impeg2d_vld_tables.h" #include "impeg2d_vld.h" #include "impeg2d_pic_proc.h" #include "impeg2d_debug.h" #include "impeg2d_globals.h" #include "impeg2d_mv_dec.h" /******************************************************************************* * Function Name : impeg2d_dec_i_mb_params * * Description : Decoding I MB parameters. * * Arguments : * dec : Decoder state * stream : Bitstream * * Values Returned : None *******************************************************************************/ void impeg2d_dec_i_mb_params(dec_state_t *ps_dec) { UWORD16 u2_next_bits; UWORD16 u2_bits_to_flush; stream_t *ps_stream = &ps_dec->s_bit_stream; /*-----------------------------------------------------------------------*/ /* Flush the MBAddrIncr Bit */ /* */ /* Since we are not supporting scalable modes there won't be skipped */ /* macroblocks in I-Picture and the MBAddrIncr will always be 1, */ /* The MBAddrIncr can never be greater than 1 for the simple and main */ /* profile MPEG2. */ /*-----------------------------------------------------------------------*/ if(impeg2d_bit_stream_nxt(ps_stream,1) == 1) //Making sure the increment is one. { impeg2d_bit_stream_flush(ps_stream,1); } else if(ps_dec->u2_first_mb && ps_dec->u2_mb_x) { WORD32 i4_mb_add_inc = impeg2d_get_mb_addr_incr(ps_stream); //VOLParams->FirstInSlice = 0; /****************************************************************/ /* Section 6.3.17 */ /* The first MB of a slice cannot be skipped */ /* But the mb_addr_incr can be > 1, because at the beginning of */ /* a slice, it indicates the offset from the last MB in the */ /* previous row. Hence for the first slice in a row, the */ /* mb_addr_incr needs to be 1. */ /****************************************************************/ /* MB_x is set to zero whenever MB_y changes. */ ps_dec->u2_mb_x = i4_mb_add_inc - 1; ps_dec->u2_mb_x = MIN(ps_dec->u2_mb_x, (ps_dec->u2_num_horiz_mb - 1)); } /*-----------------------------------------------------------------------*/ /* Decode the macroblock_type, dct_type and quantiser_scale_code */ /* */ /* macroblock_type 2 bits [can be either 1 or 01] */ /* dct_type 1 bit */ /* quantiser_scale_code 5 bits */ /*-----------------------------------------------------------------------*/ u2_next_bits = impeg2d_bit_stream_nxt(ps_stream,8); if(BIT(u2_next_bits,7) == 1) { /* read the dct_type if needed */ u2_bits_to_flush = 1; if(ps_dec->u2_read_dct_type) { u2_bits_to_flush++; ps_dec->u2_field_dct = BIT(u2_next_bits,6); } } else { u2_bits_to_flush = 7; /*------------------------------------------------------------------*/ /* read the dct_type if needed */ /*------------------------------------------------------------------*/ if(ps_dec->u2_read_dct_type) { u2_bits_to_flush++; ps_dec->u2_field_dct = BIT(u2_next_bits,5); } else { u2_next_bits >>= 1; } /*------------------------------------------------------------------*/ /* Quant scale code decoding */ /*------------------------------------------------------------------*/ { UWORD16 quant_scale_code; quant_scale_code = u2_next_bits & 0x1F; ps_dec->u1_quant_scale = (ps_dec->u2_q_scale_type) ? gau1_impeg2_non_linear_quant_scale[quant_scale_code] : (quant_scale_code << 1); } } impeg2d_bit_stream_flush(ps_stream,u2_bits_to_flush); /*************************************************************************/ /* Decoding of motion vectors if concealment motion vectors are present */ /*************************************************************************/ if(ps_dec->u2_concealment_motion_vectors) { if(ps_dec->u2_picture_structure != FRAME_PICTURE) impeg2d_bit_stream_flush(ps_stream,1); impeg2d_dec_mv(ps_stream,ps_dec->ai2_pred_mv[FORW][FIRST],ps_dec->ai2_mv[FORW][FIRST], ps_dec->au2_f_code[FORW],0,0); /* Flush the marker bit */ if(0 == (impeg2d_bit_stream_get(ps_stream,1))) { /* Ignore marker bit error */ } } ps_dec->u2_first_mb = 0; return; } /******************************************************************************* * Function Name : impeg2d_dec_i_slice * * Description : Decodes I slice * * Arguments : * dec : Decoder state * * Values Returned : None *******************************************************************************/ IMPEG2D_ERROR_CODES_T impeg2d_dec_i_slice(dec_state_t *ps_dec) { WORD16 *pi2_vld_out; UWORD32 i; yuv_buf_t *ps_cur_frm_buf = &ps_dec->s_cur_frm_buf; UWORD32 u4_frame_width = ps_dec->u2_frame_width; UWORD32 u4_frm_offset = 0; UWORD8 *pu1_out_p; IMPEG2D_ERROR_CODES_T e_error = (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE; pi2_vld_out = ps_dec->ai2_vld_buf; if(ps_dec->u2_picture_structure != FRAME_PICTURE) { u4_frame_width <<= 1; if(ps_dec->u2_picture_structure == BOTTOM_FIELD) { u4_frm_offset = ps_dec->u2_frame_width; } } do { UWORD32 u4_x_offset,u4_y_offset; UWORD32 u4_blk_pos; UWORD32 u4_x_dst_offset = 0; UWORD32 u4_y_dst_offset = 0; IMPEG2D_TRACE_MB_START(ps_dec->u2_mb_x, ps_dec->u2_mb_y); impeg2d_dec_i_mb_params(ps_dec); u4_x_dst_offset = u4_frm_offset + (ps_dec->u2_mb_x << 4); u4_y_dst_offset = (ps_dec->u2_mb_y << 4) * u4_frame_width; pu1_out_p = ps_cur_frm_buf->pu1_y + u4_x_dst_offset + u4_y_dst_offset; for(i = 0; i < NUM_LUMA_BLKS; ++i) { e_error = ps_dec->pf_vld_inv_quant(ps_dec, pi2_vld_out, ps_dec->pu1_inv_scan_matrix, 1, Y_LUMA, 0); if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error) { return e_error; } u4_x_offset = gai2_impeg2_blk_x_off[i]; if(ps_dec->u2_field_dct == 0) u4_y_offset = gai2_impeg2_blk_y_off_frm[i] ; else u4_y_offset = gai2_impeg2_blk_y_off_fld[i] ; u4_blk_pos = u4_y_offset * u4_frame_width + u4_x_offset; IMPEG2D_IDCT_INP_STATISTICS(pi2_vld_out, ps_dec->u4_non_zero_cols, ps_dec->u4_non_zero_rows); PROFILE_DISABLE_IDCT_IF0 { WORD32 i4_idx; i4_idx = 1; if(1 == (ps_dec->u4_non_zero_cols | ps_dec->u4_non_zero_rows)) i4_idx = 0; ps_dec->pf_idct_recon[i4_idx * 2 + ps_dec->i4_last_value_one](pi2_vld_out, ps_dec->ai2_idct_stg1, (UWORD8 *)gau1_impeg2_zerobuf, pu1_out_p + u4_blk_pos, 8, 8, u4_frame_width << ps_dec->u2_field_dct, ~ps_dec->u4_non_zero_cols, ~ps_dec->u4_non_zero_rows); } } /* For U and V blocks, divide the x and y offsets by 2. */ u4_x_dst_offset >>= 1; u4_y_dst_offset >>= 2; /* In case of chrominance blocks the DCT will be frame DCT */ /* i = 0, U component and */ e_error = ps_dec->pf_vld_inv_quant(ps_dec, pi2_vld_out, ps_dec->pu1_inv_scan_matrix, 1, U_CHROMA, 0); if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error) { return e_error; } pu1_out_p = ps_cur_frm_buf->pu1_u + u4_x_dst_offset + u4_y_dst_offset; IMPEG2D_IDCT_INP_STATISTICS(pi2_vld_out, ps_dec->u4_non_zero_cols, ps_dec->u4_non_zero_rows); PROFILE_DISABLE_IDCT_IF0 { WORD32 i4_idx; i4_idx = 1; if(1 == (ps_dec->u4_non_zero_cols | ps_dec->u4_non_zero_rows)) i4_idx = 0; ps_dec->pf_idct_recon[i4_idx * 2 + ps_dec->i4_last_value_one](pi2_vld_out, ps_dec->ai2_idct_stg1, (UWORD8 *)gau1_impeg2_zerobuf, pu1_out_p, 8, 8, u4_frame_width >> 1, ~ps_dec->u4_non_zero_cols, ~ps_dec->u4_non_zero_rows); } /* Write the idct_out block to the current frame dec->curFrame*/ /* In case of field DCT type, write to alternate lines */ e_error = ps_dec->pf_vld_inv_quant(ps_dec, pi2_vld_out, ps_dec->pu1_inv_scan_matrix, 1, V_CHROMA, 0); if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error) { return e_error; } pu1_out_p = ps_cur_frm_buf->pu1_v + u4_x_dst_offset + u4_y_dst_offset; IMPEG2D_IDCT_INP_STATISTICS(pi2_vld_out, ps_dec->u4_non_zero_cols, ps_dec->u4_non_zero_rows); PROFILE_DISABLE_IDCT_IF0 { WORD32 i4_idx; i4_idx = 1; if(1 == (ps_dec->u4_non_zero_cols | ps_dec->u4_non_zero_rows)) i4_idx = 0; ps_dec->pf_idct_recon[i4_idx * 2 + ps_dec->i4_last_value_one](pi2_vld_out, ps_dec->ai2_idct_stg1, (UWORD8 *)gau1_impeg2_zerobuf, pu1_out_p, 8, 8, u4_frame_width >> 1, ~ps_dec->u4_non_zero_cols, ~ps_dec->u4_non_zero_rows); } ps_dec->u2_num_mbs_left--; ps_dec->u2_mb_x++; if(ps_dec->s_bit_stream.u4_offset > ps_dec->s_bit_stream.u4_max_offset) { return IMPEG2D_BITSTREAM_BUFF_EXCEEDED_ERR; } else if (ps_dec->u2_mb_x == ps_dec->u2_num_horiz_mb) { ps_dec->u2_mb_x = 0; ps_dec->u2_mb_y++; } } while(ps_dec->u2_num_mbs_left != 0 && impeg2d_bit_stream_nxt(&ps_dec->s_bit_stream,23) != 0x0); return e_error; }