diff options
| author | Xin Li <delphij@google.com> | 2017-12-06 11:51:53 -0800 |
|---|---|---|
| committer | Xin Li <delphij@google.com> | 2017-12-06 14:24:47 -0800 |
| commit | 458d7f1d066fafd3da8dfa910ba1c08246ac3d41 (patch) | |
| tree | bbb887b13073ec48d19fb496ca75fb4f6694db87 | |
| parent | 0f4d331bb1b0d06c309d3565194c1670eeeffe84 (diff) | |
| parent | 579418c7ee3e522a00f92fa06e01143098123c85 (diff) | |
| download | platform_external_libmpeg2-o-mr1-iot-preview-8.tar.gz platform_external_libmpeg2-o-mr1-iot-preview-8.tar.bz2 platform_external_libmpeg2-o-mr1-iot-preview-8.zip | |
DO NOT MERGE: Merge Oreo MR1 into masterandroid-wear-p-preview-2android-wear-8.0.0_r1android-p-preview-5android-p-preview-4android-p-preview-3android-p-preview-2android-p-preview-1android-o-mr1-iot-release-1.0.2android-o-mr1-iot-release-1.0.1android-o-mr1-iot-release-1.0.0android-o-mr1-iot-preview-8android-o-mr1-iot-preview-7android-n-iot-release-smart-display-r2android-n-iot-release-smart-displayandroid-n-iot-release-polk-at1android-n-iot-release-lg-thinq-wk7o-mr1-iot-preview-8o-mr1-iot-preview-7
Exempt-From-Owner-Approval: Changes already landed internally
Change-Id: Id0ae9caf63e21fd4e37d6692f71f7e65d9f4b711
| -rw-r--r-- | Android.bp | 2 | ||||
| -rw-r--r-- | decoder/impeg2d_api_main.c | 10 | ||||
| -rw-r--r-- | decoder/impeg2d_bitstream.c | 20 | ||||
| -rw-r--r-- | decoder/impeg2d_dec_hdr.c | 57 | ||||
| -rw-r--r-- | decoder/impeg2d_decoder.c | 12 | ||||
| -rw-r--r-- | decoder/impeg2d_mc.c | 2 | ||||
| -rw-r--r-- | decoder/impeg2d_pnb_pic.c | 35 | ||||
| -rw-r--r-- | decoder/impeg2d_structs.h | 4 | ||||
| -rw-r--r-- | test/decoder/main.c | 6 |
9 files changed, 121 insertions, 27 deletions
@@ -1,5 +1,7 @@ cc_library_static { name: "libmpeg2dec", + vendor_available: true, + shared_libs: ["liblog", "libcutils"], cflags: [ "-D_LIB", diff --git a/decoder/impeg2d_api_main.c b/decoder/impeg2d_api_main.c index c0813c4..606a5dc 100644 --- a/decoder/impeg2d_api_main.c +++ b/decoder/impeg2d_api_main.c @@ -428,7 +428,11 @@ void impeg2d_fill_mem_rec(impeg2d_fill_mem_rec_ip_t *ps_ip, UWORD32 u4_deinterlace; UNUSED(u4_deinterlace); max_frm_width = ALIGN16(ps_ip->s_ivd_fill_mem_rec_ip_t.u4_max_frm_wd); - max_frm_height = ALIGN16(ps_ip->s_ivd_fill_mem_rec_ip_t.u4_max_frm_ht); + /* In error clips with field prediction, the mv may incorrectly refer to + * the last MB row, causing an out of bounds read access. Allocating 8 extra + * rows to handle this. Adding another extra row to handle half_y prediction. + */ + max_frm_height = ALIGN32(ps_ip->s_ivd_fill_mem_rec_ip_t.u4_max_frm_ht) + 9; max_frm_size = (max_frm_width * max_frm_height * 3) >> 1;/* 420 P */ @@ -1022,6 +1026,7 @@ IV_API_CALL_STATUS_T impeg2d_api_reset(iv_obj_t *ps_dechdl, ps_dec_state->u2_header_done = 0; /* Header decoding not done */ ps_dec_state->u4_frm_buf_stride = 0; + ps_dec_state->i4_pic_count = 0; ps_dec_state->u2_is_mpeg2 = 0; ps_dec_state->aps_ref_pics[0] = NULL; ps_dec_state->aps_ref_pics[1] = NULL; @@ -1876,6 +1881,7 @@ IV_API_CALL_STATUS_T impeg2d_api_init(iv_obj_t *ps_dechdl, ps_dec_state->pv_jobq_buf = ps_mem_rec->pv_base; ps_dec_state->i4_jobq_buf_size = ps_mem_rec->u4_mem_size; + u4_num_mem_rec++; ps_mem_rec++; if(u4_num_mem_rec > ps_dec_init_ip->s_ivd_init_ip_t.u4_num_mem_rec) @@ -1891,9 +1897,11 @@ IV_API_CALL_STATUS_T impeg2d_api_init(iv_obj_t *ps_dechdl, ps_dec_state->pv_deinterlacer_ctxt = ps_mem_rec->pv_base; + u4_num_mem_rec++; ps_mem_rec++; ps_dec_state->pu1_deint_fmt_buf = ps_mem_rec->pv_base; + u4_num_mem_rec++; ps_mem_rec++; diff --git a/decoder/impeg2d_bitstream.c b/decoder/impeg2d_bitstream.c index 36092e5..57a9e2f 100644 --- a/decoder/impeg2d_bitstream.c +++ b/decoder/impeg2d_bitstream.c @@ -191,21 +191,17 @@ INLINE UWORD8 impeg2d_bit_stream_get_bit(stream_t *ps_stream) INLINE void impeg2d_bit_stream_flush(void* pv_ctxt, UWORD32 u4_no_of_bits) { stream_t *ps_stream = (stream_t *)pv_ctxt; - if ((ps_stream->u4_offset + 64) < ps_stream->u4_max_offset) + + + if (ps_stream->u4_offset <= ps_stream->u4_max_offset) { + /* We have to flush the bytes even if the offset is equal to the maximum + * offset. This will ensure that a stream with an error exactly at the + * offset will not get stuck in an infinite loop - If we do not flush + * these bytes, then we keep feeding the erroneous bits. + */ FLUSH_BITS(ps_stream->u4_offset,ps_stream->u4_buf,ps_stream->u4_buf_nxt,u4_no_of_bits,ps_stream->pu4_buf_aligned) } - else - { - UWORD32 u4_temp; - - if (((ps_stream->u4_offset & 0x1f) + u4_no_of_bits) >= 32) - { - ps_stream->u4_buf = ps_stream->u4_buf_nxt; - ps_stream->u4_buf_nxt = 0; - } - ps_stream->u4_offset += u4_no_of_bits; - } return; } /****************************************************************************** diff --git a/decoder/impeg2d_dec_hdr.c b/decoder/impeg2d_dec_hdr.c index 19de4c8..aa3c70f 100644 --- a/decoder/impeg2d_dec_hdr.c +++ b/decoder/impeg2d_dec_hdr.c @@ -174,7 +174,16 @@ IMPEG2D_ERROR_CODES_T impeg2d_dec_seq_hdr(dec_state_t *ps_dec) } else { - if((u2_width > ps_dec->u2_create_max_width) + if (0 == ps_dec->i4_pic_count) + { + /* Decoder has not decoded a single frame since the last + * reset/init. This implies that we have two headers in the + * input stream. So, do not indicate a resolution change, since + * this can take the decoder into an infinite loop. + */ + return (IMPEG2D_ERROR_CODES_T) IMPEG2D_FRM_HDR_DECODE_ERR; + } + else if((u2_width > ps_dec->u2_create_max_width) || (u2_height > ps_dec->u2_create_max_height)) { IMPEG2D_ERROR_CODES_T e_error = IMPEG2D_UNSUPPORTED_DIMENSIONS; @@ -281,6 +290,8 @@ IMPEG2D_ERROR_CODES_T impeg2d_dec_seq_hdr(dec_state_t *ps_dec) IMPEG2D_ERROR_CODES_T impeg2d_dec_seq_ext(dec_state_t *ps_dec) { stream_t *ps_stream; + UWORD16 horizontal_value; + UWORD16 vertical_value; ps_stream = &ps_dec->s_bit_stream; @@ -330,11 +341,30 @@ IMPEG2D_ERROR_CODES_T impeg2d_dec_seq_ext(dec_state_t *ps_dec) if(impeg2d_bit_stream_get(ps_stream,2) != 0x1) return IMPEG2D_CHROMA_FMT_NOT_SUP; + /* Error resilience: store the 2 most significant bit in horizontal and vertical */ + /* variables.Use it only if adding them to the vertical and horizontal sizes */ + /* respectively, doesn't exceed the MAX_WD and MAX_HT supported by the application.*/ + + /* Read the 2 most significant bits from horizontal_size */ - ps_dec->u2_horizontal_size += (impeg2d_bit_stream_get(ps_stream,2) << 12); + horizontal_value = (impeg2d_bit_stream_get(ps_stream,2) << 12); /* Read the 2 most significant bits from vertical_size */ - ps_dec->u2_vertical_size += (impeg2d_bit_stream_get(ps_stream,2) << 12); + vertical_value = (impeg2d_bit_stream_get(ps_stream,2) << 12); + + /* Error resilience: The height and width should not be more than the*/ + /*max height and width the application can support*/ + if(ps_dec->u2_create_max_height < (ps_dec->u2_vertical_size + vertical_value)) + { + return (IMPEG2D_ERROR_CODES_T) IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED; + } + + if(ps_dec->u2_create_max_width < (ps_dec->u2_horizontal_size + horizontal_value)) + { + return (IMPEG2D_ERROR_CODES_T) IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED; + } + ps_dec->u2_vertical_size += vertical_value; + ps_dec->u2_horizontal_size += horizontal_value; /*-----------------------------------------------------------------------*/ /* Flush the following as they are not used now */ @@ -915,7 +945,7 @@ void impeg2d_dec_pic_data_thread(dec_state_t *ps_dec) { pu1_buf = ps_dec->pu1_inp_bits_buf + s_job.i4_bistream_ofst; impeg2d_bit_stream_init(&(ps_dec->s_bit_stream), pu1_buf, - (ps_dec->u4_num_inp_bytes - s_job.i4_bistream_ofst) + 8); + (ps_dec->u4_num_inp_bytes - s_job.i4_bistream_ofst)); i4_cur_row = s_job.i2_start_mb_y; ps_dec->i4_start_mb_y = s_job.i2_start_mb_y; ps_dec->i4_end_mb_y = s_job.i2_end_mb_y; @@ -957,6 +987,11 @@ void impeg2d_dec_pic_data_thread(dec_state_t *ps_dec) if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error) { impeg2d_next_start_code(ps_dec); + if(ps_dec->s_bit_stream.u4_offset >= ps_dec->s_bit_stream.u4_max_offset) + { + ps_dec->u4_error_code = IMPEG2D_BITSTREAM_BUFF_EXCEEDED_ERR; + return; + } } } @@ -1071,6 +1106,7 @@ static WORD32 impeg2d_init_thread_dec_ctxt(dec_state_t *ps_dec, ps_dec_thd->u2_mb_x = 0; ps_dec_thd->u2_mb_y = 0; ps_dec_thd->u2_is_mpeg2 = ps_dec->u2_is_mpeg2; + ps_dec_thd->i4_pic_count = ps_dec->i4_pic_count; ps_dec_thd->u2_frame_width = ps_dec->u2_frame_width; ps_dec_thd->u2_frame_height = ps_dec->u2_frame_height; ps_dec_thd->u2_picture_width = ps_dec->u2_picture_width; @@ -1343,8 +1379,6 @@ void impeg2d_dec_pic_data(dec_state_t *ps_dec) WORD32 i; dec_state_multi_core_t *ps_dec_state_multi_core; - UWORD32 u4_error_code; - dec_state_t *ps_dec_thd; WORD32 i4_status; WORD32 i4_min_mb_y; @@ -1352,7 +1386,6 @@ void impeg2d_dec_pic_data(dec_state_t *ps_dec) /* Resetting the MB address and MB coordinates at the start of the Frame */ ps_dec->u2_mb_x = ps_dec->u2_mb_y = 0; - u4_error_code = 0; ps_dec_state_multi_core = ps_dec->ps_dec_state_multi_core; impeg2d_get_slice_pos(ps_dec_state_multi_core); @@ -1396,8 +1429,6 @@ void impeg2d_dec_pic_data(dec_state_t *ps_dec) } } - ps_dec->u4_error_code = u4_error_code; - } /******************************************************************************* * @@ -1731,6 +1762,7 @@ IMPEG2D_ERROR_CODES_T impeg2d_process_video_bit_stream(dec_state_t *ps_dec) else if((ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset) && (u4_next_bits == PICTURE_START_CODE)) { + ps_dec->i4_pic_count++; e_error = impeg2d_dec_pic_hdr(ps_dec); if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error) @@ -1747,7 +1779,11 @@ IMPEG2D_ERROR_CODES_T impeg2d_process_video_bit_stream(dec_state_t *ps_dec) { return e_error; } - impeg2d_pre_pic_dec_proc(ps_dec); + e_error = impeg2d_pre_pic_dec_proc(ps_dec); + if ((IMPEG2D_ERROR_CODES_T) IVD_ERROR_NONE != e_error) + { + return e_error; + } impeg2d_dec_pic_data(ps_dec); impeg2d_post_pic_dec_proc(ps_dec); u4_start_code_found = 1; @@ -1819,6 +1855,7 @@ IMPEG2D_ERROR_CODES_T impeg2d_process_video_bit_stream(dec_state_t *ps_dec) else if ((impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN) == PICTURE_START_CODE) && (ps_dec->s_bit_stream.u4_offset < ps_dec->s_bit_stream.u4_max_offset)) { + ps_dec->i4_pic_count++; e_error = impeg2d_dec_pic_hdr(ps_dec); if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error) diff --git a/decoder/impeg2d_decoder.c b/decoder/impeg2d_decoder.c index fa88bb5..e4ff79c 100644 --- a/decoder/impeg2d_decoder.c +++ b/decoder/impeg2d_decoder.c @@ -98,12 +98,17 @@ void impeg2d_dec_hdr(void *pv_dec,impeg2d_video_decode_ip_t *ps_ip, 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 - MIN_BUFFER_BYTES_AT_EOS; + } impeg2d_bit_stream_init(&(ps_dec->s_bit_stream),ps_ip->s_ivd_video_decode_ip_t.pv_stream_buffer, - ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes); + u4_size); { { @@ -189,12 +194,15 @@ void impeg2d_dec_frm(void *pv_dec,impeg2d_video_decode_ip_t *ps_ip, 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 - MIN_BUFFER_BYTES_AT_EOS; + } ps_dec->pu1_inp_bits_buf = ps_ip->s_ivd_video_decode_ip_t.pv_stream_buffer; ps_dec->u4_num_inp_bytes = u4_size; ps_stream = &ps_dec->s_bit_stream; - impeg2d_bit_stream_init(ps_stream,ps_ip->s_ivd_video_decode_ip_t.pv_stream_buffer,u4_size); /* @ */ /* Updating the bufferID */ diff --git a/decoder/impeg2d_mc.c b/decoder/impeg2d_mc.c index 79c5ef6..229579c 100644 --- a/decoder/impeg2d_mc.c +++ b/decoder/impeg2d_mc.c @@ -1260,7 +1260,7 @@ void impeg2d_mc_fullx_fully(void *pv_dec, for(i = 0; i < u4_blk_height; i++) { - memcpy(pu1_out, pu1_ref, u4_blk_width); + memmove(pu1_out, pu1_ref, u4_blk_width); pu1_ref += u4_ref_wid; pu1_out += u4_out_wid; } diff --git a/decoder/impeg2d_pnb_pic.c b/decoder/impeg2d_pnb_pic.c index 69277e5..a3ae436 100644 --- a/decoder/impeg2d_pnb_pic.c +++ b/decoder/impeg2d_pnb_pic.c @@ -77,6 +77,12 @@ WORD32 impeg2d_dec_p_mb_params(dec_state_t *ps_dec) else { u2_mb_addr_incr = impeg2d_get_mb_addr_incr(ps_stream); + + if(!u2_mb_addr_incr) + { + return IV_FAIL; + } + if(0 == ps_dec->u2_first_mb) { /****************************************************************/ @@ -116,6 +122,33 @@ WORD32 impeg2d_dec_p_mb_params(dec_state_t *ps_dec) impeg2d_dec_skip_mbs(ps_dec, (UWORD16)(u2_mb_addr_incr - 1)); } + else + { + + /****************************************************************/ + /* 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 = u2_mb_addr_incr - 1; + /* For error resilience */ + ps_dec->u2_mb_x = MIN(ps_dec->u2_mb_x, (ps_dec->u2_num_horiz_mb - 1)); + ps_dec->u2_num_mbs_left = ((ps_dec->u2_num_vert_mb - ps_dec->u2_mb_y) + * ps_dec->u2_num_horiz_mb) - ps_dec->u2_mb_x; + + /****************************************************************/ + /* mb_addr_incr is forced to 1 because in this decoder it is used */ + /* more as an indicator of the number of MBs skipped than the */ + /* as defined by the standard (Section 6.3.17) */ + /****************************************************************/ + u2_mb_addr_incr = 1; + ps_dec->u2_first_mb = 0; + + } } u4_next_word = (UWORD16)impeg2d_bit_stream_nxt(ps_stream,16); @@ -280,6 +313,8 @@ WORD32 impeg2d_dec_pnb_mb_params(dec_state_t *ps_dec) ps_dec->u2_mb_x = u2_mb_addr_incr - 1; /* For error resilience */ ps_dec->u2_mb_x = MIN(ps_dec->u2_mb_x, (ps_dec->u2_num_horiz_mb - 1)); + ps_dec->u2_num_mbs_left = ((ps_dec->u2_num_vert_mb - ps_dec->u2_mb_y) + * ps_dec->u2_num_horiz_mb) - ps_dec->u2_mb_x; /****************************************************************/ /* mb_addr_incr is forced to 1 because in this decoder it is used */ diff --git a/decoder/impeg2d_structs.h b/decoder/impeg2d_structs.h index 03cd54c..46538bf 100644 --- a/decoder/impeg2d_structs.h +++ b/decoder/impeg2d_structs.h @@ -40,6 +40,7 @@ Because of temporal dependency in deinterlacer one additional buffer is also nee #define DEC_ORDER 0 #define MAX_BITSTREAM_BUFFER_SIZE 2000 * 1024 +#define MIN_BUFFER_BYTES_AT_EOS 8 /* Flag to signal that buffer is held by deinterlacing */ #define MPEG2_BUF_MGR_DEINT (BUF_MGR_DISP << 1) @@ -331,6 +332,9 @@ typedef struct dec_state_struct_t UWORD8 *pu1_chroma_ref_buf[BUF_MGR_MAX_CNT]; ivd_out_bufdesc_t as_disp_buffers[BUF_MGR_MAX_CNT]; + /* Count the number of pictures decoded after init/reset */ + WORD32 i4_pic_count; + /* Flag to signal last coeff in a 8x8 block is one after mismatch contol */ WORD32 i4_last_value_one; diff --git a/test/decoder/main.c b/test/decoder/main.c index 7a6db46..cfce433 100644 --- a/test/decoder/main.c +++ b/test/decoder/main.c @@ -2414,9 +2414,13 @@ int main(WORD32 argc, CHAR *argv[]) if(ret != IV_SUCCESS) { + if (IMPEG2D_UNSUPPORTED_DIMENSIONS == s_video_decode_op.u4_error_code) + { + sprintf(ac_error_str, "\nSummary\nUnsupported Dimensions. Reinit decoder with width %d and height %d\n", s_video_decode_op.u4_pic_wd, s_video_decode_op.u4_pic_ht); + codec_exit(ac_error_str); + } sprintf(ac_error_str, "\nError in header decode %x", s_video_decode_op.u4_error_code); - // codec_exit(ac_error_str); } u4_num_bytes_dec = s_video_decode_op.u4_num_bytes_consumed; |
