merge in lmp-mr1-release history after reset to lmp-mr1-dev
diff --git a/mm-core/inc/OMX_QCOMExtns.h b/mm-core/inc/OMX_QCOMExtns.h
index a5676bf..1c85a80 100755
--- a/mm-core/inc/OMX_QCOMExtns.h
+++ b/mm-core/inc/OMX_QCOMExtns.h
@@ -468,6 +468,8 @@
     QOMX_IndexParamVideoInitialQp = 0x7F00003B,
 
     OMX_QcomIndexParamSetMVSearchrange = 0x7F00003C,
+
+    OMX_QcomIndexFlexibleYUVDescription = 0x7F00003D,
 };
 
 /**
diff --git a/mm-video-legacy/vidc/vdec/inc/omx_vdec.h b/mm-video-legacy/vidc/vdec/inc/omx_vdec.h
index 240ffb6..4787b77 100644
--- a/mm-video-legacy/vidc/vdec/inc/omx_vdec.h
+++ b/mm-video-legacy/vidc/vdec/inc/omx_vdec.h
@@ -549,6 +549,7 @@
                                    OMX_PTR                appData,
                                    OMX_U32                bytes,
                                    OMX_U8                 *buffer);
+
 #ifdef MAX_RES_720P
     OMX_ERRORTYPE get_supported_profile_level_for_720p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType);
 #endif
@@ -844,11 +845,19 @@
         OMX_ERRORTYPE allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
              OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,
              OMX_U32 bytes);
+        OMX_ERRORTYPE use_output_buffer(OMX_HANDLETYPE hComp,
+             OMX_BUFFERHEADERTYPE **bufferHdr, OMX_U32 port, OMX_PTR appData,
+             OMX_U32 bytes, OMX_U8 *buffer);
+
         OMX_ERRORTYPE free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr);
+        void enable_native_buffers(bool enable) {m_native_buffers_enabled = enable;}
+        OMX_U32 get_output_stride();
+        OMX_U32 get_output_scanlines();
     private:
         #define MAX_COUNT 32
         omx_vdec *omx;
         bool enabled;
+        bool m_native_buffers_enabled;
         OMX_COLOR_FORMATTYPE ColorFormat;
         void init_members();
         bool color_convert_mode;
diff --git a/mm-video-legacy/vidc/vdec/src/omx_vdec.cpp b/mm-video-legacy/vidc/vdec/src/omx_vdec.cpp
index 06d333d..ccb3f7a 100644
--- a/mm-video-legacy/vidc/vdec/src/omx_vdec.cpp
+++ b/mm-video-legacy/vidc/vdec/src/omx_vdec.cpp
@@ -146,6 +146,9 @@
 
 #define Log2(number, power)  { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) &&  power < 16) { temp >>=0x1; power++; } }
 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power);  num = q >> power; den = 0x1 << (16 - power); }
+#define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1)))
+#define ALIGN32 32
+#define ALIGN16 16
 
 bool omx_vdec::m_secure_display = false;
 
@@ -2777,7 +2780,7 @@
                   " NoMore Color formats\n");
            eRet =  OMX_ErrorNoMore;
         }
-        ALOGI("get_parameter: color-format=%x @ index=%d", portFmt->eColorFormat, portFmt->nIndex);
+        DEBUG_PRINT_HIGH("get_parameter: color-format=%x @ index=%d", portFmt->eColorFormat, portFmt->nIndex);
       }
       else
       {
@@ -3573,6 +3576,7 @@
           EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
           if(enableNativeBuffers) {
               m_enable_android_native_buffers = enableNativeBuffers->enable;
+              client_buffers.enable_native_buffers(m_enable_android_native_buffers);
           }
       }
       break;
@@ -4403,8 +4407,9 @@
   }
   if(port == OMX_CORE_INPUT_PORT_INDEX)
     error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
-  else if(port == OMX_CORE_OUTPUT_PORT_INDEX)
-    error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
+  else if(port == OMX_CORE_OUTPUT_PORT_INDEX) {
+    error = client_buffers.use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
+  }
   else
   {
     DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d\n",(int)port);
@@ -5087,7 +5092,7 @@
     drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
                     drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
                     &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
-                    &drv_ctx.op_buf_ion_info[i].fd_ion_data, ION_FLAG_CACHED);
+                    &drv_ctx.op_buf_ion_info[i].fd_ion_data, 0);
     if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
         return OMX_ErrorInsufficientResources;
      }
@@ -7994,13 +7999,9 @@
   }
   portDefn->format.video.nFrameHeight =  drv_ctx.video_resolution.frame_height;
   portDefn->format.video.nFrameWidth  =  drv_ctx.video_resolution.frame_width;
-  portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
-  portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
-  if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
-      (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
-      portDefn->format.video.nStride = drv_ctx.video_resolution.frame_width;
-      portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
-  }
+  portDefn->format.video.nStride = client_buffers.get_output_stride();
+  portDefn->format.video.nSliceHeight = client_buffers.get_output_scanlines();
+
   DEBUG_PRINT_LOW("update_portdef Width = %d Height = %d Stride = %u"
     "SliceHeight = %u \n", portDefn->format.video.nFrameHeight,
     portDefn->format.video.nFrameWidth,
@@ -9046,6 +9047,7 @@
 omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
 {
   enabled = false;
+  m_native_buffers_enabled = false;
   omx = NULL;
   init_members();
   ColorFormat = OMX_COLOR_FormatMax;
@@ -9095,8 +9097,8 @@
   pthread_mutex_lock(&omx->c_lock);
   c2d.close();
   status = c2d.open(omx->drv_ctx.video_resolution.frame_height,
-                    omx->drv_ctx.video_resolution.frame_width,
-                    YCbCr420Tile, dest_format);
+                omx->drv_ctx.video_resolution.frame_width,
+                YCbCr420Tile, dest_format);
   if (status) {
     status = c2d.get_buffer_size(C2D_INPUT,src_size);
     if (status)
@@ -9200,6 +9202,21 @@
       status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
                   bufadd->pBuffer, bufadd->pBuffer, pmem_fd[index],
                   pmem_baseaddress[index], pmem_baseaddress[index]);
+// DEBUG: dump converted output
+#if 0
+      {
+          int w = get_output_stride();
+          int h = get_output_scanlines();
+          char fileName[128] = {0};
+          sprintf(fileName,"/data/misc/media/out_%d_%d.yuv",w,h);
+          FILE* fp = fopen(fileName,"ab");
+          if (fp) {
+              ALOGI("c2d: dumped: %s",fileName);
+              fwrite(pmem_baseaddress[index], (w * h * 3)/2, 1, fp);
+              fclose(fp);
+          }
+      }
+#endif
       pthread_mutex_unlock(&omx->c_lock);
       m_out_mem_ptr_client[index].nFilledLen = buffer_size_req;
       if (!status){
@@ -9252,6 +9269,31 @@
 	  buffer_alignment_req = omx->drv_ctx.op_buf.alignment;
     return true;
 }
+
+OMX_U32 omx_vdec::allocate_color_convert_buf::get_output_stride() {
+  // If Converting to Planar/SemiPlanar in bytebuffer mode, stride/slice-height
+  //  are not aligned per hardware restrictions.
+  if (enabled &&
+          (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
+          ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
+      return ALIGN(omx->drv_ctx.video_resolution.frame_width, ALIGN16);
+  } else {
+      return omx->drv_ctx.video_resolution.stride;
+  }
+}
+
+OMX_U32 omx_vdec::allocate_color_convert_buf::get_output_scanlines() {
+  // If Converting to Planar/SemiPlanar in bytebuffer mode, stride/slice-height
+  //  are not aligned per hardware restrictions.
+  if (enabled &&
+          (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
+          ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
+      return omx->drv_ctx.video_resolution.frame_height;
+  } else {
+      return omx->drv_ctx.video_resolution.scan_lines;
+  }
+}
+
 OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
   OMX_BUFFERHEADERTYPE *bufhdr) {
   unsigned int index = 0;
@@ -9269,12 +9311,33 @@
     DEBUG_PRINT_ERROR("\n Incorrect index color convert free_output_buffer");
     return OMX_ErrorBadParameter;
   }
-  if (pmem_fd[index] > 0) {
-    munmap(pmem_baseaddress[index], buffer_size_req);
-    close(pmem_fd[index]);
+  if (m_native_buffers_enabled) {
+      // unmap client's fd
+      if (pmem_fd[index] > 0 && pmem_baseaddress[index]) {
+          munmap(pmem_baseaddress[index], buffer_size_req);
+          pmem_baseaddress[index] = 0;
+      }
+      // free from internal set
+      // Do this explicitly as omx->free_output_buffer() does not free
+      //  the memory when native-buffers are enabled
+      if (omx->drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) {
+          DEBUG_PRINT_LOW("free_buffer(conversion): free ion mem[%d] fd=%d size=%d",
+                  index, omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
+                  omx->drv_ctx.ptr_outputbuffer[index].mmaped_size);
+          munmap (omx->drv_ctx.ptr_outputbuffer[index].bufferaddr,
+                  omx->drv_ctx.ptr_outputbuffer[index].mmaped_size);
+          omx->free_ion_memory(&(omx->drv_ctx.op_buf_ion_info[index]));
+          close (omx->drv_ctx.ptr_outputbuffer[index].pmem_fd);
+          omx->drv_ctx.ptr_outputbuffer[index].pmem_fd = -1;
+      }
+  } else {
+      if (pmem_fd[index] > 0) {
+        munmap(pmem_baseaddress[index], buffer_size_req);
+        close(pmem_fd[index]);
+      }
+      pmem_fd[index] = -1;
+      omx->free_ion_memory(&op_buf_ion_info[index]);
   }
-  pmem_fd[index] = -1;
-  omx->free_ion_memory(&op_buf_ion_info[index]);
   m_heap_ptr[index].video_heap_ptr = NULL;
   if (allocated_count > 0)
     allocated_count--;
@@ -9329,7 +9392,7 @@
   op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
     buffer_size_req,buffer_alignment_req,
     &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
-    ION_FLAG_CACHED);
+    0);
 
   pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
   if (op_buf_ion_info[i].ion_device_fd < 0) {
@@ -9370,6 +9433,85 @@
   return eRet;
 }
 
+OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::use_output_buffer(OMX_HANDLETYPE hComp,
+        OMX_BUFFERHEADERTYPE **bufferHdr, OMX_U32 port, OMX_PTR appData,
+        OMX_U32 bytes, OMX_U8 *buffer)
+{
+    OMX_ERRORTYPE eRet = OMX_ErrorNone;
+    const char *func = "use_buf(conversion)";
+
+    if (!enabled) {
+        return omx->use_output_buffer(hComp, bufferHdr, port, appData, bytes, buffer);
+    }
+    // assert native-buffer-mode is enabled
+    if (!m_native_buffers_enabled) {
+        DEBUG_PRINT_ERROR("%s: use_buffer called in non-surface mode", func);
+        return OMX_ErrorUnsupportedSetting;
+    }
+    if (omx->is_component_secure()) {
+        DEBUG_PRINT_ERROR("%s: Cannot color-convert secure buffers", func);
+        return OMX_ErrorUnsupportedSetting;
+    }
+    if (!bufferHdr || bytes > buffer_size_req) {
+        DEBUG_PRINT_ERROR("%s: Invalid params hdr=%p requested-size=%d passed-size=%d",
+                func, bufferHdr, buffer_size_req, bytes);
+        return OMX_ErrorBadParameter;
+    }
+    if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
+        DEBUG_PRINT_ERROR("%s: all buffers (%d) already allocated", func, allocated_count);
+        return OMX_ErrorInsufficientResources;
+    }
+
+    // Allocate pixel buffer for the decoder
+    OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
+    eRet = omx->allocate_output_buffer(hComp, &temp_bufferHdr,
+             port, appData, omx->drv_ctx.op_buf.buffer_size);
+    if (eRet != OMX_ErrorNone || !temp_bufferHdr){
+        DEBUG_PRINT_ERROR("%s: decoder's o/p allocation failed", func);
+        return eRet;
+    }
+    if ((temp_bufferHdr - omx->m_out_mem_ptr) >= omx->drv_ctx.op_buf.actualcount) {
+        DEBUG_PRINT_ERROR("%s: Invalid header index %d",
+                func, (temp_bufferHdr - omx->m_out_mem_ptr));
+        return OMX_ErrorUndefined;
+    }
+    unsigned int i = allocated_count;
+    private_handle_t *handle = (private_handle_t *)buffer;
+
+    pmem_fd[i] = handle->fd;
+    pmem_baseaddress[i] = (OMX_U8*)mmap(0, handle->size,
+            PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
+    if (pmem_baseaddress[i] == MAP_FAILED) {
+        DEBUG_PRINT_ERROR("%s: Failed to map native handle fd=%d size=%d",
+               func, handle->fd, handle->size);
+        return OMX_ErrorInsufficientResources;
+    }
+    m_heap_ptr[i].video_heap_ptr = NULL; //not used
+    m_pmem_info_client[i].pmem_fd = handle->fd;
+    m_pmem_info_client[i].offset = 0;
+    m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
+    m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
+    m_platform_list_client[i].nEntries = 1;
+    m_platform_list_client[i].entryList = &m_platform_entry_client[i];
+    m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
+    m_out_mem_ptr_client[i].nAllocLen = handle->size;
+    m_out_mem_ptr_client[i].nFilledLen = 0;
+    m_out_mem_ptr_client[i].nFlags = 0;
+    m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+    m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
+    m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
+    m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
+
+    m_out_mem_ptr_client[i].pBuffer = buffer;
+    m_out_mem_ptr_client[i].pAppPrivate = appData;
+
+    *bufferHdr = &m_out_mem_ptr_client[i];
+    DEBUG_PRINT_LOW("%s: allocated header[%d]=%p for native handle[fd=%d size=%d]",
+            func, i, *bufferHdr, handle->fd, handle->size);
+    allocated_count++;
+    return eRet;
+}
+
 bool omx_vdec::is_component_secure()
 {
   return secure_mode;
diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
index 3ca6d64..59fd836 100755
--- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
+++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
@@ -1036,30 +1036,18 @@
         perf_control m_perf_control;
 
         volatile int32_t m_queued_codec_config_count;
-        static OMX_COLOR_FORMATTYPE getPreferredColorFormatNonSurfaceMode(OMX_U32 index) {
-            //On Android, we default to standard YUV formats for non-surface use-cases
-            //where apps prefer known color formats.
-            OMX_COLOR_FORMATTYPE formatsNonSurfaceMode[] = {
-                [0] = OMX_COLOR_FormatYUV420SemiPlanar,
-                [1] = OMX_COLOR_FormatYUV420Planar,
-                [2] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
+        static OMX_COLOR_FORMATTYPE getColorFormatAt(OMX_U32 index) {
+            OMX_COLOR_FORMATTYPE formats[] = {
+                [0] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
+                [1] = OMX_COLOR_FormatYUV420SemiPlanar,
+                [2] = OMX_COLOR_FormatYUV420Planar,
                 [3] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView,
             };
-            return (index < sizeof(formatsNonSurfaceMode) / sizeof(OMX_COLOR_FORMATTYPE)) ?
-                formatsNonSurfaceMode[index] : OMX_COLOR_FormatMax;
+            return (index < sizeof(formats) / sizeof(OMX_COLOR_FORMATTYPE)) ?
+                formats[index] : OMX_COLOR_FormatMax;
         }
 
-        static OMX_COLOR_FORMATTYPE getPreferredColorFormatDefaultMode(OMX_U32 index) {
-            //for surface mode (normal playback), advertise native/accelerated formats first
-            OMX_COLOR_FORMATTYPE formatsDefault[] = {
-                [0] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
-                [1] = OMX_COLOR_FormatYUV420Planar,
-                [2] = OMX_COLOR_FormatYUV420SemiPlanar,
-                [3] = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView,
-            };
-            return (index < sizeof(formatsDefault) / sizeof(OMX_COLOR_FORMATTYPE)) ?
-                formatsDefault[index] : OMX_COLOR_FormatMax;
-        }
+        static OMX_ERRORTYPE describeColorFormat(DescribeColorFormatParams *params);
 };
 
 #ifdef _MSM8974_
diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp
index f5f0898..69fe2c4 100755
--- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp
+++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp
@@ -2822,17 +2822,7 @@
                                     }
                                 } else if (1 == portFmt->nPortIndex) {
                                     portFmt->eCompressionFormat =  OMX_VIDEO_CodingUnused;
-
-                                    // Distinguish non-surface mode from normal playback use-case based on
-                                    // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
-                                    // For non-android, use the default list
-                                    bool useNonSurfaceMode = false;
-#if _ANDROID_
-                                    useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
-#endif
-                                    portFmt->eColorFormat = useNonSurfaceMode ?
-                                        getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
-                                        getPreferredColorFormatDefaultMode(portFmt->nIndex);
+                                    portFmt->eColorFormat = getColorFormatAt(portFmt->nIndex);
 
                                     if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
                                         eRet = OMX_ErrorNoMore;
@@ -2971,7 +2961,11 @@
                                     }
                                     break;
 #endif
-
+        case OMX_QcomIndexFlexibleYUVDescription: {
+                DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
+                eRet = describeColorFormat((DescribeColorFormatParams *)paramData);
+                break;
+            }
         default: {
                  DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
                  eRet =OMX_ErrorUnsupportedIndex;
@@ -3613,13 +3607,6 @@
                                            if (enableNativeBuffers) {
                                                m_enable_android_native_buffers = enableNativeBuffers->enable;
                                            }
-                                           if (m_enable_android_native_buffers) {
-                                               // Use the most-preferred-native-color-format as surface-mode is hinted here
-                                               if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
-                                                   DEBUG_PRINT_ERROR("Failed to set native color format!");
-                                                   eRet = OMX_ErrorUnsupportedSetting;
-                                               }
-                                           }
                                        }
                                        break;
         case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
@@ -4159,6 +4146,9 @@
         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
     }
 #endif
+    else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
+        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
+    }
     else {
         DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
         return OMX_ErrorNotImplemented;
@@ -10093,3 +10083,70 @@
         }
     }
 }
+
+
+//static
+OMX_ERRORTYPE omx_vdec::describeColorFormat(DescribeColorFormatParams *params) {
+    if (params == NULL) {
+        DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
+        return OMX_ErrorBadParameter;
+    }
+
+    MediaImage *img = &(params->sMediaImage);
+    switch(params->eColorFormat) {
+        case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
+        {
+            img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
+            img->mNumPlanes = 3;
+            // mWidth and mHeight represent the W x H of the largest plane
+            // In our case, this happens to be the Stride x Scanlines of Y plane
+            img->mWidth = params->nFrameWidth;
+            img->mHeight = params->nFrameHeight;
+            size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
+            size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
+            img->mBitDepth = 8;
+            //Plane 0 (Y)
+            img->mPlane[MediaImage::Y].mOffset = 0;
+            img->mPlane[MediaImage::Y].mColInc = 1;
+            img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
+            img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
+            img->mPlane[MediaImage::Y].mVertSubsampling = 1;
+            //Plane 1 (U)
+            img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
+            img->mPlane[MediaImage::U].mColInc = 2;           //interleaved UV
+            img->mPlane[MediaImage::U].mRowInc =
+                    VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
+            img->mPlane[MediaImage::U].mHorizSubsampling = 2;
+            img->mPlane[MediaImage::U].mVertSubsampling = 2;
+            //Plane 2 (V)
+            img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
+            img->mPlane[MediaImage::V].mColInc = 2;           //interleaved UV
+            img->mPlane[MediaImage::V].mRowInc =
+                    VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
+            img->mPlane[MediaImage::V].mHorizSubsampling = 2;
+            img->mPlane[MediaImage::V].mVertSubsampling = 2;
+            break;
+        }
+
+        case OMX_COLOR_FormatYUV420Planar:
+        case OMX_COLOR_FormatYUV420SemiPlanar:
+            // We need not describe the standard OMX linear formats as these are
+            // understood by client. Fail this deliberately to let client fill-in
+            return OMX_ErrorUnsupportedSetting;
+
+        default:
+            // Rest all formats which are non-linear cannot be described
+            DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
+            img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
+            return OMX_ErrorNone;
+    };
+
+    DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
+    DEBUG_PRINT_LOW("  FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
+    DEBUG_PRINT_LOW("  YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
+    for (size_t i = 0; i < img->mNumPlanes; ++i) {
+        DEBUG_PRINT_LOW("    Plane[%d] : offset=%d / xStep=%d / yStep = %d",
+                i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
+    }
+    return OMX_ErrorNone;
+}