msm8998: Update to 07.00.00.279.039

msm8998: from hardware/qcom/media
  a8edebb3 mm-core: remove linkage of libgpustats temporarily
  d077eb17 Merge video components from mainline
  f4b8fc97 Promotion of video-userspace.lnx.2.1.c5-00002.
  4109b293 Promotion of video-userspace.lnx.2.1.c5-00001.
  40963fbb mm-video-v4l2: Allow openmax client to enable PQ
  394b61a9 mm-video-v4l2: venc: change default color format to NV21
  c221566d Promotion of video-userspace.lnx.2.1-00069.
  ec6dcc6b Merge "mm-video-v4l2: Add sdm660 for GPU stats computation" into video-userspace.lnx.2.1-dev
  0b24e656 Promotion of video-userspace.lnx.2.1-00068.
  124ce046 Promotion of video-userspace.lnx.2.1-00067.
  dca4eced mm-core: Add entry for apq8017 target
  94433b09 Merge "mm-video-v4l2: Enable VQZIP for auto tools" into video-userspace.lnx.2.1-dev
  8f7d5186 Merge "mm-video-v4l2: venc: Disable Pframes incase of resolution 5k/6k" into video-userspace.lnx.2.1-dev
  1ac9aa69 mm-video-v4l2: venc: handle setting performance-mode at run-time
  32b7ac24 mm-video-v4l2: Add sdm660 for GPU stats computation
  7559f68b Merge "mm-video-v4l2: create pthread with valid file descriptors" into video-userspace.lnx.2.1-dev
  fdbc40fe mm-video-v4l2: Allocate buffers in chunks less than 128MB
  2dc7c75f Merge "mm-video-v4l2: serialize FTB's for dropped frames" into video-userspace.lnx.2.1-dev
  3fb4a3cb mm-video-v4l2: create pthread with valid file descriptors
  815feb84 mm-video-v4l2: serialize FTB's for dropped frames
  14bfa7d7 mm-video-v4l2: Clear source frame after returning client buffer
  1131f3ef mm-video-v4l2: Enable VQZIP for auto tools
  77da79df mm-video-v4l2: venc: Disable Pframes incase of resolution 5k/6k
  cc5a94ba Promotion of video-userspace.lnx.2.1-00064.
  fa73ee3a Revert "mm-video-v4l2: vidc: venc: Remove sys prop for low power mode"

Signed-off-by: Thierry Strudel <tstrudel@google.com>
Change-Id: I1b3d670198dd31152405dbbf7346bc6133272c7c
diff --git a/msm8998/configure.ac b/msm8998/configure.ac
index 73cdd5a..e00ba47 100644
--- a/msm8998/configure.ac
+++ b/msm8998/configure.ac
@@ -51,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]]),
@@ -61,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]]),
@@ -128,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"])
@@ -161,8 +175,10 @@
 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"])
diff --git a/msm8998/mm-core/Android.mk b/msm8998/mm-core/Android.mk
index c9f14ba..a14e714 100644
--- a/msm8998/mm-core/Android.mk
+++ b/msm8998/mm-core/Android.mk
@@ -102,9 +102,9 @@
 LOCAL_SHARED_LIBRARIES  := liblog libdl libcutils
 LOCAL_CFLAGS            := $(OMXCORE_CFLAGS)
 
-ifneq (,$(filter msm8996 msm8998,$(TARGET_BOARD_PLATFORM)))
-LOCAL_SHARED_LIBRARIES  += libgpustats
-endif
+#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
@@ -130,9 +130,9 @@
 LOCAL_SHARED_LIBRARIES  := liblog libdl libcutils
 LOCAL_CFLAGS            := $(OMXCORE_CFLAGS)
 
-ifneq (,$(filter msm8996 msm8998,$(TARGET_BOARD_PLATFORM)))
-LOCAL_SHARED_LIBRARIES  += libgpustats
-endif
+#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
diff --git a/msm8998/mm-core/Makefile.am b/msm8998/mm-core/Makefile.am
index 01f6cbb..011e155 100644
--- a/msm8998/mm-core/Makefile.am
+++ b/msm8998/mm-core/Makefile.am
@@ -58,6 +58,10 @@
 TARGET_REGISTRY = 8909
 endif
 
+if TARGET_MSM8937
+TARGET_REGISTRY = 8937
+endif
+
 c_sources +=src/${TARGET_REGISTRY}/registry_table_android.c
 
 lib_LTLIBRARIES = libOmxCore.la
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-video-v4l2/vidc/vdec/inc/omx_vdec.h b/msm8998/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
index 784bdf7..6b827c9 100644
--- a/msm8998/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
+++ b/msm8998/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
@@ -260,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;
@@ -292,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;
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 e0771e9..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
@@ -6441,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_
             }
@@ -6786,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;
@@ -6811,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;
             }
         }
@@ -6884,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) {
@@ -6929,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++;
@@ -6983,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();
@@ -7026,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)) {
@@ -8945,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) {
@@ -10000,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();
 }
 
@@ -10548,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 {
@@ -12503,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 3210ff5..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 sdm660
+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
diff --git a/msm8998/mm-video-v4l2/vidc/venc/Makefile.am b/msm8998/mm-video-v4l2/vidc/venc/Makefile.am
index f16f1a1..50a5d53 100644
--- a/msm8998/mm-video-v4l2/vidc/venc/Makefile.am
+++ b/msm8998/mm-video-v4l2/vidc/venc/Makefile.am
@@ -55,6 +55,10 @@
 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
@@ -89,3 +93,4 @@
 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_video_base.h b/msm8998/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
index 76d26e2..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
@@ -537,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();
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 70f77f6..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
@@ -113,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/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 f7cfcb9..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
@@ -5361,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*/
@@ -5398,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;
@@ -5419,7 +5418,7 @@
             }
             index = opqBuf - m_inp_mem_ptr;
         } else {
-            opqBuf = (OMX_BUFFERHEADERTYPE* ) buffer;
+            opqBuf = (OMX_BUFFERHEADERTYPE* ) psource_frame;
             index = opqBuf - meta_buffer_hdr;
         }
 
@@ -5448,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 =
@@ -5466,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 8b41fa1..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
@@ -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)
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 b2d8969..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
@@ -1521,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;
 
@@ -2637,8 +2631,7 @@
                 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;
             }
@@ -5411,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);