Snap for 9041660 from af313de0d71b817af6e37786a0a98b33b26b9c1b to mainline-extservices-release

Change-Id: Ie834feffdad9e3081ff2fda2a26bb25f5dd01cf5
diff --git a/FrameInfo.md b/FrameInfo.md
new file mode 100755
index 0000000..6351293
--- /dev/null
+++ b/FrameInfo.md
@@ -0,0 +1,18 @@
+## Frame Info exported from libAVC
+
+### Introduction
+QP and block type maps for H264 are defined for each 8x8 MB sub-block.
+The QP values defined as unsigned 8-bit numbers can range from <0, 51> and the block type can
+be INTER/INTRA/SKIP. Set the “u4_frame_info_enable” flag to enable encoder/decoder to populate
+and return the qp values and block type data in their output structures ih264e_video_encode_op_t
+and ih264d_video_decode_op_t respectively via pu1_8x8_blk_qp_map and pu1_8x8_blk_type_map.
+
+### Mapping to the frame
+Let’s say, a frame has a total of ‘n’ MBs (each 16x16). Since the QP and block type are defined
+for each 8x8 block, hence each MB will have 4 entries in the maps. Thus, a total of n x 4 entries
+for each frame. Qp and block type values for each 8x8 block are stored in raster scan order. Refer
+to ih264d.h for details.
+
+### Plugin/Application
+The encoder/decoder keeps the QP and block type map as a part of its output handle. The plugins can
+access these data through the output structure.
diff --git a/common/ih264_defs.h b/common/ih264_defs.h
index 9c84be9..d9fea26 100644
--- a/common/ih264_defs.h
+++ b/common/ih264_defs.h
@@ -276,6 +276,14 @@
     MAX_MBTYPES,
 }MBTYPES_T;
 
+/* Pred Modes */
+enum
+{
+    BLOCK_TYPE_INTER_MB = 0,
+    BLOCK_TYPE_INTRA_MB = 1,
+    BLOCK_TYPE_SKIP_MB  = 2
+};
+
 /* Prediction list */
 /* Do not change enum values */
 enum
diff --git a/decoder/ih264d.h b/decoder/ih264d.h
index fa9d7f1..bee6b34 100644
--- a/decoder/ih264d.h
+++ b/decoder/ih264d.h
@@ -79,6 +79,8 @@
 typedef enum {
 
     IH264D_VID_HDR_DEC_NUM_FRM_BUF_NOT_SUFFICIENT   = IVD_DUMMY_ELEMENT_FOR_CODEC_EXTENSIONS + 1,
+    IH264D_FRAME_INFO_OP_BUF_NULL,
+    IH264D_INSUFFICIENT_METADATA_BUFFER,
 
 }IH264D_ERROR_CODES_T;
 
@@ -109,6 +111,11 @@
 
 typedef struct {
     ivd_create_ip_t                         s_ivd_create_ip_t;
+
+    /**
+     * enable_frm_info
+     */
+    UWORD32                                 u4_enable_frame_info;
 }ih264d_create_ip_t;
 
 
@@ -124,11 +131,84 @@
 
 typedef struct {
     ivd_video_decode_ip_t                   s_ivd_video_decode_ip_t;
+
+    /**
+     * 8x8 block QP map size
+     */
+    UWORD32                                 u4_8x8_blk_qp_map_size;
+
+    /**
+     * 8x8 block QP map
+     */
+    UWORD8                                  *pu1_8x8_blk_qp_map;
+
+    /**
+     * 8x8 block type map size
+     */
+    UWORD32                                 u4_8x8_blk_type_map_size;
+
+    /**
+     * 8x8 block type map
+     */
+    UWORD8                                  *pu1_8x8_blk_type_map;
 }ih264d_video_decode_ip_t;
 
+/*****************************************************************************/
+/* QP and block type maps are defined for each 8x8 MB sub-block.             */
+/* QP can range from <0, 51> and block type can be INTER/INTRA/SKIP.         */
+/*                                                                           */
+/* Let’s say, a frame has a total of ‘m’ MBs (each 16x16). Since the QP      */
+/* and block type are defined for each 8x8 block, hence each MB has          */
+/* 4 entries giving m x 4 total entires for QP and block type map each.      */
+/*                                                                           */
+/* For example, for a frame of size 60x60 shown in the figure down, both     */
+/* maps (QP and MB type) have the same layout.                               */
+/* Each block represents an 8x8 sub-block. Both width and height are aligned */
+/* to next largest multiple of 8, 64 in this case.                           */
+/*                                                                           */
+/*     0     8     16    24    32    40    48    56   64                     */
+/*  0   ------------------------------------------------                     */
+/*     | 0th | 1st | 2nd | 3rd | 4th | 5th | 6th | 7th |                     */
+/*  8   ------------------------------------------------                     */
+/*     | 8th | 9th | 10th | -  |  -  | -   | -   |  -  |                     */
+/* 16   ------------------------------------------------                     */
+/*     |  -  |  -  |  -   | -  |  -  |  -  |  -  |  -  |                     */
+/* 24   ------------------------------------------------                     */
+/*     |  -  |  -  |  -   | -  |  -  |  -  |  -  |  -  |                     */
+/* 32   ------------------------------------------------                     */
+/*     |  -  |  -  |  -   | -  |  -  |  -  |  -  |  -  |                     */
+/* 40   ------------------------------------------------                     */
+/*     |  -  |  -  |  -   | -  |  -  |  -  |  -  |  -  |                     */
+/* 48   ------------------------------------------------                     */
+/*     |  -  |  -  |  -   | -  |  -  |  -  |  -  |  -  |                     */
+/* 56   ------------------------------------------------                     */
+/*     |  -  |  -  |  -   | -  |  -  |  -  |  -  |  -  |                     */
+/* 64   ------------------------------------------------                     */
+/*                                                                           */
+/*****************************************************************************/
 
 typedef struct{
     ivd_video_decode_op_t                   s_ivd_video_decode_op_t;
+
+    /**
+     * 8x8 block QP map size
+     */
+    UWORD32                                 u4_8x8_blk_qp_map_size;
+
+    /**
+     * 8x8 block QP map
+     */
+    UWORD8                                  *pu1_8x8_blk_qp_map;
+
+    /**
+     * 8x8 block type map size
+     */
+    UWORD32                                 u4_8x8_blk_type_map_size;
+
+    /**
+     * 8x8 block type map
+     */
+    UWORD8                                  *pu1_8x8_blk_type_map;
 }ih264d_video_decode_op_t;
 
 
diff --git a/decoder/ih264d_api.c b/decoder/ih264d_api.c
index 923c519..cb6462e 100644
--- a/decoder/ih264d_api.c
+++ b/decoder/ih264d_api.c
@@ -506,6 +506,20 @@
                 return (IV_FAIL);
             }
 
+            {
+                dec_struct_t *ps_dec = (dec_struct_t *)(ps_handle->pv_codec_handle);
+                if(ps_dec->u1_enable_mb_info)
+                {
+                    if(!ps_ip->pu1_8x8_blk_qp_map && !ps_ip->pu1_8x8_blk_type_map)
+                    {
+                        ps_op->s_ivd_video_decode_op_t.u4_error_code |= 1
+                                        << IVD_UNSUPPORTEDPARAM;
+                        ps_op->s_ivd_video_decode_op_t.u4_error_code |=
+                                        IH264D_FRAME_INFO_OP_BUF_NULL;
+                        return IV_FAIL;
+                    }
+                }
+            }
         }
             break;
 
@@ -1491,6 +1505,7 @@
         ps_dec->u4_share_disp_buf = 0;
     }
 
+    ps_dec->u1_enable_mb_info = ps_create_ip->u4_enable_frame_info;
     ps_dec->pf_aligned_alloc = pf_aligned_alloc;
     ps_dec->pf_aligned_free = pf_aligned_free;
     ps_dec->pv_mem_ctxt = pv_mem_ctxt;
@@ -2298,6 +2313,20 @@
 
     }
 
+    if(ps_dec->u1_enable_mb_info && (ps_dec->i4_header_decoded & DECODED_SPS_MASK))
+    {
+        UWORD32 blk_qp_map_size = ps_h264d_dec_ip->u4_8x8_blk_qp_map_size;
+        UWORD32 blk_type_map_size = ps_h264d_dec_ip->u4_8x8_blk_type_map_size;
+        UWORD32 blk_8x8_map_size = ps_dec->u4_total_mbs << 2;
+        if ((ps_h264d_dec_ip->pu1_8x8_blk_qp_map && blk_qp_map_size < blk_8x8_map_size) ||
+            (ps_h264d_dec_ip->pu1_8x8_blk_type_map && blk_type_map_size < blk_8x8_map_size))
+        {
+            ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
+            ps_dec_op->u4_error_code |= IH264D_INSUFFICIENT_METADATA_BUFFER;
+            return IV_FAIL;
+        }
+    }
+
     if(ps_dec->u1_flushfrm)
     {
         if(ps_dec->u1_init_dec_flag == 0)
@@ -2328,6 +2357,26 @@
             ps_dec->u4_fmt_conv_cur_row += ps_dec->u4_fmt_conv_num_rows;
             ps_dec->u4_output_present = 1;
 
+            if(ps_dec->u1_enable_mb_info)
+            {
+                UWORD32 disp_buf_id = ps_dec->s_disp_op.u4_disp_buf_id;
+                if(ps_h264d_dec_ip->pu1_8x8_blk_qp_map)
+                {
+                    ps_h264d_dec_op->pu1_8x8_blk_qp_map = ps_h264d_dec_ip->pu1_8x8_blk_qp_map;
+                    ps_h264d_dec_op->u4_8x8_blk_qp_map_size = ps_dec->u4_total_mbs << 2;
+                    ih264_memcpy(ps_h264d_dec_op->pu1_8x8_blk_qp_map,
+                        ps_dec->as_buf_id_info_map[disp_buf_id].pu1_qp_map,
+                        ps_dec->u4_total_mbs << 2);
+                }
+                if(ps_h264d_dec_ip->pu1_8x8_blk_type_map)
+                {
+                    ps_h264d_dec_op->pu1_8x8_blk_type_map = ps_h264d_dec_ip->pu1_8x8_blk_type_map;
+                    ps_h264d_dec_op->u4_8x8_blk_type_map_size = ps_dec->u4_total_mbs << 2;
+                    ih264_memcpy(ps_h264d_dec_op->pu1_8x8_blk_type_map,
+                        ps_dec->as_buf_id_info_map[disp_buf_id].pu1_mb_type_map,
+                        ps_dec->u4_total_mbs << 2);
+                }
+            }
         }
         ih264d_export_sei_params(&ps_dec_op->s_sei_decode_op, ps_dec);
 
@@ -2820,6 +2869,26 @@
 
     }
 
+    if(ps_dec->u1_enable_mb_info && ps_dec->u4_output_present)
+    {
+        UWORD32 disp_buf_id = ps_dec->s_disp_op.u4_disp_buf_id;
+        if(ps_h264d_dec_ip->pu1_8x8_blk_qp_map)
+        {
+            ps_h264d_dec_op->pu1_8x8_blk_qp_map = ps_h264d_dec_ip->pu1_8x8_blk_qp_map;
+            ps_h264d_dec_op->u4_8x8_blk_qp_map_size = ps_dec->u4_total_mbs << 2;
+            ih264_memcpy(ps_h264d_dec_op->pu1_8x8_blk_qp_map,
+                ps_dec->as_buf_id_info_map[disp_buf_id].pu1_qp_map,
+                ps_dec->u4_total_mbs << 2);
+        }
+        if(ps_h264d_dec_ip->pu1_8x8_blk_type_map)
+        {
+            ps_h264d_dec_op->pu1_8x8_blk_type_map = ps_h264d_dec_ip->pu1_8x8_blk_type_map;
+            ps_h264d_dec_op->u4_8x8_blk_type_map_size = ps_dec->u4_total_mbs << 2;
+            ih264_memcpy(ps_h264d_dec_op->pu1_8x8_blk_type_map,
+                ps_dec->as_buf_id_info_map[disp_buf_id].pu1_mb_type_map,
+                ps_dec->u4_total_mbs << 2);
+        }
+    }
 
     /*Data memory barrier instruction,so that yuv write by the library is complete*/
     DATA_SYNC();
diff --git a/decoder/ih264d_defs.h b/decoder/ih264d_defs.h
index aeb2520..894fc78 100644
--- a/decoder/ih264d_defs.h
+++ b/decoder/ih264d_defs.h
@@ -122,6 +122,9 @@
  *  greater than the allocated buffer size*/
 #define EXTRA_BS_OFFSET 16*16*2
 
+#define DECODED_SPS_MASK 1
+#define DECODED_PPS_MASK 2
+
 /**
  ***************************************************************************
  * Enum to hold various mem records being request
diff --git a/decoder/ih264d_dpb_mgr.c b/decoder/ih264d_dpb_mgr.c
index ce977d7..f5974ba 100644
--- a/decoder/ih264d_dpb_mgr.c
+++ b/decoder/ih264d_dpb_mgr.c
@@ -118,7 +118,7 @@
                           pic_buf_id,
                           BUF_MGR_REF);
     ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_mv_buf_mgr,
-                          ps_dec->au1_pic_buf_id_mv_buf_id_map[pic_buf_id],
+                          ps_dec->as_buf_id_info_map[pic_buf_id].mv_buf_id,
                           BUF_MGR_REF);
 }
 /*!
@@ -1413,7 +1413,7 @@
                               i,
                               BUF_MGR_REF);
         ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_mv_buf_mgr,
-                              ps_dec->au1_pic_buf_id_mv_buf_id_map[i],
+                              ps_dec->as_buf_id_info_map[i].mv_buf_id,
                               BUF_MGR_REF);
     }
 }
diff --git a/decoder/ih264d_mb_utils.c b/decoder/ih264d_mb_utils.c
index ded2756..213fbc8 100644
--- a/decoder/ih264d_mb_utils.c
+++ b/decoder/ih264d_mb_utils.c
@@ -32,6 +32,7 @@
  */
 #include <string.h>
 #include <stdlib.h>
+#include "ih264_defs.h"
 #include "ih264d_bitstrm.h"
 #include "ih264d_defs.h"
 #include "ih264d_debug.h"
@@ -1468,3 +1469,95 @@
 
 }
 
+/*
+ **************************************************************************
+ * \if Function name : ih264d_populate_mb_info_map \endif
+ *
+ * \brief
+ *     Populate mb info values for mbtype and qp map at 8x8 level for each MB
+ *
+ * \return
+ *    void
+ *
+ **************************************************************************
+ */
+void ih264d_populate_mb_info_map(dec_struct_t *ps_dec, dec_mb_info_t *ps_cur_mb_info,
+                                 UWORD16 u2_blk_x, UWORD16 u2_blk_y, UWORD8 u1_qp_val)
+{
+    UWORD16 stride = ps_dec->u2_frm_wd_in_mbs << 1;
+    UWORD8 *pu1_qp_map = ps_dec->as_buf_id_info_map[ps_dec->u1_pic_buf_id].pu1_qp_map;
+    UWORD8 *pu1_mb_type_map = ps_dec->as_buf_id_info_map[ps_dec->u1_pic_buf_id].pu1_mb_type_map;
+
+    UWORD8 cur_mb_type = ps_cur_mb_info->u1_mb_type;
+    UWORD8 mb_is_inter =
+        (cur_mb_type == P_MB || cur_mb_type == B_MB || cur_mb_type == SP_MB);
+    UWORD8 mb_type = mb_is_inter ? BLOCK_TYPE_INTER_MB : BLOCK_TYPE_INTRA_MB;
+    if(cur_mb_type == MB_SKIP) mb_type = BLOCK_TYPE_SKIP_MB;
+
+    // populate qp_map, mb_type_map for mbx, mby
+    // since we store values at 8x8 level, duplicate values for blocks while storing in map
+    if(ps_dec->ps_cur_slice->u1_mbaff_frame_flag)
+    {
+        UWORD8 bot_mb = ps_cur_mb_info->u1_topmb ? 0 : 1;
+        if(ps_cur_mb_info->u1_mb_field_decodingflag)
+        {
+            pu1_qp_map[u2_blk_x +     stride * ( u2_blk_y +      bot_mb)] =
+            pu1_qp_map[u2_blk_x + 1 + stride * ( u2_blk_y +      bot_mb)] =
+            pu1_qp_map[u2_blk_x +     stride * ((u2_blk_y + 2) + bot_mb)] =
+            pu1_qp_map[u2_blk_x + 1 + stride * ((u2_blk_y + 2) + bot_mb)] =
+                u1_qp_val;
+
+            pu1_mb_type_map[u2_blk_x +     stride * ( u2_blk_y +      bot_mb)] =
+            pu1_mb_type_map[u2_blk_x + 1 + stride * ( u2_blk_y +      bot_mb)] =
+            pu1_mb_type_map[u2_blk_x +     stride * ((u2_blk_y + 2) + bot_mb)] =
+            pu1_mb_type_map[u2_blk_x + 1 + stride * ((u2_blk_y + 2) + bot_mb)] =
+                mb_type;
+        }
+        else
+        {
+            pu1_qp_map[u2_blk_x +     stride * ( u2_blk_y +      (2 * bot_mb))] =
+            pu1_qp_map[u2_blk_x + 1 + stride * ( u2_blk_y +      (2 * bot_mb))] =
+            pu1_qp_map[u2_blk_x +     stride * ((u2_blk_y + 1) + (2 * bot_mb))] =
+            pu1_qp_map[u2_blk_x + 1 + stride * ((u2_blk_y + 1) + (2 * bot_mb))] =
+                u1_qp_val;
+
+            pu1_mb_type_map[u2_blk_x +     stride * ( u2_blk_y +      (2 * bot_mb))] =
+            pu1_mb_type_map[u2_blk_x + 1 + stride * ( u2_blk_y +      (2 * bot_mb))] =
+            pu1_mb_type_map[u2_blk_x +     stride * ((u2_blk_y + 1) + (2 * bot_mb))] =
+            pu1_mb_type_map[u2_blk_x + 1 + stride * ((u2_blk_y + 1) + (2 * bot_mb))] =
+                mb_type;
+        }
+    }
+    else
+    {
+        if(ps_dec->ps_cur_slice->u1_field_pic_flag)
+        {
+            UWORD8 bot_mb = ps_dec->ps_cur_slice->u1_bottom_field_flag;
+            pu1_qp_map[u2_blk_x +     stride * (2 *  u2_blk_y +      bot_mb)] =
+            pu1_qp_map[u2_blk_x + 1 + stride * (2 *  u2_blk_y +      bot_mb)] =
+            pu1_qp_map[u2_blk_x +     stride * (2 * (u2_blk_y + 1) + bot_mb)] =
+            pu1_qp_map[u2_blk_x + 1 + stride * (2 * (u2_blk_y + 1) + bot_mb)] =
+                u1_qp_val;
+
+            pu1_mb_type_map[u2_blk_x +     stride * (2 *  u2_blk_y +      bot_mb)] =
+            pu1_mb_type_map[u2_blk_x + 1 + stride * (2 *  u2_blk_y +      bot_mb)] =
+            pu1_mb_type_map[u2_blk_x +     stride * (2 * (u2_blk_y + 1) + bot_mb)] =
+            pu1_mb_type_map[u2_blk_x + 1 + stride * (2 * (u2_blk_y + 1) + bot_mb)] =
+                mb_type;
+        }
+        else
+        {
+            pu1_qp_map[u2_blk_x +     stride *  u2_blk_y     ] =
+            pu1_qp_map[u2_blk_x + 1 + stride *  u2_blk_y     ] =
+            pu1_qp_map[u2_blk_x +     stride * (u2_blk_y + 1)] =
+            pu1_qp_map[u2_blk_x + 1 + stride * (u2_blk_y + 1)] =
+                u1_qp_val;
+
+            pu1_mb_type_map[u2_blk_x +     stride *  u2_blk_y     ] =
+            pu1_mb_type_map[u2_blk_x + 1 + stride *  u2_blk_y     ] =
+            pu1_mb_type_map[u2_blk_x +     stride * (u2_blk_y + 1)] =
+            pu1_mb_type_map[u2_blk_x + 1 + stride * (u2_blk_y + 1)] =
+                mb_type;
+        }
+    }
+}
diff --git a/decoder/ih264d_mb_utils.h b/decoder/ih264d_mb_utils.h
index 158319a..25011f5 100644
--- a/decoder/ih264d_mb_utils.h
+++ b/decoder/ih264d_mb_utils.h
@@ -288,6 +288,12 @@
                                    const UWORD8 u1_end_of_row_next /* Next n-Mb End of Row Flag */
                                    );
 
+void ih264d_populate_mb_info_map(dec_struct_t *ps_dec,
+                                 dec_mb_info_t *ps_cur_mb_info,
+                                 UWORD16 u2_blk_x,
+                                 UWORD16 u2_blk_y,
+                                 UWORD8 u1_val);
+
 //void FillRandomData(UWORD8 *pu1_buf, WORD32 u4_bufSize);
 
 #endif /* _MB_UTILS_H_ */
diff --git a/decoder/ih264d_parse_headers.c b/decoder/ih264d_parse_headers.c
index 8f0cb40..dc11adb 100644
--- a/decoder/ih264d_parse_headers.c
+++ b/decoder/ih264d_parse_headers.c
@@ -1128,6 +1128,7 @@
 
     ps_dec->u2_pic_wd = u2_pic_wd;
     ps_dec->u2_pic_ht = u2_pic_ht;
+    ps_dec->u4_total_mbs = ps_seq->u2_total_num_of_mbs << (1 - ps_seq->u1_frame_mbs_only_flag);
 
     /* Determining the Width and Height of Frame from that of Picture */
     ps_dec->u2_frm_wd_y = u2_frm_wd_y;
diff --git a/decoder/ih264d_parse_islice.c b/decoder/ih264d_parse_islice.c
index 0b8111a..21c50ea 100644
--- a/decoder/ih264d_parse_islice.c
+++ b/decoder/ih264d_parse_islice.c
@@ -865,6 +865,12 @@
             ps_cur_deblk_mb->u1_mb_qp = ps_dec->u1_qp;
         }
 
+        if(ps_dec->u1_enable_mb_info)
+        {
+            ih264d_populate_mb_info_map(ps_dec, ps_cur_mb_info, ps_cur_mb_info->u2_mbx << 1,
+                                        ps_cur_mb_info->u2_mby << 1, ps_cur_deblk_mb->u1_mb_qp);
+        }
+
         uc_more_data_flag = MORE_RBSP_DATA(ps_bitstrm);
 
         if(u1_mbaff)
@@ -1084,6 +1090,12 @@
                 ps_cur_deblk_mb->u1_mb_qp = ps_dec->u1_qp;
             }
 
+            if(ps_dec->u1_enable_mb_info)
+            {
+                ih264d_populate_mb_info_map(ps_dec, ps_cur_mb_info, ps_cur_mb_info->u2_mbx << 1,
+                                            ps_cur_mb_info->u2_mby << 1, ps_cur_deblk_mb->u1_mb_qp);
+            }
+
             if(u1_mbaff)
             {
                 ih264d_update_mbaff_left_nnz(ps_dec, ps_cur_mb_info);
diff --git a/decoder/ih264d_parse_pslice.c b/decoder/ih264d_parse_pslice.c
index 77ea4b3..beb24d4 100644
--- a/decoder/ih264d_parse_pslice.c
+++ b/decoder/ih264d_parse_pslice.c
@@ -1003,6 +1003,12 @@
 
         }
 
+        if(ps_dec->u1_enable_mb_info)
+        {
+            ih264d_populate_mb_info_map(ps_dec, ps_cur_mb_info, ps_cur_mb_info->u2_mbx << 1,
+                                        ps_cur_mb_info->u2_mby << 1, ps_cur_deblk_mb->u1_mb_qp);
+        }
+
         if(u1_mbaff)
         {
             ih264d_update_mbaff_left_nnz(ps_dec, ps_cur_mb_info);
@@ -1354,6 +1360,12 @@
         }
         ps_cur_deblk_mb->u1_mb_qp = ps_dec->u1_qp;
 
+        if(ps_dec->u1_enable_mb_info)
+        {
+            ih264d_populate_mb_info_map(ps_dec, ps_cur_mb_info, ps_cur_mb_info->u2_mbx << 1,
+                                        ps_cur_mb_info->u2_mby << 1, ps_cur_deblk_mb->u1_mb_qp);
+        }
+
         if(u1_mbaff)
         {
             ih264d_update_mbaff_left_nnz(ps_dec, ps_cur_mb_info);
diff --git a/decoder/ih264d_parse_slice.c b/decoder/ih264d_parse_slice.c
index 12fbeeb..59d187e 100644
--- a/decoder/ih264d_parse_slice.c
+++ b/decoder/ih264d_parse_slice.c
@@ -320,7 +320,7 @@
                                   j,
                                   BUF_MGR_REF);
             ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_mv_buf_mgr,
-                                  ps_dec->au1_pic_buf_id_mv_buf_id_map[j],
+                                  ps_dec->as_buf_id_info_map[j].mv_buf_id,
                                   BUF_MGR_REF);
             ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
                                   j,
@@ -409,9 +409,36 @@
             ps_cur_pic = (pic_buffer_t *)ih264_buf_mgr_get_next_free(
                             (buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
                             &cur_pic_buf_id);
+
+            /* In case of IDR slices, if there is no free picture buffer, then release
+             * all buffers from display and reference
+             */
+            if((ps_cur_pic == NULL) && (ps_cur_slice->u1_nal_unit_type == IDR_SLICE_NAL))
+            {
+                WORD32 j;
+
+                for(j = 0; j < MAX_DISP_BUFS_NEW; j++)
+                {
+                    ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
+                                          j,
+                                          BUF_MGR_REF);
+                    ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_mv_buf_mgr,
+                                          ps_dec->as_buf_id_info_map[j].mv_buf_id,
+                                          BUF_MGR_REF);
+
+                    ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
+                                          j,
+                                          BUF_MGR_IO);
+                }
+                ps_cur_pic = (pic_buffer_t *)ih264_buf_mgr_get_next_free(
+                                (buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
+                                &cur_pic_buf_id);
+            }
+
             if(ps_cur_pic == NULL)
             {
                 ps_dec->i4_error_code = ERROR_UNAVAIL_PICBUF_T;
+                ps_dec->ps_dec_err_status->u1_err_flag |= REJECT_CUR_PIC;
                 return ERROR_UNAVAIL_PICBUF_T;
             }
             if(0 == ps_dec->u4_disp_buf_mapping[cur_pic_buf_id])
@@ -425,6 +452,7 @@
         if(ps_col_mv == NULL)
         {
             ps_dec->i4_error_code = ERROR_UNAVAIL_MVBUF_T;
+            ps_dec->ps_dec_err_status->u1_err_flag |= REJECT_CUR_PIC;
             return ERROR_UNAVAIL_MVBUF_T;
         }
 
@@ -434,7 +462,17 @@
         memcpy(&ps_cur_pic->s_sei_pic, ps_dec->ps_sei, sizeof(sei));
 
         ps_cur_pic->u1_mv_buf_id = cur_mv_buf_id;
-        ps_dec->au1_pic_buf_id_mv_buf_id_map[cur_pic_buf_id] = cur_mv_buf_id;
+        ps_dec->as_buf_id_info_map[cur_pic_buf_id].mv_buf_id = cur_mv_buf_id;
+        if(ps_dec->u1_enable_mb_info)
+        {
+            UWORD32 mb_info_map_size = ps_dec->u4_total_mbs << 2;
+            ps_dec->as_buf_id_info_map[cur_pic_buf_id].pu1_qp_map
+                = ps_dec->pu1_qp_map_base + cur_pic_buf_id * mb_info_map_size;
+            ps_dec->as_buf_id_info_map[cur_pic_buf_id].pu1_mb_type_map
+                = ps_dec->pu1_mb_type_map_base + cur_pic_buf_id * mb_info_map_size;
+            memset(ps_dec->as_buf_id_info_map[cur_pic_buf_id].pu1_qp_map, 0, mb_info_map_size);
+            memset(ps_dec->as_buf_id_info_map[cur_pic_buf_id].pu1_mb_type_map, 0, mb_info_map_size);
+        }
 
         ps_cur_pic->pu1_col_zero_flag = (UWORD8 *)ps_col_mv->pv_col_zero_flag;
         ps_cur_pic->ps_mv = (mv_pred_t *)ps_col_mv->pv_mv;
@@ -460,59 +498,6 @@
             *(ps_dec->ps_dpb_mgr->ps_mod_dpb[1][MAX_REF_BUFS]) = *ps_cur_pic;
         }
 
-        if(!ps_dec->ps_cur_pic)
-        {
-            WORD32 j;
-            H264_DEC_DEBUG_PRINT("------- Display Buffers Reset --------\n");
-            for(j = 0; j < MAX_DISP_BUFS_NEW; j++)
-            {
-
-                ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
-                                      j,
-                                      BUF_MGR_REF);
-                ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_mv_buf_mgr,
-                                      ps_dec->au1_pic_buf_id_mv_buf_id_map[j],
-                                      BUF_MGR_REF);
-                ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
-                                      j,
-                                      BUF_MGR_IO);
-            }
-
-            ps_dec->i4_cur_display_seq = 0;
-            ps_dec->i4_prev_max_display_seq = 0;
-            ps_dec->i4_max_poc = 0;
-
-            ps_cur_pic = (pic_buffer_t *)ih264_buf_mgr_get_next_free(
-                            (buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
-                            &cur_pic_buf_id);
-            if(ps_cur_pic == NULL)
-            {
-                ps_dec->i4_error_code = ERROR_UNAVAIL_PICBUF_T;
-                return ERROR_UNAVAIL_PICBUF_T;
-            }
-
-            ps_col_mv = (col_mv_buf_t *)ih264_buf_mgr_get_next_free((buf_mgr_t *)ps_dec->pv_mv_buf_mgr,
-                                                                   &cur_mv_buf_id);
-            if(ps_col_mv == NULL)
-            {
-                ps_dec->i4_error_code = ERROR_UNAVAIL_MVBUF_T;
-                return ERROR_UNAVAIL_MVBUF_T;
-            }
-
-            ps_dec->ps_cur_pic = ps_cur_pic;
-            ps_dec->u1_pic_buf_id = cur_pic_buf_id;
-            ps_cur_pic->u4_ts = ps_dec->u4_ts;
-            ps_dec->apv_buf_id_pic_buf_map[cur_pic_buf_id] = (void *)ps_cur_pic;
-
-            ps_cur_pic->u1_mv_buf_id = cur_mv_buf_id;
-            ps_dec->au1_pic_buf_id_mv_buf_id_map[cur_pic_buf_id] = cur_mv_buf_id;
-
-            ps_cur_pic->pu1_col_zero_flag = (UWORD8 *)ps_col_mv->pv_col_zero_flag;
-            ps_cur_pic->ps_mv = (mv_pred_t *)ps_col_mv->pv_mv;
-            ps_dec->au1_pic_buf_ref_flag[cur_pic_buf_id] = 0;
-
-        }
-
         ps_dec->ps_cur_pic->u1_picturetype = u1_field_pic_flag;
         ps_dec->ps_cur_pic->u4_pack_slc_typ = SKIP_NONE;
         H264_DEC_DEBUG_PRINT("got a buffer\n");
@@ -793,7 +778,7 @@
                                      BUF_MGR_REF);
             /* Mark mv buf as needed for reference */
             ih264_buf_mgr_set_status((buf_mgr_t *)ps_dec->pv_mv_buf_mgr,
-                                     ps_dec->au1_pic_buf_id_mv_buf_id_map[ps_dec->u1_pic_buf_id],
+                                     ps_dec->as_buf_id_info_map[ps_dec->u1_pic_buf_id].mv_buf_id,
                                      BUF_MGR_REF);
             ps_dec->au1_pic_buf_ref_flag[ps_dec->u1_pic_buf_id] = 1;
         }
@@ -852,7 +837,7 @@
             if(ps_dec->au1_pic_buf_ref_flag[ps_dec->u1_pic_buf_id] == 0)
             {
                 ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_mv_buf_mgr,
-                                      ps_dec->au1_pic_buf_id_mv_buf_id_map[ps_dec->u1_pic_buf_id],
+                                      ps_dec->as_buf_id_info_map[ps_dec->u1_pic_buf_id].mv_buf_id,
                                       BUF_MGR_REF);
                 ps_dec->au1_pic_buf_ref_flag[ps_dec->u1_pic_buf_id] = 0;
 
@@ -893,7 +878,7 @@
                           ps_dec->u1_pic_buf_id,
                           BUF_MGR_REF);
     ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_mv_buf_mgr,
-                          ps_dec->au1_pic_buf_id_mv_buf_id_map[ps_dec->u1_pic_buf_id],
+                          ps_dec->as_buf_id_info_map[ps_dec->u1_pic_buf_id].mv_buf_id,
                           BUF_MGR_REF);
     ih264_buf_mgr_release((buf_mgr_t *)ps_dec->pv_pic_buf_mgr,
                           ps_dec->u1_pic_buf_id,
diff --git a/decoder/ih264d_structs.h b/decoder/ih264d_structs.h
index e6a962c..bcab1ea 100644
--- a/decoder/ih264d_structs.h
+++ b/decoder/ih264d_structs.h
@@ -714,6 +714,28 @@
     WORD16  ai2_level[64];
 }tu_blk8x8_coeff_data_t;
 
+/**
+ * Reference mapping from pic_buf_id to mv_buf_id and pointers to corresponding qp_map and
+ * mb_type_map
+ */
+typedef struct
+{
+    /**
+     * mv buf id
+     */
+    WORD32 mv_buf_id;
+
+    /**
+     * qp_map buffer
+     */
+    UWORD8 *pu1_qp_map;
+
+    /**
+     * mbtype buffer
+     */
+    UWORD8 *pu1_mb_type_map;
+}ref_map_t;
+
 /** Aggregating structure that is globally available */
 typedef struct _DecStruct
 {
@@ -751,6 +773,7 @@
 
     UWORD16 u2_pic_wd; /** Width of the picture being decoded */
     UWORD16 u2_pic_ht; /** Height of the picture being decoded */
+    UWORD32 u4_total_mbs; /** Total MBs in the picture being decoded */
 
     UWORD8 u1_first_slice_in_stream;
     UWORD8 u1_mb_ngbr_availablity;
@@ -761,6 +784,10 @@
     UWORD8 u1_qp_y_rem6;
     UWORD8 u1_qp_u_rem6;
 
+    /** mb_info variables - qp_map, mb_type_map */
+    UWORD8 u1_enable_mb_info;
+    UWORD8 *pu1_qp_map_base;
+    UWORD8 *pu1_mb_type_map_base;
     /*********************************/
     /* configurable mb-group numbers */
     /* very critical to the decoder  */
@@ -1390,7 +1417,7 @@
 
     void *apv_buf_id_pic_buf_map[MAX_DISP_BUFS_NEW];
 
-    UWORD8 au1_pic_buf_id_mv_buf_id_map[MAX_DISP_BUFS_NEW];
+    ref_map_t as_buf_id_info_map[MAX_DISP_BUFS_NEW];
 
     UWORD8 au1_pic_buf_ref_flag[MAX_DISP_BUFS_NEW];
 
diff --git a/decoder/ih264d_utils.c b/decoder/ih264d_utils.c
index 93c379b..9d616d3 100644
--- a/decoder/ih264d_utils.c
+++ b/decoder/ih264d_utils.c
@@ -2172,6 +2172,22 @@
     memset(pv_buf, 0, size);
     ps_dec->pu1_pic_buf_base = pv_buf;
 
+    /* Allocate memory for mb_info maps */
+    if(ps_dec->u1_enable_mb_info)
+    {
+        size = (u4_total_mbs << 2) * MAX_DISP_BUFS_NEW;
+
+        pv_buf = ps_dec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
+        RETURN_IF((NULL == pv_buf), IV_FAIL);
+        memset(pv_buf, 0, size);
+        ps_dec->pu1_qp_map_base = pv_buf;
+
+        pv_buf = ps_dec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
+        RETURN_IF((NULL == pv_buf), IV_FAIL);
+        memset(pv_buf, 0, size);
+        ps_dec->pu1_mb_type_map_base = pv_buf;
+    }
+
     /* Post allocation Increment Actions */
 
     /***************************************************************************/
@@ -2319,6 +2335,13 @@
     PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->ps_nbr_mb_row);
     PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pu1_mv_bank_buf_base);
     PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pu1_pic_buf_base);
+
+    /* Free memory for mb_info maps */
+    if(ps_dec->u1_enable_mb_info)
+    {
+        PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pu1_qp_map_base);
+        PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->pu1_mb_type_map_base);
+    }
     return 0;
 }
 
diff --git a/encoder/ih264e_encode.c b/encoder/ih264e_encode.c
index 6a4e3a2..defec7e 100644
--- a/encoder/ih264e_encode.c
+++ b/encoder/ih264e_encode.c
@@ -796,11 +796,5 @@
 
     ps_video_encode_op->s_ive_op.s_out_buf = s_out_buf.s_bits_buf;
 
-    if (1 == s_inp_buf.u4_is_last)
-    {
-        ps_video_encode_op->s_ive_op.output_present = 0;
-        ps_video_encode_op->s_ive_op.dump_recon = 0;
-    }
-
     return IV_SUCCESS;
 }
diff --git a/test/decoder/main.c b/test/decoder/main.c
index 046c689..bddf0b8 100644
--- a/test/decoder/main.c
+++ b/test/decoder/main.c
@@ -73,6 +73,8 @@
 #define MAX_DISP_BUFFERS    64
 #define EXTRA_DISP_BUFFERS  8
 #define STRLENGTH 1000
+#define STR2(x) #x
+#define STR(X) STR2(X)
 
 //#define TEST_FLUSH
 #define FLUSH_FRM_CNT 100
@@ -178,6 +180,7 @@
 {
     UWORD32 u4_piclen_flag;
     UWORD32 u4_file_save_flag;
+    UWORD32 u4_frame_info_enable;
     UWORD32 u4_chksum_save_flag;
     UWORD32 u4_max_frm_ts;
     IV_COLOR_FORMAT_T e_output_chroma_format;
@@ -202,6 +205,8 @@
     CHAR ac_piclen_fname[STRLENGTH];
     CHAR ac_ip_fname[STRLENGTH];
     CHAR ac_op_fname[STRLENGTH];
+    CHAR ac_qp_map_fname[STRLENGTH];
+    CHAR ac_blk_type_map_fname[STRLENGTH];
     CHAR ac_op_chksum_fname[STRLENGTH];
     ivd_out_bufdesc_t s_disp_buffers[MAX_DISP_BUFFERS];
     iv_yuv_buf_t s_disp_frm_queue[MAX_DISP_BUFFERS];
@@ -251,8 +256,11 @@
     VERSION,
     INPUT_FILE,
     OUTPUT,
+    QP_MAP_FILE,
+    BLK_TYPE_MAP_FILE,
     CHKSUM,
     SAVE_OUTPUT,
+    SAVE_FRAME_INFO,
     SAVE_CHKSUM,
     CHROMA_FORMAT,
     NUM_FRAMES,
@@ -295,6 +303,10 @@
          "Input file\n"},
     {"-o",  "--output",                 OUTPUT,
          "Output file\n"},
+    {"--",  "--qp_map_file",            QP_MAP_FILE,
+         "QP map file\n"},
+    {"--",  "--blk_type_map_file",         BLK_TYPE_MAP_FILE,
+         "Block type map file\n"},
     {"--",  "--piclen",                 PICLEN,
           "Flag to signal if the decoder has to use a file containing number of bytes in each picture to be fed in each call\n"},
     {"--",  "--piclen_file",                 PICLEN_FILE,
@@ -303,6 +315,8 @@
          "Output MD5 Checksum file\n"},
     { "-s", "--save_output",            SAVE_OUTPUT,
           "Save Output file\n" },
+    { "--", "--save_frame_info",        SAVE_FRAME_INFO,
+          "Save frame_info file\n" },
     { "--", "--save_chksum",            SAVE_CHKSUM,
           "Save Check sum file\n" },
     {"--",  "--chroma_format",          CHROMA_FORMAT,
@@ -883,12 +897,16 @@
 /*****************************************************************************/
 void dump_output(vid_dec_ctx_t *ps_app_ctx,
                  iv_yuv_buf_t *ps_disp_frm_buf,
+                 ih264d_video_decode_op_t *ps_h264d_decode_op,
                  UWORD32 u4_disp_frm_id,
                  FILE *ps_op_file,
+                 FILE *ps_qp_file,
+                 FILE *ps_mb_type_file,
                  FILE *ps_op_chksum_file,
                  WORD32 i4_op_frm_ts,
                  UWORD32 file_save,
-                 UWORD32 chksum_save)
+                 UWORD32 chksum_save,
+                 UWORD32 mbinfo_save)
 
 {
 
@@ -933,9 +951,26 @@
 
     release_disp_frame(ps_app_ctx->cocodec_obj, u4_disp_id);
 
-    if(0 == file_save && 0 == chksum_save)
+    if(0 == file_save && 0 == chksum_save && 0 == mbinfo_save)
         return;
 
+    if(0 != mbinfo_save)
+    {
+        UWORD8 *buf;
+        if(ps_h264d_decode_op->pu1_8x8_blk_qp_map && ps_qp_file)
+        {
+            buf = ps_h264d_decode_op->pu1_8x8_blk_qp_map;
+            fwrite(buf, 1, ps_h264d_decode_op->u4_8x8_blk_qp_map_size, ps_qp_file);
+            fflush(ps_qp_file);
+        }
+        if(ps_h264d_decode_op->pu1_8x8_blk_type_map && ps_mb_type_file)
+        {
+            buf = ps_h264d_decode_op->pu1_8x8_blk_type_map;
+            fwrite(buf, 1, ps_h264d_decode_op->u4_8x8_blk_type_map_size, ps_mb_type_file);
+            fflush(ps_mb_type_file);
+        }
+    }
+
     if(NULL == s_dump_disp_frm_buf.pv_y_buf)
         return;
 
@@ -950,7 +985,7 @@
 
         }
 #else
-        if(0 != file_save)
+        if(0 != file_save && ps_op_file)
         {
             UWORD8 *buf;
 
@@ -977,7 +1012,7 @@
 
         }
 
-        if(0 != chksum_save)
+        if(0 != chksum_save && ps_op_chksum_file)
         {
             UWORD8 au1_y_chksum[16];
             UWORD8 au1_u_chksum[16];
@@ -1178,22 +1213,34 @@
         case VERSION:
             break;
         case INPUT_FILE:
-            sscanf(value, "%s", ps_app_ctx->ac_ip_fname);
+            sscanf(value, "%" STR(STRLENGTH) "s", ps_app_ctx->ac_ip_fname);
             //input_passed = 1;
             break;
 
         case OUTPUT:
-            sscanf(value, "%s", ps_app_ctx->ac_op_fname);
+            sscanf(value, "%" STR(STRLENGTH) "s", ps_app_ctx->ac_op_fname);
+            break;
+
+        case QP_MAP_FILE:
+            sscanf(value, "%" STR(STRLENGTH) "s", ps_app_ctx->ac_qp_map_fname);
+            break;
+
+        case BLK_TYPE_MAP_FILE:
+            sscanf(value, "%" STR(STRLENGTH) "s", ps_app_ctx->ac_blk_type_map_fname);
             break;
 
         case CHKSUM:
-            sscanf(value, "%s", ps_app_ctx->ac_op_chksum_fname);
+            sscanf(value, "%" STR(STRLENGTH) "s", ps_app_ctx->ac_op_chksum_fname);
             break;
 
         case SAVE_OUTPUT:
             sscanf(value, "%d", &ps_app_ctx->u4_file_save_flag);
             break;
 
+        case SAVE_FRAME_INFO:
+            sscanf(value, "%d", &ps_app_ctx->u4_frame_info_enable);
+            break;
+
         case SAVE_CHKSUM:
             sscanf(value, "%d", &ps_app_ctx->u4_chksum_save_flag);
             break;
@@ -1303,7 +1350,7 @@
             break;
 
         case PICLEN_FILE:
-            sscanf(value, "%s", ps_app_ctx->ac_piclen_fname);
+            sscanf(value, "%" STR(STRLENGTH) "s", ps_app_ctx->ac_piclen_fname);
             break;
         case DISABLE_DEBLOCK_LEVEL:
             sscanf(value, "%d", &ps_app_ctx->u4_disable_dblk_level);
@@ -1636,6 +1683,10 @@
                   UWORD8 *pu1_bs_buf,
                   UWORD32 *pu4_op_frm_ts,
                   FILE *ps_op_file,
+                  FILE *ps_qp_file,
+                  FILE *ps_mb_type_file,
+                  UWORD8 *pu1_qp_map_buf,
+                  UWORD8 *pu1_blk_type_map_buf,
                   FILE *ps_op_chksum_file,
                   UWORD32 u4_ip_frm_ts,
                   UWORD32 u4_bytes_remaining)
@@ -1692,6 +1743,10 @@
                             ps_out_buf->u4_num_bufs;
 
             ps_video_decode_op->u4_size = sizeof(ih264d_video_decode_op_t);
+            s_h264d_decode_ip.pu1_8x8_blk_qp_map = pu1_qp_map_buf;
+            s_h264d_decode_ip.pu1_8x8_blk_type_map = pu1_blk_type_map_buf;
+            s_h264d_decode_ip.u4_8x8_blk_qp_map_size = (ADAPTIVE_MAX_HT * ADAPTIVE_MAX_WD) >> 6;
+            s_h264d_decode_ip.u4_8x8_blk_type_map_size = (ADAPTIVE_MAX_HT * ADAPTIVE_MAX_WD) >> 6;
 
             /*****************************************************************************/
             /*   API Call: Video Decode                                                  */
@@ -1847,19 +1902,19 @@
                         if (NULL == ps_op_file)
                         {
                             CHAR ac_error_str[STRLENGTH];
-                            sprintf(ac_error_str, "Could not open output file %s",
-                                    cur_fname);
+                            snprintf(ac_error_str, sizeof(ac_error_str),
+                                "Could not open output file %s", cur_fname);
 
                             codec_exit(ac_error_str);
                         }
                     }
                 }
 
-                dump_output(ps_app_ctx, &(ps_video_decode_op->s_disp_frm_buf),
-                            ps_video_decode_op->u4_disp_buf_id, ps_op_file,
-                            ps_op_chksum_file,
-                            *pu4_op_frm_ts, ps_app_ctx->u4_file_save_flag,
-                            ps_app_ctx->u4_chksum_save_flag);
+                dump_output(ps_app_ctx, &(ps_video_decode_op->s_disp_frm_buf), &s_h264d_decode_op,
+                            ps_video_decode_op->u4_disp_buf_id, ps_op_file, ps_qp_file,
+                            ps_mb_type_file, ps_op_chksum_file, *pu4_op_frm_ts,
+                            ps_app_ctx->u4_file_save_flag, ps_app_ctx->u4_chksum_save_flag,
+                            ps_app_ctx->u4_frame_info_enable);
                 if (extn != NULL)
                     fclose(ps_op_file);
                 (*pu4_op_frm_ts)++;
@@ -1923,11 +1978,15 @@
     FILE *ps_piclen_file = NULL;
     FILE *ps_ip_file = NULL;
     FILE *ps_op_file = NULL;
+    FILE *ps_qp_file = NULL;
+    FILE *ps_mb_type_file = NULL;
     FILE *ps_op_chksum_file = NULL;
     WORD32 ret;
     CHAR ac_error_str[STRLENGTH];
     vid_dec_ctx_t s_app_ctx;
     UWORD8 *pu1_bs_buf = NULL;
+    UWORD8 *pu1_qp_map_buf = NULL;
+    UWORD8 *pu1_blk_type_map_buf = NULL;
 
     ivd_out_bufdesc_t *ps_out_buf;
     UWORD32 u4_num_bytes_dec = 0;
@@ -2037,6 +2096,7 @@
     s_app_ctx.paused        = 0;
     //s_app_ctx.u4_output_present = 0;
     s_app_ctx.u4_chksum_save_flag = 0;
+    s_app_ctx.u4_frame_info_enable = 0;
 
     s_app_ctx.get_stride = &default_get_stride;
 
@@ -2104,8 +2164,8 @@
                 strcpy(ac_cfg_fname, argv[i + 1]);
                 if((fp_cfg_file = fopen(ac_cfg_fname, "r")) == NULL)
                 {
-                    sprintf(ac_error_str, "Could not open Configuration file %s",
-                            ac_cfg_fname);
+                    snprintf(ac_error_str, sizeof(ac_error_str),
+                            "Could not open Configuration file %s", ac_cfg_fname);
                     codec_exit(ac_error_str);
                 }
                 read_cfg_file(&s_app_ctx, fp_cfg_file);
@@ -2121,7 +2181,7 @@
     {
         if((fp_cfg_file = fopen(ac_cfg_fname, "r")) == NULL)
         {
-            sprintf(ac_error_str, "Could not open Configuration file %s",
+            snprintf(ac_error_str, sizeof(ac_error_str), "Could not open Configuration file %s",
                     ac_cfg_fname);
             codec_exit(ac_error_str);
         }
@@ -2129,10 +2189,10 @@
         fclose(fp_cfg_file);
     }
 #else
-    sprintf(filename_with_path, "%s/%s", homedir, ac_cfg_fname);
+    snprintf(filename_with_path, sizeof(filename_with_path), "%s/%s", homedir, ac_cfg_fname);
     if((fp_cfg_file = fopen(filename_with_path, "r")) == NULL)
     {
-        sprintf(ac_error_str, "Could not open Configuration file %s",
+        snprintf(ac_error_str, sizeof(ac_error_str),"Could not open Configuration file %s",
                 ac_cfg_fname);
         codec_exit(ac_error_str);
 
@@ -2165,20 +2225,26 @@
         exit(-1);
     }
 
+    if(1 == s_app_ctx.u4_frame_info_enable)
+    {
+        pu1_qp_map_buf = calloc((ADAPTIVE_MAX_HT * ADAPTIVE_MAX_WD) >> 6, 1);
+        pu1_blk_type_map_buf = calloc((ADAPTIVE_MAX_HT * ADAPTIVE_MAX_WD) >> 6, 1);
+    }
+
 
 
     /***********************************************************************/
     /*          create the file object for input file                      */
     /***********************************************************************/
 #ifdef IOS
-  sprintf(filename_with_path, "%s/%s", homedir, s_app_ctx.ac_ip_fname);
+   snprintf(filename_with_path, sizeof(filename_with_path), "%s/%s", homedir, s_app_ctx.ac_ip_fname);
    ps_ip_file = fopen(filename_with_path, "rb");
 #else
     ps_ip_file = fopen(s_app_ctx.ac_ip_fname, "rb");
 #endif
     if(NULL == ps_ip_file)
     {
-        sprintf(ac_error_str, "Could not open input file %s",
+        snprintf(ac_error_str, sizeof(ac_error_str), "Could not open input file %s",
                 s_app_ctx.ac_ip_fname);
         codec_exit(ac_error_str);
     }
@@ -2188,14 +2254,15 @@
     if(1 == s_app_ctx.u4_piclen_flag)
     {
 #ifdef IOS
-        sprintf(filename_with_path, "%s/%s", homedir, s_app_ctx.ac_piclen_fname);
+        snprintf(filename_with_path, sizeof(filename_with_path), "%s/%s",
+                s_app_ctx.ac_piclen_fname);
         ps_piclen_file = fopen(filename_with_path, "rb");
 #else
         ps_piclen_file = fopen(s_app_ctx.ac_piclen_fname, "rb");
 #endif
         if(NULL == ps_piclen_file)
         {
-            sprintf(ac_error_str, "Could not open piclen file %s",
+            snprintf(ac_error_str, sizeof(ac_error_str), "Could not open piclen file %s",
                 s_app_ctx.ac_piclen_fname);
             codec_exit(ac_error_str);
         }
@@ -2210,7 +2277,8 @@
     if((1 == s_app_ctx.u4_file_save_flag) && (strstr(s_app_ctx.ac_op_fname,"%d") == NULL))
     {
 #ifdef IOS
-    sprintf(filename_with_path, "%s/%s", documentdir, s_app_ctx.ac_op_fname);
+    snprintf(filename_with_path, sizeof(filename_with_path), "%s/%s", documentdir,
+            s_app_ctx.ac_op_fname);
     ps_op_file = fopen(filename_with_path,"wb");
 #else
         ps_op_file = fopen(s_app_ctx.ac_op_fname, "wb");
@@ -2218,26 +2286,59 @@
 
         if(NULL == ps_op_file)
         {
-            sprintf(ac_error_str, "Could not open output file %s",
+            snprintf(ac_error_str, sizeof(ac_error_str), "Could not open output file %s",
                     s_app_ctx.ac_op_fname);
             codec_exit(ac_error_str);
         }
     }
 
     /***********************************************************************/
+    /*          create the file object for mbinfo file                     */
+    /***********************************************************************/
+
+    if(1 == s_app_ctx.u4_frame_info_enable)
+    {
+#ifdef IOS
+        snprintf(filename_with_path, sizeof(filename_with_path), "%s/%s", documentdir,
+                s_app_ctx.ac_qp_map_fname);
+        ps_qp_file = fopen(filename_with_path, "wb");
+
+        snprintf(filename_with_path, sizeof(filename_with_path), "%s/%s", documentdir,
+                s_app_ctx.ac_blk_type_map_fname);
+        ps_mb_type_file = fopen(filename_with_path, "wb");
+#else
+        ps_qp_file = fopen(s_app_ctx.ac_qp_map_fname, "wb");
+        ps_mb_type_file = fopen(s_app_ctx.ac_blk_type_map_fname, "wb");
+
+#endif
+
+        if(NULL == ps_qp_file)
+        {
+            snprintf(ac_error_str, sizeof(ac_error_str), "Could not open block_qp map file %s",
+                    s_app_ctx.ac_qp_map_fname);
+        }
+        if(NULL == ps_mb_type_file)
+        {
+            snprintf(ac_error_str, sizeof(ac_error_str), "Could not open block_type map file %s",
+                    s_app_ctx.ac_blk_type_map_fname);
+        }
+    }
+
+    /***********************************************************************/
     /*          create the file object for check sum file                  */
     /***********************************************************************/
     if(1 == s_app_ctx.u4_chksum_save_flag)
     {
 #if IOS
-        sprintf(filename_with_path, "%s/%s", documentdir, s_app_ctx.ac_op_chksum_fname);
+        snprintf(filename_with_path, sizeof(filename_with_path), "%s/%s", documentdir,
+                s_app_ctx.ac_op_chksum_fname);
         ps_op_chksum_file = fopen(filename_with_path,"wb");
 #else
         ps_op_chksum_file = fopen(s_app_ctx.ac_op_chksum_fname, "wb");
 #endif
         if(NULL == ps_op_chksum_file)
         {
-            sprintf(ac_error_str, "Could not open check sum file %s",
+            snprintf(ac_error_str, sizeof(ac_error_str), "Could not open check sum file %s",
                     s_app_ctx.ac_op_chksum_fname);
             codec_exit(ac_error_str);
         }
@@ -2253,8 +2354,8 @@
         /*   API Call: Initialize the Decoder                                        */
         /*****************************************************************************/
         {
-            ih264d_create_ip_t s_create_ip;
-            ih264d_create_op_t s_create_op;
+            ih264d_create_ip_t s_create_ip = {};
+            ih264d_create_op_t s_create_op = {};
             void *fxns = &ivd_api_function;
 
             s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
@@ -2265,6 +2366,7 @@
             s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL;
             s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ih264d_create_ip_t);
             s_create_op.s_ivd_create_op_t.u4_size = sizeof(ih264d_create_op_t);
+            s_create_ip.u4_enable_frame_info = s_app_ctx.u4_frame_info_enable;
 
 
 
@@ -2369,10 +2471,10 @@
 
     }
 
-    flush_output(codec_obj, &s_app_ctx, ps_out_buf,
-                 pu1_bs_buf, &u4_op_frm_ts,
-                 ps_op_file, ps_op_chksum_file,
-                 u4_ip_frm_ts, u4_bytes_remaining);
+    flush_output(codec_obj, &s_app_ctx, ps_out_buf, pu1_bs_buf, &u4_op_frm_ts,
+                 ps_op_file, ps_qp_file, ps_mb_type_file,
+                 pu1_qp_map_buf, pu1_blk_type_map_buf,
+                 ps_op_chksum_file, u4_ip_frm_ts, u4_bytes_remaining);
 
     /*****************************************************************************/
     /*   Decode header to get width and height and buffer sizes                  */
@@ -2458,6 +2560,10 @@
             ps_video_decode_ip->u4_num_Bytes = u4_bytes_remaining;
             ps_video_decode_ip->u4_size = sizeof(ih264d_video_decode_ip_t);
             ps_video_decode_op->u4_size = sizeof(ih264d_video_decode_op_t);
+            s_h264d_decode_ip.pu1_8x8_blk_qp_map = pu1_qp_map_buf;
+            s_h264d_decode_ip.pu1_8x8_blk_type_map = pu1_blk_type_map_buf;
+            s_h264d_decode_ip.u4_8x8_blk_qp_map_size = (ADAPTIVE_MAX_HT * ADAPTIVE_MAX_WD) >> 6;
+            s_h264d_decode_ip.u4_8x8_blk_type_map_size = (ADAPTIVE_MAX_HT * ADAPTIVE_MAX_WD) >> 6;
 
             /*****************************************************************************/
             /*   API Call: Header Decode                                                  */
@@ -2998,6 +3104,10 @@
             ps_video_decode_ip->s_out_buffer.u4_num_bufs =
                             ps_out_buf->u4_num_bufs;
             ps_video_decode_op->u4_size = sizeof(ih264d_video_decode_op_t);
+            s_h264d_decode_ip.pu1_8x8_blk_qp_map = pu1_qp_map_buf;
+            s_h264d_decode_ip.pu1_8x8_blk_type_map = pu1_blk_type_map_buf;
+            s_h264d_decode_ip.u4_8x8_blk_qp_map_size = (ADAPTIVE_MAX_HT * ADAPTIVE_MAX_WD) >> 6;
+            s_h264d_decode_ip.u4_8x8_blk_type_map_size = (ADAPTIVE_MAX_HT * ADAPTIVE_MAX_WD) >> 6;
 
             /* Get display buffer pointers */
             if(1 == s_app_ctx.display)
@@ -3077,10 +3187,10 @@
                 ivd_ctl_reset_ip_t s_ctl_ip;
                 ivd_ctl_reset_op_t s_ctl_op;
 
-                flush_output(codec_obj, &s_app_ctx, ps_out_buf,
-                             pu1_bs_buf, &u4_op_frm_ts,
-                             ps_op_file, ps_op_chksum_file,
-                             u4_ip_frm_ts, u4_bytes_remaining);
+                flush_output(codec_obj, &s_app_ctx, ps_out_buf, pu1_bs_buf, &u4_op_frm_ts,
+                             ps_op_file, ps_qp_file, ps_mb_type_file,
+                             pu1_qp_map_buf, pu1_blk_type_map_buf,
+                             ps_op_chksum_file, u4_ip_frm_ts, u4_bytes_remaining);
 
                 s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
                 s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET;
@@ -3311,8 +3421,8 @@
                         ps_op_file = fopen(cur_fname,"wb");
                         if (NULL == ps_op_file)
                         {
-                            sprintf(ac_error_str, "Could not open output file %s",
-                                    cur_fname);
+                            snprintf(ac_error_str, sizeof(ac_error_str),
+                                    "Could not open output file %s", cur_fname);
 
                             codec_exit(ac_error_str);
                         }
@@ -3321,11 +3431,11 @@
 
                 width = ps_video_decode_op->s_disp_frm_buf.u4_y_wd;
                 height = ps_video_decode_op->s_disp_frm_buf.u4_y_ht;
-                dump_output(&s_app_ctx, &(ps_video_decode_op->s_disp_frm_buf),
+                dump_output(&s_app_ctx, &(ps_video_decode_op->s_disp_frm_buf), &s_h264d_decode_op,
                             ps_video_decode_op->u4_disp_buf_id, ps_op_file,
-                            ps_op_chksum_file,
+                            ps_qp_file, ps_mb_type_file, ps_op_chksum_file,
                             u4_op_frm_ts, s_app_ctx.u4_file_save_flag,
-                            s_app_ctx.u4_chksum_save_flag);
+                            s_app_ctx.u4_chksum_save_flag, s_app_ctx.u4_frame_info_enable);
 
                 u4_op_frm_ts++;
                 if (extn != NULL)
@@ -3347,10 +3457,10 @@
     /***********************************************************************/
     /*      To get the last decoded frames, call process with NULL input    */
     /***********************************************************************/
-    flush_output(codec_obj, &s_app_ctx, ps_out_buf,
-                 pu1_bs_buf, &u4_op_frm_ts,
-                 ps_op_file, ps_op_chksum_file,
-                 u4_ip_frm_ts, u4_bytes_remaining);
+    flush_output(codec_obj, &s_app_ctx, ps_out_buf, pu1_bs_buf, &u4_op_frm_ts,
+                 ps_op_file, ps_qp_file, ps_mb_type_file,
+                 pu1_qp_map_buf, pu1_blk_type_map_buf,
+                 ps_op_chksum_file, u4_ip_frm_ts, u4_bytes_remaining);
 
     /* set disp_end u4_flag */
     s_app_ctx.quit = 1;
@@ -3423,7 +3533,17 @@
         {
             fclose(ps_op_chksum_file);
         }
-
+        if(1 == s_app_ctx.u4_frame_info_enable)
+        {
+            if(NULL != ps_qp_file)
+            {
+                fclose(ps_qp_file);
+            }
+            if(NULL != ps_mb_type_file)
+            {
+                fclose(ps_mb_type_file);
+            }
+        }
     }
 
     if(0 == s_app_ctx.u4_share_disp_buf)
@@ -3438,6 +3558,17 @@
 
     free(ps_out_buf);
     free(pu1_bs_buf);
+    if(1 == s_app_ctx.u4_frame_info_enable)
+    {
+        if(pu1_qp_map_buf)
+        {
+            free(pu1_qp_map_buf);
+        }
+        if(pu1_blk_type_map_buf)
+        {
+            free(pu1_blk_type_map_buf);
+        }
+    }
 
     if(s_app_ctx.display_thread_handle)
         free(s_app_ctx.display_thread_handle);
diff --git a/test/encoder/main.c b/test/encoder/main.c
index fc84ad2..471d630 100644
--- a/test/encoder/main.c
+++ b/test/encoder/main.c
@@ -1470,9 +1470,9 @@
     s_vui_params_ip.u1_video_format = 0;
     s_vui_params_ip.u1_video_full_range_flag = 0;
     s_vui_params_ip.u1_colour_description_present_flag = 1;
-    s_vui_params_ip.u1_colour_primaries = 0;
-    s_vui_params_ip.u1_transfer_characteristics = 0;
-    s_vui_params_ip.u1_matrix_coefficients = 0;
+    s_vui_params_ip.u1_colour_primaries = 2;
+    s_vui_params_ip.u1_transfer_characteristics = 2;
+    s_vui_params_ip.u1_matrix_coefficients = 2;
     s_vui_params_ip.u1_chroma_loc_info_present_flag = 0;
     s_vui_params_ip.u1_chroma_sample_loc_type_top_field = 0;
     s_vui_params_ip.u1_chroma_sample_loc_type_bottom_field = 0;