mm-video-v4l2: venc: Protect buffer from being freed while accessing am: 0008e21211 am: c0f642a22f
am: 979b0e6864

Change-Id: I2faf25ea66357a2444cf2f26b195e811c1d28c03
diff --git a/msm8974/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp b/msm8974/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
index 6907ca5..07eb24d 100644
--- a/msm8974/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
+++ b/msm8974/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
@@ -3458,10 +3458,12 @@
         media_buffer = (encoder_media_buffer_type *)meta_buffer_hdr[nBufIndex].pBuffer;
         if (media_buffer) {
             if (media_buffer->buffer_type != kMetadataBufferTypeCameraSource &&
-                    media_buffer->buffer_type != kMetadataBufferTypeGrallocSource) {
+                    media_buffer->buffer_type != kMetadataBufferTypeGrallocSource &&
+                    media_buffer->buffer_type != kMetadataBufferTypeNativeHandleSource) {
                 met_error = true;
             } else {
-                if (media_buffer->buffer_type == kMetadataBufferTypeCameraSource) {
+                if ((media_buffer->buffer_type == kMetadataBufferTypeCameraSource) ||
+                        (media_buffer->buffer_type == kMetadataBufferTypeNativeHandleSource)) {
                     if (media_buffer->meta_handle == NULL)
                         met_error = true;
                     else if ((media_buffer->meta_handle->numFds != 1 &&
@@ -4478,7 +4480,8 @@
         } else {
             media_ptr = (encoder_media_buffer_type *) buffer->pBuffer;
             if (media_ptr && media_ptr->meta_handle) {
-                if (media_ptr->buffer_type == kMetadataBufferTypeCameraSource &&
+                if ((media_ptr->buffer_type == kMetadataBufferTypeCameraSource ||
+                        media_ptr->buffer_type == kMetadataBufferTypeNativeHandleSource) &&
                         media_ptr->meta_handle->numFds == 1 &&
                         media_ptr->meta_handle->numInts >= 2) {
                     Input_pmem.fd = media_ptr->meta_handle->data[0];
diff --git a/msm8974/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/msm8974/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
index cc8d6ae..6261195 100644
--- a/msm8974/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
+++ b/msm8974/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
@@ -2738,7 +2738,8 @@
             } else if (!color_format) {
 		int color_space = 0;
 
-                if (meta_buf->buffer_type == kMetadataBufferTypeCameraSource) {
+                if ((meta_buf->buffer_type == kMetadataBufferTypeCameraSource) ||
+                        (meta_buf->buffer_type == kMetadataBufferTypeNativeHandleSource)) {
                     if (meta_buf->meta_handle->numFds + meta_buf->meta_handle->numInts > 3 &&
                         meta_buf->meta_handle->data[3] & private_handle_t::PRIV_FLAGS_ITU_R_709) {
                         buf.flags = V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP;
diff --git a/msm8996/libc2dcolorconvert/Android.mk b/msm8996/libc2dcolorconvert/Android.mk
index 9b8d9a5..1871864 100644
--- a/msm8996/libc2dcolorconvert/Android.mk
+++ b/msm8996/libc2dcolorconvert/Android.mk
@@ -13,6 +13,7 @@
 endif
 
 LOCAL_SHARED_LIBRARIES := liblog libdl
+LOCAL_HEADER_LIBRARIES := copybit_headers
 
 LOCAL_MODULE_TAGS := optional
 
@@ -22,4 +23,6 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
 endif
 
+LOCAL_PROPRIETARY_MODULE := true
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8996/libstagefrighthw/Android.mk b/msm8996/libstagefrighthw/Android.mk
index 007e804..01d04eb 100644
--- a/msm8996/libstagefrighthw/Android.mk
+++ b/msm8996/libstagefrighthw/Android.mk
@@ -39,5 +39,7 @@
 
 LOCAL_MODULE := libstagefrighthw
 
+LOCAL_PROPRIETARY_MODULE := true
+
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/msm8996/mm-core/Android.mk b/msm8996/mm-core/Android.mk
index 26e7e31..bd1f7d8 100644
--- a/msm8996/mm-core/Android.mk
+++ b/msm8996/mm-core/Android.mk
@@ -53,39 +53,6 @@
 endif
 
 #===============================================================================
-#             Deploy the headers that can be exposed
-#===============================================================================
-
-LOCAL_COPY_HEADERS_TO   := mm-core/omxcore
-LOCAL_COPY_HEADERS      := inc/OMX_Audio.h
-LOCAL_COPY_HEADERS      += inc/OMX_Component.h
-LOCAL_COPY_HEADERS      += inc/OMX_ContentPipe.h
-LOCAL_COPY_HEADERS      += inc/OMX_Core.h
-LOCAL_COPY_HEADERS      += inc/OMX_Image.h
-LOCAL_COPY_HEADERS      += inc/OMX_Index.h
-LOCAL_COPY_HEADERS      += inc/OMX_IVCommon.h
-LOCAL_COPY_HEADERS      += inc/OMX_Other.h
-LOCAL_COPY_HEADERS      += inc/OMX_QCOMExtns.h
-LOCAL_COPY_HEADERS      += inc/OMX_Types.h
-LOCAL_COPY_HEADERS      += inc/OMX_Video.h
-LOCAL_COPY_HEADERS      += inc/qc_omx_common.h
-LOCAL_COPY_HEADERS      += inc/qc_omx_component.h
-LOCAL_COPY_HEADERS      += inc/qc_omx_msg.h
-LOCAL_COPY_HEADERS      += inc/QOMX_AudioExtensions.h
-LOCAL_COPY_HEADERS      += inc/QOMX_AudioIndexExtensions.h
-LOCAL_COPY_HEADERS      += inc/OMX_CoreExt.h
-LOCAL_COPY_HEADERS      += inc/QOMX_CoreExtensions.h
-LOCAL_COPY_HEADERS      += inc/QOMX_FileFormatExtensions.h
-LOCAL_COPY_HEADERS      += inc/QOMX_IVCommonExtensions.h
-LOCAL_COPY_HEADERS      += inc/QOMX_SourceExtensions.h
-LOCAL_COPY_HEADERS      += inc/QOMX_VideoExtensions.h
-LOCAL_COPY_HEADERS      += inc/OMX_IndexExt.h
-LOCAL_COPY_HEADERS      += inc/OMX_VideoExt.h
-LOCAL_COPY_HEADERS      += inc/QOMX_StreamingExtensions.h
-LOCAL_COPY_HEADERS      += inc/QCMediaDefs.h
-LOCAL_COPY_HEADERS      += inc/QCMetaData.h
-
-#===============================================================================
 #             LIBRARY for Android apps
 #===============================================================================
 
@@ -94,6 +61,7 @@
 LOCAL_PRELINK_MODULE    := false
 LOCAL_MODULE            := libOmxCore
 LOCAL_MODULE_TAGS       := optional
+LOCAL_PROPRIETARY_MODULE:= true
 LOCAL_SHARED_LIBRARIES  := liblog libdl libcutils
 LOCAL_CFLAGS            := $(OMXCORE_CFLAGS)
 
@@ -107,6 +75,11 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
+include $(CLEAR_VARS)
+LOCAL_MODULE := OmxCore_headers
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/inc
+include $(BUILD_HEADER_LIBRARY)
+
 #===============================================================================
 #             LIBRARY for command line test apps
 #===============================================================================
@@ -118,6 +91,7 @@
 LOCAL_PRELINK_MODULE    := false
 LOCAL_MODULE            := libmm-omxcore
 LOCAL_MODULE_TAGS       := optional
+LOCAL_PROPRIETARY_MODULE:= true
 LOCAL_SHARED_LIBRARIES  := liblog libdl libcutils
 LOCAL_CFLAGS            := $(OMXCORE_CFLAGS)
 
diff --git a/msm8996/mm-core/inc/OMX_IndexExt.h b/msm8996/mm-core/inc/OMX_IndexExt.h
index 468a3a3..315cc09 100644
--- a/msm8996/mm-core/inc/OMX_IndexExt.h
+++ b/msm8996/mm-core/inc/OMX_IndexExt.h
@@ -51,6 +51,7 @@
     OMX_IndexConfigCallbackRequest,  /**< reference: OMX_CONFIG_CALLBACKREQUESTTYPE */
     OMX_IndexConfigCommitMode,                      /**< reference: OMX_CONFIG_COMMITMODETYPE */
     OMX_IndexConfigCommit,                          /**< reference: OMX_CONFIG_COMMITTYPE */
+    OMX_IndexConfigAndroidVendorExtension,          /**< reference: OMX_CONFIG_VENDOR_EXTENSIONTYPE */
 
     /* Port parameters and configurations */
     OMX_IndexExtPortStartUnused = OMX_IndexKhronosExtensions + 0x00200000,
@@ -90,6 +91,57 @@
 
     OMX_IndexExtMax = 0x7FFFFFFF
 } OMX_INDEXEXTTYPE;
+#define OMX_MAX_STRINGVALUE_SIZE OMX_MAX_STRINGNAME_SIZE
+#define OMX_MAX_ANDROID_VENDOR_PARAMCOUNT 32
+
+typedef enum OMX_ANDROID_VENDOR_VALUETYPE {
+    OMX_AndroidVendorValueInt32 = 0,   /*<< int32_t value */
+    OMX_AndroidVendorValueInt64,       /*<< int64_t value */
+    OMX_AndroidVendorValueString,      /*<< string value */
+    OMX_AndroidVendorValueEndUnused,
+} OMX_ANDROID_VENDOR_VALUETYPE;
+
+/**
+ *
+ *  cKey        : parameter value name.
+ *  eValueType  : parameter value type
+ *  bSet        : if false, the parameter is not set (for OMX_GetConfig) or is unset (OMX_SetConfig)
+ *                if true, the parameter is set to the corresponding value below
+ *  nInt32      : int32 value
+ *  nInt64      : int64 value
+ *  cString     : string value
+ */
+typedef struct OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE {
+    OMX_U8 cKey[OMX_MAX_STRINGNAME_SIZE];
+    OMX_ANDROID_VENDOR_VALUETYPE eValueType;
+    OMX_BOOL bSet;
+    union {
+        OMX_S32 nInt32;
+        OMX_S64 nInt64;
+        OMX_U8 cString[OMX_MAX_STRINGVALUE_SIZE];
+    };
+} OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE;
+
+/**
+ *  nSize       : size of the structure in bytes
+ *  nVersion    : OMX specification version information
+ *  cName       : name of vendor extension
+ *  nParamCount : the number of parameter values that are part of this vendor extension
+ *  nParamSizeUsed : the size of nParam
+ *                (must be at least 1 and at most OMX_MAX_ANDROID_VENDOR_PARAMCOUNT)
+ *  nParam      : the parameter values
+ */
+typedef struct OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nIndex;
+    OMX_U8  cName[OMX_MAX_STRINGNAME_SIZE];
+    OMX_DIRTYPE eDir;
+    OMX_U32 nParamCount;
+    OMX_U32 nParamSizeUsed;
+    OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE nParam[1];
+} OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE;
+
 
 #ifdef __cplusplus
 }
diff --git a/msm8996/mm-core/inc/OMX_QCOMExtns.h b/msm8996/mm-core/inc/OMX_QCOMExtns.h
index 8e92946..2a36dcc 100644
--- a/msm8996/mm-core/inc/OMX_QCOMExtns.h
+++ b/msm8996/mm-core/inc/OMX_QCOMExtns.h
@@ -565,6 +565,7 @@
 
     OMX_QTIIndexParamVPXColorSpaceExtraData = 0x7F000062,
 
+    OMX_QTIIndexParamEnableAVTimerTimestamps = 0x7F000063,
 };
 
 /**
diff --git a/msm8996/mm-core/src/msm8996/registry_table_android.c b/msm8996/mm-core/src/msm8996/registry_table_android.c
index 1e010f4..5d8736d 100644
--- a/msm8996/mm-core/src/msm8996/registry_table_android.c
+++ b/msm8996/mm-core/src/msm8996/registry_table_android.c
@@ -56,22 +56,6 @@
     }
   },
   {
-    "OMX.qcom.video.decoder.avc.dsmode",
-    NULL, // Create instance function
-         // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVideoDSMode.so",
-    {
-      "video_decoder.avc"
-    }
-  },
-  {
     "OMX.qcom.video.decoder.avc.secure",
     NULL, // Create instance function
     // Unique instance handle
@@ -88,71 +72,6 @@
     }
   },
   {
-    "OMX.qcom.video.decoder.avc.secure.dsmode",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVideoDSMode.so",
-    {
-      "video_decoder.avc"
-    }
-  },
-
-  {
-    "OMX.qcom.video.decoder.divx4",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVdec.so",
-    {
-      "video_decoder.divx"
-    }
-  },
-  {
-    "OMX.qcom.video.decoder.divx",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVdec.so",
-    {
-      "video_decoder.divx"
-    }
-  },
-  {
-    "OMX.qcom.video.decoder.divx311",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVdec.so",
-    {
-      "video_decoder.divx"
-    }
-  },
-  {
     "OMX.qcom.video.decoder.mpeg4",
     NULL, // Create instance function
     // Unique instance handle
@@ -169,118 +88,6 @@
     }
   },
   {
-    "OMX.qcom.video.decoder.mpeg4.secure",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVdec.so",
-    {
-      "video_decoder.mpeg4"
-    }
-  },
-  {
-    "OMX.qcom.video.decoder.mpeg2",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVdec.so",
-    {
-      "video_decoder.mpeg2"
-    }
-  },
-  {
-    "OMX.qcom.video.decoder.mpeg2.secure",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVdec.so",
-    {
-      "video_decoder.mpeg2"
-    }
-  },
-  {
-    "OMX.qcom.video.decoder.vc1",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVdec.so",
-    {
-      "video_decoder.vc1"
-    }
-  },
-  {
-    "OMX.qcom.video.decoder.vc1.secure",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVdec.so",
-    {
-      "video_decoder.vc1"
-    }
-  },
-  {
-    "OMX.qcom.video.decoder.wmv",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVdec.so",
-    {
-      "video_decoder.vc1"
-    }
-  },
-  {
-    "OMX.qcom.video.decoder.wmv.secure",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVdec.so",
-    {
-      "video_decoder.vc1"
-    }
-  },
-  {
     "OMX.qcom.video.decoder.h263",
     NULL, // Create instance function
     // Unique instance handle
@@ -425,22 +232,6 @@
     }
   },
   {
-    "OMX.qcom.video.encoder.avc.secure",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVenc.so",
-    {
-      "video_encoder.avc"
-    }
-  },
-  {
     "OMX.qcom.video.encoder.vp8",
     NULL, // Create instance function
     // Unique instance handle
@@ -472,310 +263,6 @@
       "video_encoder.hevc"
     }
   },
-  {
-    "OMX.qcom.video.encoder.hevc.secure",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVenc.so",
-    {
-      "video_encoder.hevc"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.Qcelp13",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxQcelp13Dec.so",
-    {
-      "audio_decoder.Qcelp13"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.evrc",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxEvrcDec.so",
-    {
-      "audio_decoder.evrc"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.wma",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-     NULL,
-     NULL,
-     NULL,
-     NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxWmaDec.so",
-    {
-     "audio_decoder.wma"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.wma10Pro",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-     NULL,
-     NULL,
-     NULL,
-     NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxWmaDec.so",
-    {
-     "audio_decoder.wma"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.wmaLossLess",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-     NULL,
-     NULL,
-     NULL,
-     NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxWmaDec.so",
-    {
-     "audio_decoder.wma"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.amrwbplus",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-     NULL,
-     NULL,
-     NULL,
-     NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxAmrwbplusDec.so",
-    {
-     "audio_decoder.awbplus"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.alac",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxAlacDec.so",
-    {
-      "audio_decoder.alac"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.ape",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxApeDec.so",
-    {
-      "audio_decoder.ape"
-    }
-  },
-  {
-    "OMX.qcom.audio.encoder.aac",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,  // Shared object library handle
-    "libOmxAacEnc.so",
-    {
-      "audio_encoder.aac"
-    }
-  },
-  {
-    "OMX.qcom.audio.encoder.qcelp13",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxQcelp13Enc.so",
-    {
-      "audio_encoder.qcelp13"
-    }
-  },
-  {
-    "OMX.qcom.audio.encoder.evrc",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxEvrcEnc.so",
-    {
-      "audio_encoder.evrc"
-    }
-  },
-  {
-    "OMX.qcom.audio.encoder.amrnb",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxAmrEnc.so",
-    {
-      "audio_encoder.amrnb"
-    }
-  },
- {
-    "OMX.qcom.audio.decoder.aac",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxAacDec.so",
-    {
-      "audio_decoder.aac"
-    }
-  },
- {
-    "OMX.qcom.audio.decoder.multiaac",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxAacDec.so",
-    {
-      "audio_decoder.aac"
-    }
-  },
-  {
-    "AIV.play.generic",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,  // Shared object library handle
-    "libAivPlay.so",
-    {
-      "AIV.play.role.generic"
-    }
-  },
-  {
-    "OMX.qcom.file.muxer",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxMux.so",
-    {
-      "container_muxer.mp2"
-    }
-  },
-  {
-    "OMX.qcom.video.postprocessing",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVdpp.so",
-    {
-      "videopostprocessing"
-    }
-  },
-  {
-    "OMX.qti.vdec.vpp",
-    NULL, // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxVpp.so",
-    {
-      "video_decoder.vpp"
-    }
-  }
 };
 
 const unsigned int SIZE_OF_CORE = sizeof(core) / sizeof(omx_core_cb_type);
diff --git a/msm8996/mm-video-v4l2/vidc/common/Android.mk b/msm8996/mm-video-v4l2/vidc/common/Android.mk
index 3bfd614..e6092ba 100644
--- a/msm8996/mm-video-v4l2/vidc/common/Android.mk
+++ b/msm8996/mm-video-v4l2/vidc/common/Android.mk
@@ -39,9 +39,11 @@
 
 LOCAL_PRELINK_MODULE      := false
 LOCAL_SHARED_LIBRARIES    := liblog libutils libcutils libdl
+LOCAL_HEADER_LIBRARIES    := copybit_headers gralloc_headers
 
 LOCAL_SRC_FILES   := src/extra_data_handler.cpp
 LOCAL_SRC_FILES   += src/vidc_color_converter.cpp
+LOCAL_SRC_FILES   += src/vidc_vendor_extensions.cpp
 
 ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
 LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
diff --git a/msm8996/mm-video-v4l2/vidc/common/inc/vidc_debug.h b/msm8996/mm-video-v4l2/vidc/common/inc/vidc_debug.h
index 6355188..9b4b65f 100644
--- a/msm8996/mm-video-v4l2/vidc/common/inc/vidc_debug.h
+++ b/msm8996/mm-video-v4l2/vidc/common/inc/vidc_debug.h
@@ -80,6 +80,28 @@
         }                                                                      \
     }                                                                          \
 
+/*
+ * Validate OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE type param
+ * *assumes* VALIDATE_OMX_PARAM_DATA checks have passed
+ * Checks for nParamCount cannot be generalized here. it is imperative that
+ *  the calling code handles it.
+ */
+#define VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext)                                             \
+    {                                                                                             \
+        if (ext->nParamSizeUsed < 1 || ext->nParamSizeUsed > OMX_MAX_ANDROID_VENDOR_PARAMCOUNT) { \
+            ALOGE("VendorExtension: sub-params(%u) not in expected range(%u - %u)",               \
+                    ext->nParamSizeUsed, 1, OMX_MAX_ANDROID_VENDOR_PARAMCOUNT);                   \
+            return OMX_ErrorBadParameter;                                                         \
+        }                                                                                         \
+        OMX_U32 expectedSize = (OMX_U32)sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) +         \
+                ((ext->nParamSizeUsed - 1) * (OMX_U32)sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE));\
+        if (ext->nSize < expectedSize) {                                                          \
+            ALOGE("VendorExtension: Insifficient size(%u) v/s expected(%u)",                      \
+                    ext->nSize, expectedSize);                                                    \
+            return OMX_ErrorBadParameter;                                                         \
+        }                                                                                         \
+    }                                                                                             \
+
 class auto_lock {
     public:
         auto_lock(pthread_mutex_t &lock)
diff --git a/msm8996/mm-video-v4l2/vidc/common/inc/vidc_vendor_extensions.h b/msm8996/mm-video-v4l2/vidc/common/inc/vidc_vendor_extensions.h
new file mode 100644
index 0000000..6763d16
--- /dev/null
+++ b/msm8996/mm-video-v4l2/vidc/common/inc/vidc_vendor_extensions.h
@@ -0,0 +1,229 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2017, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef _VIDC_VENDOR_ENXTENSIONS_H_
+#define _VIDC_VENDOR_ENXTENSIONS_H_
+
+#include <inttypes.h>
+#include <string.h>
+#include <string>
+#include <vector>
+
+/*
+ * This class represents a Vendor-Extension (except for the data).
+ * A Vendor extension is identified by a unique extension-name and
+ * is mapped to a specific OMX-extension. it contains params that
+ * signify individual parameter-field
+ *    VendorExtension::mName         => similar to OMX extension string.
+ *                                      (Name must be unique)
+ *    VendorExtension::mId           => similar to OMX extension ID
+ *    VendorExtension::mParam[0,1..] => similar to an individual field
+ *                                      in OMX extension struct
+ *    VendorExtension::mIsSet        => flag that indicates whether this
+ *                                      extension was set by the client.
+ * This also provides utility methods to:
+ *   - copy info(keys/types..) to client's extension strcuture
+ *        including copying of param-key and type of each param
+ *   - copy data from/to the client's extension structure, given the
+ *        param-key (this is type-aware copy)
+ *   - sanity checks
+ *
+ * Extension name - naming convention
+ *   - name must be unique
+ *   - must be prefixed with "ext-" followed by component-type
+ *     Eg: "enc" "dec" "vpp"
+ *   - SHOULD NOT contain "."
+ *   - keywords SHOULD be separated by "-"
+ *   - name may contain feature-name and/or parameter-name
+ *   Eg:  "ext-enc-preprocess-rotate"
+ *        "ext-dec-picture-order"
+ *
+ * Overall paramter-key => vendor (dot) extension-name (dot) param-key
+*/
+struct VendorExtension {
+
+    /*
+     * Param represents an individual parameter (field) of a VendorExtension.
+     * This is a variant holding values of type [int32, int64 or String].
+     * Each Param has a name (unique within the extension) that is appended
+     * to the 'extension-name' and prefixed with "vendor." to generate the
+     * key that will be exposed to the client.
+     *
+     * Param name(key) - naming convention
+     *   - key must be unique (within the extension)
+     *   - SHOULD not contain "."
+     *   - Keywords seperated by "-" ONLY if required
+     *   Eg: "angle"
+     *       "n-idr-period"
+     *
+     */
+    struct Param {
+        Param (const std::string &name, OMX_ANDROID_VENDOR_VALUETYPE type)
+            : mName(name), mType(type) {}
+
+        const char *name() const {
+            return mName.c_str();
+        }
+        OMX_ANDROID_VENDOR_VALUETYPE type() const {
+            return mType;
+        }
+    private:
+        std::string mName;
+        OMX_ANDROID_VENDOR_VALUETYPE mType;
+    };
+
+    // helper to build a list of variable number or params
+    struct ParamListBuilder {
+        ParamListBuilder (std::initializer_list<Param> l)
+            : mParams(l) {}
+    private:
+        friend struct VendorExtension;
+        std::vector<Param> mParams;
+    };
+
+    VendorExtension(OMX_INDEXTYPE id, const char *name, OMX_DIRTYPE dir,
+            const ParamListBuilder& p);
+
+    // getters
+    OMX_INDEXTYPE extensionIndex() const {
+        return (OMX_INDEXTYPE)mId;
+    }
+    const char *name() const {
+        return mName.c_str();
+    }
+    OMX_U32 paramCount() const {
+        return (OMX_U32)mParams.size();
+    }
+    bool isSet() const {
+        return mIsSet;
+    }
+
+    // (the only) setter
+    void set() const {
+        mIsSet = true;
+    }
+
+    // copy extension Info to OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE* struct passed (except data)
+    OMX_ERRORTYPE copyInfoTo(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext) const;
+
+    // Type-aware data copy methods
+    // (NOTE: data here is passed explicitly to avoid this class having to know all types)
+    // returns true if value was written
+    bool setParamInt32(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey,
+            OMX_S32 setInt32) const;
+    bool setParamInt64(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey,
+            OMX_S32 setInt64) const;
+    bool setParamString(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey,
+            const char *setStr) const;
+
+    // read-values are updated ONLY IF the param[paramIndex] is set by client
+    // returns true if value was read
+    bool readParamInt32(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey,
+            OMX_S32 *readInt32) const;
+    bool readParamInt64(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey,
+            OMX_S32 *readInt64) const;
+    bool readParamInt64(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey,
+            char *readStr) const;
+
+    // Sanity checkers
+    // Check if the extension-name, port-dir, allotted params match
+    //    for each param, check if key and type both match
+    // Must be called to check whether config data provided with setConfig is valid
+    OMX_ERRORTYPE isConfigValid(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext) const;
+
+    // utils
+    static const char* typeString(OMX_ANDROID_VENDOR_VALUETYPE type);
+    std::string debugString() const;
+
+private:
+    // Id assigned to the extension
+    OMX_INDEXTYPE mId;
+    // Name of the extension
+    std::string mName;
+    // Port that this setting applies to
+    OMX_DIRTYPE mPortDir;
+    // parameters required for this extension
+    std::vector<Param> mParams;
+    // Flag that indicates client has set this extension.
+    mutable bool mIsSet;
+
+    // check if the index is valid, name matches, type matches and is set
+    // This must be called to verify config-data passed with setConfig()
+    bool _isParamAccessOK(
+            OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, int paramIndex) const;
+
+    // check if the index is valid, check against explicit type
+    bool _isParamAccessTypeOK(
+            OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, int paramIndex,
+            OMX_ANDROID_VENDOR_VALUETYPE type) const;
+
+    int indexOfParam(const char *key) const;
+};
+
+/*
+ * Store(List) of all vendor extensions *that are supported* by a component.
+ * The list is populated (per-component) at init, based on the capabilities.
+ * The store is immutable once created, except for setting the flag to indicate
+ * -whether the extension was set by the Client
+ */
+struct VendorExtensionStore {
+    VendorExtensionStore()
+        : mInvalid(VendorExtension((OMX_INDEXTYPE)-1, "invalid", OMX_DirMax, {{}})) {
+    }
+
+    VendorExtensionStore(const VendorExtensionStore&) = delete;
+    VendorExtensionStore& operator= (const VendorExtensionStore&) = delete;
+
+    void add(const VendorExtension& _e) {
+        mExt.push_back(_e);
+    }
+    const VendorExtension& operator[] (OMX_U32 index) const {
+        return index < mExt.size() ? mExt[index] : mInvalid;
+    }
+    OMX_U32 size() const {
+        return mExt.size();
+    }
+    void dumpExtensions(const char *prefix) const;
+
+private:
+    std::vector<VendorExtension> mExt;
+    VendorExtension mInvalid;
+};
+
+// Macros to help add extensions
+#define ADD_EXTENSION(_name, _extIndex, _dir)                                   \
+    store.add(VendorExtension((OMX_INDEXTYPE)_extIndex, _name, _dir, {          \
+
+#define ADD_PARAM(_key, _type)                                                             \
+    {_key, _type},
+
+#define ADD_PARAM_END(_key, _type)                                                             \
+    {_key, _type} }));
+
+#endif // _VIDC_VENDOR_ENXTENSIONS_H_
diff --git a/msm8996/mm-video-v4l2/vidc/common/src/vidc_vendor_extensions.cpp b/msm8996/mm-video-v4l2/vidc/common/src/vidc_vendor_extensions.cpp
new file mode 100644
index 0000000..bc69b1f
--- /dev/null
+++ b/msm8996/mm-video-v4l2/vidc/common/src/vidc_vendor_extensions.cpp
@@ -0,0 +1,268 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2017, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#define LOG_TAG "OMX-VENDOR-EXT"
+#include <utils/Log.h>
+#include "vidc_debug.h"
+
+#include "OMX_Core.h"
+#include "OMX_QCOMExtns.h"
+#include "OMX_VideoExt.h"
+#include "OMX_IndexExt.h"
+#include "vidc_vendor_extensions.h"
+
+VendorExtension::VendorExtension(OMX_INDEXTYPE id, const char *name, OMX_DIRTYPE dir,
+        const ParamListBuilder& p)
+    : mId(id),
+      mName(name),
+      mPortDir(dir),
+      mParams(std::move(p.mParams)),
+      mIsSet(false) {
+}
+
+// copy extension Info to OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE* struct passed
+OMX_ERRORTYPE VendorExtension::copyInfoTo(
+        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext) const {
+
+    // Extension info
+    strncpy((char *)ext->cName, mName.c_str(), OMX_MAX_STRINGNAME_SIZE);
+    ext->eDir = mPortDir;
+    ext->nParamCount = paramCount();
+
+    // Per-parameter info
+    // Must be copied only if there are enough params to fill-in
+    if (ext->nParamSizeUsed < ext->nParamCount) {
+        return OMX_ErrorNone;
+    }
+
+    int i = 0;
+    for (const Param& p : mParams) {
+        strncpy((char *)ext->nParam[i].cKey, p.name(), OMX_MAX_STRINGNAME_SIZE);
+        ext->nParam[i].bSet = mIsSet ? OMX_TRUE : OMX_FALSE;
+        ext->nParam[i].eValueType = p.type();
+        ++i;
+    }
+    return OMX_ErrorNone;
+}
+
+bool VendorExtension::setParamInt32(
+        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey,
+        OMX_S32 setInt32) const {
+    int paramIndex = indexOfParam(paramKey);
+    if (!_isParamAccessTypeOK(ext, paramIndex, OMX_AndroidVendorValueInt32)) {
+        return false;
+    }
+    ext->nParam[paramIndex].nInt32 = setInt32;
+    return true;
+}
+
+bool VendorExtension::setParamInt64(
+        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey,
+        OMX_S32 setInt64) const {
+    int paramIndex = indexOfParam(paramKey);
+    if (!_isParamAccessTypeOK(ext, paramIndex, OMX_AndroidVendorValueInt64)) {
+        return false;
+    }
+    ext->nParam[paramIndex].nInt64 = setInt64;
+    return true;
+}
+
+bool VendorExtension::setParamString(
+        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey,
+        const char *setStr) const {
+    int paramIndex = indexOfParam(paramKey);
+    if (!_isParamAccessTypeOK(ext, paramIndex, OMX_AndroidVendorValueString)) {
+        return false;
+    }
+    strncpy((char *)ext->nParam[paramIndex].cString, setStr, OMX_MAX_STRINGVALUE_SIZE);
+    return true;
+}
+
+bool VendorExtension::readParamInt32(
+        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey,
+        OMX_S32 *readInt32) const {
+    int paramIndex = indexOfParam(paramKey);
+    if (!_isParamAccessTypeOK(ext, paramIndex, OMX_AndroidVendorValueInt32)) {
+        return false;
+    }
+    if (ext->nParam[paramIndex].bSet == OMX_TRUE) {
+        *readInt32 = ext->nParam[paramIndex].nInt32;
+        return true;
+    }
+    return false;
+}
+
+bool VendorExtension::readParamInt64(
+        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey,
+        OMX_S32 *readInt64) const {
+    int paramIndex = indexOfParam(paramKey);
+    if (!_isParamAccessTypeOK(ext, paramIndex, OMX_AndroidVendorValueInt64)) {
+        return false;
+    }
+    if (ext->nParam[paramIndex].bSet == OMX_TRUE) {
+        *readInt64 = ext->nParam[paramIndex].nInt64;
+        return true;
+    }
+    return false;
+}
+
+bool VendorExtension::readParamInt64(
+            OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, const char *paramKey,
+            char *readStr) const {
+    int paramIndex = indexOfParam(paramKey);
+    if (!_isParamAccessTypeOK(ext, paramIndex, OMX_AndroidVendorValueString)) {
+        return false;
+    }
+    if (ext->nParam[paramIndex].bSet == OMX_TRUE) {
+        strncpy(readStr,
+                (const char *)ext->nParam[paramIndex].cString, OMX_MAX_STRINGVALUE_SIZE);
+        return true;
+    }
+    return false;
+}
+
+// Checkers
+OMX_ERRORTYPE VendorExtension::isConfigValid(
+    OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext) const {
+    ALOGI("isConfigValid");
+
+    if (ext->nParamSizeUsed < ext->nParamCount) {
+        DEBUG_PRINT_ERROR("allotted params(%u) < required(%u) for %s",
+                ext->nParamSizeUsed, ext->nParamCount, mName.c_str());
+        return OMX_ErrorBadParameter;
+    }
+    if (ext->nParamCount != paramCount()) {
+        DEBUG_PRINT_ERROR("incorrect param count(%u) v/s required(%u) for %s",
+                ext->nParamCount, paramCount(), mName.c_str());
+        return OMX_ErrorBadParameter;
+    }
+    if (strncmp((char *)ext->cName, mName.c_str(), OMX_MAX_STRINGNAME_SIZE) != 0) {
+        DEBUG_PRINT_ERROR("extension name mismatch(%s) v/s expected(%s)",
+                (char *)ext->cName, mName.c_str());
+        return OMX_ErrorBadParameter;
+    }
+
+    for (OMX_U32 i = 0; i < paramCount(); ++i) {
+        if (!_isParamAccessOK(ext, i)) {
+            ALOGI("_isParamAccessOK failed for %u", i);
+            return OMX_ErrorBadParameter;
+        }
+    }
+
+    return OMX_ErrorNone;
+}
+
+//static
+const char* VendorExtension::typeString(OMX_ANDROID_VENDOR_VALUETYPE type) {
+    switch (type) {
+        case OMX_AndroidVendorValueInt32: return "Int32";
+        case OMX_AndroidVendorValueInt64: return "Int64";
+        case OMX_AndroidVendorValueString: return "String";
+        default: return "InvalidType";
+    }
+}
+
+std::string VendorExtension::debugString() const {
+    std::string str = "vendor." + mName + "{";
+    for (const Param& p : mParams) {
+        str += "{ ";
+        str += p.name();
+        str += " : ";
+        str += typeString(p.type());
+        str += " },  ";
+    }
+    str += "}";
+    return str;
+}
+
+bool VendorExtension::_isParamAccessTypeOK(
+        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, int paramIndex,
+        OMX_ANDROID_VENDOR_VALUETYPE type) const {
+    if (paramIndex < 0
+            || paramIndex >= (int)ext->nParamSizeUsed
+            || paramIndex >= (int)paramCount()) {
+        DEBUG_PRINT_ERROR("Invalid Param index(%d) for %s (max=%u)",
+                paramIndex, mName.c_str(), paramCount());
+        return false;
+    }
+    if (type != mParams[paramIndex].type()) {
+        DEBUG_PRINT_ERROR("Invalid Type for field(%s) for %s.%s (expected=%s)",
+                typeString(type), mName.c_str(), mParams[paramIndex].name(),
+                typeString(mParams[paramIndex].type()));
+        return false;
+    }
+    return true;
+}
+
+bool VendorExtension::_isParamAccessOK(
+        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext, int paramIndex) const {
+    if (paramIndex < 0
+            || paramIndex >= (int)ext->nParamSizeUsed
+            || paramIndex >= (int)paramCount()) {
+        DEBUG_PRINT_ERROR("Invalid Param index(%d) for %s (max=%u)",
+                paramIndex, mName.c_str(), paramCount());
+        return false;
+    }
+    if (ext->nParam[paramIndex].eValueType != mParams[paramIndex].type()) {
+        DEBUG_PRINT_ERROR("Invalid Type for field(%s) for %s.%s (expected=%s)",
+                typeString(ext->nParam[paramIndex].eValueType),
+                mName.c_str(), mParams[paramIndex].name(),
+                typeString(mParams[paramIndex].type()));
+        return false;
+    }
+    if (strncmp((const char *)ext->nParam[paramIndex].cKey,
+            mParams[paramIndex].name(), OMX_MAX_STRINGNAME_SIZE) != 0) {
+        DEBUG_PRINT_ERROR("Invalid Key for field(%s) for %s.%s (expected=%s)",
+                ext->nParam[paramIndex].cKey,
+                mName.c_str(), mParams[paramIndex].name(),
+                mParams[paramIndex].name());
+        return false;
+    }
+    return true;
+}
+
+int VendorExtension::indexOfParam(const char *key) const {
+    int i = 0;
+    for (const Param& p : mParams) {
+        if (!strncmp(key, p.name(), OMX_MAX_STRINGNAME_SIZE)) {
+            return i;
+        }
+        ++i;
+    }
+    DEBUG_PRINT_ERROR("Failed to lookup param(%s) in extension(%s)",
+            key, mName.c_str());
+    return -1;
+}
+
+void VendorExtensionStore::dumpExtensions(const char *prefix) const {
+    DEBUG_PRINT_HIGH("%s : Vendor extensions supported (%u)", prefix, size());
+    for (const VendorExtension& v : mExt) {
+        DEBUG_PRINT_HIGH("   %s", v.debugString().c_str());
+    }
+}
diff --git a/msm8996/mm-video-v4l2/vidc/vdec/Android.mk b/msm8996/mm-video-v4l2/vidc/vdec/Android.mk
index a1c04ea..9ae425c 100644
--- a/msm8996/mm-video-v4l2/vidc/vdec/Android.mk
+++ b/msm8996/mm-video-v4l2/vidc/vdec/Android.mk
@@ -108,6 +108,7 @@
 
 LOCAL_MODULE                    := libOmxVdec
 LOCAL_MODULE_TAGS               := optional
+LOCAL_PROPRIETARY_MODULE        := true
 LOCAL_CFLAGS                    := $(libmm-vdec-def) -Werror
 LOCAL_C_INCLUDES                += $(libmm-vdec-inc)
 LOCAL_ADDITIONAL_DEPENDENCIES   := $(libmm-vdec-add-dep)
@@ -116,6 +117,7 @@
 LOCAL_SHARED_LIBRARIES  := liblog libutils libbinder libcutils libdl
 
 LOCAL_SHARED_LIBRARIES  += libqdMetaData
+LOCAL_HEADER_LIBRARIES  := copybit_headers gralloc_headers
 
 LOCAL_SRC_FILES         := src/frameparser.cpp
 LOCAL_SRC_FILES         += src/h264_utils.cpp
@@ -141,6 +143,7 @@
 
 LOCAL_MODULE                    := libOmxVdecHevc
 LOCAL_MODULE_TAGS               := optional
+LOCAL_PROPRIETARY_MODULE        := true
 LOCAL_CFLAGS                    := $(libmm-vdec-def)
 LOCAL_C_INCLUDES                += $(libmm-vdec-inc)
 LOCAL_ADDITIONAL_DEPENDENCIES   := $(libmm-vdec-add-dep)
@@ -180,6 +183,7 @@
 
 LOCAL_MODULE                  := libOmxSwVdec
 LOCAL_MODULE_TAGS             := optional
+LOCAL_PROPRIETARY_MODULE      := true
 LOCAL_CFLAGS                  := $(libmm-vdec-def)
 LOCAL_C_INCLUDES              += $(libmm-vdec-inc)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libmm-vdec-add-dep)
diff --git a/msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
index d400fc3..95b9621 100644
--- a/msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
+++ b/msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
@@ -107,6 +107,7 @@
 #include "ts_parser.h"
 #include "vidc_color_converter.h"
 #include "vidc_debug.h"
+#include "vidc_vendor_extensions.h"
 #ifdef _ANDROID_
 #include <cutils/properties.h>
 #else
@@ -142,6 +143,10 @@
 //                       Module specific globals
 //////////////////////////////////////////////////////////////////////////////
 #define OMX_SPEC_VERSION  0x00000101
+#define OMX_INIT_STRUCT(_s_, _name_)         \
+    memset((_s_), 0x0, sizeof(_name_));      \
+(_s_)->nSize = sizeof(_name_);               \
+(_s_)->nVersion.nVersion = OMX_SPEC_VERSION  \
 
 
 //////////////////////////////////////////////////////////////////////////////
@@ -990,6 +995,7 @@
         OMX_U32 m_reconfig_width;
         OMX_U32 m_reconfig_height;
         bool m_smoothstreaming_mode;
+        bool m_decode_order_mode;
 
         bool m_input_pass_buffer_fd;
         DescribeColorAspectsParams m_client_color_space;
@@ -1173,6 +1179,15 @@
         static OMX_ERRORTYPE describeColorFormat(OMX_PTR params);
         void prefetchNewBuffers();
 
+        OMX_ERRORTYPE get_vendor_extension_config(
+                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext);
+        OMX_ERRORTYPE set_vendor_extension_config(
+                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext);
+
+        void init_vendor_extensions (VendorExtensionStore&);
+
+        // list of extensions is not mutable after initialization
+        const VendorExtensionStore mVendorExtensionStore;
 };
 
 #ifdef _MSM8974_
diff --git a/msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_extensions.hpp b/msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_extensions.hpp
new file mode 100644
index 0000000..ac6d629
--- /dev/null
+++ b/msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_extensions.hpp
@@ -0,0 +1,128 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2017, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+void omx_vdec::init_vendor_extensions (VendorExtensionStore &store) {
+
+    //TODO: add extensions based on Codec, m_platform and/or other capability queries
+
+    ADD_EXTENSION("qti-ext-dec-picture-order", OMX_QcomIndexParamVideoDecoderPictureOrder, OMX_DirOutput)
+    ADD_PARAM_END("enable", OMX_AndroidVendorValueInt32)
+}
+
+
+OMX_ERRORTYPE omx_vdec::get_vendor_extension_config(
+                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext) {
+    if (ext->nIndex >= mVendorExtensionStore.size()) {
+        return OMX_ErrorNoMore;
+    }
+
+    const VendorExtension& vExt = mVendorExtensionStore[ext->nIndex];
+    DEBUG_PRINT_LOW("VendorExt: getConfig: index=%u (%s)", ext->nIndex, vExt.name());
+
+    vExt.copyInfoTo(ext);
+    if (ext->nParamSizeUsed < vExt.paramCount()) {
+        // this happens during initial getConfig to query only extension-name and param-count
+        return OMX_ErrorNone;
+    }
+
+    // We now have sufficient params allocated in extension data passed.
+    // Following code is to set the extension-specific data
+
+    bool setStatus = true;
+
+    switch ((OMX_U32)vExt.extensionIndex()) {
+        case OMX_QcomIndexParamVideoDecoderPictureOrder:
+        {
+            setStatus &= vExt.setParamInt32(ext, "enable", m_decode_order_mode);
+            break;
+        }
+        default:
+        {
+            return OMX_ErrorNotImplemented;
+        }
+    }
+    return setStatus ? OMX_ErrorNone : OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE omx_vdec::set_vendor_extension_config(
+                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext) {
+
+    ALOGI("set_vendor_extension_config");
+    if (ext->nIndex >= mVendorExtensionStore.size()) {
+        DEBUG_PRINT_ERROR("unrecognized vendor extension index (%u) max(%u)",
+                ext->nIndex, mVendorExtensionStore.size());
+        return OMX_ErrorBadParameter;
+    }
+
+    const VendorExtension& vExt = mVendorExtensionStore[ext->nIndex];
+    DEBUG_PRINT_LOW("VendorExt: setConfig: index=%u (%s)", ext->nIndex, vExt.name());
+
+    OMX_ERRORTYPE err = OMX_ErrorNone;
+    err = vExt.isConfigValid(ext);
+    if (err != OMX_ErrorNone) {
+        return err;
+    }
+
+    // mark this as set, regardless of set_config succeeding/failing.
+    // App will know by inconsistent values in output-format
+    vExt.set();
+
+    bool valueSet = false;
+    switch ((OMX_U32)vExt.extensionIndex()) {
+        case OMX_QcomIndexParamVideoDecoderPictureOrder:
+        {
+            OMX_S32 pic_order_enable = 0;
+            valueSet |= vExt.readParamInt32(ext, "enable", &pic_order_enable);
+            if (!valueSet) {
+                break;
+            }
+
+            DEBUG_PRINT_HIGH("VENDOR-EXT: set_config: OMX_QcomIndexParamVideoDecoderPictureOrder : %d",
+                    pic_order_enable);
+
+            QOMX_VIDEO_DECODER_PICTURE_ORDER decParam;
+            OMX_INIT_STRUCT(&decParam, QOMX_VIDEO_DECODER_PICTURE_ORDER);
+            decParam.eOutputPictureOrder =
+                    pic_order_enable ? QOMX_VIDEO_DECODE_ORDER : QOMX_VIDEO_DISPLAY_ORDER;
+
+            err = set_parameter(
+                    NULL, (OMX_INDEXTYPE)OMX_QcomIndexParamVideoDecoderPictureOrder, &decParam);
+            if (err != OMX_ErrorNone) {
+                DEBUG_PRINT_ERROR("set_config: OMX_QcomIndexParamVideoDecoderPictureOrder failed !");
+            }
+            break;
+        }
+        default:
+        {
+            return OMX_ErrorNotImplemented;
+        }
+    }
+
+    return err;
+}
diff --git a/msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp b/msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
index 9d041e9..154d45d 100644
--- a/msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
+++ b/msm8996/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
@@ -787,6 +787,7 @@
     m_smoothstreaming_mode = false;
     m_smoothstreaming_width = 0;
     m_smoothstreaming_height = 0;
+    m_decode_order_mode = false;
     is_q6_platform = false;
     m_perf_control.send_hint_to_mpctl(true);
     m_input_pass_buffer_fd = false;
@@ -2536,6 +2537,12 @@
         }
     }
 
+    {
+        VendorExtensionStore *extStore = const_cast<VendorExtensionStore *>(&mVendorExtensionStore);
+        init_vendor_extensions(*extStore);
+        mVendorExtensionStore.dumpExtensions((const char *)role);
+    }
+
     if (eRet != OMX_ErrorNone) {
         DEBUG_PRINT_ERROR("Component Init Failed");
     } else {
@@ -4472,6 +4479,8 @@
                                              eRet = OMX_ErrorUnsupportedSetting;
                                          }
                                      }
+                                     m_decode_order_mode =
+                                            pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER;
                                      break;
                                  }
         case OMX_QcomIndexParamConcealMBMapExtraData:
@@ -5068,10 +5077,20 @@
 
             break;
         }
-        default: {
-                 DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
-                 eRet = OMX_ErrorBadParameter;
-             }
+        case OMX_IndexConfigAndroidVendorExtension:
+        {
+            VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
+
+            OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
+                reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
+            VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
+            return get_vendor_extension_config(ext);
+        }
+        default:
+        {
+            DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
+            eRet = OMX_ErrorBadParameter;
+        }
 
     }
 
@@ -5290,6 +5309,14 @@
         print_debug_color_aspects(&(params->sAspects), "Set Config");
         memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
         return ret;
+    } else if ((int)configIndex == (int)OMX_IndexConfigAndroidVendorExtension) {
+        VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
+
+        OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
+                reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
+        VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
+
+        return set_vendor_extension_config(ext);
     }
 
     return OMX_ErrorNotImplemented;
@@ -12339,3 +12366,7 @@
     }
 }
 
+// No code beyond this !
+
+// inline import of vendor-extensions implementation
+#include "omx_vdec_extensions.hpp"
diff --git a/msm8996/mm-video-v4l2/vidc/venc/Android.mk b/msm8996/mm-video-v4l2/vidc/venc/Android.mk
index 25e9601..e1da46b 100644
--- a/msm8996/mm-video-v4l2/vidc/venc/Android.mk
+++ b/msm8996/mm-video-v4l2/vidc/venc/Android.mk
@@ -82,6 +82,7 @@
 
 LOCAL_MODULE                    := libOmxVenc
 LOCAL_MODULE_TAGS               := optional
+LOCAL_PROPRIETARY_MODULE        := true
 LOCAL_CFLAGS                    := $(libmm-venc-def)
 LOCAL_C_INCLUDES                := $(libmm-venc-inc)
 LOCAL_ADDITIONAL_DEPENDENCIES   := $(libmm-venc-add-dep)
@@ -90,6 +91,7 @@
 LOCAL_SHARED_LIBRARIES    := liblog libutils libbinder libcutils \
                              libc2dcolorconvert libdl libgui
 LOCAL_SHARED_LIBRARIES    += libqdMetaData
+LOCAL_HEADER_LIBRARIES    := copybit_headers gralloc_headers
 LOCAL_STATIC_LIBRARIES    := libOmxVidcCommon
 
 LOCAL_SRC_FILES   := src/omx_video_base.cpp
@@ -110,6 +112,7 @@
 LOCAL_MODULE                    := libOmxSwVencMpeg4
 
 LOCAL_MODULE_TAGS               := optional
+LOCAL_PROPRIETARY_MODULE        := true
 LOCAL_CFLAGS                    := $(libmm-venc-def)
 LOCAL_C_INCLUDES                := $(libmm-venc-inc)
 LOCAL_ADDITIONAL_DEPENDENCIES   := $(libmm-venc-add-dep)
@@ -136,6 +139,7 @@
 
 LOCAL_MODULE                    := libOmxSwVencHevc
 LOCAL_MODULE_TAGS               := optional
+LOCAL_PROPRIETARY_MODULE        := true
 LOCAL_CFLAGS                    := $(libmm-venc-def)
 LOCAL_C_INCLUDES                := $(libmm-venc-inc)
 LOCAL_ADDITIONAL_DEPENDENCIES   := $(libmm-venc-add-dep)
diff --git a/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_base.h b/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
index 351c011..f97bcd7 100644
--- a/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
+++ b/msm8996/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
@@ -68,6 +68,8 @@
 #include <dlfcn.h>
 #include "C2DColorConverter.h"
 #include "vidc_debug.h"
+#include <vector>
+#include "vidc_vendor_extensions.h"
 
 #ifdef _ANDROID_
 using namespace android;
@@ -565,6 +567,15 @@
         bool is_conv_needed(int, int);
         void print_debug_color_aspects(ColorAspects *aspects, const char *prefix);
 
+        OMX_ERRORTYPE get_vendor_extension_config(
+                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext);
+        OMX_ERRORTYPE set_vendor_extension_config(
+                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext);
+        void init_vendor_extensions(VendorExtensionStore&);
+        // Extensions-store is immutable after initialization (i.e cannot add/remove/change
+        //  extensions once added !)
+        const VendorExtensionStore mVendorExtensionStore;
+
 #ifdef USE_ION
         int alloc_map_ion_memory(int size,
                                  struct ion_allocation_data *alloc_data,
@@ -642,6 +653,7 @@
         OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE m_sParamTemporalLayers;
         OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE m_sConfigTemporalLayers;
         DescribeColorAspectsParams m_sConfigColorAspects;
+        QOMX_ENABLETYPE m_sParamAVTimerTimestampMode;   // use VT-timestamps in gralloc-handle
 
         // fill this buffer queue
         omx_cmd_queue m_ftb_q;
diff --git a/msm8996/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h b/msm8996/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
index 8ad2235..74978d4 100644
--- a/msm8996/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
+++ b/msm8996/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
@@ -356,6 +356,7 @@
         bool venc_set_config(void *configData, OMX_INDEXTYPE index);
         bool venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel);
         bool venc_get_seq_hdr(void *, unsigned, unsigned *);
+        bool venc_get_dimensions(OMX_U32 portIndex, OMX_U32 *w, OMX_U32 *h);
         bool venc_loaded_start(void);
         bool venc_loaded_stop(void);
         bool venc_loaded_start_done(void);
@@ -598,6 +599,7 @@
             static inline int getTimeStampAt(native_handle_t *, int index);
         };
         BatchInfo mBatchInfo;
+        bool mUseAVTimerTimestamps;
 };
 
 enum instance_state {
diff --git a/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp b/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
index 691ede8..87f8d42 100644
--- a/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
+++ b/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
@@ -2282,6 +2282,16 @@
                 }
                 break;
             }
+        case OMX_IndexConfigAndroidVendorExtension:
+            {
+                VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
+
+                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
+                    reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
+                VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
+                return get_vendor_extension_config(ext);
+            }
+
         default:
             DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
             return OMX_ErrorUnsupportedIndex;
@@ -2914,6 +2924,14 @@
     if (index < m_sInPortDef.nBufferCountActual && m_pInput_pmem) {
         auto_lock l(m_lock);
 
+        if (mUseProxyColorFormat) {
+            if (m_opq_pmem_q.m_size) {
+                unsigned long addr, p1, id;
+                m_opq_pmem_q.pop_entry(&addr, &p1, &id);
+                DEBUG_PRINT_LOW("Removed entry in m_opq_pmem_q: address %lu", addr);
+            }
+        }
+
         if (m_pInput_pmem[index].fd > 0 && input_use_buffer == false) {
             DEBUG_PRINT_LOW("FreeBuffer:: i/p AllocateBuffer case");
             if(!secure_session) {
@@ -5290,3 +5308,8 @@
     --pending_input_buffers;
     return retVal;
 }
+
+// no code beyond this !
+
+// inline import of vendor extensions implementation
+#include "omx_video_extensions.hpp"
diff --git a/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp b/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
index c216eee..74c2869 100644
--- a/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
+++ b/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
@@ -556,6 +556,9 @@
 
     OMX_INIT_STRUCT(&m_sConfigTemporalLayers, OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE);
 
+    OMX_INIT_STRUCT(&m_sParamAVTimerTimestampMode, QOMX_ENABLETYPE);
+    m_sParamAVTimerTimestampMode.bEnable = OMX_FALSE;
+
     m_state                   = OMX_StateLoaded;
     m_sExtraData = 0;
 
@@ -600,6 +603,13 @@
     }
 
     DEBUG_PRINT_INFO("Component_init : %s : return = 0x%x", m_nkind, eRet);
+
+    {
+        VendorExtensionStore *extStore = const_cast<VendorExtensionStore *>(&mVendorExtensionStore);
+        init_vendor_extensions(*extStore);
+        mVendorExtensionStore.dumpExtensions((const char *)m_nkind);
+    }
+
     return eRet;
 init_error:
     handle->venc_close();
@@ -1658,6 +1668,17 @@
                         OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS * sizeof(OMX_U32));
                 break;
             }
+        case OMX_QTIIndexParamEnableAVTimerTimestamps:
+            {
+                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+                if (!handle->venc_set_param(paramData,
+                            (OMX_INDEXTYPE)OMX_QTIIndexParamEnableAVTimerTimestamps)) {
+                    DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamEnableAVTimerTimestamps failed");
+                    return OMX_ErrorUnsupportedSetting;
+                }
+                memcpy(&m_sParamAVTimerTimestampMode, paramData, sizeof(QOMX_ENABLETYPE));
+                break;
+            }
         case OMX_IndexParamVideoSliceFMO:
         default:
             {
@@ -1922,6 +1943,15 @@
                 } else {
                     m_sConfigFrameRotation.nRotation = pParam->nRotation;
                 }
+
+                // Update output-port resolution (since it might have been flipped by rotation)
+                if (handle->venc_get_dimensions(PORT_INDEX_OUT,
+                        &m_sOutPortDef.format.video.nFrameWidth,
+                        &m_sOutPortDef.format.video.nFrameHeight)) {
+                    DEBUG_PRINT_HIGH("set Rotation: updated dimensions = %u x %u",
+                            m_sOutPortDef.format.video.nFrameWidth,
+                            m_sOutPortDef.format.video.nFrameHeight);
+                }
                 break;
             }
         case OMX_QcomIndexConfigVideoFramePackingArrangement:
@@ -2117,6 +2147,17 @@
                memcpy(&m_sConfigColorAspects, configData, sizeof(m_sConfigColorAspects));
                break;
            }
+        case OMX_IndexConfigAndroidVendorExtension:
+            {
+                VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
+
+                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext =
+                    reinterpret_cast<OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *>(configData);
+                VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext);
+
+                return set_vendor_extension_config(ext);
+            }
+
         default:
             DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
             break;
diff --git a/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_extensions.hpp b/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_extensions.hpp
new file mode 100644
index 0000000..5be091e
--- /dev/null
+++ b/msm8996/mm-video-v4l2/vidc/venc/src/omx_video_extensions.hpp
@@ -0,0 +1,241 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2017, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+void omx_video::init_vendor_extensions(VendorExtensionStore &store) {
+
+    //TODO: add extensions based on Codec, m_platform and/or other capability queries
+
+    ADD_EXTENSION("qti-ext-enc-preprocess-rotate", OMX_IndexConfigCommonRotate, OMX_DirOutput)
+    ADD_PARAM_END("angle", OMX_AndroidVendorValueInt32)
+
+    ADD_EXTENSION("qti-ext-enc-avc-intra-period", OMX_IndexConfigVideoAVCIntraPeriod, OMX_DirOutput)
+    ADD_PARAM    ("n-pframes",    OMX_AndroidVendorValueInt32)
+    ADD_PARAM_END("n-idr-period", OMX_AndroidVendorValueInt32)
+
+    ADD_EXTENSION("qti-ext-enc-error-correction", OMX_IndexParamVideoErrorCorrection, OMX_DirOutput)
+    ADD_PARAM_END("resync-marker-spacing-bits", OMX_AndroidVendorValueInt32)
+
+    ADD_EXTENSION("qti-ext-enc-custom-profile-level", OMX_IndexParamVideoProfileLevelCurrent, OMX_DirOutput)
+    ADD_PARAM    ("profile", OMX_AndroidVendorValueInt32)
+    ADD_PARAM_END("level",   OMX_AndroidVendorValueInt32)
+
+    ADD_EXTENSION("qti-ext-enc-timestamp-source-avtimer", OMX_QTIIndexParamEnableAVTimerTimestamps, OMX_DirInput)
+    ADD_PARAM_END("enable", OMX_AndroidVendorValueInt32)
+}
+
+OMX_ERRORTYPE omx_video::get_vendor_extension_config(
+                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext) {
+    if (ext->nIndex >= mVendorExtensionStore.size()) {
+        return OMX_ErrorNoMore;
+    }
+
+    const VendorExtension& vExt = mVendorExtensionStore[ext->nIndex];
+    DEBUG_PRINT_LOW("VendorExt: getConfig: index=%u (%s)", ext->nIndex, vExt.name());
+
+    vExt.copyInfoTo(ext);
+    if (ext->nParamSizeUsed < vExt.paramCount()) {
+        // this happens during initial getConfig to query only extension-name and param-count
+        return OMX_ErrorNone;
+    }
+
+    // We now have sufficient params allocated in extension data passed.
+    // Following code is to set the extension-specific data
+
+    bool setStatus = true;
+
+    switch ((OMX_U32)vExt.extensionIndex()) {
+        case OMX_IndexConfigCommonRotate:
+        {
+            setStatus &= vExt.setParamInt32(ext, "angle", m_sConfigFrameRotation.nRotation);
+            break;
+        }
+        case OMX_IndexConfigVideoAVCIntraPeriod:
+        {
+            setStatus &= vExt.setParamInt32(ext, "n-pframes", m_sConfigAVCIDRPeriod.nPFrames);
+            setStatus &= vExt.setParamInt32(ext, "n-idr-period", m_sConfigAVCIDRPeriod.nIDRPeriod);
+            break;
+        }
+        case OMX_IndexParamVideoErrorCorrection:
+        {
+            // "bits" @0
+            setStatus &= vExt.setParamInt32(ext,
+                    "resync-marker-spacing-bits", m_sErrorCorrection.nResynchMarkerSpacing);
+            break;
+        }
+        case OMX_IndexParamVideoProfileLevelCurrent:
+        {
+            setStatus &= vExt.setParamInt32(ext, "profile", m_sParamProfileLevel.eProfile);
+            setStatus &= vExt.setParamInt32(ext, "level", m_sParamProfileLevel.eLevel);
+
+            break;
+        }
+        case OMX_QTIIndexParamEnableAVTimerTimestamps:
+        {
+            setStatus &= vExt.setParamInt32(ext, "enable", m_sParamAVTimerTimestampMode.bEnable);
+            break;
+        }
+        default:
+        {
+            return OMX_ErrorNotImplemented;
+        }
+    }
+    return setStatus ? OMX_ErrorNone : OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE omx_video::set_vendor_extension_config(
+                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext) {
+
+    ALOGI("set_vendor_extension_config");
+    if (ext->nIndex >= mVendorExtensionStore.size()) {
+        DEBUG_PRINT_ERROR("unrecognized vendor extension index (%u) max(%u)",
+                ext->nIndex, mVendorExtensionStore.size());
+        return OMX_ErrorBadParameter;
+    }
+
+    const VendorExtension& vExt = mVendorExtensionStore[ext->nIndex];
+    DEBUG_PRINT_LOW("VendorExt: setConfig: index=%u (%s)", ext->nIndex, vExt.name());
+
+    OMX_ERRORTYPE err = OMX_ErrorNone;
+    err = vExt.isConfigValid(ext);
+    if (err != OMX_ErrorNone) {
+        return err;
+    }
+
+    // mark this as set, regardless of set_config succeeding/failing.
+    // App will know by inconsistent values in output-format
+    vExt.set();
+
+    bool valueSet = false;
+    switch ((OMX_U32)vExt.extensionIndex()) {
+        case OMX_IndexConfigCommonRotate:
+        {
+            OMX_CONFIG_ROTATIONTYPE rotationParam;
+            memcpy(&rotationParam, &m_sConfigFrameRotation, sizeof(OMX_CONFIG_ROTATIONTYPE));
+            valueSet |= vExt.readParamInt32(ext, "angle", &rotationParam.nRotation);
+            if (!valueSet) {
+                break;
+            }
+
+            DEBUG_PRINT_HIGH("VENDOR-EXT: set_config: OMX_IndexConfigCommonRotate : %d",
+                    rotationParam.nRotation);
+
+            err = set_config(
+                    NULL, OMX_IndexConfigCommonRotate, &rotationParam);
+            if (err != OMX_ErrorNone) {
+                DEBUG_PRINT_ERROR("set_config: OMX_IndexConfigCommonRotate failed !");
+            }
+            break;
+        }
+        case OMX_IndexConfigVideoAVCIntraPeriod:
+        {
+            OMX_VIDEO_CONFIG_AVCINTRAPERIOD idrConfig;
+            memcpy(&idrConfig, &m_sConfigAVCIDRPeriod, sizeof(OMX_VIDEO_CONFIG_AVCINTRAPERIOD));
+            valueSet |= vExt.readParamInt32(ext, "n-pframes", (OMX_S32 *)&(idrConfig.nPFrames));
+            valueSet |= vExt.readParamInt32(ext, "n-idr-period", (OMX_S32 *)&(idrConfig.nIDRPeriod));
+            if (!valueSet) {
+                break;
+            }
+
+            DEBUG_PRINT_HIGH("VENDOR-EXT: set_config: AVC-intra-period : nP=%d, nIDR=%d",
+                    idrConfig.nPFrames, idrConfig.nIDRPeriod);
+
+            err = set_config(
+                    NULL, OMX_IndexConfigVideoAVCIntraPeriod, &idrConfig);
+            if (err != OMX_ErrorNone) {
+                DEBUG_PRINT_ERROR("set_config: OMX_IndexConfigVideoAVCIntraPeriod failed !");
+            }
+            break;
+        }
+        case OMX_IndexParamVideoErrorCorrection:
+        {
+            OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE ecParam;
+            memcpy(&ecParam, &m_sErrorCorrection, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE));
+            valueSet |= vExt.readParamInt32(ext,
+                    "resync-marker-spacing-bits", (OMX_S32 *)&(ecParam.nResynchMarkerSpacing));
+            if (!valueSet) {
+                break;
+            }
+
+            DEBUG_PRINT_HIGH("VENDOR-EXT: set_config: resync-marker-spacing : %d bits",
+                    ecParam.nResynchMarkerSpacing);
+
+            err = set_parameter(
+                    NULL, OMX_IndexParamVideoErrorCorrection, &ecParam);
+            if (err != OMX_ErrorNone) {
+                DEBUG_PRINT_ERROR("set_config: OMX_IndexParamVideoErrorCorrection failed !");
+            }
+            break;
+        }
+        case OMX_IndexParamVideoProfileLevelCurrent:
+        {
+            OMX_VIDEO_PARAM_PROFILELEVELTYPE profileParam;
+            memcpy(&profileParam, &m_sParamProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE));
+            valueSet |= vExt.readParamInt32(ext, "profile", (OMX_S32 *)&(profileParam.eProfile));
+            valueSet |= vExt.readParamInt32(ext, "level", (OMX_S32 *)&(profileParam.eLevel));
+            if (!valueSet) {
+                break;
+            }
+
+            DEBUG_PRINT_HIGH("VENDOR-EXT: set_config: custom-profile/level : profile=%u level=%u",
+                    (OMX_U32)profileParam.eProfile, (OMX_U32)profileParam.eLevel);
+
+            err = set_parameter(
+                    NULL, OMX_IndexParamVideoProfileLevelCurrent, &profileParam);
+            if (err != OMX_ErrorNone) {
+                DEBUG_PRINT_ERROR("set_config: OMX_IndexParamVideoProfileLevelCurrent failed !");
+            }
+
+            break;
+        }
+        case OMX_QTIIndexParamEnableAVTimerTimestamps:
+        {
+            QOMX_ENABLETYPE avTimerEnableParam;
+            memcpy(&avTimerEnableParam, &m_sParamAVTimerTimestampMode, sizeof(QOMX_ENABLETYPE));
+            valueSet |= vExt.readParamInt32(ext, "enable", (OMX_S32 *)&(avTimerEnableParam.bEnable));
+            if (!valueSet) {
+                break;
+            }
+
+            DEBUG_PRINT_HIGH("VENDOR-EXT: AV-timer timestamp mode enable=%u", avTimerEnableParam.bEnable);
+
+            err = set_parameter(
+                    NULL, (OMX_INDEXTYPE)OMX_QTIIndexParamEnableAVTimerTimestamps, &avTimerEnableParam);
+            if (err != OMX_ErrorNone) {
+                DEBUG_PRINT_ERROR("set_param: OMX_QTIIndexParamEnableAVTimerTimestamps failed !");
+            }
+
+            break;
+        }
+        default:
+        {
+            return OMX_ErrorNotImplemented;
+        }
+    }
+    return err;
+}
diff --git a/msm8996/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/msm8996/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
index 76bd24a..ed0ce88 100644
--- a/msm8996/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
+++ b/msm8996/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
@@ -236,6 +236,9 @@
     color_format = 0;
     hw_overload = false;
     mBatchSize = 0;
+    m_profile_set = false;
+    m_level_set = false;
+    rc_off_level = 0;
     pthread_mutex_init(&pause_resume_mlock, NULL);
     pthread_cond_init(&pause_resume_cond, NULL);
     memset(&idrperiod, 0, sizeof(idrperiod));
@@ -304,6 +307,8 @@
     }
     snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX,
              "%s", BUFFER_LOG_LOC);
+
+    mUseAVTimerTimestamps = false;
 }
 
 venc_dev::~venc_dev()
@@ -1451,6 +1456,22 @@
     return true;
 }
 
+bool venc_dev::venc_get_dimensions(OMX_U32 portIndex, OMX_U32 *w, OMX_U32 *h) {
+    struct v4l2_format fmt;
+    memset(&fmt, 0, sizeof(fmt));
+    fmt.type = portIndex == PORT_INDEX_OUT ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
+            V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+    if (ioctl(m_nDriver_fd, VIDIOC_G_FMT, &fmt)) {
+        DEBUG_PRINT_ERROR("Failed to get format on %s port",
+                portIndex == PORT_INDEX_OUT ? "capture" : "output");
+        return false;
+    }
+    *w = fmt.fmt.pix_mp.width;
+    *h = fmt.fmt.pix_mp.height;
+    return true;
+}
+
 bool venc_dev::venc_get_buf_req(OMX_U32 *min_buff_count,
         OMX_U32 *actual_buff_count,
         OMX_U32 *buff_size,
@@ -2309,6 +2330,13 @@
                 }
                 break;
             }
+        case OMX_QTIIndexParamEnableAVTimerTimestamps:
+            {
+                QOMX_ENABLETYPE *pParam = (QOMX_ENABLETYPE *)paramData;
+                mUseAVTimerTimestamps = pParam->bEnable == OMX_TRUE;
+                DEBUG_PRINT_INFO("AVTimer timestamps enabled");
+                break;
+            }
         case OMX_IndexParamVideoSliceFMO:
         default:
             DEBUG_PRINT_ERROR("ERROR: Unsupported parameter in venc_set_param: %u",
@@ -3501,8 +3529,22 @@
                             fd, plane[0].bytesused, plane[0].length, buf.flags, m_sVenc_cfg.inputformat);
                 } else if (meta_buf->buffer_type == kMetadataBufferTypeGrallocSource) {
                     private_handle_t *handle = (private_handle_t *)meta_buf->meta_handle;
-                    if (!streaming[OUTPUT_PORT] && handle) {
 
+                    if (!handle) {
+                        DEBUG_PRINT_ERROR("%s : handle is null!", __FUNCTION__);
+                        return false;
+                    }
+
+                    if (mUseAVTimerTimestamps) {
+                        uint64_t avTimerTimestampNs = bufhdr->nTimeStamp * 1000;
+                        if (getMetaData(handle, GET_VT_TIMESTAMP, &avTimerTimestampNs) == 0
+                                && avTimerTimestampNs > 0) {
+                            bufhdr->nTimeStamp = avTimerTimestampNs / 1000;
+                            DEBUG_PRINT_LOW("AVTimer TS : %llu us", (unsigned long long)bufhdr->nTimeStamp);
+                        }
+                    }
+
+                    if (!streaming[OUTPUT_PORT]) {
                         // Moment of truth... actual colorspace is known here..
                         ColorSpace_t colorSpace = ITU_R_601;
                         if (getMetaData(handle, GET_COLOR_SPACE, &colorSpace) == 0) {
@@ -5766,6 +5808,15 @@
 
     memset(&fmt, 0, sizeof(fmt));
     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+    if (rotation_angle == 90 || rotation_angle == 270) {
+        OMX_U32 nWidth = m_sVenc_cfg.dvs_height;
+        OMX_U32 nHeight = m_sVenc_cfg.dvs_width;
+        m_sVenc_cfg.dvs_height = nHeight;
+        m_sVenc_cfg.dvs_width = nWidth;
+        DEBUG_PRINT_LOW("Rotation (%u) Flipping wxh to %lux%lu",
+                rotation_angle, m_sVenc_cfg.dvs_width, m_sVenc_cfg.dvs_height);
+    }
+
     fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
     fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
     fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.codectype;
diff --git a/msm8998/Makefile.am b/msm8998/Makefile.am
index aa14ba8..4315263 100644
--- a/msm8998/Makefile.am
+++ b/msm8998/Makefile.am
@@ -2,4 +2,10 @@
 #
 ACLOCAL_AMFLAGS = -I m4
 
-SUBDIRS = mm-core mm-video-v4l2
\ No newline at end of file
+BUILD_COMPONENTS := mm-core
+
+if BUILD_MM_VIDEO
+BUILD_COMPONENTS += mm-video-v4l2
+endif
+
+SUBDIRS := $(BUILD_COMPONENTS)
diff --git a/msm8998/configure.ac b/msm8998/configure.ac
index 2228410..e00ba47 100644
--- a/msm8998/configure.ac
+++ b/msm8998/configure.ac
@@ -31,6 +31,11 @@
                 [Enable conditional compile for target msm8953 [default=no]]),
         [target_msm8953="${enableval}"])
 
+AC_ARG_ENABLE([target-msm8909],
+        AC_HELP_STRING([--enable-target-msm8909],
+                [Enable conditional compile for target msm8909 [default=no]]),
+        [target_msm8909="${enableval}"])
+
 AC_ARG_ENABLE([target-msm8996],
         AC_HELP_STRING([--enable-target-msm8996],
                 [Enable conditional compile for target msm8996 [default=no]]),
@@ -46,6 +51,11 @@
                 [Enable conditional compile for target msm8610 [default=no]]),
         [target_msm8226="${enableval}"])
 
+AC_ARG_ENABLE([target-msm8937],
+        AC_HELP_STRING([--enable-target-msm8937],
+                [Enable conditional compile for target msm8937 [default=no]]),
+        [target_msm8937="${enableval}"])
+
 AC_ARG_ENABLE([is-ubwc-supported],
         AC_HELP_STRING([--enable-ubwc-supported],
                 [Enable conditional compile for target msm8953 [default=no]]),
@@ -56,6 +66,11 @@
                 [Enable conditional compile for target msm8953 [default=no]]),
         [targets_that_support_pq="${enableval}"])
 
+AC_ARG_ENABLE([targets-that-support-vqzip],
+        AC_HELP_STRING([--enable-targets-that-support-vqzip],
+                [Enable conditional compile for target msm8953 [default=no]]),
+        [targets_that_support_vqzip="${enableval}"])
+
 AC_ARG_ENABLE([target-uses-ion],
         AC_HELP_STRING([--enable-target-uses-ion],
                 [Enable conditional compile for target target-uses-ion [default=no]]),
@@ -76,11 +91,21 @@
                 [Enable conditional compile for target master_side_cp_target_list [default=no]]),
         [master_side_cp_target_list="${enableval}"])
 
+AC_ARG_ENABLE([targets-that-use-hevc-adsp-heap],
+        AC_HELP_STRING([-targets-that-use-hevc-adsp-heap],
+                [Enable conditional compile for target target-uses-ion [default=no]]),
+        [targets_that_use_hevc_adsp_heap="${enableval}"])
+
 AC_ARG_ENABLE([use-glib],
         AC_HELP_STRING([--enable-use-glib],
                 [Enable conditional compile for use glib [default=no]]),
         [use_glib="${enableval}"])
 
+AC_ARG_ENABLE([build-mm-video],
+        AC_HELP_STRING([--enable-use-glib],
+                [Enable conditional compile for use glib [default=no]]),
+        [build_mm_video="${enableval}"])
+
 AC_ARG_WITH([sanitized-headers],
         [AS_HELP_STRING([--with-sanitized-headers=DIR],[location of the sanitized Linux kernel headers])],
         [CPPFLAGS="$CPPFLAGS -I $withval"])
@@ -113,6 +138,10 @@
         [AS_HELP_STRING([--with-libgpustats-headers=DIR],[location of common headers])],
         [CPPFLAGS="$CPPFLAGS -I$withval"])
 
+AC_ARG_WITH([libpqstats-headers],
+        [AS_HELP_STRING([--with-libpqstats-headers=DIR],[location of common headers])],
+        [CPPFLAGS="$CPPFLAGS -I$withval"])
+
 AC_ARG_WITH([ui-headers],
         [AS_HELP_STRING([--with-ui-inc=DIR],[location of common headers])],
         [CPPFLAGS="$CPPFLAGS -I$withval"])
@@ -133,21 +162,29 @@
         [AS_HELP_STRING([--with-binder-inc=DIR],[location of common headers])],
         [CPPFLAGS="$CPPFLAGS -I$withval"])
 
+AC_ARG_WITH([qdutils-headers],
+        [AS_HELP_STRING([--with-binder-inc=DIR],[location of common headers])],
+        [CPPFLAGS="$CPPFLAGS -I$withval"])
+
 AC_ARG_WITH([glib-lib-dir],
         [AS_HELP_STRING([--with-binder-inc=DIR],[location of common headers])],
         [CPPFLAGS="$CPPFLAGS -I$withval"])
 
 AM_CONDITIONAL(TARGET_MSM8953, [test "x$target_msm8953" = "xyes"])
+AM_CONDITIONAL(TARGET_MSM8909, [test "x$target_msm8909" = "xyes"])
 AM_CONDITIONAL(TARGET_MSM8996, [test "x$target_msm8996" = "xyes"])
 AM_CONDITIONAL(TARGET_MSM8610, [test "x$target_msm8610" = "xyes"])
 AM_CONDITIONAL(TARGET_MSM8226, [test "x$target_msm8226" = "xyes"])
+AM_CONDITIONAL(TARGET_MSM8937, [test "x$target_msm8937" = "xyes"])
 AM_CONDITIONAL(TARGETS_THAT_SUPPORT_UBWC, [test "x$targets_that_support_ubwc" = "xyes"])
 AM_CONDITIONAL(TARGETS_THAT_SUPPORT_PQ, [test "x$targets_that_support_pq" = "xyes"])
+AM_CONDITIONAL(TARGETS_THAT_SUPPORT_VQZIP, [test "x$targets_that_support_vqzip" = "xyes"])
 AM_CONDITIONAL(TARGET_USES_ION, [test "x$target_uses_ion" = "xyes"])
 AM_CONDITIONAL(TARGETS_THAT_USE_FLAG_MSM8226, [test "x$targets_that_use_flag_msm8226" = "xyes"])
 AM_CONDITIONAL(TARGET_USES_MEDIA_EXTENSIONS, [test "x$target_uses_media_extensions" = "xyes"])
 AM_CONDITIONAL(MASTER_SIDE_CP_TARGET_LIST, [test "x$master_side_cp_target_list" = "xyes"])
 AM_CONDITIONAL(USE_GLIB, [test "x$use_glib" = "xyes"])
+AM_CONDITIONAL(BUILD_MM_VIDEO, [test "x$build_mm_video" = "xyes"])
 
 AC_ARG_WITH([glib],
       AC_HELP_STRING([--with-glib],
@@ -170,5 +207,6 @@
         mm-video-v4l2/Makefile \
         mm-video-v4l2/vidc/Makefile \
         mm-video-v4l2/vidc/venc/Makefile \
+        mm-video-v4l2/vidc/vdec/Makefile \
         ])
 AC_OUTPUT
diff --git a/msm8998/mm-core/Android.mk b/msm8998/mm-core/Android.mk
index 6584953..a14e714 100644
--- a/msm8998/mm-core/Android.mk
+++ b/msm8998/mm-core/Android.mk
@@ -50,6 +50,8 @@
 MM_CORE_TARGET = msm8953
 else ifeq ($(TARGET_BOARD_PLATFORM),msm8998)
 MM_CORE_TARGET = msm8998
+else ifeq ($(TARGET_BOARD_PLATFORM),sdm660)
+MM_CORE_TARGET = sdm660
 else
 MM_CORE_TARGET = default
 endif
@@ -100,9 +102,13 @@
 LOCAL_SHARED_LIBRARIES  := liblog libdl libcutils
 LOCAL_CFLAGS            := $(OMXCORE_CFLAGS)
 
+#ifneq (,$(filter msm8996 msm8998 sdm660,$(TARGET_BOARD_PLATFORM)))
+#LOCAL_SHARED_LIBRARIES  += libgpustats
+#endif
+
 LOCAL_SRC_FILES         := src/common/omx_core_cmp.cpp
 LOCAL_SRC_FILES         += src/common/qc_omx_core.c
-ifneq (,$(filter msm8916 msm8994 msm8909 msm8937 msm8996 msm8992 msm8952 msm8953 msm8998,$(TARGET_BOARD_PLATFORM)))
+ifneq (,$(filter msm8916 msm8994 msm8909 msm8937 msm8996 msm8992 msm8952 msm8953 msm8998 sdm660,$(TARGET_BOARD_PLATFORM)))
 LOCAL_SRC_FILES         += src/$(MM_CORE_TARGET)/registry_table_android.c
 else
 LOCAL_SRC_FILES         += src/$(MM_CORE_TARGET)/qc_registry_table_android.c
@@ -124,9 +130,13 @@
 LOCAL_SHARED_LIBRARIES  := liblog libdl libcutils
 LOCAL_CFLAGS            := $(OMXCORE_CFLAGS)
 
+#ifneq (,$(filter msm8996 msm8998 sdm660,$(TARGET_BOARD_PLATFORM)))
+#LOCAL_SHARED_LIBRARIES  += libgpustats
+#endif
+
 LOCAL_SRC_FILES         := src/common/omx_core_cmp.cpp
 LOCAL_SRC_FILES         += src/common/qc_omx_core.c
-ifneq (,$(filter msm8916 msm8994 msm8909 msm8937 msm8996 msm8992 msm8952 msm8953 msm8998,$(TARGET_BOARD_PLATFORM)))
+ifneq (,$(filter msm8916 msm8994 msm8909 msm8937 msm8996 msm8992 msm8952 msm8953 msm8998 sdm660,$(TARGET_BOARD_PLATFORM)))
 LOCAL_SRC_FILES         += src/$(MM_CORE_TARGET)/registry_table.c
 else
 LOCAL_SRC_FILES         += src/$(MM_CORE_TARGET)/qc_registry_table.c
diff --git a/msm8998/mm-core/Makefile.am b/msm8998/mm-core/Makefile.am
index 51f68da..011e155 100644
--- a/msm8998/mm-core/Makefile.am
+++ b/msm8998/mm-core/Makefile.am
@@ -10,7 +10,7 @@
 
 AM_CPPFLAGS = -D__packed__=
 AM_CPPFLAGS += -D_ANDROID_
-AM_CPPFLAGS += -D_ENABLE_QC_MSG_LOG_
+AM_CPPFLAGS += -U_ENABLE_QC_MSG_LOG_
 #AM_CPPFLAGS += -g -O3
 #AM_CPPFLAGS += -O0 -fno-inline -fno-short-enums
 AM_CPPFLAGS += -I$(top_srcdir)/mm-core/inc/
@@ -54,6 +54,14 @@
 TARGET_REGISTRY = msm8996
 endif
 
+if TARGET_MSM8909
+TARGET_REGISTRY = 8909
+endif
+
+if TARGET_MSM8937
+TARGET_REGISTRY = 8937
+endif
+
 c_sources +=src/${TARGET_REGISTRY}/registry_table_android.c
 
 lib_LTLIBRARIES = libOmxCore.la
@@ -61,8 +69,8 @@
 libOmxCore_la_SOURCES = $(c_sources)
 libOmxCore_la_CFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) -fPIC
 libOmxCore_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) -fPIC
-libOmxCore_la_LDFLAGS = -ldl -lrt -lpthread -lglib-2.0
-libOmxCore_la_LDFLAGS += -shared -version-info 0
+libOmxCore_la_LDFLAGS = -ldl -lrt -lpthread -lglib-2.0 -lcutils
+libOmxCore_la_LDFLAGS += -shared -avoid-version
 
 lib_LTLIBRARIES += libmm-omxcore.la
 
@@ -74,6 +82,6 @@
 libmm_omxcore_la_SOURCES = $(c_sources)
 libmm_omxcore_la_CFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) -fPIC
 libmm_omxcore_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) -fPIC
-libmm_omxcore_la_LDFLAGS = -ldl -lrt -lpthread -lglib-2.0
-libmm_omxcore_la_LDFLAGS += -shared -version-info 0
+libmm_omxcore_la_LDFLAGS = -ldl -lrt -lpthread -lglib-2.0 -lcutils
+libmm_omxcore_la_LDFLAGS += -shared -avoid-version
 
diff --git a/msm8998/mm-core/inc/OMX_QCOMExtns.h b/msm8998/mm-core/inc/OMX_QCOMExtns.h
index 5d81f1b..db13f54 100644
--- a/msm8998/mm-core/inc/OMX_QCOMExtns.h
+++ b/msm8998/mm-core/inc/OMX_QCOMExtns.h
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2009-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
@@ -636,6 +636,8 @@
     /* Dither control for 10bit */
     OMX_QTIIndexParamDitherControl = 0x7F000069,
 
+    /* Suggest how big Iframe sizes should be */
+    OMX_QTIIndexParamIframeSizeType = 0x7F000070,
 };
 
 /**
@@ -1344,6 +1346,7 @@
    OMX_QCOM_ASPECT_RATIO  aspectRatio;
    OMX_QCOM_DISPLAY_ASPECT_RATIO displayAspectRatio;
    OMX_U32                nConcealedMacroblocks;
+   OMX_U32                nRecoverySeiFlag;
    OMX_U32                nFrameRate;
    OMX_TICKS              nTimeStamp;
 } OMX_QCOM_EXTRADATA_FRAMEINFO;
@@ -1461,6 +1464,26 @@
    OMX_InterlaceFrameBottomFieldFirst
 } OMX_INTERLACES;
 
+typedef enum QOMX_VIDEO_RECOVERYSEITYPE {
+/*
+ * 0: Frame reconstruction is incorrect
+ *   a) Open Gop, frames before recovery point SEI
+ * 1: Frame reconstruction is correct.
+ *   a) Closed Gop, When decoding starts from the top of closed GOP at IDR
+ *   b) Open Gop, Output at and subsequent to recovery point SEI with
+ *      exact_match_flag = true
+ * 2: Frame reconstruction is approximately correct:
+ *   a) Closed Gop, When decoding starts from a P/B/I frames wihtout
+ *      any recovery point SEI information
+ *   b) Open Gop, Output at and subsequent to recovery point SEI with
+ *      exact_match_flag = false
+ * In case flag is set to 0 or 2, DATACORRUPT shall be enabled
+ * for buffer (nFlags) in FILL_BUFFER_DONE
+ */
+    OMX_FRAME_RECONSTRUCTION_INCORRECT = 0,
+    OMX_FRAME_RECONSTRUCTION_CORRECT = 1,
+    OMX_FRAME_RECONSTRUCTION_APPROXIMATELY_CORRECT = 2
+} QOMX_VIDEO_RECOVERYSEI;
 
 #define OMX_EXTRADATA_HEADER_SIZE 20
 
@@ -1886,6 +1909,18 @@
    OMX_U32 nCabacInitIdc;
 } QOMX_VIDEO_H264ENTROPYCODINGTYPE;
 
+typedef enum QOMX_VIDEO_IFRAMESIZE_TYPE {
+    QOMX_IFRAMESIZE_DEFAULT,
+    QOMX_IFRAMESIZE_MEDIUM,
+    QOMX_IFRAMESIZE_HUGE,
+    QOMX_IFRAMESIZE_UNLIMITED,
+} QOMX_VIDEO_IFRAMESIZE_TYPE;
+
+typedef struct QOMX_VIDEO_IFRAMESIZE {
+   OMX_U32 nSize;
+   OMX_VERSIONTYPE nVersion;
+   QOMX_VIDEO_IFRAMESIZE_TYPE eType;
+} QOMX_VIDEO_IFRAMESIZE;
 
 /* VIDEO POSTPROCESSING CTRLS AND ENUMS */
 /* MUST KEEP SAME AS IN vpp.h */
@@ -2034,6 +2069,8 @@
 
 #if defined(__cplusplus) && defined(USE_CAMERA_METABUFFER_UTILS)
 
+#define CAM_META_BUFFER_EVENT_PERF 0x01
+
 /**
  * Camera1 meta-buffer payload create/access/modify utility
  */
@@ -2046,7 +2083,8 @@
         INT_TIMESTAMP   = 4,
         INT_COLORFORMAT = 5,
         INT_BUFINDEX    = 6,
-        INT_TOTAL       = INT_BUFINDEX,
+        INT_BUFEVENT    = 7,
+        INT_TOTAL       = INT_BUFEVENT,
     };
 
     static int getNumFdsForBatch(int batchSize) {
diff --git a/msm8998/mm-core/inc/OMX_VideoExt.h b/msm8998/mm-core/inc/OMX_VideoExt.h
index 8abe5e4..79561c5 100644
--- a/msm8998/mm-core/inc/OMX_VideoExt.h
+++ b/msm8998/mm-core/inc/OMX_VideoExt.h
@@ -112,6 +112,8 @@
 typedef enum OMX_VIDEO_HEVCPROFILETYPE {
     OMX_VIDEO_HEVCProfileMain    = 0x01,
     OMX_VIDEO_HEVCProfileMain10  = 0x02,
+    // Main10 profile with HDR SEI support.
+    OMX_VIDEO_HEVCProfileMain10HDR10  = 0x1000,
     OMX_VIDEO_HEVCProfileUnknown = 0x6EFFFFFF,
     OMX_VIDEO_HEVCProfileMax      = 0x7FFFFFFF
 } OMX_VIDEO_HEVCPROFILETYPE;
diff --git a/msm8998/mm-core/mm-core.pc.in b/msm8998/mm-core/mm-core.pc.in
new file mode 100644
index 0000000..5ac2706
--- /dev/null
+++ b/msm8998/mm-core/mm-core.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: mm-core
+Description: mm-core library
+Version: @VERSION@
+Libs: -L${libdir} -lOmxCore -lmm-omxcore
+Cflags: -I${includedir}/mm-core/omxcore
diff --git a/msm8998/mm-core/src/8909/registry_table.c b/msm8998/mm-core/src/8909/registry_table.c
index b6b0c0f..c8b6ad9 100644
--- a/msm8998/mm-core/src/8909/registry_table.c
+++ b/msm8998/mm-core/src/8909/registry_table.c
@@ -222,6 +222,103 @@
       "audio_encoder.amrnb"
     }
   },
+      {
+    "OMX.qcom.audio.encoder.g711mlaw",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL,
+      NULL,
+      NULL,
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxG711Enc.so",
+    {
+      "audio_encoder.g711"
+    }
+  },
+  {
+    "OMX.qcom.audio.encoder.g711alaw",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL,
+      NULL,
+      NULL,
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxG711Enc.so",
+    {
+      "audio_encoder.g711"
+    }
+  },
+  {
+    "OMX.qcom.audio.encoder.amrwb",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxAmrEnc.so",
+    {
+      "audio_encoder.amrwb"
+    }
+  },
+  {
+    "OMX.qcom.audio.decoder.g711mlaw",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxG711Dec.so",
+    {
+      "audio_decoder.g711"
+    }
+  },
+  {
+    "OMX.qcom.audio.decoder.g711alaw",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxG711Dec.so",
+    {
+      "audio_decoder.g711"
+    }
+  },
+  {
+    "OMX.qcom.audio.decoder.amrwb",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxAmrDec.so",
+    {
+     "audio_decoder.amrwb"
+    }
+  },
+  {
+    "OMX.qcom.audio.decoder.amrnb",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxAmrDec.so",
+    {
+      "audio_decoder.amrnb"
+    }
+  },
  {
     "OMX.qcom.audio.decoder.aac",
     NULL,   // Create instance function
diff --git a/msm8998/mm-core/src/8909/registry_table_android.c b/msm8998/mm-core/src/8909/registry_table_android.c
index 94cbead..608bd2a 100644
--- a/msm8998/mm-core/src/8909/registry_table_android.c
+++ b/msm8998/mm-core/src/8909/registry_table_android.c
@@ -261,6 +261,103 @@
       "audio_encoder.amrnb"
     }
   },
+      {
+    "OMX.qcom.audio.encoder.g711mlaw",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL,
+      NULL,
+      NULL,
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxG711Enc.so",
+    {
+      "audio_encoder.g711"
+    }
+  },
+  {
+    "OMX.qcom.audio.encoder.g711alaw",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL,
+      NULL,
+      NULL,
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxG711Enc.so",
+    {
+      "audio_encoder.g711"
+    }
+  },
+  {
+    "OMX.qcom.audio.encoder.amrwb",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxAmrEnc.so",
+    {
+      "audio_encoder.amrwb"
+    }
+  },
+  {
+    "OMX.qcom.audio.decoder.g711mlaw",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxG711Dec.so",
+    {
+      "audio_decoder.g711"
+    }
+  },
+  {
+    "OMX.qcom.audio.decoder.g711alaw",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxG711Dec.so",
+    {
+      "audio_decoder.g711"
+    }
+  },
+  {
+    "OMX.qcom.audio.decoder.amrwb",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxAmrDec.so",
+    {
+     "audio_decoder.amrwb"
+    }
+  },
+  {
+    "OMX.qcom.audio.decoder.amrnb",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxAmrDec.so",
+    {
+      "audio_decoder.amrnb"
+    }
+  },
  {
     "OMX.qcom.audio.decoder.aac",
     NULL,   // Create instance function
diff --git a/msm8998/mm-core/src/8937/registry_table.c b/msm8998/mm-core/src/8937/registry_table.c
index d3aee99..3722631 100755
--- a/msm8998/mm-core/src/8937/registry_table.c
+++ b/msm8998/mm-core/src/8937/registry_table.c
@@ -477,6 +477,22 @@
     }
   },
   {
+    "OMX.qti.audio.decoder.flac.sw",
+    NULL, // Create instance function
+    // Unique instance handle
+    {
+      NULL,
+      NULL,
+      NULL,
+      NULL
+    },
+    NULL,  // Shared object library handle
+    "libOmxFlacDecSw.so",
+    {
+      "audio_decoder.flac"
+    }
+  },
+  {
     "OMX.qcom.audio.encoder.aac",
     NULL, // Create instance function
     // Unique instance handle
diff --git a/msm8998/mm-core/src/msm8953/registry_table.c b/msm8998/mm-core/src/msm8953/registry_table.c
index b6ac3ed..a2fa23c 100755
--- a/msm8998/mm-core/src/msm8953/registry_table.c
+++ b/msm8998/mm-core/src/msm8953/registry_table.c
@@ -557,6 +557,22 @@
     }
   },
   {
+    "OMX.qti.audio.decoder.flac.sw",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL,
+      NULL,
+      NULL,
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxFlacDecSw.so",
+    {
+      "audio_decoder.flac"
+    }
+  },
+  {
     "OMX.qcom.audio.encoder.aac",
     NULL, // Create instance function
     // Unique instance handle
diff --git a/msm8998/mm-core/src/msm8953/registry_table_android.c b/msm8998/mm-core/src/msm8953/registry_table_android.c
index b5aaa5f..0e9405f 100755
--- a/msm8998/mm-core/src/msm8953/registry_table_android.c
+++ b/msm8998/mm-core/src/msm8953/registry_table_android.c
@@ -612,6 +612,22 @@
     }
   },
   {
+    "OMX.qti.audio.decoder.flac.sw",
+    NULL,   // Create instance function
+    // Unique instance handle
+    {
+      NULL,
+      NULL,
+      NULL,
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxFlacDecSw.so",
+    {
+      "audio_decoder.flac"
+    }
+  },
+  {
     "OMX.qcom.audio.encoder.aac",
     NULL, // Create instance function
     // Unique instance handle
diff --git a/msm8998/mm-core/src/msmcobalt/registry_table.c b/msm8998/mm-core/src/sdm660/registry_table.c
similarity index 86%
rename from msm8998/mm-core/src/msmcobalt/registry_table.c
rename to msm8998/mm-core/src/sdm660/registry_table.c
index 7381960..c35ac9b 100644
--- a/msm8998/mm-core/src/msmcobalt/registry_table.c
+++ b/msm8998/mm-core/src/sdm660/registry_table.c
@@ -504,103 +504,6 @@
       "audio_encoder.amrnb"
     }
   },
-   {
-    "OMX.qcom.audio.encoder.g711mlaw",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxG711Enc.so",
-    {
-      "audio_encoder.g711"
-    }
-  },
-  {
-    "OMX.qcom.audio.encoder.g711alaw",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxG711Enc.so",
-    {
-      "audio_encoder.g711"
-    }
-  },
-  {
-    "OMX.qcom.audio.encoder.amrwb",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxAmrEnc.so",
-    {
-      "audio_encoder.amrwb"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.g711mlaw",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxG711Dec.so",
-    {
-      "audio_decoder.g711"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.g711alaw",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxG711Dec.so",
-    {
-      "audio_decoder.g711"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.amrwb",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxAmrDec.so",
-    {
-     "audio_decoder.amrwb"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.amrnb",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxAmrDec.so",
-    {
-      "audio_decoder.amrnb"
-    }
-  },
  {
     "OMX.qcom.audio.decoder.aac",
     NULL,   // Create instance function
@@ -634,6 +537,22 @@
     }
   },
   {
+    "OMX.qcom.video.postprocessing",
+    NULL, // Create instance function
+    // Unique instance handle
+    {
+      NULL,
+      NULL,
+      NULL,
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxVdpp.so",
+    {
+      "videopostprocessing"
+    }
+  },
+  {
     "OMX.qti.vdec.vpp",
     NULL, // Create instance function
     // Unique instance handle
diff --git a/msm8998/mm-core/src/msmcobalt/registry_table_android.c b/msm8998/mm-core/src/sdm660/registry_table_android.c
similarity index 90%
rename from msm8998/mm-core/src/msmcobalt/registry_table_android.c
rename to msm8998/mm-core/src/sdm660/registry_table_android.c
index 4997afe..1da53e6 100644
--- a/msm8998/mm-core/src/msmcobalt/registry_table_android.c
+++ b/msm8998/mm-core/src/sdm660/registry_table_android.c
@@ -726,103 +726,6 @@
       "audio_encoder.amrnb"
     }
   },
-   {
-    "OMX.qcom.audio.encoder.g711mlaw",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxG711Enc.so",
-    {
-      "audio_encoder.g711"
-    }
-  },
-  {
-    "OMX.qcom.audio.encoder.g711alaw",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL,
-      NULL,
-      NULL,
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxG711Enc.so",
-    {
-      "audio_encoder.g711"
-    }
-  },
-  {
-    "OMX.qcom.audio.encoder.amrwb",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxAmrEnc.so",
-    {
-      "audio_encoder.amrwb"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.g711mlaw",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxG711Dec.so",
-    {
-      "audio_decoder.g711"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.g711alaw",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxG711Dec.so",
-    {
-      "audio_decoder.g711"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.amrwb",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxAmrDec.so",
-    {
-     "audio_decoder.amrwb"
-    }
-  },
-  {
-    "OMX.qcom.audio.decoder.amrnb",
-    NULL,   // Create instance function
-    // Unique instance handle
-    {
-      NULL
-    },
-    NULL,   // Shared object library handle
-    "libOmxAmrDec.so",
-    {
-      "audio_decoder.amrnb"
-    }
-  },
  {
     "OMX.qcom.audio.decoder.aac",
     NULL,   // Create instance function
@@ -888,6 +791,22 @@
     }
   },
   {
+    "OMX.qcom.video.postprocessing",
+    NULL, // Create instance function
+    // Unique instance handle
+    {
+      NULL,
+      NULL,
+      NULL,
+      NULL
+    },
+    NULL,   // Shared object library handle
+    "libOmxVdpp.so",
+    {
+      "videopostprocessing"
+    }
+  },
+  {
     "OMX.qti.vdec.vpp",
     NULL, // Create instance function
     // Unique instance handle
diff --git a/msm8998/mm-video-v4l2/vidc/Makefile.am b/msm8998/mm-video-v4l2/vidc/Makefile.am
index 4621239..a0a1f3d 100644
--- a/msm8998/mm-video-v4l2/vidc/Makefile.am
+++ b/msm8998/mm-video-v4l2/vidc/Makefile.am
@@ -2,4 +2,4 @@
 #
 ACLOCAL_AMFLAGS = -I m4
 
-SUBDIRS = venc
+SUBDIRS = vdec venc
diff --git a/msm8998/mm-video-v4l2/vidc/common/src/extra_data_handler.cpp b/msm8998/mm-video-v4l2/vidc/common/src/extra_data_handler.cpp
index 187eb77..b7b931a 100644
--- a/msm8998/mm-video-v4l2/vidc/common/src/extra_data_handler.cpp
+++ b/msm8998/mm-video-v4l2/vidc/common/src/extra_data_handler.cpp
@@ -26,6 +26,10 @@
 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 --------------------------------------------------------------------------*/
 
+#include <inttypes.h>
+#include <cstddef>
+#include <qdMetaData.h>
+#include <gralloc_priv.h>
 #include "extra_data_handler.h"
 
 int debug_level = PRIO_ERROR;
diff --git a/msm8998/mm-video-v4l2/vidc/vdec/Android.mk b/msm8998/mm-video-v4l2/vidc/vdec/Android.mk
index c29710d..f2aa5db 100644
--- a/msm8998/mm-video-v4l2/vidc/vdec/Android.mk
+++ b/msm8998/mm-video-v4l2/vidc/vdec/Android.mk
@@ -28,7 +28,7 @@
 
 TARGETS_THAT_USE_HEVC_ADSP_HEAP := msm8226 msm8974
 TARGETS_THAT_HAVE_VENUS_HEVC := apq8084 msm8994 msm8996
-TARGETS_THAT_SUPPORT_UBWC := msm8996 msm8953 msm8998
+TARGETS_THAT_SUPPORT_UBWC := msm8996 msm8953 msm8998 sdm660
 TARGETS_THAT_NEED_SW_VDEC := msm8937
 
 ifeq ($(call is-board-platform-in-list, $(TARGETS_THAT_USE_HEVC_ADSP_HEAP)),true)
@@ -60,6 +60,8 @@
 libmm-vdec-def += -DMASTER_SIDE_CP
 endif
 
+libmm-vdec-def += -D_QUERY_DISP_RES_
+
 include $(CLEAR_VARS)
 
 # Common Includes
@@ -115,7 +117,7 @@
 LOCAL_ADDITIONAL_DEPENDENCIES   := $(libmm-vdec-add-dep)
 
 LOCAL_PRELINK_MODULE    := false
-LOCAL_SHARED_LIBRARIES  := liblog libutils libbinder libcutils libdl
+LOCAL_SHARED_LIBRARIES  := liblog libutils libbinder libcutils libdl libqdutils
 
 LOCAL_SHARED_LIBRARIES  += libqdMetaData
 
diff --git a/msm8998/mm-video-v4l2/vidc/vdec/Makefile.am b/msm8998/mm-video-v4l2/vidc/vdec/Makefile.am
index b80e6d2..284644a 100644
--- a/msm8998/mm-video-v4l2/vidc/vdec/Makefile.am
+++ b/msm8998/mm-video-v4l2/vidc/vdec/Makefile.am
@@ -7,12 +7,14 @@
 AM_CPPFLAGS := -D__alignx\(x\)=__attribute__\(\(__aligned__\(x\)\)\)
 AM_CPPFLAGS += -D__align=__alignx
 AM_CPPFLAGS += -Dinline=__inline
+AM_CPPFLAGS += -g -O3
 AM_CPPFLAGS += -DIMAGE_APPS_PROC
+AM_CPPFLAGS += -D_ANDROID_
 AM_CPPFLAGS += -DCDECL
 AM_CPPFLAGS += -DT_ARM
 AM_CPPFLAGS += -DNO_ARM_CLZ
 AM_CPPFLAGS += -UENABLE_DEBUG_LOW
-AM_CPPFLAGS += -DENABLE_DEBUG_HIGH
+AM_CPPFLAGS += -UENABLE_DEBUG_HIGH
 AM_CPPFLAGS += -DENABLE_DEBUG_ERROR
 AM_CPPFLAGS += -UINPUT_BUFFER_LOG
 AM_CPPFLAGS += -UOUTPUT_BUFFER_LOG
@@ -22,65 +24,52 @@
 AM_CPPFLAGS += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT
 AM_CPPFLAGS += -DMAX_RES_1080P
 AM_CPPFLAGS += -DMAX_RES_1080P_EBI
+#AM_CPPFLAGS += "-include stdint.h"
+AM_CPPFLAGS += "-Dstrlcpy=g_strlcpy"
+AM_CPPFLAGS += "-Dstrlcat=g_strlcat"
+AM_CPPFLAGS += "-std=c++11"
+AM_CPPFLAGS += "-DHAVE_ANDROID_OS"
+AM_CPPFLAGS += -DSYS_IOCTL
+AM_CPPFLAGS += -Wno-multichar
 
-if TARGET_MSM8960
-AM_CPPFLAGS += -DMAX_RES_1080P
-AM_CPPFLAGS += -DMAX_RES_1080P_EBI
-AM_CPPFLAGS += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT
+if USE_GLIB
+AM_CPPFLAGS += -D_USE_GLIB_
+endif
+
+if TARGET_MSM8610
+AM_CPPFLAGS += -DVENUS_HEVC
+endif
+
+if TARGETS_THAT_SUPPORT_UBWC
+AM_CPPFLAGS += -D_UBWC_
+endif
+
+if TARGET_USES_ION
 AM_CPPFLAGS += -DUSE_ION
 endif
 
-if TARGET_B_FAMILY
-AM_CPPFLAGS += -DMAX_RES_1080P
-AM_CPPFLAGS += -DMAX_RES_1080P_EBI
-AM_CPPFLAGS += -DPROCESS_EXTRADATA_IN_OUTPUT_PORT
-AM_CPPFLAGS += -DUSE_ION
-AM_CPPFLAGS += -D_MSM8974_
-#AM_CPPFLAGS += -D_HEVC_USE_ADSP_HEAP_
+if MASTER_SIDE_CP_TARGET_LIST
+AM_CPPFLAGS += -DMASTER_SIDE_CP
 endif
 
-AM_CPPFLAGS += -I./inc
-AM_CPPFLAGS += -I../common/inc
-AM_CPPFLAGS += -I../../../libc2dcolorconvert
-AM_CPPFLAGS += -I../../../mm-core/inc
-AM_CPPFLAGS += -I../../../mm-core/src/common
+AM_CPPFLAGS += -I$(top_srcdir)/mm-video-v4l2/vidc/common/inc/
+AM_CPPFLAGS += -I$(top_srcdir)/mm-video-v4l2/vidc/vdec/inc/
+AM_CPPFLAGS += -I$(top_srcdir)/libc2dcolorconvert/
+AM_CPPFLAGS += -I$(top_srcdir)/mm-core/inc/
+AM_CPPFLAGS += -I$(top_srcdir)/mm-core/src/common/
 
-c_sources = src/frameparser.cpp
-c_sources += src/h264_utils.cpp
-c_sources += src/ts_parser.cpp
-c_sources += src/mp4_utils.cpp
-
-if TARGET_MSM8960
-c_sources += src/omx_vdec.cpp
-endif
-
-if TARGET_B_FAMILY
-c_sources += src/omx_vdec_msm8974.cpp
-endif
-
-c_sources += ../common/src/extra_data_handler.cpp
-c_sources += ../common/src/vidc_color_converter.cpp
+c_sources         := src/frameparser.cpp
+c_sources         += src/h264_utils.cpp
+c_sources         += src/ts_parser.cpp
+c_sources         += src/mp4_utils.cpp
+c_sources         += src/hevc_utils.cpp
+c_sources         += src/omx_vdec_v4l2.cpp
+c_sources += $(top_srcdir)/mm-video-v4l2/vidc/common/src/extra_data_handler.cpp
+c_sources += $(top_srcdir)/mm-video-v4l2/vidc/common/src/vidc_color_converter.cpp
 
 lib_LTLIBRARIES = libOmxVdec.la
 libOmxVdec_la_SOURCES = $(c_sources)
 libOmxVdec_la_CFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) -fPIC
 libOmxVdec_la_CFLAGS += ../libc2d2colorconvert/libc2dcolorconvert.la
-libOmxVdec_la_LDFLAGS = -shared -version-info $(OMXVIDEO_LIBRARY_VERSION)
-
-bin_PROGRAMS = mm-vdec-omx-test
-
-mm_vdec_omx_test_CPPFLAGS = -I./inc
-mm_vdec_omx_test_CPPFLAGS += -I../../../mm-core/inc
-mm_vdec_omx_test_CPPFLAGS += -I../common/inc
-mm_vdec_omx_test_CPPFLAGS += -DUSE_ION
-mm_vdec_omx_test_CPPFLAGS += -D_NOFBMEM_
-
-if TARGET_B_FAMILY
-mm_vdec_omx_test_CPPFLAGS += -D_MSM8974_
-endif
-
-mm_vdec_omx_test_SOURCES := src/queue.c
-mm_vdec_omx_test_SOURCES += test/omx_vdec_test.cpp
-mm_vdec_omx_test_LDADD = -ldl -lpthread -lOmxCore
-mm_vdec_omx_test_LDADD +=  ./libOmxVdec.la
+libOmxVdec_la_LDFLAGS = -llog -lutils -lbinder -lcutils -ldl -lqdMetaData -lglib-2.0 -shared -version-info 0
 
diff --git a/msm8998/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/msm8998/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
index 05d6bc7..6b827c9 100644
--- a/msm8998/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
+++ b/msm8998/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010 - 2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2010 - 2017, The Linux Foundation. All rights reserved.
 
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
@@ -49,6 +49,7 @@
 #include <cstddef>
 #include <cutils/atomic.h>
 #include <qdMetaData.h>
+#include <color_metadata.h>
 
 static ptrdiff_t x;
 
@@ -243,6 +244,14 @@
     VIDC_NOMINAL = 1,
     VIDC_TURBO = 2
 };
+
+enum turbo_mode {
+    TURBO_MODE_NONE = 0x0,
+    TURBO_MODE_CLIENT_REQUESTED = 0x1,
+    TURBO_MODE_HIGH_FPS = 0x2,
+    TURBO_MODE_MAX = 0xFF
+};
+
 #ifdef USE_ION
 struct vdec_ion {
     int ion_device_fd;
@@ -251,6 +260,13 @@
 };
 #endif
 
+struct vdec_ion_map_info {
+    bool free_buffer;
+    unsigned char *base_address;
+    int map_size;
+    int offset;
+};
+
 #ifdef _MSM8974_
 struct extradata_buffer_info {
     unsigned long buffer_size;
@@ -283,6 +299,7 @@
     struct vdec_ion meta_buffer;
     struct vdec_ion meta_buffer_iommu;
 #endif
+    struct vdec_ion_map_info *op_buf_map_info;
     struct vdec_framerate frame_rate;
     unsigned extradata;
     bool timestamp_adjust;
@@ -697,13 +714,21 @@
         void convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
             OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space,
             ColorAspects *aspects);
-        bool handle_color_space_info(void *data, unsigned int buf_index);
+        bool handle_color_space_info(void *data,
+                                     ColorSpace_t *color_space,
+                                     ColorMetaData* color_mdata,
+                                     bool& set_color_aspects_only);
         void set_colorspace_in_handle(ColorSpace_t color, unsigned int buf_index);
         void print_debug_color_aspects(ColorAspects *aspects, const char *prefix);
         void print_debug_hdr_color_info(HDRStaticInfo *hdr_info, const char *prefix);
-        bool handle_content_light_level_info(void* data);
-        bool handle_mastering_display_color_info(void* data);
+        void print_debug_hdr_color_info_mdata(ColorMetaData* color_mdata);
+        bool handle_content_light_level_info(void* data, ContentLightLevel* light_level_mdata);
+        bool handle_mastering_display_color_info(void* data, MasteringDisplay* mastering_display_mdata);
         void print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra);
+        void set_colormetadata_in_handle(ColorMetaData *color_mdata, unsigned int buf_index);
+        void prepare_color_aspects_metadata(OMX_U32 primaries, OMX_U32 range,
+                                            OMX_U32 transfer, OMX_U32 matrix,
+                                            ColorMetaData *color_mdata);
 #ifdef _MSM8974_
         void append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
                 OMX_U32 interlaced_format_type);
@@ -711,6 +736,7 @@
                 bool enable = true);
         void append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
                 OMX_U32 num_conceal_mb,
+                OMX_U32 recovery_sei_flag,
                 OMX_U32 picture_type,
                 OMX_U32 frame_rate,
                 OMX_TICKS time_stamp,
@@ -723,6 +749,7 @@
 #endif
         void append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
                 OMX_U32 num_conceal_mb,
+                OMX_U32 recovery_sei_flag,
                 OMX_U32 picture_type,
                 OMX_S64 timestamp,
                 OMX_U32 frame_rate,
@@ -1034,9 +1061,10 @@
         DescribeHDRStaticInfoParams m_internal_hdr_info;
         bool m_change_client_hdr_info;
         pthread_mutex_t m_hdr_info_client_lock;
+        ColorMetaData m_color_mdata;
 
         OMX_U32 operating_frame_rate;
-        bool high_fps;
+        uint8_t m_need_turbo;
 
         OMX_U32 m_smoothstreaming_width;
         OMX_U32 m_smoothstreaming_height;
@@ -1045,6 +1073,7 @@
         bool is_thulium_v1;
         bool m_disable_ubwc_mode;
         bool m_disable_split_mode;
+        bool m_enable_downscalar;
         OMX_U32 m_downscalar_width;
         OMX_U32 m_downscalar_height;
         int decide_downscalar();
diff --git a/msm8998/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp b/msm8998/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
index 99b0c6e..7081cf6 100644
--- a/msm8998/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
+++ b/msm8998/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010 - 2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2010 - 2017, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
@@ -55,14 +55,23 @@
 #include <media/msm_media_info.h>
 #include <sys/eventfd.h>
 
-#ifndef _ANDROID_
+#if !defined(_ANDROID_) || defined(SYS_IOCTL)
 #include <sys/ioctl.h>
 #include <sys/mman.h>
-#endif //_ANDROID_
+#endif
 
 #ifdef _ANDROID_
 #include <cutils/properties.h>
 #undef USE_EGL_IMAGE_GPU
+
+#ifdef _QUERY_DISP_RES_
+#include "display_config.h"
+#endif
+#endif
+
+#ifdef _USE_GLIB_
+#include <glib.h>
+#define strlcpy g_strlcpy
 #endif
 
 #include <qdMetaData.h>
@@ -150,6 +159,9 @@
 
 #define LUMINANCE_DIV_FACTOR 10000.0
 
+#define MIN(x,y) (((x) < (y)) ? (x) : (y))
+#define MAX(x,y) (((x) > (y)) ? (x) : (y))
+
 static OMX_U32 maxSmoothStreamingWidth = 1920;
 static OMX_U32 maxSmoothStreamingHeight = 1088;
 
@@ -253,19 +265,27 @@
                 }
             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
                 struct vdec_msginfo vdec_msg;
-                vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
+                uint32_t flush_type = *(uint32_t *)dqevent.u.data;
+                // Old driver doesn't send flushType information.
+                // To make this backward compatible fallback to old approach
+                // if the flush_type is not present.
                 vdec_msg.status_code=VDEC_S_SUCCESS;
-                DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
-                if (omx->async_message_process(input,&vdec_msg) < 0) {
-                    DEBUG_PRINT_HIGH("async_message_thread Exited");
-                    break;
+                if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_OUTPUT)) {
+                    vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
+                    DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
+                    if (omx->async_message_process(input,&vdec_msg) < 0) {
+                        DEBUG_PRINT_HIGH("async_message_thread Exited");
+                        break;
+                    }
                 }
-                vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
-                vdec_msg.status_code=VDEC_S_SUCCESS;
-                DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
-                if (omx->async_message_process(input,&vdec_msg) < 0) {
-                    DEBUG_PRINT_HIGH("async_message_thread Exited");
-                    break;
+
+                if (!flush_type || (flush_type & V4L2_QCOM_CMD_FLUSH_CAPTURE)) {
+                    vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
+                    DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
+                    if (omx->async_message_process(input,&vdec_msg) < 0) {
+                        DEBUG_PRINT_HIGH("async_message_thread Exited");
+                        break;
+                    }
                 }
             } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
                 struct vdec_msginfo vdec_msg;
@@ -569,7 +589,7 @@
 {
     char platform_name[PROPERTY_VALUE_MAX] = {0};
     property_get("ro.board.platform", platform_name, "0");
-    if (!strncmp(platform_name, "msm8998", 9)) {
+    if (!strncmp(platform_name, "msm8998", 7)) {
         DEBUG_PRINT_HIGH("TP10 on capture port is supported");
         return true;
     }
@@ -661,6 +681,7 @@
     allocate_native_handle(false),
     m_other_extradata(NULL),
     m_profile(0),
+    m_need_turbo(0),
     client_set_fps(false),
     stereo_output_mode(HAL_NO_3D),
     m_last_rendered_TS(-1),
@@ -773,6 +794,7 @@
     memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
     memset(&m_client_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
     memset(&m_internal_hdr_info, 0, sizeof(DescribeHDRStaticInfoParams));
+    memset(&m_color_mdata, 0, sizeof(ColorMetaData));
     m_demux_entries = 0;
     msg_thread_id = 0;
     async_thread_id = 0;
@@ -809,6 +831,7 @@
     dynamic_buf_mode = false;
     out_dynamic_list = NULL;
     is_down_scalar_enabled = false;
+    m_enable_downscalar = 0;
     m_downscalar_width = 0;
     m_downscalar_height = 0;
     m_force_down_scalar = 0;
@@ -1213,6 +1236,7 @@
     struct v4l2_format fmt;
     enum color_fmts color_format;
     OMX_U32 width, height;
+    OMX_BOOL isPortraitVideo = OMX_FALSE;
 
     if (capture_capability == V4L2_PIX_FMT_NV12_TP10_UBWC) {
         rc = disable_downscalar();
@@ -1223,11 +1247,77 @@
         return 0;
     }
 
-    if  (!m_downscalar_width || !m_downscalar_height) {
+    if  (!m_enable_downscalar) {
         DEBUG_PRINT_LOW("%s: downscalar not supported", __func__);
         return 0;
     }
 
+#ifdef _QUERY_DISP_RES_
+    memset(&fmt, 0x0, sizeof(struct v4l2_format));
+    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+    fmt.fmt.pix_mp.pixelformat = capture_capability;
+    rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
+    if (rc < 0) {
+       DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
+       return rc;
+    }
+    isPortraitVideo = fmt.fmt.pix_mp.width < fmt.fmt.pix_mp.height ? OMX_TRUE : OMX_FALSE;
+    if (!m_downscalar_width || !m_downscalar_height) {
+        qdutils::DisplayAttributes dpa = {}, dsa = {}, dva = {};
+        int prim_config, ext_config, virt_config;
+
+        prim_config = qdutils::getActiveConfig(qdutils::DISPLAY_PRIMARY);
+        dpa = qdutils::getDisplayAttributes(prim_config, qdutils::DISPLAY_PRIMARY);
+        DEBUG_PRINT_HIGH("%s: Primary dpa.xres = %d  dpa.yres=%d   dpa.xdpi = %f  dpa.ydpi = %f ",
+            __func__, dpa.xres, dpa.yres, dpa.xdpi, dpa.ydpi);
+
+        ext_config = qdutils::getActiveConfig(qdutils::DISPLAY_EXTERNAL);
+        dsa = qdutils::getDisplayAttributes(ext_config, qdutils::DISPLAY_EXTERNAL);
+        DEBUG_PRINT_HIGH("%s: HDMI dsa.xres = %d  dsa.yres = %d   dsa.xdpi = %f  dsa.ydpi = %f ",
+            __func__, dsa.xres, dsa.yres, dsa.xdpi, dsa.ydpi);
+
+        virt_config = qdutils::getActiveConfig(qdutils::DISPLAY_VIRTUAL);
+        dva = qdutils::getDisplayAttributes(virt_config, qdutils::DISPLAY_VIRTUAL);
+        DEBUG_PRINT_HIGH("%s: Virtual dva.xres = %d  dva.yres = %d   dva.xdpi = %f  dva.ydpi = %f ",
+            __func__, dva.xres, dva.yres, dva.xdpi, dva.ydpi);
+
+        /* Below logic takes care of following conditions:
+         *   1. Choose display resolution as maximum resolution of all the connected
+         *      displays (secondary, primary, virtual), so that we do not downscale
+         *      unnecessarily which might be supported on one of the display losing quality.
+         *   2. Displays connected might be in landscape or portrait mode, so the xres might
+         *      be smaller or greater than the yres. So we first take the max of the two
+         *      in width and min of two in height and then rotate it if below point is true.
+         *   3. Video might also be in portrait mode, so invert the downscalar width and
+         *      height for such cases.
+         */
+        if (dsa.xres * dsa.yres > dpa.xres * dpa.yres) {
+            m_downscalar_width = MAX(dsa.xres, dsa.yres);
+            m_downscalar_height = MIN(dsa.xres, dsa.yres);
+        } else if (dva.xres * dva.yres > dpa.xres * dpa.yres) {
+            m_downscalar_width = MAX(dva.xres, dva.yres);
+            m_downscalar_height = MIN(dva.xres, dva.yres);
+
+        } else {
+            m_downscalar_width = MAX(dpa.xres, dpa.yres);
+            m_downscalar_height = MIN(dpa.xres, dpa.yres);
+        }
+        if (isPortraitVideo) {
+            // Swap width and height
+            m_downscalar_width = m_downscalar_width ^ m_downscalar_height;
+            m_downscalar_height = m_downscalar_width ^ m_downscalar_height;
+            m_downscalar_width = m_downscalar_width ^ m_downscalar_height;
+        }
+    }
+    m_downscalar_width = ALIGN(m_downscalar_width, 128);
+    m_downscalar_height = ALIGN(m_downscalar_height, 32);
+#endif
+
+    if (!m_downscalar_width || !m_downscalar_height) {
+        DEBUG_PRINT_LOW("%s: Invalid downscalar configuration", __func__);
+        return 0;
+    }
+
     if (m_force_down_scalar) {
         DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar);
         return 0;
@@ -1248,7 +1338,7 @@
     DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d m_is_display_session = %d", __func__,
         fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height, m_is_display_session);
 
-    if ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height >= m_downscalar_width * m_downscalar_height) &&
+    if ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height > m_downscalar_width * m_downscalar_height) &&
          m_is_display_session) {
         rc = enable_downscalar();
         if (rc < 0) {
@@ -1403,7 +1493,6 @@
                                     if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT))
                                         DEBUG_PRINT_HIGH("Failed to release output buffers");
                                     OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
-                                    pThis->in_reconfig = false;
                                     if (eRet !=  OMX_ErrorNone) {
                                         DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet);
                                         pThis->omx_report_error();
@@ -1417,6 +1506,7 @@
                                 DEBUG_PRINT_HIGH("OMX_CommandPortEnable complete for port [%lu]", p2);
                                 pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
                                         OMX_EventCmdComplete, p1, p2, NULL );
+                                pThis->in_reconfig = false;
                                 break;
 
                             default:
@@ -1709,6 +1799,7 @@
                                         if (p2 == OMX_IndexParamPortDefinition) {
                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
                                             pThis->in_reconfig = true;
+                                            pThis->m_need_turbo &= ~TURBO_MODE_HIGH_FPS;
                                         }  else if (p2 == OMX_IndexConfigCommonOutputCrop) {
                                             DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
 
@@ -2026,7 +2117,10 @@
     int buf_index = 0;
     char *temp = NULL;
 
-    if (m_debug.out_buffer_log && !m_debug.outfile && buffer->nFilledLen) {
+    if (!(m_debug.out_buffer_log || m_debug.out_meta_buffer_log) || !buffer || !buffer->nFilledLen)
+        return 0;
+
+    if (m_debug.out_buffer_log && !m_debug.outfile) {
         snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.yuv",
                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
         m_debug.outfile = fopen (m_debug.outfile_name, "ab");
@@ -2037,8 +2131,7 @@
         }
     }
 
-    if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file
-        && buffer->nFilledLen) {
+    if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file) {
         snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
                 m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
         snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
@@ -2053,9 +2146,6 @@
         }
     }
 
-    if ((!m_debug.outfile && !m_debug.out_ymeta_file) || !buffer || !buffer->nFilledLen)
-        return 0;
-
     buf_index = buffer - m_out_mem_ptr;
     temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
 
@@ -2101,7 +2191,7 @@
                 temp += uv_meta_stride;
             }
         }
-    } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
+    } else if (m_debug.outfile && drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
         int stride = drv_ctx.video_resolution.stride;
         int scanlines = drv_ctx.video_resolution.scan_lines;
         if (m_smoothstreaming_mode) {
@@ -2261,7 +2351,6 @@
     drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
     drv_ctx.frame_rate.fps_denominator = 1;
     operating_frame_rate = DEFAULT_FPS;
-    high_fps = false;
     m_poll_efd = eventfd(0, 0);
     if (m_poll_efd < 0) {
         DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
@@ -2603,24 +2692,27 @@
         drv_ctx.idr_only_decoding = 0;
 
 #ifdef _ANDROID_
-        property_get("vidc.dec.downscalar_width",property_value,"0");
+        property_get("vidc.dec.enable.downscalar",property_value,"0");
         if (atoi(property_value)) {
-            m_downscalar_width = atoi(property_value);
-        }
-        property_get("vidc.dec.downscalar_height",property_value,"0");
-        if (atoi(property_value)) {
-            m_downscalar_height = atoi(property_value);
-        }
+            m_enable_downscalar =  atoi(property_value);
+            property_get("vidc.dec.downscalar_width",property_value,"0");
+            if (atoi(property_value)) {
+                m_downscalar_width = atoi(property_value);
+            }
+            property_get("vidc.dec.downscalar_height",property_value,"0");
+            if (atoi(property_value)) {
+                m_downscalar_height = atoi(property_value);
+            }
 
-        if (m_downscalar_width < m_decoder_capability.min_width ||
-            m_downscalar_height < m_decoder_capability.min_height) {
-            m_downscalar_width = 0;
-            m_downscalar_height = 0;
+            if (m_downscalar_width < m_decoder_capability.min_width ||
+                m_downscalar_height < m_decoder_capability.min_height) {
+                m_downscalar_width = 0;
+                m_downscalar_height = 0;
+            }
+
+            DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n",
+                m_downscalar_width, m_downscalar_height);
         }
-
-        DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n",
-            m_downscalar_width, m_downscalar_height);
-
         property_get("vidc.disable.split.mode",property_value,"0");
         m_disable_split_mode = atoi(property_value);
         DEBUG_PRINT_HIGH("split mode is %s", m_disable_split_mode ? "disabled" : "enabled");
@@ -2864,9 +2956,13 @@
             if (eState == OMX_StateLoaded) {
                 if (release_done()) {
                     /*
-                       Since error is None , we will post an event at the end
-                       of this function definition
+                     * Since error is None , we will post an event at the end
+                     * of this function definition
+                     * Reset buffer requirements here to ensure setting buffer requirement
+                     * when component move to executing state from loaded state via Idle.
                      */
+                    drv_ctx.op_buf.buffer_size = 0;
+                    drv_ctx.op_buf.actualcount = 0;
                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded");
                 } else {
                     DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
@@ -3490,7 +3586,7 @@
 
     if (profileLevelType->nPortIndex == 0) {
         if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
-            profileLevelType->eLevel = OMX_VIDEO_AVCLevel52;
+            profileLevelType->eLevel = OMX_VIDEO_AVCLevel51;
             if (profileLevelType->nProfileIndex == 0) {
                 profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
             } else if (profileLevelType->nProfileIndex == 1) {
@@ -3522,6 +3618,9 @@
             } else if (profileLevelType->nProfileIndex == 1) {
                 profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10;
                 profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
+            } else if (profileLevelType->nProfileIndex == 2) {
+                profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10HDR10;
+                profileLevelType->eLevel   = OMX_VIDEO_HEVCMainTierLevel51;
             } else {
                 DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
                         (unsigned int)profileLevelType->nProfileIndex);
@@ -5048,25 +5147,35 @@
             OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam =
                 (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData;
                 DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable);
+
             eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
                 ((QOMX_ENABLETYPE *)paramData)->bEnable);
             if (eRet != OMX_ErrorNone) {
                 DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata");
                 eRet = OMX_ErrorBadParameter;
                 client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
-            } else {
-                eRet = enable_extradata(OMX_QP_EXTRADATA, false,
+                break;
+            }
+            eRet = enable_extradata(OMX_QP_EXTRADATA, false,
                     ((QOMX_ENABLETYPE *)paramData)->bEnable);
-                if (eRet != OMX_ErrorNone) {
-                    DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
-                    eRet = OMX_ErrorBadParameter;
-                    client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
-                    client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
-                }
+            if (eRet != OMX_ErrorNone) {
+                DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
+                eRet = OMX_ErrorBadParameter;
+                client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
+                client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
+                break;
+            }
+            eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
+                        ((QOMX_ENABLETYPE *)paramData)->bEnable);
+            if (eRet != OMX_ErrorNone) {
+                DEBUG_PRINT_ERROR("ERROR: Failed to set FrameInfo Extradata");
+                eRet = OMX_ErrorBadParameter;
+                client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
+                client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
+                client_extradata = client_extradata & ~OMX_FRAMEINFO_EXTRADATA;
             }
             break;
         }
-
         case OMX_QTIIndexParamPassInputBufferFd:
         {
             VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
@@ -5476,15 +5585,16 @@
         struct v4l2_control control;
 
         DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel);
-
         control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
 
         switch (perf->ePerfLevel) {
             case OMX_QCOM_PerfLevelNominal:
                 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
+                m_need_turbo &= ~TURBO_MODE_CLIENT_REQUESTED;
                 break;
             case OMX_QCOM_PerfLevelTurbo:
                 control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
+                m_need_turbo |= TURBO_MODE_CLIENT_REQUESTED;
                 break;
             default:
                 ret = OMX_ErrorUnsupportedSetting;
@@ -6283,6 +6393,7 @@
 #ifdef USE_ION
             free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
 #endif
+            m_in_alloc_cnt--;
         }
     }
 
@@ -6330,21 +6441,32 @@
                 drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
             } else {
 #endif
-                if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) {
-                    if (!secure_mode) {
-                        DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
-                                drv_ctx.ptr_outputbuffer[0].pmem_fd);
-                        DEBUG_PRINT_LOW("unmap the ouput buffer size=%u  address = %p",
-                                (unsigned int)drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount,
-                                drv_ctx.ptr_outputbuffer[0].bufferaddr);
-                        munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr,
-                                drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount);
-                    }
-                    close (drv_ctx.ptr_outputbuffer[0].pmem_fd);
-                    drv_ctx.ptr_outputbuffer[0].pmem_fd = -1;
+                if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0
+                    && !ouput_egl_buffers && !m_use_output_pmem) {
+                    if (drv_ctx.op_buf_map_info[index].free_buffer) {
+                        if (!secure_mode) {
+                            DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
+                                    drv_ctx.ptr_outputbuffer[0].pmem_fd);
+                            DEBUG_PRINT_LOW("unmap the ouput buffer size=%u  address = %p",
+                                    (unsigned int)drv_ctx.op_buf_map_info[index].map_size,
+                                    drv_ctx.op_buf_map_info[index].base_address);
+                            munmap (drv_ctx.op_buf_map_info[index].base_address,
+                                    drv_ctx.op_buf_map_info[index].map_size);
+                        }
+                        close (drv_ctx.ptr_outputbuffer[index].pmem_fd);
+                        drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
 #ifdef USE_ION
-                    free_ion_memory(&drv_ctx.op_buf_ion_info[0]);
+                        free_ion_memory(&drv_ctx.op_buf_ion_info[index]);
 #endif
+                    } else {
+                        drv_ctx.op_buf_ion_info[index].ion_device_fd = -1;
+                        drv_ctx.op_buf_ion_info[index].ion_alloc_data.handle = 0;
+                        drv_ctx.op_buf_ion_info[index].fd_ion_data.fd = -1;
+                    }
+                    drv_ctx.op_buf_map_info[index].free_buffer = false;
+                    drv_ctx.op_buf_map_info[index].base_address = NULL;
+                    drv_ctx.op_buf_map_info[index].map_size = 0;
+                    drv_ctx.op_buf_map_info[index].offset = 0;
                 }
 #ifdef _ANDROID_
             }
@@ -6675,8 +6797,6 @@
         int nPlatformEntrySize = 0;
         int nPlatformListSize  = 0;
         int nPMEMInfoSize = 0;
-        int pmem_fd = -1;
-        unsigned char *pmem_baseaddress = NULL;
 
         OMX_QCOM_PLATFORM_PRIVATE_LIST      *pPlatformList;
         OMX_QCOM_PLATFORM_PRIVATE_ENTRY     *pPlatformEntry;
@@ -6700,51 +6820,103 @@
                 nPlatformListSize);
         DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize,
                 drv_ctx.op_buf.actualcount);
+        unsigned char *pmem_baseaddress_temp[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {NULL};
+        int pmem_fd[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {-1};
+        int alloc_size[MAX_NUM_INPUT_OUTPUT_BUFFERS] = {0};
+        static const int block_max_size = 128 * 1024 * 1024;
+        unsigned int block_buf_count = block_max_size / drv_ctx.op_buf.buffer_size;
+        unsigned int last_block_buf_count = 0, block_count = 1;
+        if (drv_ctx.op_buf.actualcount <= block_buf_count) {
+            block_buf_count = drv_ctx.op_buf.actualcount;
+        } else {
+            last_block_buf_count = drv_ctx.op_buf.actualcount % block_buf_count;
+            block_count = (drv_ctx.op_buf.actualcount + block_buf_count - 1) / block_buf_count;
+        }
+        unsigned int idx = 0;
+        DEBUG_PRINT_LOW("block_count = %d block_buf_count = %d last_block_buf_count = %d",
+            block_count, block_buf_count, last_block_buf_count);
 #ifdef USE_ION
-        // Allocate output buffers as cached to improve performance of software-reading
-        // of the YUVs. Output buffers are cache-invalidated in driver.
-        // If color-conversion is involved, Only the C2D output buffers are cached, no
-        // need to cache the decoder's output buffers
+        struct vdec_ion op_buf_ion_info_temp[MAX_NUM_INPUT_OUTPUT_BUFFERS];
         int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
-        ion_device_fd = alloc_map_ion_memory(
-                drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount,
-                secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment,
-                &ion_alloc_data, &fd_ion_data,
-                (secure_mode && !secure_scaling_to_non_secure_opb) ?
-                SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
-        if (ion_device_fd < 0) {
+        for (; idx < block_count; idx++) {
+            int cnt = ((idx == block_count - 1) && last_block_buf_count) ?
+                last_block_buf_count : block_buf_count;
+            alloc_size[idx] = drv_ctx.op_buf.buffer_size * cnt;
+            // Allocate output buffers as cached to improve performance of software-reading
+            // of the YUVs. Output buffers are cache-invalidated in driver.
+            // If color-conversion is involved, Only the C2D output buffers are cached, no
+            // need to cache the decoder's output buffers
+            op_buf_ion_info_temp[idx].ion_device_fd = alloc_map_ion_memory(
+                    alloc_size[idx],
+                    secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment,
+                    &op_buf_ion_info_temp[idx].ion_alloc_data, &op_buf_ion_info_temp[idx].fd_ion_data,
+                    (secure_mode && !secure_scaling_to_non_secure_opb) ?
+                    SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
+            if (op_buf_ion_info_temp[idx].ion_device_fd < 0) {
+                DEBUG_PRINT_LOW("Failed to allocate chunk %ul size = %d", idx, alloc_size[idx]);
+                break;
+            }
+            pmem_fd[idx] = op_buf_ion_info_temp[idx].fd_ion_data.fd;
+            DEBUG_PRINT_LOW("Allocated chunk %ul fd = %ul size = %d", idx, pmem_fd[idx], alloc_size[idx]);
+        }
+        if (idx != block_count) {
+            for (OMX_U32 i = 0; i < idx; i++) {
+                close(pmem_fd[i]);
+                free_ion_memory(&op_buf_ion_info_temp[i]);
+            }
             return OMX_ErrorInsufficientResources;
         }
-        pmem_fd = fd_ion_data.fd;
+
 #else
-        pmem_fd = open (MEM_DEVICE,O_RDWR);
+        for (idx = 0; idx < block_count; idx++) {
+            pmem_fd[idx] = open (MEM_DEVICE,O_RDWR);
 
-        if (pmem_fd < 0) {
-            DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
-                    drv_ctx.op_buf.buffer_size);
-            return OMX_ErrorInsufficientResources;
+            if (pmem_fd[idx] < 0) {
+                DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
+                        drv_ctx.op_buf.buffer_size);
+                break;
+            }
+            int cnt = ((idx == block_count - 1) && last_block_buf_count) ?
+                last_block_buf_count : block_buf_count;
+            if (!align_pmem_buffers(pmem_fd[idx], drv_ctx.op_buf.buffer_size * cnt,
+                        drv_ctx.op_buf.alignment)) {
+                DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
+                close(pmem_fd[idx]);
+                break;
+            }
         }
-
-        if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size *
-                    drv_ctx.op_buf.actualcount,
-                    drv_ctx.op_buf.alignment)) {
-            DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
-            close(pmem_fd);
+        if (idx != block_count) {
+            for (i = 0; i < idx; i++) {
+                close(pmem_fd[i]);
+            }
             return OMX_ErrorInsufficientResources;
         }
 #endif
         if (!secure_mode) {
-            pmem_baseaddress = (unsigned char *)mmap(NULL,
-                    (drv_ctx.op_buf.buffer_size *
-                     drv_ctx.op_buf.actualcount),
-                    PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
-            if (pmem_baseaddress == MAP_FAILED) {
-                DEBUG_PRINT_ERROR("MMAP failed for Size %u",
-                        (unsigned int)drv_ctx.op_buf.buffer_size);
-                close(pmem_fd);
+            idx = 0;
+            for (; idx < block_count; idx++) {
+                pmem_baseaddress_temp[idx] = (unsigned char *)mmap(NULL,
+                        alloc_size[idx],
+                        PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd[idx], 0);
+
+                if (pmem_baseaddress_temp[idx] == MAP_FAILED) {
+                    DEBUG_PRINT_ERROR("MMAP failed for Size %u for fd = %d",
+                            (unsigned int)alloc_size[idx], pmem_fd[idx]);
+                    close(pmem_fd[idx]);
 #ifdef USE_ION
-                free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
+                    free_ion_memory(&op_buf_ion_info_temp[idx]);
 #endif
+                    break;
+                }
+            }
+            if (idx != block_count) {
+                for (i = 0; i < idx; i++) {
+                    munmap(pmem_baseaddress_temp[idx], alloc_size[idx]);
+                    close(pmem_fd[i]);
+#ifdef USE_ION
+                    free_ion_memory(&op_buf_ion_info_temp[i]);
+#endif
+                }
                 return OMX_ErrorInsufficientResources;
             }
         }
@@ -6773,6 +6945,13 @@
             return OMX_ErrorInsufficientResources;
         }
 #endif
+        drv_ctx.op_buf_map_info = (struct vdec_ion_map_info *)\
+                      calloc (sizeof(struct vdec_ion_map_info),
+                              drv_ctx.op_buf.actualcount);
+        if (!drv_ctx.op_buf_map_info) {
+            DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_map_info");
+            return OMX_ErrorInsufficientResources;
+        }
 
         if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
                 && drv_ctx.ptr_respbuffer) {
@@ -6818,27 +6997,32 @@
                 pPMEMInfo->pmem_fd = -1;
                 bufHdr->pPlatformPrivate = pPlatformList;
 
-                drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd;
-                m_pmem_info[i].pmem_fd = pmem_fd;
+                int block_idx = i / block_buf_count;
+                drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd[block_idx];
+                m_pmem_info[i].pmem_fd = pmem_fd[block_idx];
 #ifdef USE_ION
-                drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd;
-                drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data;
-                drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data;
+                drv_ctx.op_buf_ion_info[i].ion_device_fd = op_buf_ion_info_temp[block_idx].ion_device_fd;
+                drv_ctx.op_buf_ion_info[i].ion_alloc_data = op_buf_ion_info_temp[block_idx].ion_alloc_data;
+                drv_ctx.op_buf_ion_info[i].fd_ion_data = op_buf_ion_info_temp[block_idx].fd_ion_data;
 #endif
+                drv_ctx.op_buf_map_info[i].free_buffer = !(i % block_buf_count);
+                drv_ctx.op_buf_map_info[i].base_address = pmem_baseaddress_temp[block_idx];
+                drv_ctx.op_buf_map_info[i].map_size = alloc_size[block_idx];
+                drv_ctx.op_buf_map_info[i].offset = drv_ctx.op_buf.buffer_size * (i % block_buf_count);
 
                 /*Create a mapping between buffers*/
                 bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
                 drv_ctx.ptr_respbuffer[i].client_data = (void *)\
                                     &drv_ctx.ptr_outputbuffer[i];
-                drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i;
+                drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size * (i % block_buf_count);
                 drv_ctx.ptr_outputbuffer[i].bufferaddr =
-                    pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i);
+                    pmem_baseaddress_temp[block_idx] + (drv_ctx.op_buf.buffer_size * (i % block_buf_count));
                 m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
                 m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
                 m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
 
                 DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p",
-                        pmem_fd, (unsigned int)drv_ctx.ptr_outputbuffer[i].offset,
+                        pmem_fd[block_idx], (unsigned int)drv_ctx.ptr_outputbuffer[i].offset,
                         drv_ctx.ptr_outputbuffer[i].bufferaddr);
                 // Move the buffer and buffer header pointers
                 bufHdr++;
@@ -6872,7 +7056,9 @@
                 drv_ctx.op_buf_ion_info = NULL;
             }
 #endif
-            eRet =  OMX_ErrorInsufficientResources;
+            free(drv_ctx.op_buf_map_info);
+            drv_ctx.op_buf_map_info = NULL;
+           eRet =  OMX_ErrorInsufficientResources;
         }
         if (eRet == OMX_ErrorNone)
             eRet = allocate_extradata();
@@ -6915,7 +7101,7 @@
 #ifdef USE_ION
             plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
 #endif
-            plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
+            plane[0].reserved[1] = drv_ctx.op_buf_map_info[i].offset;
             plane[0].data_offset = 0;
             extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
             if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
@@ -7188,6 +7374,13 @@
     if ((eRet == OMX_ErrorNone) &&
             (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
         if (release_done()) {
+            /*
+             * Reset buffer requirements here to ensure setting buffer requirement
+             * when component move to executing state from loaded state via idle.
+             */
+            drv_ctx.op_buf.buffer_size = 0;
+            drv_ctx.op_buf.actualcount = 0;
+
             // Send the callback now
             BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
             post_event(OMX_CommandStateSet, OMX_StateLoaded,
@@ -7749,12 +7942,13 @@
 
     rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
     if (rc) {
-        /*TODO: How to handle this case */
         buffer->nFilledLen = 0;
-        DEBUG_PRINT_ERROR("Failed to qbuf to driver, send FTB back to client");
+        DEBUG_PRINT_ERROR("Failed to qbuf to driver, error %s", strerror(errno));
         m_cb.FillBufferDone(hComp, m_app_data, buffer);
+        return OMX_ErrorHardware;
     }
-return OMX_ErrorNone;
+
+    return OMX_ErrorNone;
 }
 
 /* ======================================================================
@@ -8826,40 +9020,15 @@
                            !omx->output_flush_progress &&
                            !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) &&
                            !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) {
-                       unsigned int index = v4l2_buf_ptr->index;
-                       unsigned int extra_idx = EXTRADATA_IDX(omx->drv_ctx.num_planes);
                        omx->time_stamp_dts.remove_time_stamp(
                                omxhdr->nTimeStamp,
                                (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
                                ?true:false);
-                       plane[0].bytesused = 0;
-                       plane[0].m.userptr =
-                           (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].bufferaddr -
-                           (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].offset;
-                       plane[0].reserved[0] = omx->drv_ctx.ptr_outputbuffer[index].pmem_fd;
-                       plane[0].reserved[1] = omx->drv_ctx.ptr_outputbuffer[index].offset;
-                       plane[0].data_offset = 0;
-                       v4l2_buf_ptr->flags = 0x0;
-                       if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
-                           plane[extra_idx].bytesused = 0;
-                           plane[extra_idx].length = omx->drv_ctx.extradata_info.buffer_size;
-                           plane[extra_idx].m.userptr = (long unsigned int) (omx->drv_ctx.extradata_info.uaddr + index * omx->drv_ctx.extradata_info.buffer_size);
-#ifdef USE_ION
-                           plane[extra_idx].reserved[0] = omx->drv_ctx.extradata_info.ion.fd_ion_data.fd;
-#endif
-                           plane[extra_idx].reserved[1] = v4l2_buf_ptr->index * omx->drv_ctx.extradata_info.buffer_size;
-                           plane[extra_idx].data_offset = 0;
-                       } else if (extra_idx >= VIDEO_MAX_PLANES) {
-                           DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
-                           return -1;
-                       }
 
-                       DEBUG_PRINT_LOW("SENDING FTB TO F/W from async_message_process - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
-                               plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], omx->output_flush_progress);
-                       if(ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_QBUF, v4l2_buf_ptr)) {
-                            DEBUG_PRINT_ERROR("Failed to queue buffer back to driver: %d, %d, %d", v4l2_buf_ptr->length, v4l2_buf_ptr->m.planes[0].reserved[0], v4l2_buf_ptr->m.planes[1].reserved[0]);
-                            return -1;
-                       }
+                       omxhdr->nFilledLen = 0;
+                       omx->pending_output_buffers--;
+                       omx->post_event ((unsigned long)NULL,(unsigned long)omx->client_buffers.get_il_buf_hdr(omxhdr),
+                               OMX_COMPONENT_GENERATE_FTB);
                        break;
                    }
                    if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
@@ -9029,7 +9198,7 @@
                    if (omxhdr->nFilledLen)
                        omx->prev_n_filled_len = omxhdr->nFilledLen;
 
-                   if (omxhdr && omxhdr->nFilledLen && !omx->high_fps) {
+                   if (omxhdr && omxhdr->nFilledLen && !omx->m_need_turbo) {
                         omx->request_perf_level(VIDC_NOMINAL);
                    }
                    if (omx->output_use_buffer && omxhdr->pBuffer &&
@@ -9062,7 +9231,7 @@
             omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
             omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
                     OMX_COMPONENT_GENERATE_PORT_RECONFIG);
-            if (!omx->high_fps) {
+            if (!omx->m_need_turbo) {
                 omx->request_perf_level(VIDC_NOMINAL);
             }
             break;
@@ -9881,6 +10050,8 @@
         drv_ctx.op_buf_ion_info = NULL;
     }
 #endif
+    free(drv_ctx.op_buf_map_info);
+    drv_ctx.op_buf_map_info = NULL;
     buf_ref_remove();
 }
 
@@ -10017,7 +10188,7 @@
         if (increase_output && fps_above_180 &&
             output_capability == V4L2_PIX_FMT_H264 &&
             is_res_1080p_or_below) {
-            high_fps = true;
+            m_need_turbo |= TURBO_MODE_HIGH_FPS;
             DEBUG_PRINT_LOW("High fps - fps = %d operating_rate = %d", fps, operating_frame_rate);
             DEBUG_PRINT_LOW("getbufreq[output]: Increase buffer count (%d) to (%d) to support high fps",
                             bufreq.count, bufreq.count + 10);
@@ -10208,7 +10379,7 @@
     } else if (1 == portDefn->nPortIndex) {
         unsigned int buf_size = 0;
         int ret = 0;
-       if (!is_down_scalar_enabled) {
+       if (in_reconfig && !is_down_scalar_enabled) {
            fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
            ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
            fmt.fmt.pix_mp.pixelformat = capture_capability;
@@ -10429,6 +10600,8 @@
                 drv_ctx.op_buf_ion_info = NULL;
             }
 #endif
+            free(drv_ctx.op_buf_map_info);
+            drv_ctx.op_buf_map_info = NULL;
             eRet =  OMX_ErrorInsufficientResources;
         }
     } else {
@@ -10663,13 +10836,32 @@
                 prefix, aspects->mPrimaries, aspects->mRange, aspects->mTransfer, aspects->mMatrixCoeffs);
 }
 
-bool omx_vdec::handle_color_space_info(void *data, unsigned int buf_index)
+void omx_vdec::prepare_color_aspects_metadata(OMX_U32 primaries, OMX_U32 range,
+                                              OMX_U32 transfer, OMX_U32 matrix,
+                                              ColorMetaData *color_mdata)
 {
-    ColorSpace_t color_space = ITU_R_601;
+
+    /* ColorAspects in qdMetaData */
+    color_mdata->colorPrimaries = (enum ColorPrimaries) primaries;
+    color_mdata->range = (enum ColorRange)range;
+    color_mdata->transfer = (enum GammaTransfer)transfer;
+    color_mdata->matrixCoefficients = (enum MatrixCoEfficients)matrix;
+}
+
+bool omx_vdec::handle_color_space_info(void *data,
+                                       ColorSpace_t *color_space,
+                                       ColorMetaData *color_mdata,
+                                       bool& set_color_aspects_only)
+{
     ColorAspects tempAspects;
     memset(&tempAspects, 0x0, sizeof(ColorAspects));
     ColorAspects *aspects = &tempAspects;
 
+    /* Set default ColorAspects */
+    prepare_color_aspects_metadata(ColorPrimaries_BT601_6_625, Range_Full,
+                                           Transfer_SMPTE_170M, MatrixCoEff_BT601_6_625,
+                                           color_mdata);
+
     switch(output_capability) {
         case V4L2_PIX_FMT_MPEG2:
             {
@@ -10683,9 +10875,13 @@
 
                     convert_color_space_info(seqdisp_payload->color_primaries, 1,
                             seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
-                            &color_space,aspects);
+                            color_space,aspects);
                     m_disp_hor_size = seqdisp_payload->disp_width;
                     m_disp_vert_size = seqdisp_payload->disp_height;
+                    set_color_aspects_only = true;
+                    prepare_color_aspects_metadata(seqdisp_payload->color_primaries, 1,
+                                                    seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
+                                                    color_mdata);
                 }
             }
             break;
@@ -10703,7 +10899,13 @@
                             display_info_payload->video_full_range_flag,
                             display_info_payload->transfer_characteristics,
                             display_info_payload->matrix_coefficients,
-                            &color_space,aspects);
+                            color_space,aspects);
+                    set_color_aspects_only = true;
+                    prepare_color_aspects_metadata(display_info_payload->color_primaries,
+                                                   display_info_payload->video_full_range_flag,
+                                                   display_info_payload->transfer_characteristics,
+                                                   display_info_payload->matrix_coefficients,
+                                                   color_mdata);
                 }
             }
             break;
@@ -10723,7 +10925,13 @@
                             1,
                             vc1_seq_disp_payload->transfer_char,
                             vc1_seq_disp_payload->matrix_coeffs,
-                            &color_space,aspects);
+                            color_space,aspects);
+                    set_color_aspects_only = true;
+                    prepare_color_aspects_metadata(vc1_seq_disp_payload->color_primaries,
+                                                   1,
+                                                   vc1_seq_disp_payload->transfer_char,
+                                                   vc1_seq_disp_payload->matrix_coeffs,
+                                                   color_mdata);
                 }
             }
             break;
@@ -10731,12 +10939,12 @@
             {
                 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
                 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
-
+                set_color_aspects_only = false;
                 /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011
                  * to understand this code */
 
                 if (vpx_color_space_payload->color_space == 0) {
-                    color_space = ITU_R_601;
+                    *color_space = ITU_R_601;
                 } else {
                     DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
                     break;
@@ -10747,7 +10955,7 @@
             {
                 struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
                 vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
-
+                set_color_aspects_only = false;
                 /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
                  * to understand this code */
 
@@ -10759,7 +10967,7 @@
                         aspects->mRange = m_client_color_space.sAspects.mRange;
                         break;
                     case MSM_VIDC_CS_BT_709:
-                        color_space = ITU_R_709;
+                        *color_space = ITU_R_709;
                         aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
                         aspects->mTransfer = ColorAspects::TransferSMPTE170M;
                         aspects->mPrimaries =  ColorAspects::PrimariesBT709_5;
@@ -10803,10 +11011,7 @@
         default:
             break;
     }
-    if (m_enable_android_native_buffers) {
-        DEBUG_PRINT_HIGH("setMetaData for Color Space = 0x%x (601=%u FR=%u 709=%u)", color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
-        set_colorspace_in_handle(color_space, buf_index);
-    }
+
     print_debug_color_aspects(aspects, "Bitstream");
 
     if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries ||
@@ -10816,6 +11021,11 @@
         memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects));
         m_internal_color_space.bDataSpaceChanged = OMX_TRUE;
 
+        m_color_mdata.colorPrimaries = color_mdata->colorPrimaries;
+        m_color_mdata.range = color_mdata->range;
+        m_color_mdata.transfer = color_mdata->transfer;
+        m_color_mdata.matrixCoefficients = color_mdata->matrixCoefficients;
+
         DEBUG_PRINT_HIGH("Initiating PORT Reconfig due to Color Aspects Change");
         print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal");
         print_debug_color_aspects(&(m_client_color_space.sAspects), "Client");
@@ -10859,13 +11069,42 @@
 
 }
 
+void omx_vdec::print_debug_hdr_color_info_mdata(ColorMetaData* color_mdata)
+{
+    DEBUG_PRINT_LOW("setMetaData COLOR_METADATA : color_primaries = %u, range = %u, transfer = %u, matrix = %u",
+                    color_mdata->colorPrimaries, color_mdata->range,
+                    color_mdata->transfer, color_mdata->matrixCoefficients);
+
+    for(uint8_t i = 0; i < 3; i++) {
+        for(uint8_t j = 0; j < 2; j++) {
+            DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : rgbPrimaries[%d][%d] = %d", i, j, color_mdata->masteringDisplayInfo.primaries.rgbPrimaries[i][j]);
+        }
+    }
+
+    DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : whitepoint[0] = %d whitepoint[1] = %d",
+                    color_mdata->masteringDisplayInfo.primaries.whitePoint[0],
+                    color_mdata->masteringDisplayInfo.primaries.whitePoint[1]);
+
+    DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxDispLum = %d minDispLum = %d",
+                    color_mdata->masteringDisplayInfo.maxDisplayLuminance,
+                    color_mdata->masteringDisplayInfo.minDisplayLuminance);
+
+    DEBUG_PRINT_LOW("setMetadata COLOR_METADATA : maxCLL = %d maxFLL = %d",
+                    color_mdata->contentLightLevel.maxContentLightLevel,
+                    color_mdata->contentLightLevel.minPicAverageLightLevel);
 
 
-bool omx_vdec::handle_content_light_level_info(void* data)
+}
+
+bool omx_vdec::handle_content_light_level_info(void* data, ContentLightLevel* light_level_mdata)
 {
     struct msm_vidc_content_light_level_sei_payload *light_level_payload =
         (msm_vidc_content_light_level_sei_payload*)(data);
 
+    light_level_mdata->lightLevelSEIEnabled = true;
+    light_level_mdata->maxContentLightLevel = light_level_payload->nMaxContentLight;
+    light_level_mdata->minPicAverageLightLevel = light_level_payload->nMaxPicAverageLight;
+
     if ((m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel != light_level_payload->nMaxContentLight) ||
         (m_internal_hdr_info.sInfo.sType1.mMaxFrameAverageLightLevel != light_level_payload->nMaxPicAverageLight)) {
         m_internal_hdr_info.sInfo.sType1.mMaxContentLightLevel = light_level_payload->nMaxContentLight;
@@ -10875,14 +11114,24 @@
     return false;
 }
 
-bool omx_vdec::handle_mastering_display_color_info(void* data)
+bool omx_vdec::handle_mastering_display_color_info(void* data, MasteringDisplay* mastering_display_mdata)
 {
     struct msm_vidc_mastering_display_colour_sei_payload *mastering_display_payload =
         (msm_vidc_mastering_display_colour_sei_payload*)(data);
     HDRStaticInfo* hdr_info = &m_internal_hdr_info.sInfo;
     bool internal_disp_changed_flag = false;
 
-    internal_disp_changed_flag  = (hdr_info->sType1.mR.x != mastering_display_payload->nDisplayPrimariesX[0]) ||
+    mastering_display_mdata->colorVolumeSEIEnabled = true;
+    for (uint8_t i = 0; i < 3; i++) {
+        mastering_display_mdata->primaries.rgbPrimaries[i][0] = mastering_display_payload->nDisplayPrimariesX[i];
+        mastering_display_mdata->primaries.rgbPrimaries[i][1] = mastering_display_payload->nDisplayPrimariesY[i];
+    }
+    mastering_display_mdata->primaries.whitePoint[0] = mastering_display_payload->nWhitePointX;
+    mastering_display_mdata->primaries.whitePoint[1] = mastering_display_payload->nWhitePointY;
+    mastering_display_mdata->maxDisplayLuminance = mastering_display_payload->nMaxDisplayMasteringLuminance;
+    mastering_display_mdata->minDisplayLuminance = mastering_display_payload->nMinDisplayMasteringLuminance;
+
+    internal_disp_changed_flag |= (hdr_info->sType1.mR.x != mastering_display_payload->nDisplayPrimariesX[0]) ||
         (hdr_info->sType1.mR.y != mastering_display_payload->nDisplayPrimariesY[0]);
     internal_disp_changed_flag |= (hdr_info->sType1.mG.x != mastering_display_payload->nDisplayPrimariesX[1]) ||
         (hdr_info->sType1.mG.y != mastering_display_payload->nDisplayPrimariesY[1]);
@@ -10917,6 +11166,19 @@
     return internal_disp_changed_flag;
 }
 
+void omx_vdec::set_colormetadata_in_handle(ColorMetaData *color_mdata, unsigned int buf_index)
+{
+    private_handle_t *private_handle = NULL;
+    if (buf_index < drv_ctx.op_buf.actualcount &&
+        buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
+        native_buffer[buf_index].privatehandle) {
+        private_handle = native_buffer[buf_index].privatehandle;
+    }
+    if (private_handle) {
+        setMetaData(private_handle, COLOR_METADATA, (void*)color_mdata);
+    }
+}
+
 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
 {
     OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL, *p_client_extra = NULL;
@@ -10930,8 +11192,10 @@
     int enable = OMX_InterlaceFrameProgressive;
     bool internal_hdr_info_changed_flag = false;
     bool color_event = false;
-    if (output_flush_progress)
-        return;
+    ColorMetaData color_mdata;
+    memset(&color_mdata, 0x0, sizeof(ColorMetaData));
+    bool set_disp_color_aspects_only = false;
+    ColorSpace_t color_space = ITU_R_601;
 
     int buf_index = p_buf_hdr - m_out_mem_ptr;
     if (buf_index >= drv_ctx.extradata_info.count) {
@@ -11129,7 +11393,7 @@
                 case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
                 case MSM_VIDC_EXTRADATA_VC1_SEQDISP:
                 case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
-                    color_event = handle_color_space_info((void *)data->data, buf_index);
+                    color_event = handle_color_space_info((void *)data->data, &color_space, &color_mdata, set_disp_color_aspects_only);
                     break;
                 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
                     struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
@@ -11211,10 +11475,13 @@
                     }
                     break;
                 case MSM_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI:
-                    internal_hdr_info_changed_flag |= handle_content_light_level_info((void*)data->data);
+
+                    internal_hdr_info_changed_flag |= handle_content_light_level_info((void*)data->data,
+                                                                                      &(color_mdata.contentLightLevel));
                     break;
                 case MSM_VIDC_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI:
-                    internal_hdr_info_changed_flag |= handle_mastering_display_color_info((void*)data->data);
+                    internal_hdr_info_changed_flag |= handle_mastering_display_color_info((void*)data->data,
+                                                                                          &(color_mdata.masteringDisplayInfo));
                     break;
                 default:
                     DEBUG_PRINT_LOW("Unrecognized extradata");
@@ -11226,13 +11493,13 @@
         if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
             p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
             append_frame_info_extradata(p_extra,
-                    num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
+                    num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
                     time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
                         p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
             p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
             if (p_client_extra) {
                 append_frame_info_extradata(p_client_extra,
-                        num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
+                        num_conceal_MB, recovery_sei_flags, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
                         time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
                             p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
                 p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
@@ -11250,6 +11517,7 @@
         if(internal_hdr_info_changed_flag) {
             print_debug_hdr_color_info(&(m_internal_hdr_info.sInfo), "Internal");
             print_debug_hdr_color_info(&(m_client_hdr_info.sInfo), "Client");
+            memcpy(&m_color_mdata, &color_mdata, sizeof(ColorMetaData));
             auto_lock lock(m_hdr_info_client_lock);
             m_change_client_hdr_info = true;
             if(!color_event) {
@@ -11260,6 +11528,16 @@
             }
         }
 
+        if (m_enable_android_native_buffers) {
+            if (set_disp_color_aspects_only) {
+                print_debug_hdr_color_info_mdata(&m_color_mdata);
+                set_colormetadata_in_handle(&m_color_mdata, buf_index);
+            } else {
+                DEBUG_PRINT_HIGH("setMetaData for Color Space = 0x%x (601=%u FR=%u 709=%u)", color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
+                set_colorspace_in_handle(color_space, buf_index);
+            }
+        }
+
     }
 unrecognized_extradata:
     if (client_extradata && p_extra) {
@@ -11508,6 +11786,7 @@
                 "           Interlace Type: %d\n"
                 " Pan Scan Total Frame Num: %u\n"
                 "   Concealed Macro Blocks: %u\n"
+                "        Recovery SEI Flag: %u\n"
                 "               frame rate: %u\n"
                 "               Time Stamp: %llu\n"
                 "           Aspect Ratio X: %u\n"
@@ -11516,6 +11795,7 @@
                 fminfo->interlaceType,
                 (unsigned int)fminfo->panScan.numWindows,
                 (unsigned int)fminfo->nConcealedMacroblocks,
+                (unsigned int)fminfo->nRecoverySeiFlag,
                 (unsigned int)fminfo->nFrameRate,
                 fminfo->nTimeStamp,
                 (unsigned int)fminfo->aspectRatio.aspectRatioX,
@@ -11695,7 +11975,7 @@
 }
 
 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
-        OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate,
+        OMX_U32 num_conceal_mb, OMX_U32 recovery_sei_flag, OMX_U32 picture_type, OMX_U32 frame_rate,
         OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
         struct vdec_aspectratioinfo *aspect_ratio_info)
 {
@@ -11731,6 +12011,7 @@
         frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
     memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
     frame_info->nConcealedMacroblocks = num_conceal_mb;
+    frame_info->nRecoverySeiFlag = recovery_sei_flag;
     frame_info->nFrameRate = frame_rate;
     frame_info->nTimeStamp = time_stamp;
     frame_info->panScan.numWindows = 0;
@@ -12276,7 +12557,7 @@
             pthread_mutex_lock(&omx->c_lock);
             cache_clean_buffer(index);
             status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
-                    omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer, pmem_fd[index],
+                    omx->drv_ctx.op_buf_map_info[index].base_address, bufadd->pBuffer, pmem_fd[index],
                     pmem_baseaddress[index], pmem_baseaddress[index]);
             if (!status) {
                 DEBUG_PRINT_ERROR("Failed color conversion %d", status);
diff --git a/msm8998/mm-video-v4l2/vidc/venc/Android.mk b/msm8998/mm-video-v4l2/vidc/venc/Android.mk
index e1cd555..595daff 100644
--- a/msm8998/mm-video-v4l2/vidc/venc/Android.mk
+++ b/msm8998/mm-video-v4l2/vidc/venc/Android.mk
@@ -26,7 +26,8 @@
 TARGETS_THAT_NEED_SW_VENC_HEVC := msm8992
 TARGETS_THAT_SUPPORT_UBWC := msm8996 msm8998
 TARGETS_THAT_SUPPORT_VQZIP := msm8996 msm8998
-TARGETS_THAT_SUPPORT_PQ := msm8996 msm8998
+TARGETS_THAT_SUPPORT_PQ := msm8996 msm8998 sdm660 msm8953
+TARGETS_THAT_USE_NV21 := sdm660 msm8953
 
 ifeq ($(TARGET_BOARD_PLATFORM),msm8610)
 libmm-venc-def += -DMAX_RES_720P
@@ -44,6 +45,10 @@
 libmm-venc-def += -D_UBWC_
 endif
 
+ifeq ($(call is-board-platform-in-list, $(TARGETS_THAT_USE_NV21)),true)
+libmm-venc-def += -D_NV21_
+endif
+
 ifeq ($(call is-board-platform-in-list, $(TARGETS_THAT_SUPPORT_VQZIP)),true)
 libmm-venc-def += -D_VQZIP_
 endif
@@ -85,12 +90,14 @@
 libmm-venc-inc      += frameworks/native/include/media/openmax
 libmm-venc-inc      += $(QCOM_MEDIA_ROOT)/libc2dcolorconvert
 libmm-venc-inc      += $(TARGET_OUT_HEADERS)/libvqzip
-libmm-venc-inc      += $(TARGET_OUT_HEADERS)/libgpustats
 libmm-venc-inc      += frameworks/av/include/media/stagefright
-ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
 libmm-venc-inc      += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+ifeq ($(call is-board-platform-in-list, $(TARGETS_THAT_SUPPORT_PQ)),true)
+libmm-venc-inc      += $(TARGET_OUT_HEADERS)/libgpustats
+endif
 
 # Common Dependencies
+ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
 libmm-venc-add-dep  := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
 endif
 
diff --git a/msm8998/mm-video-v4l2/vidc/venc/Makefile.am b/msm8998/mm-video-v4l2/vidc/venc/Makefile.am
index 22aed6f..50a5d53 100644
--- a/msm8998/mm-video-v4l2/vidc/venc/Makefile.am
+++ b/msm8998/mm-video-v4l2/vidc/venc/Makefile.am
@@ -28,6 +28,8 @@
 AM_CPPFLAGS += -Wno-undef
 AM_CPPFLAGS += -Wno-multichar
 AM_CPPFLAGS += -g -O3
+AM_CPPFLAGS += "-DHAVE_ANDROID_OS"
+AM_CPPFLAGS += "-DUSE_CAMERA_METABUFFER_UTILS"
 
 if USE_GLIB
 AM_CPPFLAGS += -D_USE_GLIB_
@@ -49,6 +51,14 @@
 AM_CPPFLAGS += -D_PQ_
 endif
 
+if TARGETS_THAT_SUPPORT_UBWC
+AM_CPPFLAGS += -D_UBWC_
+endif
+
+if TARGETS_THAT_SUPPORT_VQZIP
+AM_CPPFLAGS += -D_VQZIP_
+endif
+
 if TARGETS_THAT_USE_FLAG_MSM8226
 AM_CPPFLAGS += -D_MSM8226_
 endif
@@ -80,6 +90,7 @@
 libOmxVenc_la_CFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) -fPIC
 #libOmxVenc_la_LDLIBS = ../libc2d2colorconvert/libc2dcolorconvert.la
 #libOmxVenc_la_LIBADD  = ../../../mm-core/libOmxCore.la
-libOmxVenc_la_LDFLAGS = -lstdc++ -lpthread -llog -lutils -lbinder -lcutils -lglib-2.0 -lbase -ldl -lpthread -shared
-# -lqdMetaData  -lc2d2 -lgui -lOmxCore -lgpustats -ldl -lpthread
-libOmxVenc_la_LDFLAGS += -version-info 0
\ No newline at end of file
+libOmxVenc_la_LDFLAGS = -lstdc++ -lpthread -llog -lutils -lbinder -lcutils -lglib-2.0 -lbase -ldl -lpthread -shared -lqdMetaData
+#  -lc2d2 -lgui -lOmxCore -lgpustats -ldl -lpthread
+libOmxVenc_la_LDFLAGS += -version-info 0
+
diff --git a/msm8998/mm-video-v4l2/vidc/venc/inc/omx_swvenc_mpeg4.h b/msm8998/mm-video-v4l2/vidc/venc/inc/omx_swvenc_mpeg4.h
index 5971fbc..ce78cf1 100644
--- a/msm8998/mm-video-v4l2/vidc/venc/inc/omx_swvenc_mpeg4.h
+++ b/msm8998/mm-video-v4l2/vidc/venc/inc/omx_swvenc_mpeg4.h
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -137,6 +137,9 @@
                     OMX_U32 * /*nMaxBLayers*/) {
             return false;
         }
+        bool dev_get_pq_status(OMX_BOOL *) {
+            return false;
+        }
         bool dev_is_video_session_supported(OMX_U32 width, OMX_U32 height);
         bool dev_color_align(OMX_BUFFERHEADERTYPE *buffer, OMX_U32 width,
                         OMX_U32 height);
diff --git a/msm8998/mm-video-v4l2/vidc/venc/inc/omx_video_base.h b/msm8998/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
index b2e21af..341fac6 100644
--- a/msm8998/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
+++ b/msm8998/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -167,6 +167,10 @@
     native_handle_t *nh;
 };
 
+typedef struct encoder_meta_buffer_payload_type {
+    char data[sizeof(LEGACY_CAM_METADATA_TYPE) + sizeof(int)];
+} encoder_meta_buffer_payload_type;
+
 // OMX video class
 class omx_video: public qc_omx_component
 {
@@ -174,7 +178,7 @@
 #ifdef _ANDROID_ICS_
         bool meta_mode_enable;
         bool c2d_opened;
-        LEGACY_CAM_METADATA_TYPE meta_buffers[MAX_NUM_INPUT_BUFFERS];
+        encoder_meta_buffer_payload_type meta_buffers[MAX_NUM_INPUT_BUFFERS];
         OMX_BUFFERHEADERTYPE *opaque_buffer_hdr[MAX_NUM_INPUT_BUFFERS];
         bool get_syntaxhdr_enable;
         OMX_BUFFERHEADERTYPE  *psource_frame;
@@ -263,6 +267,7 @@
         virtual bool dev_buffer_ready_to_queue(OMX_BUFFERHEADERTYPE *buffer) = 0;
         virtual bool dev_get_temporal_layer_caps(OMX_U32 * /*nMaxLayers*/,
                 OMX_U32 * /*nMaxBLayers*/) = 0;
+        virtual bool dev_get_pq_status(OMX_BOOL *) = 0;
 #ifdef _ANDROID_ICS_
         void omx_release_meta_buffer(OMX_BUFFERHEADERTYPE *buffer);
 #endif
@@ -532,8 +537,7 @@
                 struct pmem &Input_pmem_info,unsigned long &index);
         OMX_ERRORTYPE queue_meta_buffer(OMX_HANDLETYPE hComp,
                 struct pmem &Input_pmem_info);
-        OMX_ERRORTYPE push_empty_eos_buffer(OMX_HANDLETYPE hComp,
-                OMX_BUFFERHEADERTYPE *buffer);
+        OMX_ERRORTYPE push_empty_eos_buffer(OMX_HANDLETYPE hComp);
         OMX_ERRORTYPE fill_this_buffer_proxy(OMX_HANDLETYPE hComp,
                 OMX_BUFFERHEADERTYPE *buffer);
         bool release_done();
@@ -691,11 +695,14 @@
         int pending_input_buffers;
         int pending_output_buffers;
 
+        bool allocate_native_handle;
+
         uint64_t m_out_bm_count;
         uint64_t m_inp_bm_count;
         uint64_t m_flags;
         uint64_t m_etb_count;
         uint64_t m_fbd_count;
+        OMX_TICKS m_etb_timestamp;
 #ifdef _ANDROID_
         // Heap pointer to frame buffers
         sp<MemoryHeapBase>    m_heap_ptr;
diff --git a/msm8998/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h b/msm8998/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h
old mode 100644
new mode 100755
index fc26690..74467f9
--- a/msm8998/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h
+++ b/msm8998/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
+Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -86,6 +86,7 @@
         bool dev_get_batch_size(OMX_U32 *);
         bool dev_get_temporal_layer_caps(OMX_U32 * /*nMaxLayers*/,
                 OMX_U32 * /*nMaxBLayers*/);
+        bool dev_get_pq_status(OMX_BOOL *);
         bool dev_is_video_session_supported(OMX_U32 width, OMX_U32 height);
         bool dev_color_align(OMX_BUFFERHEADERTYPE *buffer, OMX_U32 width,
                         OMX_U32 height);
@@ -112,6 +113,9 @@
 #ifdef _UBWC_
     #define QOMX_DEFAULT_COLOR_FMT    QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed
     #define V4L2_DEFAULT_OUTPUT_COLOR_FMT   V4L2_PIX_FMT_NV12_UBWC
+#elif _NV21_
+    #define QOMX_DEFAULT_COLOR_FMT    QOMX_COLOR_FormatYVU420SemiPlanar
+    #define V4L2_DEFAULT_OUTPUT_COLOR_FMT   V4L2_PIX_FMT_NV21
 #else
     #define QOMX_DEFAULT_COLOR_FMT    QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m
     #define V4L2_DEFAULT_OUTPUT_COLOR_FMT   V4L2_PIX_FMT_NV12
diff --git a/msm8998/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h b/msm8998/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
index b13d613..fab7317 100644
--- a/msm8998/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
+++ b/msm8998/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -48,6 +48,7 @@
 #include <linux/videodev2.h>
 #include <media/msm_vidc.h>
 #include <poll.h>
+#include <list>
 
 #define TIMEOUT 5*60*1000
 #define BIT(num) (1 << (num))
@@ -356,6 +357,7 @@
         bool venc_get_vqzip_sei_info(OMX_U32 *enabled);
         bool venc_get_peak_bitrate(OMX_U32 *peakbitrate);
         bool venc_get_batch_size(OMX_U32 *size);
+        bool venc_get_pq_status(OMX_BOOL *pq_status);
         bool venc_get_temporal_layer_caps(OMX_U32 * /*nMaxLayers*/,
                 OMX_U32 * /*nMaxBLayers*/);
         bool venc_get_output_log_flag();
@@ -575,6 +577,7 @@
         bool venc_set_colorspace(OMX_U32 primaries, OMX_U32 range, OMX_U32 transfer_chars, OMX_U32 matrix_coeffs);
         OMX_ERRORTYPE venc_set_temporal_layers(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pTemporalParams);
         OMX_ERRORTYPE venc_set_temporal_layers_internal();
+        bool venc_set_iframesize_type(QOMX_VIDEO_IFRAMESIZE_TYPE type);
 
 #ifdef MAX_RES_1080P
         OMX_U32 pmem_free();
@@ -606,11 +609,15 @@
         bool is_thulium_v1;
         bool camera_mode_enabled;
         OMX_BOOL low_latency_mode;
-        struct {
+        struct roidata {
             bool dirty;
+            OMX_TICKS timestamp;
             OMX_QTI_VIDEO_CONFIG_ROIINFO info;
-        } roi;
-
+        };
+        bool m_roi_enabled;
+        pthread_mutex_t m_roilock;
+        std::list<roidata> m_roilist;
+        void get_roi_for_timestamp(struct roidata &roi, OMX_TICKS timestamp);
         bool venc_empty_batch (OMX_BUFFERHEADERTYPE *buf, unsigned index);
         static const int kMaxBuffersInBatch = 16;
         unsigned int mBatchSize;
diff --git a/msm8998/mm-video-v4l2/vidc/venc/src/omx_swvenc_mpeg4.cpp b/msm8998/mm-video-v4l2/vidc/venc/src/omx_swvenc_mpeg4.cpp
index 358f797..c2ac288 100644
--- a/msm8998/mm-video-v4l2/vidc/venc/src/omx_swvenc_mpeg4.cpp
+++ b/msm8998/mm-video-v4l2/vidc/venc/src/omx_swvenc_mpeg4.cpp
@@ -437,17 +437,15 @@
             {
                 m_pipe_in = fds[0];
                 m_pipe_out = fds[1];
-            }
-        }
 
-        if (pthread_create(&msg_thread_id,0, message_thread_enc, this) < 0)
-        {
-            eRet = OMX_ErrorInsufficientResources;
-            msg_thread_created = false;
-        }
-        else
-        {
-            msg_thread_created = true;
+                if (pthread_create(&msg_thread_id,0, message_thread_enc, this) < 0) {
+                    eRet = OMX_ErrorInsufficientResources;
+                    msg_thread_created = false;
+                }
+                else {
+                    msg_thread_created = true;
+                }
+            }
         }
     }
 
diff --git a/msm8998/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp b/msm8998/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
index 7563ae3..b4fe545 100644
--- a/msm8998/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
+++ b/msm8998/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010-2016, Linux Foundation. All rights reserved.
+Copyright (c) 2010-2017, Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
@@ -1890,7 +1890,6 @@
                         eRet = OMX_ErrorUnsupportedIndex;
                     }
                 }
-#ifndef _MSM8974_
                 else if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoLTRInfo) {
                     if (pParam->nPortIndex == PORT_INDEX_OUT) {
                         pParam->bEnabled =
@@ -1902,7 +1901,6 @@
                         eRet = OMX_ErrorUnsupportedIndex;
                     }
                 }
-#endif
                 else {
                     DEBUG_PRINT_ERROR("get_parameter: unsupported extradata index (0x%x)",
                             pParam->nIndex);
@@ -2126,6 +2124,19 @@
                 memcpy(pLayerInfo, &m_sParamTemporalLayers, sizeof(m_sParamTemporalLayers));
                 break;
             }
+        case OMX_QTIIndexParamDisablePQ:
+            {
+                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_DISABLETYPE);
+                OMX_BOOL pq_status;
+                QOMX_DISABLETYPE *pParam =
+                        reinterpret_cast<QOMX_DISABLETYPE*>(paramData);
+                if (!dev_get_pq_status(&pq_status)) {
+                    DEBUG_PRINT_ERROR("Failed to get PQ status");
+                    eRet = OMX_ErrorHardware;
+                }
+                pParam->bDisable = pq_status ? OMX_FALSE : OMX_TRUE;
+                break;
+            }
         case OMX_IndexParamVideoSliceFMO:
         default:
             {
@@ -2467,6 +2478,12 @@
         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
         return OMX_ErrorNone;
     }
+
+    if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
+        *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
+        return OMX_ErrorNone;
+    }
+
     return OMX_ErrorNotImplemented;
 }
 
@@ -3044,11 +3061,18 @@
                 munmap (m_pOutput_pmem[index].buffer,
                         m_pOutput_pmem[index].size);
             } else {
-                char *data = (char*) m_pOutput_pmem[index].buffer;
-                native_handle_t *handle = NULL;
-                memcpy(&handle, data + sizeof(OMX_U32), sizeof(native_handle_t*));
-                native_handle_delete(handle);
-                free(m_pOutput_pmem[index].buffer);
+                if (allocate_native_handle) {
+                    native_handle_t *handle = NULL;
+                    handle = (native_handle_t *)m_pOutput_pmem[index].buffer;
+                    native_handle_close(handle);
+                    native_handle_delete(handle);
+                } else {
+                    char *data = (char*) m_pOutput_pmem[index].buffer;
+                    native_handle_t *handle = NULL;
+                    memcpy(&handle, data + sizeof(OMX_U32), sizeof(native_handle_t*));
+                    native_handle_delete(handle);
+                    free(m_pOutput_pmem[index].buffer);
+                }
             }
             close (m_pOutput_pmem[index].fd);
 #ifdef USE_ION
@@ -3439,24 +3463,37 @@
             else {
                 //This should only be used for passing reference to source type and
                 //secure handle fd struct native_handle_t*
-                native_handle_t *handle = native_handle_create(1, 3); //fd, offset, size, alloc length
-                if (!handle) {
-                    DEBUG_PRINT_ERROR("ERROR: native handle creation failed");
-                    return OMX_ErrorInsufficientResources;
+                if (allocate_native_handle) {
+                    native_handle_t *nh = native_handle_create(1 /*numFds*/, 3 /*numInts*/);
+                    if (!nh) {
+                        DEBUG_PRINT_ERROR("Native handle create failed");
+                        return OMX_ErrorInsufficientResources;
+                    }
+                    nh->data[0] = m_pOutput_pmem[i].fd;
+                    nh->data[1] = 0;
+                    nh->data[2] = 0;
+                    nh->data[3] = ALIGN(m_sOutPortDef.nBufferSize, 4096);
+                    m_pOutput_pmem[i].buffer = (OMX_U8 *)nh;
+                } else {
+                    native_handle_t *handle = native_handle_create(1, 3); //fd, offset, size, alloc length
+                    if (!handle) {
+                        DEBUG_PRINT_ERROR("ERROR: native handle creation failed");
+                        return OMX_ErrorInsufficientResources;
+                    }
+                    m_pOutput_pmem[i].buffer = malloc(sizeof(output_metabuffer));
+                    if (m_pOutput_pmem[i].buffer == NULL) {
+                        DEBUG_PRINT_ERROR("%s: Failed to allocate meta buffer", __func__);
+                        return OMX_ErrorInsufficientResources;
+                    }
+                    (*bufferHdr)->nAllocLen = sizeof(output_metabuffer);
+                    handle->data[0] = m_pOutput_pmem[i].fd;
+                    handle->data[1] = 0;
+                    handle->data[2] = 0;
+                    handle->data[3] = ALIGN(m_sOutPortDef.nBufferSize, 4096);
+                    output_metabuffer *buffer = (output_metabuffer*) m_pOutput_pmem[i].buffer;
+                    buffer->type = 1;
+                    buffer->nh = handle;
                 }
-                m_pOutput_pmem[i].buffer = malloc(sizeof(output_metabuffer));
-                if (m_pOutput_pmem[i].buffer == NULL) {
-                    DEBUG_PRINT_ERROR("%s: Failed to allocate meta buffer", __func__);
-                    return OMX_ErrorInsufficientResources;
-                }
-                (*bufferHdr)->nAllocLen = sizeof(output_metabuffer);
-                handle->data[0] = m_pOutput_pmem[i].fd;
-                handle->data[1] = 0;
-                handle->data[2] = 0;
-                handle->data[3] = ALIGN(m_sOutPortDef.nBufferSize, 4096);
-                output_metabuffer *buffer = (output_metabuffer*) m_pOutput_pmem[i].buffer;
-                buffer->type = 1;
-                buffer->nh = handle;
             }
 
             (*bufferHdr)->pBuffer = (OMX_U8 *)m_pOutput_pmem[i].buffer;
@@ -3775,6 +3812,7 @@
     }
 
     m_etb_count++;
+    m_etb_timestamp = buffer->nTimeStamp;
     DEBUG_PRINT_LOW("DBG: i/p nTimestamp = %u", (unsigned)buffer->nTimeStamp);
     post_event ((unsigned long)hComp,(unsigned long)buffer,m_input_msg_id);
     return OMX_ErrorNone;
@@ -4751,10 +4789,7 @@
         } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingHEVC) {
             if (profileLevelType->nProfileIndex == 0) {
                 profileLevelType->eProfile =  OMX_VIDEO_HEVCProfileMain;
-                profileLevelType->eLevel   =  OMX_VIDEO_HEVCMainTierLevel52;
-            } else if (profileLevelType->nProfileIndex == 1) {
-                profileLevelType->eProfile =  OMX_VIDEO_HEVCProfileMain10;
-                profileLevelType->eLevel   =  OMX_VIDEO_HEVCMainTierLevel52;
+                profileLevelType->eLevel   =  OMX_VIDEO_HEVCMainTierLevel51;
             } else {
                 DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
                 (unsigned int)profileLevelType->nProfileIndex);
@@ -5326,7 +5361,7 @@
         // separately by queueing an intermediate color-conversion buffer
         // and propagate the EOS.
         if (psource_frame->nFilledLen == 0 && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
-            return push_empty_eos_buffer(hComp, psource_frame);
+            return push_empty_eos_buffer(hComp);
         }
         media_buffer = (LEGACY_CAM_METADATA_TYPE *)psource_frame->pBuffer;
         /*Will enable to verify camcorder in current TIPS can be removed*/
@@ -5363,8 +5398,7 @@
     return ret;
 }
 
-OMX_ERRORTYPE omx_video::push_empty_eos_buffer(OMX_HANDLETYPE hComp,
-        OMX_BUFFERHEADERTYPE* buffer) {
+OMX_ERRORTYPE omx_video::push_empty_eos_buffer(OMX_HANDLETYPE hComp) {
     OMX_BUFFERHEADERTYPE* opqBuf = NULL;
     OMX_ERRORTYPE retVal = OMX_ErrorNone;
     unsigned index = 0;
@@ -5384,7 +5418,7 @@
             }
             index = opqBuf - m_inp_mem_ptr;
         } else {
-            opqBuf = (OMX_BUFFERHEADERTYPE* ) buffer;
+            opqBuf = (OMX_BUFFERHEADERTYPE* ) psource_frame;
             index = opqBuf - meta_buffer_hdr;
         }
 
@@ -5413,8 +5447,8 @@
         OMX_BUFFERHEADERTYPE emptyEosBufHdr;
         memcpy(&emptyEosBufHdr, opqBuf, sizeof(OMX_BUFFERHEADERTYPE));
         emptyEosBufHdr.nFilledLen = 0;
-        emptyEosBufHdr.nTimeStamp = buffer->nTimeStamp;
-        emptyEosBufHdr.nFlags = buffer->nFlags;
+        emptyEosBufHdr.nTimeStamp = psource_frame->nTimeStamp;
+        emptyEosBufHdr.nFlags = psource_frame->nFlags;
         emptyEosBufHdr.pBuffer = NULL;
         if (!mUsesColorConversion)
             emptyEosBufHdr.nAllocLen =
@@ -5431,7 +5465,8 @@
 
     //return client's buffer regardless since intermediate color-conversion
     //buffer is sent to the the encoder
-    m_pCallbacks.EmptyBufferDone(hComp, m_app_data, buffer);
+    m_pCallbacks.EmptyBufferDone(hComp, m_app_data, psource_frame);
+    psource_frame = NULL;
     --pending_input_buffers;
     VIDC_TRACE_INT_LOW("ETB-pending", pending_input_buffers);
     return retVal;
diff --git a/msm8998/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp b/msm8998/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
index d5ac1d9..b42c288 100644
--- a/msm8998/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
+++ b/msm8998/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
@@ -44,6 +44,7 @@
 extern int m_pipe;
 static int bframes;
 static int entropy;
+static int perfmode;
 static int lowlatency;
 // factory function executed by the core to create instances
 void *get_omx_component_factory_fn(void)
@@ -147,6 +148,9 @@
     property_get("vidc.debug.entropy", property_value, "1");
     entropy = !!atoi(property_value);
     property_value[0] = '\0';
+    property_get("vidc.debug.perf.mode", property_value, "0");
+    perfmode = atoi(property_value);
+    property_value[0] = '\0';
     handle = NULL;
     property_get("vidc.debug.lowlatency", property_value, "0");
     lowlatency = atoi(property_value);
@@ -431,6 +435,7 @@
                 &m_sOutPortDef.nBufferSize,
                 m_sOutPortDef.nPortIndex) != true) {
         eRet = OMX_ErrorUndefined;
+        goto init_error;
     }
 
     // Initialize the video color format for input port
@@ -576,32 +581,52 @@
         if (pipe(fds)) {
             DEBUG_PRINT_ERROR("ERROR: pipe creation failed");
             eRet = OMX_ErrorInsufficientResources;
+            goto init_error;
         } else {
             if (fds[0] == 0 || fds[1] == 0) {
                 if (pipe(fds)) {
                     DEBUG_PRINT_ERROR("ERROR: pipe creation failed");
                     eRet = OMX_ErrorInsufficientResources;
+                    goto init_error;
                 }
             }
             if (eRet == OMX_ErrorNone) {
                 m_pipe_in = fds[0];
                 m_pipe_out = fds[1];
+
+                msg_thread_created = true;
+                r = pthread_create(&msg_thread_id,0, message_thread_enc, this);
+                if (r < 0) {
+                    DEBUG_PRINT_ERROR("ERROR: message_thread_enc thread creation failed");
+                    eRet = OMX_ErrorInsufficientResources;
+                    msg_thread_created = false;
+                    goto init_error;
+                } else {
+                    async_thread_created = true;
+                    r = pthread_create(&async_thread_id,0, venc_dev::async_venc_message_thread, this);
+                    if (r < 0) {
+                        DEBUG_PRINT_ERROR("ERROR: venc_dev::async_venc_message_thread thread creation failed");
+                        eRet = OMX_ErrorInsufficientResources;
+                        async_thread_created = false;
+
+                        msg_thread_stop = true;
+                        pthread_join(msg_thread_id,NULL);
+                        msg_thread_created = false;
+
+                        goto init_error;
+                    } else
+                        dev_set_message_thread_id(async_thread_id);
+                }
             }
         }
-        msg_thread_created = true;
-        r = pthread_create(&msg_thread_id,0, message_thread_enc, this);
-        if (r < 0) {
-            eRet = OMX_ErrorInsufficientResources;
-            msg_thread_created = false;
-        } else {
-            async_thread_created = true;
-            r = pthread_create(&async_thread_id,0, venc_dev::async_venc_message_thread, this);
-            if (r < 0) {
-                eRet = OMX_ErrorInsufficientResources;
-                async_thread_created = false;
-            } else
-                dev_set_message_thread_id(async_thread_id);
-        }
+    }
+
+    if (perfmode) {
+        QOMX_EXTNINDEX_VIDEO_PERFMODE pParam;
+        pParam.nPerfMode = perfmode;
+        DEBUG_PRINT_LOW("Perfmode = 0x%x", pParam.nPerfMode);
+        if (!handle->venc_set_config(&pParam, (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoVencPerfMode))
+            DEBUG_PRINT_ERROR("Failed setting PerfMode to %d", pParam.nPerfMode);
     }
 
     if (lowlatency)
@@ -1148,6 +1173,31 @@
                 break;
 
             }
+        case OMX_GoogleAndroidIndexAllocateNativeHandle:
+            {
+                VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams);
+
+                AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData;
+
+                if (!secure_session) {
+                    DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle allowed only in secure session");
+                    eRet = OMX_ErrorUnsupportedSetting;
+                    break;
+                } else if (allocateNativeHandleParams->nPortIndex != PORT_INDEX_OUT) {
+                    DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle allowed only on Output port!");
+                    eRet = OMX_ErrorUnsupportedSetting;
+                    break;
+                } else if (m_out_mem_ptr) {
+                    DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Output port is not free !");
+                    eRet = OMX_ErrorInvalidState;
+                    break;
+                }
+
+                if (allocateNativeHandleParams != NULL) {
+                    allocate_native_handle = allocateNativeHandleParams->enable;
+                }
+                break;
+            }
         case OMX_IndexParamVideoQuantization:
             {
                 VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_QUANTIZATIONTYPE);
@@ -1292,14 +1342,9 @@
                         }
                     }
                 } else if (pParam->nPortIndex == PORT_INDEX_OUT && secure_session) {
-                    if (pParam->bStoreMetaData != meta_mode_enable) {
-                        if (!handle->venc_set_meta_mode(pParam->bStoreMetaData)) {
-                            DEBUG_PRINT_ERROR("\nERROR: set Metabuffer mode %d fail",
-                                    pParam->bStoreMetaData);
+                            DEBUG_PRINT_ERROR("set_parameter: metamode is "
+                            "valid for input port only in secure session");
                             return OMX_ErrorUnsupportedSetting;
-                        }
-                        meta_mode_enable = pParam->bStoreMetaData;
-                    }
                 } else {
                     DEBUG_PRINT_ERROR("set_parameter: metamode is "
                             "valid for input port only");
@@ -1364,8 +1409,6 @@
                         break;
                     }
                 }
-
-#ifndef _MSM8974_
                 else if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoLTRInfo) {
                     if (pParam->nPortIndex == PORT_INDEX_OUT) {
                         if (pParam->bEnabled == OMX_TRUE)
@@ -1380,7 +1423,6 @@
                         break;
                     }
                 }
-#endif
                 else {
                     DEBUG_PRINT_ERROR("set_parameter: unsupported extrdata index (%x)",
                             pParam->nIndex);
@@ -1727,6 +1769,16 @@
                         (OMX_INDEXTYPE)OMX_QTIIndexParamDisablePQ);
                 break;
             }
+        case OMX_QTIIndexParamIframeSizeType:
+            {
+                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_IFRAMESIZE);
+                if (!handle->venc_set_param(paramData,
+                            (OMX_INDEXTYPE)OMX_QTIIndexParamIframeSizeType)) {
+                    DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamIframeSizeType failed");
+                    return OMX_ErrorUnsupportedSetting;
+                }
+                break;
+            }
         case OMX_IndexParamVideoSliceFMO:
         default:
             {
@@ -2216,6 +2268,15 @@
                 DEBUG_PRINT_ERROR("Setting/modifying Temporal layers at run-time is not supported !");
                 return OMX_ErrorUnsupportedSetting;
             }
+        case OMX_QcomIndexConfigPerfLevel:
+            {
+                VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL);
+                if (!handle->venc_set_config(configData,
+                        (OMX_INDEXTYPE)OMX_QcomIndexConfigPerfLevel)) {
+                    DEBUG_PRINT_ERROR("Failed to set perf level");
+                    return OMX_ErrorUnsupportedSetting;
+                }
+            }
         default:
             DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
             break;
@@ -2455,6 +2516,10 @@
     return handle->venc_get_temporal_layer_caps(nMaxLayers, nMaxBLayers);
 }
 
+bool omx_venc::dev_get_pq_status(OMX_BOOL *pq_status) {
+    return handle->venc_get_pq_status(pq_status);
+}
+
 bool omx_venc::dev_loaded_start()
 {
     return handle->venc_loaded_start();
@@ -2612,13 +2677,22 @@
                                 m_sVenc_msg->buf.len);
                     }
                 } else if (omx->is_secure_session()) {
-                    output_metabuffer *meta_buf = (output_metabuffer *)(omxhdr->pBuffer);
-                    native_handle_t *nh = meta_buf->nh;
-                    nh->data[1] = m_sVenc_msg->buf.offset;
-                    nh->data[2] = m_sVenc_msg->buf.len;
-                    omxhdr->nFilledLen = sizeof(output_metabuffer);
-                    omxhdr->nTimeStamp = m_sVenc_msg->buf.timestamp;
-                    omxhdr->nFlags = m_sVenc_msg->buf.flags;
+                    if (omx->allocate_native_handle) {
+                        native_handle_t *nh = (native_handle_t *)(omxhdr->pBuffer);
+                        nh->data[1] = m_sVenc_msg->buf.offset;
+                        nh->data[2] = m_sVenc_msg->buf.len;
+                        omxhdr->nFilledLen = m_sVenc_msg->buf.len;
+                        omxhdr->nTimeStamp = m_sVenc_msg->buf.timestamp;
+                        omxhdr->nFlags = m_sVenc_msg->buf.flags;
+                    } else {
+                        output_metabuffer *meta_buf = (output_metabuffer *)(omxhdr->pBuffer);
+                        native_handle_t *nh = meta_buf->nh;
+                        nh->data[1] = m_sVenc_msg->buf.offset;
+                        nh->data[2] = m_sVenc_msg->buf.len;
+                        omxhdr->nFilledLen = sizeof(output_metabuffer);
+                        omxhdr->nTimeStamp = m_sVenc_msg->buf.timestamp;
+                        omxhdr->nFlags = m_sVenc_msg->buf.flags;
+                    }
                 } else {
                     omxhdr->nFilledLen = 0;
                 }
diff --git a/msm8998/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/msm8998/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
index 73e7cf7..1b4cd07 100644
--- a/msm8998/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
+++ b/msm8998/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
@@ -187,6 +187,8 @@
     hw_overload = false;
     mBatchSize = 0;
     deinterlace_enabled = false;
+    m_roi_enabled = false;
+    pthread_mutex_init(&m_roilock, NULL);
     pthread_mutex_init(&pause_resume_mlock, NULL);
     pthread_cond_init(&pause_resume_cond, NULL);
     memset(&input_extradata_info, 0, sizeof(input_extradata_info));
@@ -220,7 +222,6 @@
     memset(&ltrinfo, 0, sizeof(ltrinfo));
     memset(&fd_list, 0, sizeof(fd_list));
     memset(&hybrid_hp, 0, sizeof(hybrid_hp));
-    memset(&roi, 0, sizeof(roi));
     sess_priority.priority = 1;
     operating_rate = 0;
     low_latency_mode = OMX_FALSE;
@@ -273,7 +274,18 @@
 
 venc_dev::~venc_dev()
 {
-    //nothing to do
+    if (m_roi_enabled) {
+        std::list<roidata>::iterator iter;
+        pthread_mutex_lock(&m_roilock);
+        for (iter = m_roilist.begin(); iter != m_roilist.end(); iter++) {
+            DEBUG_PRINT_HIGH("roidata with timestamp (%lld) should have been removed already",
+                iter->timestamp);
+            free(iter->info.pRoiMBInfo);
+        }
+        m_roilist.clear();
+        pthread_mutex_unlock(&m_roilock);
+    }
+    pthread_mutex_destroy(&m_roilock);
 }
 
 void* venc_dev::async_venc_message_thread (void *input)
@@ -372,6 +384,12 @@
                 if (v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME)
                     venc_msg.buf.flags |= OMX_BUFFERFLAG_SYNCFRAME;
 
+                if (v4l2_buf.flags & V4L2_BUF_FLAG_PFRAME) {
+                    venc_msg.buf.flags |= OMX_VIDEO_PictureTypeP;
+                } else if (v4l2_buf.flags & V4L2_BUF_FLAG_BFRAME) {
+                    venc_msg.buf.flags |= OMX_VIDEO_PictureTypeB;
+                }
+
                 if (v4l2_buf.flags & V4L2_QCOM_BUF_FLAG_CODECCONFIG)
                     venc_msg.buf.flags |= OMX_BUFFERFLAG_CODECCONFIG;
 
@@ -543,6 +561,48 @@
     return eRet;
 }
 
+void venc_dev::get_roi_for_timestamp(struct roidata &roi, OMX_TICKS timestamp)
+{
+    std::list<roidata>::iterator iter;
+    bool found = false;
+
+    memset(&roi, 0, sizeof(struct roidata));
+    roi.dirty = false;
+
+    /*
+     * look for the roi data which has timestamp nearest and
+     * lower than the etb timestamp, we should not take the
+     * roi data which has the timestamp greater than etb timestamp.
+     */
+    pthread_mutex_lock(&m_roilock);
+    iter = m_roilist.begin();
+    while (iter != m_roilist.end()) {
+        if (iter->timestamp <= timestamp) {
+            if (found) {
+                /* we found roidata in previous iteration already and got another
+                 * roidata in this iteration, so we will use this iteration's
+                 * roidata and free the previous roidata which is no longer used.
+                 */
+                DEBUG_PRINT_LOW("freeing unused roidata with timestamp %lld us", roi.timestamp);
+                free(roi.info.pRoiMBInfo);
+            }
+            found = true;
+            roi = *iter;
+            /* we got roidata so erase the elment in the roi list.
+             * after list erase iterator will point to next element
+             * so we don't need to increment iter after erase.
+             */
+            iter = m_roilist.erase(iter);
+        } else {
+            iter++;
+        }
+    }
+    if (found) {
+        DEBUG_PRINT_LOW("found roidata with timestamp %lld us", roi.timestamp);
+    }
+    pthread_mutex_unlock(&m_roilock);
+}
+
 int venc_dev::append_mbi_extradata(void *dst, struct msm_vidc_extradata_header* src)
 {
     OMX_QCOM_EXTRADATA_MBINFO *mbi = (OMX_QCOM_EXTRADATA_MBINFO *)dst;
@@ -559,15 +619,41 @@
     return mbi->nDataSize + sizeof(*mbi);
 }
 
+inline int get_yuv_size(unsigned long fmt, int width, int height) {
+    unsigned int y_stride, uv_stride, y_sclines,
+                uv_sclines, y_plane, uv_plane;
+    unsigned int y_ubwc_plane = 0, uv_ubwc_plane = 0;
+    unsigned size = 0;
+
+    y_stride = VENUS_Y_STRIDE(fmt, width);
+    uv_stride = VENUS_UV_STRIDE(fmt, width);
+    y_sclines = VENUS_Y_SCANLINES(fmt, height);
+    uv_sclines = VENUS_UV_SCANLINES(fmt, height);
+
+    switch (fmt) {
+        case COLOR_FMT_NV12:
+            y_plane = y_stride * y_sclines;
+            uv_plane = uv_stride * uv_sclines;
+            size = MSM_MEDIA_ALIGN(y_plane + uv_plane, 4096);
+            break;
+         default:
+            break;
+    }
+    return size;
+}
+
 bool venc_dev::handle_input_extradata(struct v4l2_buffer buf)
 {
     OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
-    unsigned int consumed_len = 0, index = 0;
-    int enable = 0, i = 0;
-    int height = 0, width = 0;
+    unsigned int consumed_len = 0, filled_len = 0;
+    unsigned int yuv_size = 0, index = 0;
+    int enable = 0, i = 0, size = 0;
+    unsigned char *pVirt = NULL;
+    int height = m_sVenc_cfg.input_height;
+    int width = m_sVenc_cfg.input_width;
     OMX_TICKS nTimeStamp = buf.timestamp.tv_sec * 1000000 + buf.timestamp.tv_usec;
     int fd = buf.m.planes[0].reserved[0];
-    bool unknown_extradata = false;
+    bool vqzip_sei_found = false;
 
     if (!EXTRADATA_IDX(num_input_planes)) {
         DEBUG_PRINT_LOW("Input extradata not enabled");
@@ -576,134 +662,146 @@
 
     if (!input_extradata_info.uaddr) {
         DEBUG_PRINT_ERROR("Extradata buffers not allocated\n");
-        return false;
+        return true;
     }
 
-    /*
-     * At this point encoder component doesn't know where the extradata is
-     * located in YUV buffer. For all practical usecases, decoder appends
-     * extradata after nFilledLen which is calcualted as 32 aligned height
-     * and width * 3 / 2. Hence start looking for extradata from this point.
-     */
-
     DEBUG_PRINT_HIGH("Processing Extradata for Buffer = %lld", nTimeStamp); // Useful for debugging
 
-    height = ALIGN(m_sVenc_cfg.input_height, 32);
-    width = ALIGN(m_sVenc_cfg.input_width, 32);
+    if (m_sVenc_cfg.inputformat == V4L2_PIX_FMT_NV12 || m_sVenc_cfg.inputformat == V4L2_PIX_FMT_NV21) {
+        size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
+        yuv_size = get_yuv_size(COLOR_FMT_NV12, width, height);
+        pVirt = (unsigned char *)mmap(NULL, size, PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0);
+        if (pVirt == MAP_FAILED) {
+            DEBUG_PRINT_ERROR("%s Failed to mmap",__func__);
+            return false;
+        }
+        p_extra = (OMX_OTHER_EXTRADATATYPE *) ((unsigned long)(pVirt + yuv_size + 3)&(~3));
+    }
 
     index = venc_get_index_from_fd(input_extradata_info.m_ion_dev,fd);
-
-    unsigned char *pVirt;
-    int size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
-    pVirt= (unsigned char *)mmap(NULL, size, PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0);
-
-    p_extra = (OMX_OTHER_EXTRADATATYPE *) ((unsigned long)(pVirt + ((width * height * 3) / 2) + 3)&(~3));
     char *p_extradata = input_extradata_info.uaddr + index * input_extradata_info.buffer_size;
     OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
     memset((void *)(data), 0, (input_extradata_info.buffer_size)); // clear stale data in current buffer
-    if (p_extra) {
-        bool vqzip_sei_found = false;
 
-        while ((consumed_len < input_extradata_info.buffer_size)
-            && (p_extra->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)
-            && !unknown_extradata) {
-            DEBUG_PRINT_LOW("Extradata Type = 0x%x", (OMX_QCOM_EXTRADATATYPE)p_extra->eType);
-            switch ((OMX_QCOM_EXTRADATATYPE)p_extra->eType) {
-            case OMX_ExtraDataFrameDimension:
-            {
-                struct msm_vidc_extradata_index *payload;
-                OMX_QCOM_EXTRADATA_FRAMEDIMENSION *framedimension_format;
-                data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct msm_vidc_extradata_index) + 3)&(~3);
-                data->nVersion.nVersion = OMX_SPEC_VERSION;
-                data->nPortIndex = 0;
-                data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_INDEX;
-                data->nDataSize = sizeof(struct msm_vidc_input_crop_payload);
-                framedimension_format = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)p_extra->data;
-                payload = (struct msm_vidc_extradata_index *)(data->data);
-                payload->type = (msm_vidc_extradata_type)MSM_VIDC_EXTRADATA_INPUT_CROP;
-                payload->input_crop.left = framedimension_format->nDecWidth;
-                payload->input_crop.top = framedimension_format->nDecHeight;
-                payload->input_crop.width = framedimension_format->nActualWidth;
-                payload->input_crop.height = framedimension_format->nActualHeight;
-                DEBUG_PRINT_LOW("Height = %d Width = %d Actual Height = %d Actual Width = %d",
-                    framedimension_format->nDecWidth, framedimension_format->nDecHeight,
-                    framedimension_format->nActualWidth, framedimension_format->nActualHeight);
-                data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
-                break;
+    while (p_extra && (consumed_len + sizeof(OMX_OTHER_EXTRADATATYPE)) <= (size - yuv_size)
+        && (consumed_len + p_extra->nSize) <= (size - yuv_size)
+        && (filled_len + sizeof(OMX_OTHER_EXTRADATATYPE) <= input_extradata_info.buffer_size)
+        && (filled_len + p_extra->nSize <= input_extradata_info.buffer_size)
+        && (p_extra->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
+
+        DEBUG_PRINT_LOW("Extradata Type = 0x%x", (OMX_QCOM_EXTRADATATYPE)p_extra->eType);
+        switch ((OMX_QCOM_EXTRADATATYPE)p_extra->eType) {
+        case OMX_ExtraDataFrameDimension:
+        {
+            struct msm_vidc_extradata_index *payload;
+            OMX_QCOM_EXTRADATA_FRAMEDIMENSION *framedimension_format;
+            data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct msm_vidc_extradata_index) + 3)&(~3);
+            data->nVersion.nVersion = OMX_SPEC_VERSION;
+            data->nPortIndex = 0;
+            data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_INDEX;
+            data->nDataSize = sizeof(struct msm_vidc_input_crop_payload);
+            framedimension_format = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)p_extra->data;
+            payload = (struct msm_vidc_extradata_index *)(data->data);
+            payload->type = (msm_vidc_extradata_type)MSM_VIDC_EXTRADATA_INPUT_CROP;
+            payload->input_crop.left = framedimension_format->nDecWidth;
+            payload->input_crop.top = framedimension_format->nDecHeight;
+            payload->input_crop.width = framedimension_format->nActualWidth;
+            payload->input_crop.height = framedimension_format->nActualHeight;
+            DEBUG_PRINT_LOW("Height = %d Width = %d Actual Height = %d Actual Width = %d",
+                framedimension_format->nDecWidth, framedimension_format->nDecHeight,
+                framedimension_format->nActualWidth, framedimension_format->nActualHeight);
+            filled_len += data->nSize;
+            data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
+            break;
+        }
+        case OMX_ExtraDataQP:
+        {
+            OMX_QCOM_EXTRADATA_QP * qp_payload = NULL;
+            struct msm_vidc_frame_qp_payload *payload;
+            data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct msm_vidc_frame_qp_payload) + 3)&(~3);
+            data->nVersion.nVersion = OMX_SPEC_VERSION;
+            data->nPortIndex = 0;
+            data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_FRAME_QP;
+            data->nDataSize = sizeof(struct  msm_vidc_frame_qp_payload);
+            qp_payload = (OMX_QCOM_EXTRADATA_QP *)p_extra->data;
+            payload = (struct  msm_vidc_frame_qp_payload *)(data->data);
+            payload->frame_qp = qp_payload->nQP;
+            DEBUG_PRINT_LOW("Frame QP = %d", payload->frame_qp);
+            filled_len += data->nSize;
+            data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
+            break;
+        }
+        case OMX_ExtraDataVQZipSEI:
+            DEBUG_PRINT_LOW("VQZIP SEI Found ");
+            input_extradata_info.vqzip_sei_found = true;
+            break;
+        case OMX_ExtraDataFrameInfo:
+        {
+            OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
+            frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(p_extra->data);
+            if (frame_info->ePicType == OMX_VIDEO_PictureTypeI) {
+                if (venc_set_intra_vop_refresh((OMX_BOOL)true) == false)
+                    DEBUG_PRINT_ERROR("%s Error in requesting I Frame ", __func__);
             }
-            case OMX_ExtraDataQP:
-            {
-                OMX_QCOM_EXTRADATA_QP * qp_payload = NULL;
-                struct msm_vidc_frame_qp_payload *payload;
-                data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) + sizeof(struct msm_vidc_frame_qp_payload) + 3)&(~3);
-                data->nVersion.nVersion = OMX_SPEC_VERSION;
-                data->nPortIndex = 0;
-                data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_FRAME_QP;
-                data->nDataSize = sizeof(struct  msm_vidc_frame_qp_payload);
-                qp_payload = (OMX_QCOM_EXTRADATA_QP *)p_extra->data;
-                payload = (struct  msm_vidc_frame_qp_payload *)(data->data);
-                payload->frame_qp = qp_payload->nQP;
-                DEBUG_PRINT_LOW("Frame QP = %d", payload->frame_qp);
-                data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
-                break;
-            }
-            case OMX_ExtraDataVQZipSEI:
-                DEBUG_PRINT_LOW("VQZIP SEI Found ");
-                input_extradata_info.vqzip_sei_found = true;
-                break;
-            default:
-                unknown_extradata = true;
-                break;
-            }
-            if (!unknown_extradata) {
-                consumed_len += p_extra->nSize;
-                p_extra = (OMX_OTHER_EXTRADATATYPE *)((char *)p_extra + p_extra->nSize);
-            } else  {
-                DEBUG_PRINT_HIGH(" Unknown Extradata. Exiting parsing ");
-                break;
-            }
+            break;
+        }
+        default:
+            DEBUG_PRINT_HIGH("Unknown Extradata 0x%x", (OMX_QCOM_EXTRADATATYPE)p_extra->eType);
+            break;
         }
 
-        /*
-         * Below code is based on these points.
-         * 1) _PQ_ not defined :
-         *     a) Send data to Venus as ROI.
-         *     b) ROI enabled : Processed under unlocked context.
-         *     c) ROI disabled : Nothing to fill.
-         *     d) pq enabled : Not possible.
-         * 2) _PQ_ defined, but pq is not enabled :
-         *     a) Send data to Venus as ROI.
-         *     b) ROI enabled and dirty : Copy the data to Extradata buffer here
-         *     b) ROI enabled and no dirty : Nothing to fill
-         *     d) ROI disabled : Nothing to fill
-         * 3) _PQ_ defined and pq is enabled :
-         *     a) Send data to Venus as PQ.
-         *     b) ROI enabled and dirty : Copy the ROI contents to pq_roi buffer
-         *     c) ROI enabled and no dirty : pq_roi is already memset. Hence nothing to do here
-         *     d) ROI disabled : Just PQ data will be filled by GPU.
-         * 4) Normal ROI handling is in #else part as PQ can introduce delays.
-         *     By this time if client sets next ROI, then we shouldn't process new ROI here.
-         */
+        consumed_len += p_extra->nSize;
+        p_extra = (OMX_OTHER_EXTRADATATYPE *)((char *)p_extra + p_extra->nSize);
+    }
+
+    /*
+       * Below code is based on these points.
+       * 1) _PQ_ not defined :
+       *     a) Send data to Venus as ROI.
+       *     b) ROI enabled : Processed under unlocked context.
+       *     c) ROI disabled : Nothing to fill.
+       *     d) pq enabled : Not possible.
+       * 2) _PQ_ defined, but pq is not enabled :
+       *     a) Send data to Venus as ROI.
+       *     b) ROI enabled and dirty : Copy the data to Extradata buffer here
+       *     b) ROI enabled and no dirty : Nothing to fill
+       *     d) ROI disabled : Nothing to fill
+       * 3) _PQ_ defined and pq is enabled :
+       *     a) Send data to Venus as PQ.
+       *     b) ROI enabled and dirty : Copy the ROI contents to pq_roi buffer
+       *     c) ROI enabled and no dirty : pq_roi is already memset. Hence nothing to do here
+       *     d) ROI disabled : Just PQ data will be filled by GPU.
+       * 4) Normal ROI handling is in #else part as PQ can introduce delays.
+       *     By this time if client sets next ROI, then we shouldn't process new ROI here.
+       */
+
+    struct roidata roi;
+    memset(&roi, 0, sizeof(struct roidata));
+    roi.dirty = false;
+    if (m_roi_enabled) {
+        get_roi_for_timestamp(roi, nTimeStamp);
+    }
 
 #ifdef _PQ_
-        pthread_mutex_lock(&m_pq.lock);
-        if (m_pq.is_pq_enabled) {
-            if (roi.dirty) {
-                struct msm_vidc_roi_qp_payload *roiData =
-                    (struct msm_vidc_roi_qp_payload *)(m_pq.roi_extradata_info.uaddr);
-                roiData->upper_qp_offset = roi.info.nUpperQpOffset;
-                roiData->lower_qp_offset = roi.info.nLowerQpOffset;
-                roiData->b_roi_info = roi.info.bUseRoiInfo;
-                roiData->mbi_info_size = roi.info.nRoiMBInfoSize;
-                DEBUG_PRINT_HIGH("Using PQ + ROI QP map: Enable = %d", roiData->b_roi_info);
-                memcpy(roiData->data, roi.info.pRoiMBInfo, roi.info.nRoiMBInfoSize);
-                roi.dirty = false;
-            }
-            consumed_len += sizeof(msm_vidc_extradata_header) - sizeof(unsigned int);
-            data->nDataSize = m_pq.fill_pq_stats(buf, consumed_len);
-            data->nSize = ALIGN(sizeof(msm_vidc_extradata_header) +  data->nDataSize, 4);
-            data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_PQ_INFO;
-        } else {
+    pthread_mutex_lock(&m_pq.lock);
+    if (m_pq.is_pq_enabled) {
+        if (roi.dirty) {
+            struct msm_vidc_roi_qp_payload *roiData =
+                (struct msm_vidc_roi_qp_payload *)(m_pq.roi_extradata_info.uaddr);
+            roiData->upper_qp_offset = roi.info.nUpperQpOffset;
+            roiData->lower_qp_offset = roi.info.nLowerQpOffset;
+            roiData->b_roi_info = roi.info.bUseRoiInfo;
+            roiData->mbi_info_size = roi.info.nRoiMBInfoSize;
+            DEBUG_PRINT_HIGH("Using PQ + ROI QP map: Enable = %d", roiData->b_roi_info);
+            memcpy(roiData->data, roi.info.pRoiMBInfo, roi.info.nRoiMBInfoSize);
+        }
+        filled_len += sizeof(msm_vidc_extradata_header) - sizeof(unsigned int);
+        data->nDataSize = m_pq.fill_pq_stats(buf, filled_len);
+        data->nSize = ALIGN(sizeof(msm_vidc_extradata_header) +  data->nDataSize, 4);
+        data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_PQ_INFO;
+        data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
+    } else {
+        if (roi.dirty) {
             data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) +
                     sizeof(struct msm_vidc_roi_qp_payload) +
                     roi.info.nRoiMBInfoSize - 2 * sizeof(unsigned int), 4);
@@ -711,50 +809,55 @@
             data->nPortIndex = 0;
             data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP;
             data->nDataSize = sizeof(struct msm_vidc_roi_qp_payload);
-
             struct msm_vidc_roi_qp_payload *roiData =
-                (struct msm_vidc_roi_qp_payload *)(data->data);
+                    (struct msm_vidc_roi_qp_payload *)(data->data);
             roiData->upper_qp_offset = roi.info.nUpperQpOffset;
             roiData->lower_qp_offset = roi.info.nLowerQpOffset;
             roiData->b_roi_info = roi.info.bUseRoiInfo;
             roiData->mbi_info_size = roi.info.nRoiMBInfoSize;
             DEBUG_PRINT_HIGH("Using ROI QP map: Enable = %d", roiData->b_roi_info);
             memcpy(roiData->data, roi.info.pRoiMBInfo, roi.info.nRoiMBInfoSize);
-            roi.dirty = false;
-        }
-        pthread_mutex_unlock(&m_pq.lock);
-        data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
-#else // _PQ_
-        if (roi.dirty) {
-            data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) +
-                sizeof(struct msm_vidc_roi_qp_payload) +
-                roi.info.nRoiMBInfoSize - 2 * sizeof(unsigned int), 4);
-            data->nVersion.nVersion = OMX_SPEC_VERSION;
-            data->nPortIndex = 0;
-            data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP;
-            data->nDataSize = sizeof(struct msm_vidc_roi_qp_payload);
-
-            struct msm_vidc_roi_qp_payload *roiData =
-                (struct msm_vidc_roi_qp_payload *)(data->data);
-            roiData->upper_qp_offset = roi.info.nUpperQpOffset;
-            roiData->lower_qp_offset = roi.info.nLowerQpOffset;
-            roiData->b_roi_info = roi.info.bUseRoiInfo;
-            roiData->mbi_info_size = roi.info.nRoiMBInfoSize;
-            DEBUG_PRINT_HIGH("Using ROI QP map: Enable = %d", roiData->b_roi_info);
-            memcpy(roiData->data, roi.info.pRoiMBInfo, roi.info.nRoiMBInfoSize);
-
-            roi.dirty = false;
             data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
         }
+    }
+    pthread_mutex_unlock(&m_pq.lock);
+#else // _PQ_
+    if (roi.dirty) {
+        data->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) +
+            sizeof(struct msm_vidc_roi_qp_payload) +
+            roi.info.nRoiMBInfoSize - 2 * sizeof(unsigned int), 4);
+        data->nVersion.nVersion = OMX_SPEC_VERSION;
+        data->nPortIndex = 0;
+        data->eType = (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_ROI_QP;
+        data->nDataSize = sizeof(struct msm_vidc_roi_qp_payload);
+        struct msm_vidc_roi_qp_payload *roiData =
+                (struct msm_vidc_roi_qp_payload *)(data->data);
+        roiData->upper_qp_offset = roi.info.nUpperQpOffset;
+        roiData->lower_qp_offset = roi.info.nLowerQpOffset;
+        roiData->b_roi_info = roi.info.bUseRoiInfo;
+        roiData->mbi_info_size = roi.info.nRoiMBInfoSize;
+        DEBUG_PRINT_HIGH("Using ROI QP map: Enable = %d", roiData->b_roi_info);
+        memcpy(roiData->data, roi.info.pRoiMBInfo, roi.info.nRoiMBInfoSize);
+        data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
+    }
 #endif // _PQ_
 
+    if (m_roi_enabled) {
+        if (roi.dirty) {
+            DEBUG_PRINT_LOW("free roidata with timestamp %lld us", roi.timestamp);
+            free(roi.info.pRoiMBInfo);
+            roi.dirty = false;
+        }
+    }
+
 #ifdef _VQZIP_
     if (vqzip_sei_info.enabled && !input_extradata_info.vqzip_sei_found) {
         DEBUG_PRINT_ERROR("VQZIP is enabled, But no VQZIP SEI found. Rejecting the session");
-        munmap(pVirt, size);
-        return false;
+        if (pVirt)
+            munmap(pVirt, size);
+        return false; //This should be treated as fatal error
     }
-    if (vqzip_sei_info.enabled) {
+    if (vqzip_sei_info.enabled && pVirt) {
         data->nSize = (sizeof(OMX_OTHER_EXTRADATATYPE) +  sizeof(struct VQZipStats) + 3)&(~3);
         data->nVersion.nVersion = OMX_SPEC_VERSION;
         data->nPortIndex = 0;
@@ -764,15 +867,15 @@
         data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
     }
 #endif
-
         data->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
         data->nVersion.nVersion = OMX_SPEC_VERSION;
         data->eType = OMX_ExtraDataNone;
         data->nDataSize = 0;
         data->data[0] = 0;
 
-    }
-    munmap(pVirt, size);
+    if (pVirt)
+        munmap(pVirt, size);
+
     return true;
 }
 
@@ -819,12 +922,13 @@
             }
             case MSM_VIDC_EXTRADATA_METADATA_LTR:
             {
-                *p_extra->data = *p_extradata->data;
                 p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + p_extradata->data_size, 4);
                 p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
                 p_extra->nPortIndex = OMX_DirOutput;
                 p_extra->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataVideoLTRInfo;
                 p_extra->nDataSize = p_extradata->data_size;
+                memcpy(p_extra->data, p_extradata->data, p_extradata->data_size);
+                DEBUG_PRINT_LOW("LTRInfo Extradata = 0x%x", *((OMX_U32 *)p_extra->data));
                 break;
             }
             case MSM_VIDC_EXTRADATA_NONE:
@@ -1417,12 +1521,6 @@
     }
 #endif // _PQ_
 
-    /* Enable Low power mode by default for better power */
-
-    if (venc_set_perf_mode(V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE) == false) {
-        DEBUG_PRINT_HIGH("Failed to set Perf Mode");
-    }
-
     input_extradata_info.port_index = OUTPUT_PORT;
     output_extradata_info.port_index = CAPTURE_PORT;
 
@@ -1587,6 +1685,7 @@
                 bufreq.count);
             bufreq.count = 9;
         }
+
         if (m_sVenc_cfg.input_height * m_sVenc_cfg.input_width >= 3840*2160) {
             DEBUG_PRINT_LOW("Increasing buffer count = %d to 11", bufreq.count);
             bufreq.count = 11;
@@ -1707,6 +1806,7 @@
     struct v4l2_format fmt;
     struct v4l2_requestbuffers bufreq;
     int ret;
+    bool isCBR;
 
     switch ((int)index) {
         case OMX_IndexParamPortDefinition:
@@ -2265,6 +2365,19 @@
                 extradata = true;
                 break;
             }
+        case OMX_ExtraDataVideoLTRInfo:
+            {
+                DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataVideoLTRInfo");
+                OMX_BOOL extra_data =  *(OMX_BOOL *)(paramData);
+
+                if (venc_set_extradata(OMX_ExtraDataVideoLTRInfo, extra_data) == false) {
+                    DEBUG_PRINT_ERROR("ERROR: Setting OMX_ExtraDataVideoLTRInfo failed");
+                    return false;
+                }
+
+                extradata = true;
+                break;
+            }
         case OMX_QcomIndexParamSequenceHeaderWithIDR:
             {
                 PrependSPSPPSToIDRFramesParams * pParam =
@@ -2468,6 +2581,12 @@
         case OMX_QTIIndexParamVideoEnableRoiInfo:
             {
                 struct v4l2_control control;
+                OMX_QTI_VIDEO_PARAM_ENABLE_ROIINFO *pParam =
+                    (OMX_QTI_VIDEO_PARAM_ENABLE_ROIINFO *)paramData;
+                if (pParam->bEnableRoiInfo == OMX_FALSE) {
+                    DEBUG_PRINT_INFO("OMX_QTIIndexParamVideoEnableRoiInfo: bEnableRoiInfo is false");
+                    break;
+                }
                 if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_H264 &&
                         m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
                     DEBUG_PRINT_ERROR("OMX_QTIIndexParamVideoEnableRoiInfo is not supported for %lu codec", m_sVenc_cfg.codectype);
@@ -2480,6 +2599,7 @@
                     DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamVideoEnableRoiInfo failed");
                     return OMX_ErrorUnsupportedSetting;
                 }
+                m_roi_enabled = true;
 #ifdef _PQ_
                 m_pq.pConfig.a_qp.roi_enabled = (OMX_U32)true;
                 allocate_extradata(&m_pq.roi_extradata_info, ION_FLAG_CACHED);
@@ -2511,11 +2631,27 @@
                 QOMX_DISABLETYPE * pParam = (QOMX_DISABLETYPE *)paramData;
                 DEBUG_PRINT_LOW("venc_set_param: OMX_QTIIndexParamDisablePQ: %d", pParam->bDisable);
 #ifdef _PQ_
-                if (pParam->bDisable)
-                    m_pq.is_pq_force_disable = true;
+                m_pq.is_pq_force_disable = (pParam->bDisable == OMX_TRUE);
 #endif
                 break;
             }
+        case OMX_QTIIndexParamIframeSizeType:
+            {
+                QOMX_VIDEO_IFRAMESIZE* pParam =
+                    (QOMX_VIDEO_IFRAMESIZE *)paramData;
+                isCBR = rate_ctrl.rcmode == V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_VFR ||
+                    rate_ctrl.rcmode == V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR;
+                if (!isCBR) {
+                    DEBUG_PRINT_ERROR("venc_set_param: OMX_QTIIndexParamIframeSizeType not allowed for this configuration isCBR(%d)",
+                        isCBR);
+                    return OMX_ErrorUnsupportedSetting;
+                }
+                if (!venc_set_iframesize_type(pParam->eType)) {
+                    DEBUG_PRINT_ERROR("ERROR: Setting OMX_QTIIndexParamIframeSizeType failed");
+                    return OMX_ErrorUnsupportedSetting;
+                }
+                break;
+            }
         case OMX_IndexParamVideoSliceFMO:
         default:
             DEBUG_PRINT_ERROR("ERROR: Unsupported parameter in venc_set_param: %u",
@@ -3372,10 +3508,9 @@
 
     DEBUG_PRINT_HIGH("ENC_CONFIG: Session Priority: %u", sess_priority.priority);
 
+    DEBUG_PRINT_HIGH("ENC_CONFIG: ROI : %u", m_roi_enabled);
 #ifdef _PQ_
     DEBUG_PRINT_HIGH("ENC_CONFIG: Adaptive QP (PQ): %u", m_pq.is_pq_enabled);
-
-    DEBUG_PRINT_HIGH("ENC_CONFIG: ROI : %u", m_pq.pConfig.a_qp.roi_enabled);
 #endif // _PQ_
 
     DEBUG_PRINT_HIGH("ENC_CONFIG: Operating Rate: %u", operating_rate);
@@ -3735,16 +3870,22 @@
                         DEBUG_PRINT_ERROR("ERROR: venc_etb: handle is NULL");
                         return false;
                     }
+                    int usage = 0;
+                    usage = MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_USAGE);
+                    usage = usage > 0 ? usage : 0;
+
+                    if ((usage & private_handle_t::PRIV_FLAGS_ITU_R_601_FR)
+                            && (is_csc_enabled)) {
+                        buf.flags |= V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP;
+                    }
 
                     if (!streaming[OUTPUT_PORT] && !(m_sVenc_cfg.inputformat == V4L2_PIX_FMT_RGB32 ||
                         m_sVenc_cfg.inputformat == V4L2_PIX_FMT_RGBA8888_UBWC)) {
-                        int usage = 0;
+
                         struct v4l2_format fmt;
                         OMX_COLOR_FORMATTYPE color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
 
                         color_format = (OMX_COLOR_FORMATTYPE)MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_COLORFORMAT);
-                        usage = MetaBufferUtil::getIntAt(hnd, 0, MetaBufferUtil::INT_USAGE);
-                        usage = usage > 0 ? usage : 0;
 
                         memset(&fmt, 0, sizeof(fmt));
                         if (usage & private_handle_t::PRIV_FLAGS_ITU_R_709 ||
@@ -3754,10 +3895,17 @@
                         }
                         if (usage & private_handle_t::PRIV_FLAGS_ITU_R_601_FR) {
                             if (is_csc_enabled) {
-                                buf.flags = V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP;
-                                fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709;
-                                venc_set_colorspace(MSM_VIDC_BT709_5, 1,
-                                        MSM_VIDC_TRANSFER_BT709_5, MSM_VIDC_MATRIX_BT_709_5);
+                                struct v4l2_control control;
+                                control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC;
+                                control.value = V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_ENABLE;
+                                if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
+                                    DEBUG_PRINT_ERROR("venc_empty_buf: Failed to set VPE CSC for 601_to_709");
+                                } else {
+                                    DEBUG_PRINT_INFO("venc_empty_buf: Will convert 601-FR to 709");
+                                    fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709;
+                                    venc_set_colorspace(MSM_VIDC_BT709_5, 1,
+                                            MSM_VIDC_TRANSFER_BT709_5, MSM_VIDC_MATRIX_BT_709_5);
+                                }
                             } else {
                                 venc_set_colorspace(MSM_VIDC_BT601_6_525, 1,
                                         MSM_VIDC_TRANSFER_601_6_525, MSM_VIDC_MATRIX_601_6_525);
@@ -3772,10 +3920,6 @@
                             m_sVenc_cfg.inputformat = V4L2_PIX_FMT_NV12_UBWC;
                         }
 
-                        if (usage & private_handle_t::PRIV_FLAGS_ITU_R_709) {
-                            buf.flags = V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP;
-                        }
-
                         if (color_format > 0 && !venc_set_color_format(color_format)) {
                             DEBUG_PRINT_ERROR("Failed setting color format in Camerasource %lx", m_sVenc_cfg.inputformat);
                             return false;
@@ -3987,16 +4131,18 @@
     plane[0].reserved[1] = 0;
     buf.m.planes = plane;
     buf.length = num_input_planes;
+    buf.timestamp.tv_sec = bufhdr->nTimeStamp / 1000000;
+    buf.timestamp.tv_usec = (bufhdr->nTimeStamp % 1000000);
 
-    handle_input_extradata(buf);
-
+    if (!handle_input_extradata(buf)) {
+        DEBUG_PRINT_ERROR("%s Failed to handle input extradata", __func__);
+        return false;
+    }
     VIDC_TRACE_INT_LOW("ETB-TS", bufhdr->nTimeStamp / 1000);
 
     if (bufhdr->nFlags & OMX_BUFFERFLAG_EOS)
         buf.flags |= V4L2_QCOM_BUF_FLAG_EOS;
 
-    buf.timestamp.tv_sec = bufhdr->nTimeStamp / 1000000;
-    buf.timestamp.tv_usec = (bufhdr->nTimeStamp % 1000000);
     if (m_debug.in_buffer_log) {
         venc_input_log_buffers(bufhdr, fd, plane[0].data_offset, m_sVenc_cfg.inputformat);
     }
@@ -4093,6 +4239,7 @@
         }
         for (int i = 0; i < numBufs; ++i) {
             int v4l2Id = v4l2Ids[i];
+            int usage = 0;
 
             memset(&buf, 0, sizeof(buf));
             memset(&plane, 0, sizeof(plane));
@@ -4109,6 +4256,14 @@
             buf.m.planes = plane;
             buf.length = num_input_planes;
 
+            usage = MetaBufferUtil::getIntAt(hnd, i, MetaBufferUtil::INT_USAGE);
+            usage = usage > 0 ? usage : 0;
+
+            if ((usage & private_handle_t::PRIV_FLAGS_ITU_R_601_FR)
+                    && (is_csc_enabled)) {
+                buf.flags |= V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP;
+            }
+
             extra_idx = EXTRADATA_IDX(num_input_planes);
 
             if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
@@ -4141,8 +4296,6 @@
             }
 #endif // _PQ_
 
-            handle_input_extradata(buf);
-
             rc = ioctl(m_nDriver_fd, VIDIOC_PREPARE_BUF, &buf);
             if (rc)
                 DEBUG_PRINT_LOW("VIDIOC_PREPARE_BUF Failed");
@@ -4163,6 +4316,10 @@
             buf.timestamp.tv_sec = bufTimeStamp / 1000000;
             buf.timestamp.tv_usec = (bufTimeStamp % 1000000);
 
+            if (!handle_input_extradata(buf)) {
+                DEBUG_PRINT_ERROR("%s Failed to handle input extradata", __func__);
+                return false;
+            }
             VIDC_TRACE_INT_LOW("ETB-TS", bufTimeStamp / 1000);
 
             rc = ioctl(m_nDriver_fd, VIDIOC_QBUF, &buf);
@@ -4233,9 +4390,14 @@
     buf.flags = 0;
 
     if (venc_handle->is_secure_session()) {
-        output_metabuffer *meta_buf = (output_metabuffer *)(bufhdr->pBuffer);
-        native_handle_t *handle_t = meta_buf->nh;
-        plane[0].length = handle_t->data[3];
+        if (venc_handle->allocate_native_handle) {
+            native_handle_t *handle_t = (native_handle_t *)(bufhdr->pBuffer);
+            plane[0].length = handle_t->data[3];
+        } else {
+            output_metabuffer *meta_buf = (output_metabuffer *)(bufhdr->pBuffer);
+            native_handle_t *handle_t = meta_buf->nh;
+            plane[0].length = handle_t->data[3];
+        }
     }
 
     if (mBatchSize) {
@@ -4362,22 +4524,17 @@
 
 bool venc_dev::venc_set_vqzip_sei_type(OMX_BOOL enable)
 {
-    struct v4l2_control sei_control, yuvstats_control;
+    struct v4l2_control sei_control = {0,0}, yuvstats_control = {0,0};
 
     DEBUG_PRINT_HIGH("Set VQZIP SEI: %d", enable);
     sei_control.id = V4L2_CID_MPEG_VIDC_VIDEO_VQZIP_SEI;
     yuvstats_control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
 
-    if (ioctl(m_nDriver_fd, VIDIOC_G_CTRL, &yuvstats_control) < 0) {
-        DEBUG_PRINT_HIGH("Non-Fatal: Request to set VQZIP failed");
-    }
-
     if(enable) {
         sei_control.value = V4L2_CID_MPEG_VIDC_VIDEO_VQZIP_SEI_ENABLE;
-        yuvstats_control.value |= V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS;
+        yuvstats_control.value = V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS;
     } else {
         sei_control.value = V4L2_CID_MPEG_VIDC_VIDEO_VQZIP_SEI_DISABLE;
-        yuvstats_control.value &= ~V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS;
     }
 
     if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &sei_control) < 0) {
@@ -4388,8 +4545,8 @@
         DEBUG_PRINT_HIGH("Non-Fatal: Request to set YUVSTATS failed");
     }
 #ifdef _VQZIP_
-    vqzip.pConfig.nWidth = ALIGN(m_sVenc_cfg.input_width, 16);
-    vqzip.pConfig.nHeight = ALIGN(m_sVenc_cfg.input_height, 16);
+    vqzip.pConfig.nWidth = m_sVenc_cfg.input_width;
+    vqzip.pConfig.nHeight = m_sVenc_cfg.input_height;
     vqzip.init();
     vqzip_sei_info.enabled = true;
 #endif
@@ -4503,6 +4660,9 @@
         case OMX_ExtraDataEncoderOverrideQPInfo:
             control.value = V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO;
             break;
+        case OMX_ExtraDataVideoLTRInfo:
+            control.value = V4L2_MPEG_VIDC_EXTRADATA_LTR;
+            break;
         default:
             DEBUG_PRINT_ERROR("Unrecognized extradata index 0x%x", (unsigned int)extra_data);
             return false;
@@ -5244,6 +5404,13 @@
                          intra_period.num_pframes, intra_period.num_bframes);
     }
 
+    if (m_sVenc_cfg.input_width * m_sVenc_cfg.input_height >= 5376 * 2688 &&
+        (property_get("vidc.enc.disable_pframes", property_value, "0") && atoi(property_value))) {
+          intra_period.num_pframes = 0;
+          DEBUG_PRINT_LOW("Warning: Disabling P frames for 5k/6k resolutions pFrames = %lu bFrames = %lu",
+          intra_period.num_pframes, intra_period.num_bframes);
+    }
+
     control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
     control.value = intra_period.num_pframes;
     rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
@@ -5788,15 +5955,13 @@
         int rc;
         control.id = V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME;
         control.value = 1;
-       DEBUG_PRINT_ERROR("Calling IOCTL set control for id=%x, val=%d", control.id, control.value);
-        rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
 
+        rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
         if (rc) {
-           DEBUG_PRINT_ERROR("Failed to set Intra Frame Request control");
+            DEBUG_PRINT_ERROR("Failed to set Intra Frame Request control");
             return false;
         }
-
-       DEBUG_PRINT_ERROR("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
+        DEBUG_PRINT_HIGH("Success IOCTL set control for id=%x, value=%d", control.id, control.value);
     } else {
         DEBUG_PRINT_ERROR("ERROR: VOP Refresh is False, no effect");
     }
@@ -6396,6 +6561,7 @@
         control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
         break;
     default:
+        control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
         status = false;
         break;
     }
@@ -6410,6 +6576,8 @@
         }
 
         DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
+        DEBUG_PRINT_INFO("Requested perf level : %s",
+                ePerfLevel == OMX_QCOM_PerfLevelTurbo ? "turbo" : "nominal");
     }
     return status;
 }
@@ -6549,6 +6717,37 @@
     return true;
 }
 
+bool venc_dev::venc_set_iframesize_type(QOMX_VIDEO_IFRAMESIZE_TYPE type)
+{
+    struct v4l2_control control;
+    control.id = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE;
+
+    switch (type) {
+        case QOMX_IFRAMESIZE_DEFAULT:
+            control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT;
+            break;
+        case QOMX_IFRAMESIZE_MEDIUM:
+            control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM;
+            break;
+        case QOMX_IFRAMESIZE_HUGE:
+            control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE;
+            break;
+        case QOMX_IFRAMESIZE_UNLIMITED:
+            control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED;
+            break;
+        default:
+            DEBUG_PRINT_INFO("Unknown Iframe Size found setting it to default");
+            control.value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT;
+    }
+
+    if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
+        DEBUG_PRINT_ERROR("Failed to set iframe size hint");
+        return false;
+    }
+
+    return true;
+}
+
 bool venc_dev::venc_set_baselayerid(OMX_U32 baseid)
 {
     struct v4l2_control control;
@@ -6673,7 +6872,14 @@
     return true;
 }
 
-bool venc_dev::venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO *roiInfo) {
+bool venc_dev::venc_set_roi_qp_info(OMX_QTI_VIDEO_CONFIG_ROIINFO *roiInfo)
+{
+    struct roidata roi;
+
+    if (!m_roi_enabled) {
+        DEBUG_PRINT_ERROR("ROI info not enabled");
+        return false;
+    }
     if (!roiInfo) {
         DEBUG_PRINT_ERROR("No ROI info present");
         return false;
@@ -6684,15 +6890,66 @@
         return false;
     }
 
-#ifdef _PQ_
     DEBUG_PRINT_HIGH("ROI QP info received");
+    memset(&roi, 0, sizeof(struct roidata));
+
+#ifdef _PQ_
     pthread_mutex_lock(&m_pq.lock);
-    roi.info = *roiInfo;
+    roi.info.nUpperQpOffset = roiInfo->nUpperQpOffset;
+    roi.info.nLowerQpOffset = roiInfo->nLowerQpOffset;
+    roi.info.bUseRoiInfo = roiInfo->bUseRoiInfo;
+    roi.info.nRoiMBInfoSize = roiInfo->nRoiMBInfoSize;
+
+    roi.info.pRoiMBInfo = malloc(roi.info.nRoiMBInfoSize);
+    if (!roi.info.pRoiMBInfo) {
+        DEBUG_PRINT_ERROR("venc_set_roi_qp_info: malloc failed");
+        return false;
+    }
+    memcpy(roi.info.pRoiMBInfo, roiInfo->pRoiMBInfo, roiInfo->nRoiMBInfoSize);
+    /*
+     * set the timestamp equal to previous etb timestamp + 1
+     * to know this roi data arrived after previous etb
+     */
+    if (venc_handle->m_etb_count)
+        roi.timestamp = venc_handle->m_etb_timestamp + 1;
+    else
+        roi.timestamp = 0;
+
     roi.dirty = true;
+
+    pthread_mutex_lock(&m_roilock);
+    DEBUG_PRINT_LOW("list add roidata with timestamp %lld us", roi.timestamp);
+    m_roilist.push_back(roi);
+    pthread_mutex_unlock(&m_roilock);
+
     pthread_mutex_unlock(&m_pq.lock);
 #else // _PQ_
-    roi.info = *roiInfo;
+    roi.info.nUpperQpOffset = roiInfo->nUpperQpOffset;
+    roi.info.nLowerQpOffset = roiInfo->nLowerQpOffset;
+    roi.info.bUseRoiInfo = roiInfo->bUseRoiInfo;
+    roi.info.nRoiMBInfoSize = roiInfo->nRoiMBInfoSize;
+
+    roi.info.pRoiMBInfo = malloc(roi.info.nRoiMBInfoSize);
+    if (!roi.info.pRoiMBInfo) {
+        DEBUG_PRINT_ERROR("venc_set_roi_qp_info: malloc failed.");
+        return false;
+    }
+    memcpy(roi.info.pRoiMBInfo, roiInfo->pRoiMBInfo, roiInfo->nRoiMBInfoSize);
+    /*
+     * set the timestamp equal to previous etb timestamp + 1
+     * to know this roi data arrived after previous etb
+     */
+    if (venc_handle->m_etb_count)
+        roi.timestamp = venc_handle->m_etb_timestamp + 1;
+    else
+        roi.timestamp = 0;
+
     roi.dirty = true;
+
+    pthread_mutex_lock(&m_roilock);
+    DEBUG_PRINT_LOW("list add roidata with timestamp %lld us.", roi.timestamp);
+    m_roilist.push_back(roi);
+    pthread_mutex_unlock(&m_roilock);
 #endif // _PQ_
 
     return true;
@@ -6769,6 +7026,18 @@
     return true;
 }
 
+bool venc_dev::venc_get_pq_status(OMX_BOOL *pq_status) {
+
+    if (pq_status == NULL) {
+        return false;
+    }
+    *pq_status = OMX_FALSE;
+#ifdef _PQ_
+    *pq_status = m_pq.is_pq_force_disable ? OMX_FALSE : OMX_TRUE;
+#endif // _PQ_
+    return true;
+}
+
 bool venc_dev::venc_get_temporal_layer_caps(OMX_U32 *nMaxLayers,
         OMX_U32 *nMaxBLayers) {
 
@@ -7778,6 +8047,8 @@
         (m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den) <=
         (m_pq.caps.max_mb_per_sec / ((m_sVenc_cfg.input_height * m_sVenc_cfg.input_width) / 256));
 
+    frame_rate_supported = (((operating_rate >> 16) > 0) && ((operating_rate >> 16) < 5)) ? false : frame_rate_supported;
+
     yuv_format_supported = ((m_sVenc_cfg.inputformat == V4L2_PIX_FMT_NV12 && (m_pq.caps.color_formats & BIT(COLOR_FMT_NV12)))
             || (m_sVenc_cfg.inputformat == V4L2_PIX_FMT_NV21 && (m_pq.caps.color_formats & BIT(COLOR_FMT_NV21)))
             || (m_sVenc_cfg.inputformat == V4L2_PIX_FMT_NV12_UBWC && (m_pq.caps.color_formats & BIT(COLOR_FMT_NV12_UBWC))));
@@ -7838,6 +8109,11 @@
     configured_format = 0;
     is_pq_force_disable = 0;
     pthread_mutex_init(&lock, NULL);
+    memset(&pConfig, 0, sizeof(gpu_stats_lib_input_config));
+    memset(&roi_extradata_info, 0, sizeof(extradata_buffer_info));
+    roi_extradata_info.size = 16 * 1024;            // Max size considering 4k
+    roi_extradata_info.buffer_size = 16 * 1024;     // Max size considering 4k
+    roi_extradata_info.port_index = OUTPUT_PORT;
 }
 
 bool venc_dev::venc_dev_pq::init(unsigned long format)
@@ -7905,11 +8181,6 @@
         mPQConfigure = NULL;
         mPQComputeStats = NULL;
     }
-    memset(&pConfig, 0, sizeof(gpu_stats_lib_input_config));
-    memset(&roi_extradata_info, 0, sizeof(extradata_buffer_info));
-    roi_extradata_info.size = 16 * 1024;            // Max size considering 4k
-    roi_extradata_info.buffer_size = 16 * 1024;     // Max size considering 4k
-    roi_extradata_info.port_index = OUTPUT_PORT;
     is_YUV_format_uncertain = false;
     configured_format = format;