| /****************************************************************************** |
| * |
| * 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 "impeg2_defs.h" |
| #include "impeg2_globals.h" |
| #include "impeg2_platform_macros.h" |
| #include "impeg2_inter_pred.h" |
| #include "impeg2_idct.h" |
| #include "impeg2_mem_func.h" |
| #include "impeg2_format_conv.h" |
| #include "impeg2_disp_mgr.h" |
| #include "impeg2_buf_mgr.h" |
| |
| #include "impeg2d.h" |
| #include "impeg2d_bitstream.h" |
| #include "impeg2d_structs.h" |
| #include "impeg2d_vld.h" |
| #include "impeg2d_vld_tables.h" |
| |
| #define BLK_SIZE 8 |
| #define LUMA_BLK_SIZE (2 * (BLK_SIZE)) |
| #define CHROMA_BLK_SIZE (BLK_SIZE) |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : impeg2d_get_luma_dc_diff */ |
| /* */ |
| /* Description : Decode the DC differential value from the bitstream for */ |
| /* luma block */ |
| /* */ |
| /* Inputs : stream - Input stream */ |
| /* */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Decode the vlc for dc_diff */ |
| /* */ |
| /* Outputs : dc_diff - dc differential used in dc prediction */ |
| /* */ |
| /* Returns : dc_diff - dc differential used in dc prediction */ |
| /* */ |
| /* Issues : None */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes */ |
| /* 14 09 2005 Harish M First Version */ |
| /* */ |
| /*****************************************************************************/ |
| WORD16 impeg2d_get_luma_dc_diff(stream_t *ps_stream) |
| { |
| UWORD16 u2_dc_size; |
| WORD16 i2_dc_diff; |
| |
| u2_dc_size = impeg2d_dec_vld_symbol(ps_stream,gai2_impeg2d_dct_dc_size[0], |
| MPEG2_DCT_DC_LUMA_SIZE_LEN) + |
| MPEG2_DCT_DC_SIZE_OFFSET; |
| if (u2_dc_size != 0) |
| { |
| i2_dc_diff = impeg2d_bit_stream_get(ps_stream,u2_dc_size); |
| if ((i2_dc_diff & (1 << (u2_dc_size - 1))) == 0) |
| i2_dc_diff -= (1 << u2_dc_size) - 1; |
| } |
| else |
| { |
| i2_dc_diff = 0; |
| } |
| return i2_dc_diff; |
| } |
| |
| /*****************************************************************************/ |
| /* */ |
| /* Function Name : impeg2d_get_chroma_dc_diff */ |
| /* */ |
| /* Description : Decode the DC differential value from the bitstream for */ |
| /* chroma block */ |
| /* */ |
| /* Inputs : stream - Input stream */ |
| /* */ |
| /* Globals : None */ |
| /* */ |
| /* Processing : Decode the vlc for dc_diff */ |
| /* */ |
| /* Outputs : dc_diff - dc differential used in dc prediction */ |
| /* */ |
| /* Returns : dc_diff - dc differential used in dc prediction */ |
| /* */ |
| /* Issues : None */ |
| /* */ |
| /* Revision History: */ |
| /* */ |
| /* DD MM YYYY Author(s) Changes */ |
| /* 14 09 2005 Harish M First Version */ |
| /* */ |
| /*****************************************************************************/ |
| WORD16 impeg2d_get_chroma_dc_diff(stream_t *ps_stream) |
| { |
| UWORD16 u2_dc_size; |
| WORD16 i2_dc_diff; |
| u2_dc_size = impeg2d_dec_vld_symbol(ps_stream,gai2_impeg2d_dct_dc_size[1], |
| MPEG2_DCT_DC_CHROMA_SIZE_LEN) + |
| MPEG2_DCT_DC_SIZE_OFFSET; |
| if (u2_dc_size != 0) |
| { |
| i2_dc_diff = impeg2d_bit_stream_get(ps_stream,u2_dc_size); |
| if ((i2_dc_diff & (1 << (u2_dc_size - 1))) == 0) |
| i2_dc_diff -= (1 << u2_dc_size) - 1; |
| } |
| else |
| { |
| i2_dc_diff = 0; |
| } |
| return i2_dc_diff; |
| } |
| /******************************************************************************* |
| * Function Name : impeg2d_dec_d_slice |
| * |
| * Description : Decodes I slice |
| * |
| * Arguments : |
| * dec : Decoder state |
| * |
| * Values Returned : None |
| *******************************************************************************/ |
| IMPEG2D_ERROR_CODES_T impeg2d_dec_d_slice(dec_state_t *ps_dec) |
| { |
| UWORD32 i; |
| yuv_buf_t *ps_cur_frm_buf = &ps_dec->s_cur_frm_buf; |
| |
| stream_t *ps_stream = &ps_dec->s_bit_stream; |
| UWORD8 *pu1_vld_buf; |
| |
| WORD16 i2_dc_diff; |
| UWORD32 u4_frame_width = ps_dec->u2_frame_width; |
| UWORD32 u4_frm_offset = 0; |
| 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; |
| WORD16 i2_dc_val; |
| |
| UWORD32 u4_dst_x_offset = u4_frm_offset + (ps_dec->u2_mb_x << 4); |
| UWORD32 u4_dst_y_offset = (ps_dec->u2_mb_y << 4) * u4_frame_width; |
| UWORD8 *pu1_vld_buf8 = ps_cur_frm_buf->pu1_y + u4_dst_x_offset + u4_dst_y_offset; |
| UWORD32 u4_dst_wd = u4_frame_width; |
| /*------------------------------------------------------------------*/ |
| /* Discard the Macroblock stuffing in case of MPEG-1 stream */ |
| /*------------------------------------------------------------------*/ |
| while(impeg2d_bit_stream_nxt(ps_stream,MB_STUFFING_CODE_LEN) == MB_STUFFING_CODE && |
| ps_stream->u4_offset < ps_stream->u4_max_offset) |
| impeg2d_bit_stream_flush(ps_stream,MB_STUFFING_CODE_LEN); |
| |
| /*------------------------------------------------------------------*/ |
| /* Flush 2 bits from bitstream [MB_Type and MacroBlockAddrIncrement]*/ |
| /*------------------------------------------------------------------*/ |
| impeg2d_bit_stream_flush(ps_stream,1); |
| |
| if(impeg2d_bit_stream_get(ps_stream, 1) != 0x01) |
| { |
| /* Ignore and continue decoding. */ |
| } |
| |
| /* Process LUMA blocks of the MB */ |
| for(i = 0; i < NUM_LUMA_BLKS; ++i) |
| { |
| |
| u4_x_offset = gai2_impeg2_blk_x_off[i]; |
| u4_y_offset = gai2_impeg2_blk_y_off_frm[i] ; |
| u4_blk_pos = (u4_y_offset * u4_dst_wd) + u4_x_offset; |
| pu1_vld_buf = pu1_vld_buf8 + u4_blk_pos; |
| |
| i2_dc_diff = impeg2d_get_luma_dc_diff(ps_stream); |
| i2_dc_val = ps_dec->u2_def_dc_pred[Y_LUMA] + i2_dc_diff; |
| ps_dec->u2_def_dc_pred[Y_LUMA] = i2_dc_val; |
| i2_dc_val = CLIP_U8(i2_dc_val); |
| |
| ps_dec->pf_memset_8bit_8x8_block(pu1_vld_buf, i2_dc_val, u4_dst_wd); |
| } |
| |
| |
| |
| /* Process U block of the MB */ |
| |
| u4_dst_x_offset >>= 1; |
| u4_dst_y_offset >>= 2; |
| u4_dst_wd >>= 1; |
| pu1_vld_buf = ps_cur_frm_buf->pu1_u + u4_dst_x_offset + u4_dst_y_offset; |
| i2_dc_diff = impeg2d_get_chroma_dc_diff(ps_stream); |
| i2_dc_val = ps_dec->u2_def_dc_pred[U_CHROMA] + i2_dc_diff; |
| ps_dec->u2_def_dc_pred[U_CHROMA] = i2_dc_val; |
| i2_dc_val = CLIP_U8(i2_dc_val); |
| ps_dec->pf_memset_8bit_8x8_block(pu1_vld_buf, i2_dc_val, u4_dst_wd); |
| |
| |
| /* Process V block of the MB */ |
| |
| pu1_vld_buf = ps_cur_frm_buf->pu1_v + u4_dst_x_offset + u4_dst_y_offset; |
| i2_dc_diff = impeg2d_get_chroma_dc_diff(ps_stream); |
| i2_dc_val = ps_dec->u2_def_dc_pred[V_CHROMA] + i2_dc_diff; |
| ps_dec->u2_def_dc_pred[V_CHROMA] = i2_dc_val; |
| i2_dc_val = CLIP_U8(i2_dc_val); |
| ps_dec->pf_memset_8bit_8x8_block(pu1_vld_buf, i2_dc_val, u4_dst_wd); |
| |
| /* Common MB processing Steps */ |
| |
| |
| 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++; |
| |
| } |
| |
| /* Flush end of macro block */ |
| impeg2d_bit_stream_flush(ps_stream,1); |
| } |
| while(ps_dec->u2_num_mbs_left != 0 && impeg2d_bit_stream_nxt(&ps_dec->s_bit_stream,23) != 0x0); |
| return (IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE; |
| }/* End of impeg2d_dec_d_slice() */ |