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;