DO NOT MERGE: Merge Oreo MR1 into master
Exempt-From-Owner-Approval: Changes already landed internally
Change-Id: Id0ae9caf63e21fd4e37d6692f71f7e65d9f4b711
diff --git a/Android.bp b/Android.bp
index 98fa818..c5487c3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -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 @@
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 @@
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 @@
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 @@
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,20 +191,16 @@
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)
- {
- 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;
+
+ 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)
}
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 @@
}
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_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 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
/* 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 @@
}
}
- ps_dec->u4_error_code = u4_error_code;
-
}
/*******************************************************************************
*
@@ -1731,6 +1762,7 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
#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 @@
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 @@
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;