mm-video-v4l2: vidc: Add support for color aspects

Add support for color aspects setting from clients and embed that
information in bit-stream. When client sets different color format
than in bit-stream, update them with correct one.

Author: Praneeth Paladugu <ppaladug@codeaurora.org>

Bug: 29189938
Bug: 29620306

Change-Id: I31bf3a81ef0690dc3565875d2fba4607abf46536
diff --git a/msm8996/mm-core/inc/OMX_QCOMExtns.h b/msm8996/mm-core/inc/OMX_QCOMExtns.h
index ad88a8f..8e92946 100644
--- a/msm8996/mm-core/inc/OMX_QCOMExtns.h
+++ b/msm8996/mm-core/inc/OMX_QCOMExtns.h
@@ -553,6 +553,18 @@
 
     /*"OMX.google.android.index.allocateNativeHandle"*/
     OMX_GoogleAndroidIndexAllocateNativeHandle = 0x7F00005B,
+
+    /*"OMX.google.android.index.describeColorAspects"*/
+    OMX_QTIIndexConfigDescribeColorAspects = 0x7F00005E,
+
+    OMX_QTIIndexParamVUIExtraDataExtraData = 0x7F00005F,
+
+    OMX_QTIIndexParamMPEG2SeqDispExtraData = 0x7F000060,
+
+    OMX_QTIIndexParamVC1SeqDispExtraData = 0x7F000061,
+
+    OMX_QTIIndexParamVPXColorSpaceExtraData = 0x7F000062,
+
 };
 
 /**
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 2928ae8..624524a 100644
--- a/msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
+++ b/msm8996/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
@@ -48,6 +48,7 @@
 #include <inttypes.h>
 #include <cstddef>
 #include <cutils/atomic.h>
+#include <qdMetaData.h>
 
 static ptrdiff_t x;
 
@@ -665,6 +666,10 @@
         void set_frame_rate(OMX_S64 act_timestamp);
         void handle_extradata_secure(OMX_BUFFERHEADERTYPE *p_buf_hdr);
         void handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr);
+        void convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
+            OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space,
+            ColorAspects *aspects);
+        void handle_color_space_info(void *data, unsigned int buf_index);
         void print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra);
 #ifdef _MSM8974_
         void append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
@@ -985,6 +990,8 @@
         bool m_smoothstreaming_mode;
 
         bool m_input_pass_buffer_fd;
+        DescribeColorAspectsParams m_client_color_space;
+        DescribeColorAspectsParams m_internal_color_space;
 
         OMX_U32 m_smoothstreaming_width;
         OMX_U32 m_smoothstreaming_height;
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 fd3cbca..b1ef763 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
@@ -741,6 +741,8 @@
     memset (m_hwdevice_name,0,sizeof(m_hwdevice_name));
     memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
     memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
+    memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams));
+    memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
     m_demux_entries = 0;
     msg_thread_id = 0;
     async_thread_id = 0;
@@ -788,6 +790,11 @@
     is_q6_platform = false;
     m_perf_control.send_hint_to_mpctl(true);
     m_input_pass_buffer_fd = false;
+    m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
+    m_client_color_space.sAspects.mRange =  ColorAspects::RangeUnspecified;
+    m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
+    m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
+    m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
 }
 
 static const int event_type[] = {
@@ -1647,6 +1654,8 @@
                                             DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
                                                     pThis->rectangle.nLeft, pThis->rectangle.nTop,
                                                     pThis->rectangle.nWidth, pThis->rectangle.nHeight);
+                                        } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) {
+                                            DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects");
                                         } else {
                                             DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
                                             break;
@@ -4989,6 +4998,20 @@
 
             break;
         }
+        case OMX_QTIIndexConfigDescribeColorAspects:
+        {
+         // VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
+         // FIXME Till Framework fills right size
+            DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
+            DEBUG_PRINT_HIGH("Get Config : Color Space values : sAspects.mPrimaries  = %d sAspects.mRange = %d"
+               " sAspects.mTransfer %d, sAspects.mMatrixCoeffs = %d", m_internal_color_space.sAspects.mPrimaries,
+               m_internal_color_space.sAspects.mRange, m_internal_color_space.sAspects.mTransfer,
+               m_internal_color_space.sAspects.mMatrixCoeffs);
+            memcpy(params, &m_internal_color_space, sizeof(DescribeColorAspectsParams));
+            // Sync component's client struct and values informed to client
+            memcpy(&m_client_color_space, &m_internal_color_space, sizeof(DescribeColorAspectsParams));
+            break;
+        }
         default: {
                  DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
                  eRet = OMX_ErrorBadParameter;
@@ -5200,6 +5223,18 @@
                     rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
         }
         return ret;
+
+    } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) {
+        VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
+        DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
+        enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, true, true);
+
+        DEBUG_PRINT_HIGH("Set Config : Color Space values : sAspects.mPrimaries  = %d sAspects.mRange = %d"
+                " sAspects.mTransfer %d, sAspects.mMatrixCoeffs = %d", params->sAspects.mPrimaries,
+                params->sAspects.mRange, params->sAspects.mTransfer,
+                params->sAspects.mMatrixCoeffs);
+        memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
+        return ret;
     }
 
     return OMX_ErrorNotImplemented;
@@ -5279,6 +5314,8 @@
         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
     } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
+    } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
+        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
     } else {
         DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
         return OMX_ErrorNotImplemented;
@@ -9964,6 +10001,260 @@
     }
 }
 
+void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
+    OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space, ColorAspects *aspects)
+{
+    switch (primaries) {
+        case MSM_VIDC_BT709_5:
+            *color_space = ITU_R_709;
+            aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
+            break;
+        case MSM_VIDC_UNSPECIFIED:
+            aspects->mPrimaries = ColorAspects::PrimariesUnspecified;
+            break;
+        case MSM_VIDC_BT470_6_M:
+            aspects->mPrimaries = ColorAspects::PrimariesBT470_6M;
+            break;
+        case MSM_VIDC_BT601_6_625:
+            aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
+            *color_space = range ? ITU_R_601_FR : ITU_R_601;
+            break;
+        case MSM_VIDC_BT601_6_525:
+            *color_space = range ? ITU_R_601_FR : ITU_R_601;
+            aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
+            break;
+        case MSM_VIDC_GENERIC_FILM:
+            aspects->mPrimaries = ColorAspects::PrimariesGenericFilm;
+            break;
+        case MSM_VIDC_BT2020:
+            aspects->mPrimaries = ColorAspects::PrimariesBT2020;
+            break;
+        default:
+            aspects->mPrimaries = ColorAspects::PrimariesOther;
+            break;
+    }
+
+    aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
+
+    switch (transfer) {
+        case MSM_VIDC_TRANSFER_BT709_5:
+        case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625:
+            aspects->mTransfer = ColorAspects::TransferSMPTE170M;
+            break;
+        case MSM_VIDC_TRANSFER_UNSPECIFIED:
+            aspects->mTransfer = ColorAspects::TransferUnspecified;
+            break;
+        case MSM_VIDC_TRANSFER_BT_470_6_M:
+            aspects->mTransfer = ColorAspects::TransferGamma22;
+            break;
+        case MSM_VIDC_TRANSFER_BT_470_6_BG:
+            aspects->mTransfer = ColorAspects::TransferGamma28;
+            break;
+        case MSM_VIDC_TRANSFER_SMPTE_240M:
+            aspects->mTransfer = ColorAspects::TransferSMPTE240M;
+            break;
+        case MSM_VIDC_TRANSFER_LINEAR:
+            aspects->mTransfer = ColorAspects::TransferLinear;
+            break;
+        case MSM_VIDC_TRANSFER_IEC_61966:
+            aspects->mTransfer = ColorAspects::TransferXvYCC;
+            break;
+        case MSM_VIDC_TRANSFER_BT_1361:
+            aspects->mTransfer = ColorAspects::TransferBT1361;
+            break;
+        case MSM_VIDC_TRANSFER_SRGB:
+            aspects->mTransfer = ColorAspects::TransferSRGB;
+            break;
+        default:
+            aspects->mTransfer = ColorAspects::TransferOther;
+            break;
+    }
+
+    switch (matrix) {
+        case MSM_VIDC_MATRIX_BT_709_5:
+            aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
+            break;
+        case MSM_VIDC_MATRIX_FCC_47:
+            aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M;
+            break;
+        case MSM_VIDC_MATRIX_601_6_625:
+        case MSM_VIDC_MATRIX_601_6_525:
+            aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
+            break;
+        case MSM_VIDC_MATRIX_SMPTE_240M:
+            aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
+            break;
+        case MSM_VIDC_MATRIX_BT_2020:
+            aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
+            break;
+        case MSM_VIDC_MATRIX_BT_2020_CONST:
+            aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant;
+            break;
+        default:
+            aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
+            break;
+    }
+}
+
+void omx_vdec::handle_color_space_info(void *data, unsigned int buf_index)
+{
+    ColorSpace_t color_space = ITU_R_601_FR;
+    ColorAspects *aspects = &m_internal_color_space.sAspects;
+
+    memcpy(aspects, &m_client_color_space.sAspects, sizeof(ColorAspects));
+    switch(output_capability) {
+        case V4L2_PIX_FMT_MPEG2:
+            {
+                struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
+                seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data;
+
+                /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to
+                 * understand this code */
+
+                if (seqdisp_payload && seqdisp_payload->color_descp) {
+
+                    convert_color_space_info(seqdisp_payload->color_primaries, 1,
+                            seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
+                            &color_space,aspects);
+                    m_disp_hor_size = seqdisp_payload->disp_width;
+                    m_disp_vert_size = seqdisp_payload->disp_height;
+                }
+            }
+            break;
+        case V4L2_PIX_FMT_H264:
+        case V4L2_PIX_FMT_HEVC:
+            {
+                struct msm_vidc_vui_display_info_payload *display_info_payload;
+                display_info_payload = (struct msm_vidc_vui_display_info_payload*)data;
+
+                /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */
+
+                if (display_info_payload->video_signal_present_flag &&
+                        display_info_payload->color_description_present_flag) {
+                    convert_color_space_info(display_info_payload->color_primaries,
+                            display_info_payload->video_full_range_flag,
+                            display_info_payload->transfer_characteristics,
+                            display_info_payload->matrix_coefficients,
+                            &color_space,aspects);
+                }
+            }
+            break;
+        case V4L2_PIX_FMT_VC1_ANNEX_G:
+        case V4L2_PIX_FMT_VC1_ANNEX_L:
+            {
+                struct msm_vidc_vc1_seqdisp_payload *vc1_seq_disp_payload;
+                vc1_seq_disp_payload = (struct msm_vidc_vc1_seqdisp_payload*)data;
+
+                /* Refer VC-1 Spec @ SMPTE Draft Standard for Television Date: 2005-08-23
+                 * SMPTE 421M to understand this code */
+
+                if (m_enable_android_native_buffers &&
+                        vc1_seq_disp_payload->color_primaries) {
+
+                    convert_color_space_info(vc1_seq_disp_payload->color_primaries,
+                            1,
+                            vc1_seq_disp_payload->transfer_char,
+                            vc1_seq_disp_payload->matrix_coeffs,
+                            &color_space,aspects);
+                }
+            }
+            break;
+        case V4L2_PIX_FMT_VP8:
+            {
+                struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
+                vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
+
+                /* Refer VP8 Spec @ RFC 6386 VP8 Data Format and Decoding Guide November 2011
+                 * to understand this code */
+
+                if (vpx_color_space_payload->color_space == 0) {
+                    color_space = ITU_R_601;
+                } else {
+                    DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
+                    break;
+                }
+            }
+            break;
+        case V4L2_PIX_FMT_VP9:
+            {
+                struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
+                vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
+
+                /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
+                 * to understand this code */
+
+                switch(vpx_color_space_payload->color_space) {
+                    case MSM_VIDC_CS_BT_601:
+                        aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
+                        aspects->mTransfer = ColorAspects::TransferSMPTE170M;
+                        aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
+                        aspects->mRange = m_client_color_space.sAspects.mRange;
+                        break;
+                    case MSM_VIDC_CS_BT_709:
+                        color_space = ITU_R_709;
+                        aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
+                        aspects->mTransfer = ColorAspects::TransferSMPTE170M;
+                        aspects->mPrimaries =  ColorAspects::PrimariesBT709_5;
+                        aspects->mRange = m_client_color_space.sAspects.mRange;
+                        break;
+                    case MSM_VIDC_CS_SMPTE_170:
+                        aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
+                        aspects->mTransfer = ColorAspects::TransferSMPTE170M;
+                        aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
+                        aspects->mRange = m_client_color_space.sAspects.mRange;
+                        break;
+                    case MSM_VIDC_CS_SMPTE_240:
+                        aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
+                        aspects->mTransfer = ColorAspects::TransferSMPTE240M;
+                        aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
+                        aspects->mRange = m_client_color_space.sAspects.mRange;
+                        break;
+                    case MSM_VIDC_CS_BT_2020:
+                        aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
+                        aspects->mTransfer = ColorAspects:: TransferSMPTE170M;
+                        aspects->mPrimaries = ColorAspects::PrimariesBT2020;
+                        aspects->mRange = m_client_color_space.sAspects.mRange;
+                        break;
+                    case MSM_VIDC_CS_RESERVED:
+                        aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
+                        aspects->mTransfer = ColorAspects::TransferOther;
+                        aspects->mPrimaries = ColorAspects::PrimariesOther;
+                        aspects->mRange = m_client_color_space.sAspects.mRange;
+                        break;
+                    case MSM_VIDC_CS_RGB:
+                        aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
+                        aspects->mTransfer = ColorAspects::TransferSMPTE170M;
+                        aspects->mPrimaries = ColorAspects::PrimariesOther;
+                        aspects->mRange = m_client_color_space.sAspects.mRange;
+                        break;
+                    default:
+                        break;
+                }
+            }
+            break;
+        default:
+            break;
+    }
+    if (m_enable_android_native_buffers)
+        setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
+                UPDATE_COLOR_SPACE, (void*)&color_space);
+    if (m_internal_color_space.sAspects.mPrimaries != m_client_color_space.sAspects.mPrimaries ||
+            m_internal_color_space.sAspects.mTransfer != m_client_color_space.sAspects.mTransfer ||
+            m_internal_color_space.sAspects.mMatrixCoeffs != m_client_color_space.sAspects.mMatrixCoeffs ||
+            m_internal_color_space.sAspects.mRange != m_client_color_space.sAspects.mRange) {
+        DEBUG_PRINT_HIGH("Initiating PORT Reconfig");
+        DEBUG_PRINT_HIGH("Bit stream Color Space values : sAspects.mPrimaries  = %d sAspects.mRange = %d"
+                " sAspects.mTransfer %d, sAspects.mMatrixCoeffs = %d", m_internal_color_space.sAspects.mPrimaries, m_internal_color_space.sAspects.mRange,
+                m_internal_color_space.sAspects.mTransfer, m_internal_color_space.sAspects.mMatrixCoeffs);
+        DEBUG_PRINT_HIGH("Client set Color Space values : sAspects.mPrimaries  = %d sAspects.mRange = %d"
+                " sAspects.mTransfer %d, sAspects.mMatrixCoeffs = %d", m_client_color_space.sAspects.mPrimaries,
+                m_client_color_space.sAspects.mRange, m_client_color_space.sAspects.mTransfer, m_client_color_space.sAspects.mMatrixCoeffs);
+        post_event(OMX_CORE_OUTPUT_PORT_INDEX,
+                OMX_QTIIndexConfigDescribeColorAspects,
+                OMX_COMPONENT_GENERATE_PORT_RECONFIG);
+    }
+}
+
 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
 {
     OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL;
@@ -10027,7 +10318,7 @@
                 return;
             }
 
-            DEBUG_PRINT_LOW("handle_extradata: eType = %d", data->eType);
+            DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType);
             switch ((unsigned long)data->eType) {
                 case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
                     struct msm_vidc_interlace_payload *payload;
@@ -10138,26 +10429,10 @@
                     }
                     break;
                 case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
-                    struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
-                    seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)(void *)data->data;
-                    if (seqdisp_payload && m_enable_android_native_buffers &&
-                            seqdisp_payload->color_descp) {
-                        ColorSpace_t color_space = ITU_R_601_FR;
-
-                        switch (seqdisp_payload->color_primaries) {
-                            case MSM_VIDC_BT709_5:
-                                color_space = ITU_R_709;
-                                break;
-                            default:
-                                color_space = ITU_R_601_FR;
-                                break;
-                        }
-
-                        m_disp_hor_size = seqdisp_payload->disp_width;
-                        m_disp_vert_size = seqdisp_payload->disp_height;
-                        setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
-                                UPDATE_COLOR_SPACE, (void*)&color_space);
-                    }
+                case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
+                case MSM_VIDC_EXTRADATA_VC1_SEQDISP:
+                case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
+                        handle_color_space_info((void *)data->data, buf_index);
                     break;
                 case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
                     struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
@@ -10198,83 +10473,6 @@
                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
                     }
                     break;
-                case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
-                    struct msm_vidc_vui_display_info_payload *display_info_payload;
-                    display_info_payload = (struct msm_vidc_vui_display_info_payload*)(void *)data->data;
-
-                    if (m_enable_android_native_buffers &&
-                            display_info_payload->video_signal_present_flag &&
-                            display_info_payload->color_description_present_flag) {
-                        ColorSpace_t color_space = ITU_R_601_FR;
-
-                        switch (display_info_payload->color_primaries) {
-                            case MSM_VIDC_BT709_5:
-                                color_space = ITU_R_709;
-                                break;
-                            case MSM_VIDC_BT601_6_525:
-                            case MSM_VIDC_BT601_6_625:
-                                color_space = display_info_payload->video_full_range_flag ?
-                                    ITU_R_601_FR : ITU_R_601;
-                                break;
-                            default:
-                                break;
-                        }
-                        DEBUG_PRINT_LOW("Color Space = %d", color_space);
-                        setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
-                               UPDATE_COLOR_SPACE, (void*)&color_space);
-                    }
-                    break;
-                case MSM_VIDC_EXTRADATA_VC1_SEQDISP:
-                    struct msm_vidc_vc1_seqdisp_payload *vc1_seq_disp_payload;
-                    vc1_seq_disp_payload = (struct msm_vidc_vc1_seqdisp_payload*)(void *)data->data;
-
-                    if (m_enable_android_native_buffers &&
-                            vc1_seq_disp_payload->color_primaries) {
-                        ColorSpace_t color_space = ITU_R_601_FR;
-
-                        switch (vc1_seq_disp_payload->color_primaries) {
-                            case MSM_VIDC_BT709_5:
-                                color_space = ITU_R_709;
-                                break;
-                            default:
-                                color_space = ITU_R_601_FR;
-                                break;
-                        }
-                        setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
-                               UPDATE_COLOR_SPACE, (void*)&color_space);
-                    }
-                    break;
-                case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
-                    struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
-                    vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)(void *)data->data;
-
-                    if (m_enable_android_native_buffers) {
-                        ColorSpace_t color_space = ITU_R_601_FR;
-                        if (output_capability == V4L2_PIX_FMT_VP8) {
-                            if (vpx_color_space_payload->color_space == 0) {
-                                color_space = ITU_R_601;
-                            } else {
-                                DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
-                                break;
-                            }
-                        } else if (output_capability == V4L2_PIX_FMT_VP9) {
-                            if (vpx_color_space_payload->color_space == 1) {
-                                color_space = ITU_R_601;
-                            } else if (vpx_color_space_payload->color_space == 2) {
-                                color_space = ITU_R_709;
-                            } else {
-                                DEBUG_PRINT_ERROR("Unsupported Color space for VP9");
-                                break;
-                            }
-                        } else {
-                            DEBUG_PRINT_ERROR("Unrecognized Extradata");
-                            break;
-                        }
-
-                        setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
-                                UPDATE_COLOR_SPACE, (void*)&color_space);
-                    }
-                    break;
                 default:
                     DEBUG_PRINT_LOW("Unrecognized extradata");
                     goto unrecognized_extradata;
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 2f725b9..4ded11f 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
@@ -640,6 +640,7 @@
         OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE m_sConfigIntraRefresh;
         OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE m_sParamTemporalLayers;
         OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE m_sConfigTemporalLayers;
+        DescribeColorAspectsParams m_sConfigColorAspects;
 
         // fill this buffer queue
         omx_cmd_queue m_ftb_q;
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 a832666..4a43840 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
@@ -2249,7 +2249,15 @@
                 memcpy(configData, &m_sConfigTemporalLayers, sizeof(m_sConfigTemporalLayers));
                 break;
             }
-
+       case OMX_QTIIndexConfigDescribeColorAspects:
+            {
+                VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
+                DescribeColorAspectsParams* pParam =
+                    reinterpret_cast<DescribeColorAspectsParams*>(configData);
+                DEBUG_PRINT_LOW("get_config: OMX_QTIIndexConfigDescribeColorAspects");
+                memcpy(pParam, &m_sConfigColorAspects, sizeof(m_sConfigColorAspects));
+                break;
+            }
         default:
             DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
             return OMX_ErrorUnsupportedIndex;
@@ -2354,11 +2362,16 @@
         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoEnableRoiInfo;
         return OMX_ErrorNone;
     }
+
     if (extn_equals(paramName, OMX_QTI_INDEX_CONFIG_VIDEO_ROIINFO)) {
         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigVideoRoiInfo;
         return OMX_ErrorNone;
     }
 
+    if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
+        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
+        return OMX_ErrorNone;
+    }
     return OMX_ErrorNotImplemented;
 }
 
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 1f4d18b..b97eedc 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
@@ -342,6 +342,13 @@
     m_sConfigIntraRefresh.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
     m_sConfigIntraRefresh.nRefreshPeriod = 0;
 
+    OMX_INIT_STRUCT(&m_sConfigColorAspects, DescribeColorAspectsParams);
+    m_sConfigColorAspects.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+    m_sConfigColorAspects.sAspects.mRange =  ColorAspects::RangeUnspecified;
+    m_sConfigColorAspects.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
+    m_sConfigColorAspects.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
+    m_sConfigColorAspects.sAspects.mTransfer = ColorAspects::TransferUnspecified;
+
     if (codec_type == OMX_VIDEO_CodingMPEG4) {
         m_sParamProfileLevel.eProfile = (OMX_U32) OMX_VIDEO_MPEG4ProfileSimple;
         m_sParamProfileLevel.eLevel = (OMX_U32) OMX_VIDEO_MPEG4Level0;
@@ -2085,6 +2092,16 @@
                 DEBUG_PRINT_ERROR("Setting/modifying Temporal layers at run-time is not supported !");
                 return OMX_ErrorUnsupportedSetting;
             }
+        case OMX_QTIIndexConfigDescribeColorAspects:
+           {
+               VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
+               if (!handle->venc_set_config(configData, (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects)) {
+                   DEBUG_PRINT_ERROR("Failed to set OMX_QTIIndexConfigDescribeColorAspects");
+                   return OMX_ErrorUnsupportedSetting;
+               }
+               memcpy(&m_sConfigColorAspects, configData, sizeof(m_sConfigColorAspects));
+               break;
+           }
         default:
             DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
             break;
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 02cd13a..c34d9a7 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
@@ -47,6 +47,8 @@
 #include <gralloc_priv.h>
 #endif
 
+#include <qdMetaData.h>
+
 #define ALIGN(x, to_align) ((((unsigned long) x) + (to_align - 1)) & ~(to_align - 1))
 #define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
 #define MAXDPB 16
@@ -2620,6 +2622,122 @@
                 }
                 break;
             }
+        case OMX_QTIIndexConfigDescribeColorAspects:
+            {
+                DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
+                DEBUG_PRINT_LOW("OMX_QTIIndexConfigDescribeColorAspects : sAspects.mPrimaries  = %d sAspects.mRange = %d"
+                    "sAspects.mTransfer %d, sAspects.mMatrixCoeffs = %d", params->sAspects.mPrimaries, params->sAspects.mRange,
+                    params->sAspects.mTransfer, params->sAspects.mMatrixCoeffs);
+                OMX_U32 color_space = MSM_VIDC_BT601_6_525;
+                OMX_U32 full_range = 1;
+                OMX_U32 matrix_coeffs = MSM_VIDC_MATRIX_601_6_525;
+                OMX_U32 transfer_chars = MSM_VIDC_TRANSFER_601_6_525;
+
+                switch((ColorAspects::Primaries)(params->sAspects.mPrimaries)) {
+                    case ColorAspects::PrimariesBT709_5:
+                        color_space = MSM_VIDC_BT709_5;
+                        break;
+                    case ColorAspects::PrimariesUnspecified:
+                        color_space = MSM_VIDC_UNSPECIFIED;
+                        break;
+                    case ColorAspects::PrimariesBT470_6M:
+                        color_space = MSM_VIDC_BT470_6_M;
+                        break;
+                    case ColorAspects::PrimariesBT601_6_625:
+                        color_space = MSM_VIDC_BT601_6_625;
+                        break;
+                    case ColorAspects::PrimariesBT601_6_525:
+                        color_space = MSM_VIDC_BT601_6_525;
+                        break;
+                    case ColorAspects::PrimariesGenericFilm:
+                        color_space = MSM_VIDC_GENERIC_FILM;
+                        break;
+                    case ColorAspects::PrimariesBT2020:
+                        color_space = MSM_VIDC_BT2020;
+                        break;
+                    default:
+                        color_space = MSM_VIDC_BT601_6_525;
+                        params->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_525;
+                        break;
+                }
+                switch((ColorAspects::Range)params->sAspects.mRange) {
+                    case ColorAspects::RangeFull:
+                        full_range = 1;
+                        break;
+                    case ColorAspects::RangeLimited:
+                        full_range = 0;
+                        break;
+                    default:
+                        break;
+                }
+                switch((ColorAspects::Transfer)params->sAspects.mTransfer) {
+                    case ColorAspects::TransferSMPTE170M:
+                        transfer_chars = MSM_VIDC_TRANSFER_601_6_525;
+                        break;
+                    case ColorAspects::TransferUnspecified:
+                        transfer_chars = MSM_VIDC_TRANSFER_UNSPECIFIED;
+                        break;
+                    case ColorAspects::TransferGamma22:
+                        transfer_chars = MSM_VIDC_TRANSFER_BT_470_6_M;
+                        break;
+                    case ColorAspects::TransferGamma28:
+                        transfer_chars = MSM_VIDC_TRANSFER_BT_470_6_BG;
+                        break;
+                    case ColorAspects::TransferSMPTE240M:
+                        transfer_chars = MSM_VIDC_TRANSFER_SMPTE_240M;
+                        break;
+                    case ColorAspects::TransferLinear:
+                        transfer_chars = MSM_VIDC_TRANSFER_LINEAR;
+                        break;
+                    case ColorAspects::TransferXvYCC:
+                        transfer_chars = MSM_VIDC_TRANSFER_IEC_61966;
+                        break;
+                    case ColorAspects::TransferBT1361:
+                        transfer_chars = MSM_VIDC_TRANSFER_BT_1361;
+                        break;
+                    case ColorAspects::TransferSRGB:
+                        transfer_chars = MSM_VIDC_TRANSFER_SRGB;
+                        break;
+                    default:
+                        params->sAspects.mTransfer = ColorAspects::TransferSMPTE170M;
+                        transfer_chars = MSM_VIDC_TRANSFER_601_6_525;
+                        break;
+                }
+                switch((ColorAspects::MatrixCoeffs)params->sAspects.mMatrixCoeffs) {
+                    case ColorAspects::MatrixUnspecified:
+                        matrix_coeffs = MSM_VIDC_MATRIX_UNSPECIFIED;
+                        break;
+                    case ColorAspects::MatrixBT709_5:
+                        matrix_coeffs = MSM_VIDC_MATRIX_BT_709_5;
+                        break;
+                    case ColorAspects::MatrixBT470_6M:
+                        matrix_coeffs = MSM_VIDC_MATRIX_FCC_47;
+                        break;
+                    case ColorAspects::MatrixBT601_6:
+                        matrix_coeffs = MSM_VIDC_MATRIX_601_6_525;
+                        break;
+                    case ColorAspects::MatrixSMPTE240M:
+                        transfer_chars = MSM_VIDC_MATRIX_SMPTE_240M;
+                        break;
+                    case ColorAspects::MatrixBT2020:
+                        matrix_coeffs = MSM_VIDC_MATRIX_BT_2020;
+                        break;
+                    case ColorAspects::MatrixBT2020Constant:
+                        matrix_coeffs = MSM_VIDC_MATRIX_BT_2020_CONST;
+                        break;
+                    default:
+                        params->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6;
+                        matrix_coeffs = MSM_VIDC_MATRIX_601_6_525;
+                        break;
+                }
+                if (!venc_set_colorspace(color_space, full_range,
+                            transfer_chars, matrix_coeffs)) {
+
+                    DEBUG_PRINT_ERROR("Failed to set operating rate");
+                    return false;
+                }
+                break;
+            }
         default:
             DEBUG_PRINT_ERROR("Unsupported config index = %u", index);
             break;
@@ -3417,10 +3535,23 @@
                             color_space = V4L2_COLORSPACE_REC709;
                             venc_set_colorspace(MSM_VIDC_BT709_5, 1,
                                     MSM_VIDC_TRANSFER_BT709_5, MSM_VIDC_MATRIX_BT_709_5);
-                        } else if (handle->flags & private_handle_t::PRIV_FLAGS_ITU_R_601_FR){
-                            venc_set_colorspace(MSM_VIDC_BT601_6_525, 1,
-                                    MSM_VIDC_TRANSFER_601_6_525, MSM_VIDC_MATRIX_601_6_525);
-                            color_space = V4L2_COLORSPACE_470_SYSTEM_BG;
+                        } else {
+                            if (is_csc_enabled) {
+                                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("Failed to set VPE CSC for 601_to_709");
+                                }
+                                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);
+                            } else {
+                                venc_set_colorspace(MSM_VIDC_BT601_6_525, 1,
+                                        MSM_VIDC_TRANSFER_601_6_525, MSM_VIDC_MATRIX_601_6_525);
+                                fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+                            }
                         }
                         fmt.fmt.pix_mp.pixelformat = m_sVenc_cfg.inputformat;
                         fmt.fmt.pix_mp.colorspace = static_cast<decltype(fmt.fmt.pix_mp.colorspace)>(color_space);