mm-video-v4l2: venc: Add extradata support in encoder

- Create new Input and Output extradata ports.
- Add port definition support on extradata ports.
- Add changes to use and free the buffers on
  extradata port

Change-Id: I856448dfe4b1bf767fd6af13289f547c9f560817
diff --git a/mm-video-v4l2/vidc/common/inc/extra_data_handler.h b/mm-video-v4l2/vidc/common/inc/extra_data_handler.h
index c064469..7a12338 100644
--- a/mm-video-v4l2/vidc/common/inc/extra_data_handler.h
+++ b/mm-video-v4l2/vidc/common/inc/extra_data_handler.h
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+Copyright (c) 2010-2013, 2021 The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
@@ -35,6 +35,7 @@
 #include <stdlib.h>
 #include "OMX_QCOMExtns.h"
 #include <media/msm_vidc.h>
+#include <media/msm_media_info.h>
 
 #ifdef _ANDROID_
 extern "C" {
@@ -96,4 +97,39 @@
         OMX_S32 parse_ltrinfo(OMX_OTHER_EXTRADATATYPE *pExtra);
 };
 
+class client_extradata_info {
+    private:
+        OMX_U32 size; // size of extradata of each frame
+        OMX_U32 buffer_count;
+        OMX_BOOL enable;
+
+    public:
+        client_extradata_info() {
+            size = VENUS_EXTRADATA_SIZE(4096, 2160);
+            buffer_count = 0;
+            enable = OMX_FALSE;
+        }
+
+        ~client_extradata_info() {
+        }
+
+        bool set_extradata_info(OMX_U32 size, OMX_U32 buffer_count) {
+            this->size = size;
+            this->buffer_count = buffer_count;
+            return true;
+        }
+        void enable_client_extradata(OMX_BOOL enable) {
+            this->enable = enable;
+        }
+        bool is_client_extradata_enabled() {
+            return enable;
+        }
+        OMX_U32 getSize() const {
+            return size;
+        }
+        OMX_U32 getBufferCount() const {
+            return buffer_count;
+        }
+};
+
 #endif
diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
index 80bdd97..2124a26 100644
--- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
+++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010 - 2018, The Linux Foundation. All rights reserved.
+Copyright (c) 2010 - 2018, 2021 The Linux Foundation. All rights reserved.
 
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
@@ -1731,40 +1731,7 @@
         void prefetchNewBuffers(bool in_reconfig);
         void drainPrefetchedBuffers();
 
-        class client_extradata_info {
-            private:
-                OMX_U32 size; // size of extradata of each frame
-                OMX_U32 buffer_count;
-                OMX_BOOL enable;
 
-            public:
-                client_extradata_info() {
-                    size = VENUS_EXTRADATA_SIZE(4096, 2160);;
-                    buffer_count = 0;
-                    enable = OMX_FALSE;
-                }
-
-                ~client_extradata_info() {
-                }
-
-                bool set_extradata_info(OMX_U32 size, OMX_U32 buffer_count) {
-                    this->size = size;
-                    this->buffer_count = buffer_count;
-                    return true;
-                }
-                void enable_client_extradata(OMX_BOOL enable) {
-                    this->enable = enable;
-                }
-                bool is_client_extradata_enabled() {
-                    return enable;
-                }
-                OMX_U32 getSize() const {
-                    return size;
-                }
-                OMX_U32 getBufferCount() const {
-                    return buffer_count;
-                }
-        };
         client_extradata_info m_client_out_extradata_info;
         bool m_buffer_error;
 
diff --git a/mm-video-v4l2/vidc/venc/inc/omx_video_base.h b/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
index 680c0f9..ee9f257 100644
--- a/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
+++ b/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2010-2017, 2021 The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -831,9 +831,13 @@
         bool allocate_done(void);
         bool allocate_input_done(void);
         bool allocate_output_done(void);
+        bool allocate_output_extradata_done(void);
 
         OMX_ERRORTYPE free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr);
         OMX_ERRORTYPE free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr);
+        void free_output_extradata_buffer_header();
+
+        OMX_ERRORTYPE allocate_client_output_extradata_headers();
 
         OMX_ERRORTYPE allocate_input_buffer(OMX_HANDLETYPE       hComp,
                 OMX_BUFFERHEADERTYPE **bufferHdr,
@@ -865,6 +869,13 @@
                 OMX_U32                bytes,
                 OMX_U8                 *buffer);
 
+        OMX_ERRORTYPE use_client_output_extradata_buffer(OMX_HANDLETYPE hComp,
+                OMX_BUFFERHEADERTYPE   **bufferHdr,
+                OMX_U32                port,
+                OMX_PTR                appData,
+                OMX_U32                bytes,
+                OMX_U8                 *buffer);
+
         bool execute_omx_flush(OMX_U32);
         bool execute_output_flush(void);
         bool execute_input_flush(void);
@@ -892,6 +903,7 @@
 
         bool release_output_done();
         bool release_input_done();
+        bool release_output_extradata_done();
 
         OMX_ERRORTYPE send_command_proxy(OMX_HANDLETYPE  hComp,
                 OMX_COMMANDTYPE cmd,
@@ -929,6 +941,8 @@
             }
         }
 
+        client_extradata_info m_client_out_extradata_info;
+
         void complete_pending_buffer_done_cbs();
         bool is_conv_needed(int, int);
         void print_debug_color_aspects(ColorAspects *aspects, const char *prefix);
@@ -1047,6 +1061,8 @@
         OMX_BUFFERHEADERTYPE *m_inp_mem_ptr;
         // Output memory pointer
         OMX_BUFFERHEADERTYPE *m_out_mem_ptr;
+        // Client extradata memory pointer
+        OMX_BUFFERHEADERTYPE  *m_client_output_extradata_mem_ptr;
         omx_cmd_queue m_opq_meta_q;
         omx_cmd_queue m_opq_pmem_q;
         OMX_BUFFERHEADERTYPE meta_buffer_hdr[MAX_NUM_INPUT_BUFFERS];
@@ -1065,6 +1081,8 @@
         uint64_t m_client_out_bm_count;
         uint64_t m_client_in_bm_count;
         uint64_t m_inp_bm_count;
+        // bitmask array size for extradata
+        uint64_t m_out_extradata_bm_count;
         uint64_t m_flags;
         uint64_t m_etb_count;
         uint64_t m_fbd_count;
diff --git a/mm-video-v4l2/vidc/venc/inc/omx_video_common.h b/mm-video-v4l2/vidc/venc/inc/omx_video_common.h
index b4024ac..643c7c0 100644
--- a/mm-video-v4l2/vidc/venc/inc/omx_video_common.h
+++ b/mm-video-v4l2/vidc/venc/inc/omx_video_common.h
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2010-2016, 2021 The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
@@ -76,6 +76,8 @@
 enum PortIndexType {
     PORT_INDEX_IN = 0,
     PORT_INDEX_OUT = 1,
+    PORT_INDEX_EXTRADATA_IN = 2,
+    PORT_INDEX_EXTRADATA_OUT = 3,
     PORT_INDEX_BOTH = -1,
     PORT_INDEX_NONE = -2
 };
diff --git a/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h b/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
index 7f8d16b..d7a685a 100644
--- a/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
+++ b/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2012-2017, 2021 The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -481,6 +481,9 @@
         void free_extradata_all();
         void free_extradata(struct extradata_buffer_info *extradata_info);
         int append_mbi_extradata(void *, struct msm_vidc_extradata_header*);
+        void append_extradata_mbidata(OMX_OTHER_EXTRADATATYPE *, struct msm_vidc_extradata_header *);
+        void append_extradata_ltrinfo(OMX_OTHER_EXTRADATATYPE *, struct msm_vidc_extradata_header *);
+        void append_extradata_none(OMX_OTHER_EXTRADATATYPE *);
         bool handle_output_extradata(void *, int);
         bool handle_input_extradata(struct v4l2_buffer);
         int venc_set_format(int);
diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
index bf7a8b9..1842dbe 100644
--- a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
+++ b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
@@ -246,6 +246,7 @@
     m_input_msg_id(OMX_COMPONENT_GENERATE_ETB),
     m_inp_mem_ptr(NULL),
     m_out_mem_ptr(NULL),
+    m_client_output_extradata_mem_ptr(NULL),
     input_flush_progress (false),
     output_flush_progress (false),
     input_use_buffer (false),
@@ -257,6 +258,7 @@
     m_client_out_bm_count(0),
     m_client_in_bm_count(0),
     m_inp_bm_count(0),
+    m_out_extradata_bm_count(0),
     m_flags(0),
     m_etb_count(0),
     m_fbd_count(0),
@@ -1553,6 +1555,14 @@
                         portDefn->nBufferSize =
                                 sizeof(native_handle_t) + (sizeof(int) * (1/*numFds*/ + 3/*numInts*/));
                     }
+                } else if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_EXTRADATA_OUT) {
+                    portDefn->nBufferSize = m_client_out_extradata_info.getSize();
+                    portDefn->nBufferCountMin= m_sOutPortDef.nBufferCountMin;
+                    portDefn->nBufferCountActual = m_client_out_extradata_info.getBufferCount();
+                    portDefn->eDir =  OMX_DirOutput;
+                    DEBUG_PRINT_LOW("extradata port: size = %u, min cnt = %u, actual cnt = %u",
+                            (unsigned int)portDefn->nBufferSize, (unsigned int)portDefn->nBufferCountMin,
+                            (unsigned int)portDefn->nBufferCountActual);
                 } else {
                     DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
                     eRet = OMX_ErrorBadPortIndex;
@@ -1889,7 +1899,23 @@
                 }
                 else {
                     DEBUG_PRINT_ERROR("get_parameter: unsupported extradata index (0x%x)",
-                            pParam->nIndex);
+                            pParam->nPortIndex);
+                    eRet = OMX_ErrorUnsupportedIndex;
+                }
+                break;
+            }
+        case OMX_QTIIndexParamVideoClientExtradata:
+            {
+                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
+                DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamVideoClientExtradata");
+                QOMX_EXTRADATA_ENABLE *pParam =
+                    (QOMX_EXTRADATA_ENABLE *)paramData;
+                if (pParam->nPortIndex == PORT_INDEX_EXTRADATA_OUT) {
+                    pParam->bEnable = m_sExtraData ? OMX_TRUE : OMX_FALSE;
+                    eRet = OMX_ErrorNone;
+                } else {
+                    DEBUG_PRINT_ERROR("get_parameter: unsupported extradata index (0x%x)",
+                            pParam->nPortIndex);
                     eRet = OMX_ErrorUnsupportedIndex;
                 }
                 break;
@@ -2487,6 +2513,10 @@
         return OMX_ErrorNone;
     }
 
+    if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_CLIENT_EXTRADATA)) {
+        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoClientExtradata;
+        return OMX_ErrorNone;
+    }
     return OMX_ErrorNotImplemented;
 }
 
@@ -2938,6 +2968,8 @@
         eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
     } else if (port == PORT_INDEX_OUT) {
         eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
+    } else if (port == PORT_INDEX_EXTRADATA_OUT) {
+        eRet = use_client_output_extradata_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
     } else {
         DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d",(int)port);
         eRet = OMX_ErrorBadPortIndex;
@@ -2972,6 +3004,92 @@
     return eRet;
 }
 
+OMX_ERRORTYPE omx_video::allocate_client_output_extradata_headers() {
+    OMX_ERRORTYPE eRet = OMX_ErrorNone;
+    OMX_BUFFERHEADERTYPE *bufHdr = NULL;
+    int i = 0;
+
+    if (!m_client_output_extradata_mem_ptr) {
+        int nBufferCount       = 0;
+
+        nBufferCount = m_client_out_extradata_info.getBufferCount();
+        DEBUG_PRINT_HIGH("allocate_client_output_extradata_headers buffer_count - %d", nBufferCount);
+
+        m_client_output_extradata_mem_ptr = (OMX_BUFFERHEADERTYPE  *)calloc(nBufferCount, sizeof(OMX_BUFFERHEADERTYPE));
+
+        if (m_client_output_extradata_mem_ptr) {
+            bufHdr          =  m_client_output_extradata_mem_ptr;
+            for (i=0; i < nBufferCount; i++) {
+                bufHdr->nSize              = sizeof(OMX_BUFFERHEADERTYPE);
+                bufHdr->nVersion.nVersion  = OMX_SPEC_VERSION;
+                // Set the values when we determine the right HxW param
+                bufHdr->nAllocLen          = 0;
+                bufHdr->nFilledLen         = 0;
+                bufHdr->pAppPrivate        = NULL;
+                bufHdr->nOutputPortIndex   = PORT_INDEX_EXTRADATA_OUT;
+                bufHdr->pBuffer            = NULL;
+                bufHdr->pOutputPortPrivate = NULL;
+                bufHdr++;
+            }
+        } else {
+             DEBUG_PRINT_ERROR("Extradata header buf mem alloc failed[0x%p]",\
+                    m_client_output_extradata_mem_ptr);
+              eRet =  OMX_ErrorInsufficientResources;
+        }
+    }
+    return eRet;
+}
+OMX_ERRORTYPE  omx_video::use_client_output_extradata_buffer(
+        OMX_IN OMX_HANDLETYPE            hComp,
+        OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+        OMX_IN OMX_U32                   port,
+        OMX_IN OMX_PTR                   appData,
+        OMX_IN OMX_U32                   bytes,
+        OMX_IN OMX_U8*                   buffer)
+{
+    OMX_ERRORTYPE eRet = OMX_ErrorNone;
+    unsigned i = 0; // Temporary counter
+    unsigned buffer_count = m_client_out_extradata_info.getBufferCount();;
+    OMX_U32 buffer_size = m_client_out_extradata_info.getSize();
+    (void) hComp;
+
+    if (port != PORT_INDEX_EXTRADATA_OUT ||
+            !m_sExtraData || bytes != buffer_size|| bufferHdr == NULL) {
+        DEBUG_PRINT_ERROR("Bad Parameters PortIndex is - %d expected is- %d,"
+            "client_extradata - %d, bytes = %d expected is %d bufferHdr - %p", port,
+            PORT_INDEX_EXTRADATA_OUT, m_sExtraData, bytes, buffer_size, bufferHdr);
+        eRet = OMX_ErrorBadParameter;
+        return eRet;
+    }
+
+    if (!m_client_output_extradata_mem_ptr) {
+        eRet = allocate_client_output_extradata_headers();
+    }
+
+    if (eRet == OMX_ErrorNone) {
+        for (i = 0; i < buffer_count; i++) {
+            if (BITMASK_ABSENT(&m_out_extradata_bm_count,i)) {
+                break;
+            }
+        }
+    }
+
+    if (i >= buffer_count) {
+        DEBUG_PRINT_ERROR("Already using %d Extradata o/p buffers", buffer_count);
+        eRet = OMX_ErrorInsufficientResources;
+    }
+
+    if (eRet == OMX_ErrorNone) {
+        BITMASK_SET(&m_out_extradata_bm_count,i);
+        *bufferHdr = (m_client_output_extradata_mem_ptr + i );
+        (*bufferHdr)->pAppPrivate = appData;
+        (*bufferHdr)->pBuffer = buffer;
+        (*bufferHdr)->nAllocLen = bytes;
+    }
+
+    return eRet;
+}
+
 OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
 {
     unsigned int index = 0;
@@ -3761,6 +3879,15 @@
                     OMX_COMPONENT_GENERATE_EVENT);
 
         }
+    } else if (port == PORT_INDEX_EXTRADATA_OUT) {
+        nPortIndex = buffer - m_client_output_extradata_mem_ptr;
+        DEBUG_PRINT_LOW("free_buffer on extradata output port - Port idx %d", nPortIndex);
+
+        BITMASK_CLEAR(&m_out_extradata_bm_count,nPortIndex);
+
+        if (release_output_extradata_done()) {
+            free_output_extradata_buffer_header();
+        }
     } else {
         eRet = OMX_ErrorBadPortIndex;
     }
@@ -3787,6 +3914,14 @@
     return eRet;
 }
 
+void omx_video::free_output_extradata_buffer_header() {
+    m_sExtraData = false;
+    if (m_client_output_extradata_mem_ptr) {
+        DEBUG_PRINT_LOW("Free extradata pmem Pointer area");
+        free(m_client_output_extradata_mem_ptr);
+        m_client_output_extradata_mem_ptr = NULL;
+    }
+}
 
 /* ======================================================================
    FUNCTION
@@ -4088,6 +4223,11 @@
         return OMX_ErrorInvalidState;
     }
 
+    if (buffer->nOutputPortIndex == PORT_INDEX_EXTRADATA_OUT) {
+        DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->invalid port in header");
+        return OMX_ErrorBadParameter;
+    }
+
     if (buffer == NULL ||(buffer->nSize != sizeof(OMX_BUFFERHEADERTYPE))) {
         DEBUG_PRINT_ERROR("ERROR: omx_video::ftb-->Invalid buffer or size");
         return OMX_ErrorBadParameter;
@@ -4353,11 +4493,13 @@
     bool bRet = false;
     bool bRet_In = false;
     bool bRet_Out = false;
+    bool bRet_Out_Extra = false;
 
     bRet_In = allocate_input_done();
     bRet_Out = allocate_output_done();
+    bRet_Out_Extra = allocate_output_extradata_done();
 
-    if (bRet_In && bRet_Out) {
+    if (bRet_In && bRet_Out && bRet_Out_Extra) {
         bRet = true;
     }
 
@@ -4441,6 +4583,33 @@
     return bRet;
 }
 
+bool omx_video::allocate_output_extradata_done(void) {
+    bool bRet = false;
+    unsigned j=0;
+    unsigned nBufferCount = 0;
+
+    nBufferCount = m_client_out_extradata_info.getBufferCount();
+
+    if (!m_client_out_extradata_info.is_client_extradata_enabled()) {
+        return true;
+    }
+
+    if (m_client_output_extradata_mem_ptr) {
+        for (; j < nBufferCount; j++) {
+            if (BITMASK_ABSENT(&m_out_extradata_bm_count,j)) {
+                break;
+            }
+        }
+
+        if (j == nBufferCount) {
+            bRet = true;
+            DEBUG_PRINT_HIGH("Allocate done for all extradata o/p buffers");
+        }
+    }
+
+    return bRet;
+}
+
 /* ======================================================================
    FUNCTION
    omx_venc::ReleaseDone
@@ -4461,7 +4630,9 @@
     DEBUG_PRINT_LOW("Inside release_done()");
     if (release_input_done()) {
         if (release_output_done()) {
-            bRet = true;
+            if (release_output_extradata_done()) {
+                bRet = true;
+            }
         }
     }
     return bRet;
@@ -4537,6 +4708,29 @@
     return bRet;
 }
 
+bool omx_video::release_output_extradata_done(void) {
+    bool bRet = false;
+    unsigned i=0,j=0, buffer_count=0;
+
+    buffer_count = m_client_out_extradata_info.getBufferCount();
+    DEBUG_PRINT_LOW("Value of m_client_output_extradata_mem_ptr %p buffer_count - %d",
+            m_client_output_extradata_mem_ptr, buffer_count);
+
+    if (m_client_output_extradata_mem_ptr) {
+        for (; j<buffer_count; j++) {
+            if ( BITMASK_PRESENT(&m_out_extradata_bm_count,j)) {
+                break;
+            }
+        }
+        if (j == buffer_count) {
+            bRet = true;
+        }
+    } else {
+        bRet = true;
+    }
+    return bRet;
+}
+
 OMX_ERRORTYPE omx_video::fill_buffer_done(OMX_HANDLETYPE hComp,
         OMX_BUFFERHEADERTYPE * buffer)
 {
diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
index ac7939c..67f950e 100644
--- a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
+++ b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
+Copyright (c) 2010-2018, 2021 The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
@@ -765,6 +765,19 @@
                             &m_sOutPortDef.nBufferSize,
                             m_sOutPortDef.nPortIndex);
                     m_sInPortDef.nBufferCountActual = portDefn->nBufferCountActual;
+                } else if (PORT_INDEX_EXTRADATA_OUT == portDefn->nPortIndex) {
+                    DEBUG_PRINT_LOW("extradata actual cnt =%u , min cnt =%u ,buffersize requested = %u",
+                        (unsigned int)portDefn->nBufferCountActual,(unsigned int)portDefn->nBufferCountMin,
+                        (unsigned int)portDefn->nBufferSize);
+                    if (portDefn->nBufferCountActual != m_client_out_extradata_info.getBufferCount() ||
+                        portDefn->nBufferSize != m_client_out_extradata_info.getSize()) {
+                            DEBUG_PRINT_ERROR("ERROR: Bad parameeters request for extradata limit %d size - %d",
+                            portDefn->nBufferCountActual, portDefn->nBufferSize);
+                            eRet = OMX_ErrorBadParameter;
+                            break;
+                    }
+                    m_client_out_extradata_info.set_extradata_info(portDefn->nBufferSize,
+                                        portDefn->nBufferCountActual);
                 } else if (PORT_INDEX_OUT == portDefn->nPortIndex) {
                     DEBUG_PRINT_LOW("o/p actual cnt requested = %u", (unsigned int)portDefn->nBufferCountActual);
                     DEBUG_PRINT_LOW("o/p min cnt requested = %u", (unsigned int)portDefn->nBufferCountMin);
@@ -1484,6 +1497,25 @@
                 }
                 break;
             }
+        case OMX_QTIIndexParamVideoClientExtradata:
+            {
+                VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTRADATA_ENABLE);
+                DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoClientExtradata");
+                QOMX_EXTRADATA_ENABLE *pParam = (QOMX_EXTRADATA_ENABLE *)paramData;
+
+                if (m_state != OMX_StateLoaded) {
+                    DEBUG_PRINT_ERROR("Set Parameter called in Invalid state");
+                    return OMX_ErrorIncorrectStateOperation;
+                }
+
+                if (pParam->nPortIndex == PORT_INDEX_EXTRADATA_OUT) {
+                    m_client_out_extradata_info.enable_client_extradata(pParam->bEnable);
+                } else {
+                    DEBUG_PRINT_ERROR("Incorrect portIndex - %d", pParam->nPortIndex);
+                    eRet = OMX_ErrorUnsupportedIndex;
+                }
+                break;
+            }
         case QOMX_IndexParamVideoLTRMode:
             {
                 VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_PARAM_LTRMODE_TYPE);
diff --git a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
index 56db2b9..3e643c9 100644
--- a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
+++ b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2010-2017, 2021 The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
@@ -679,6 +679,38 @@
     return size;
 }
 
+void venc_dev::append_extradata_mbidata(OMX_OTHER_EXTRADATATYPE *p_extra,
+            struct msm_vidc_extradata_header *p_extradata)
+{
+    OMX_U32 payloadSize = append_mbi_extradata(&p_extra->data, p_extradata);
+    p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + payloadSize, 4);
+    p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
+    p_extra->nPortIndex = OMX_DirOutput;
+    p_extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVideoEncoderMBInfo;
+    p_extra->nDataSize = payloadSize;
+
+}
+
+void venc_dev::append_extradata_ltrinfo(OMX_OTHER_EXTRADATATYPE *p_extra,
+            struct msm_vidc_extradata_header *p_extradata)
+{
+    p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + p_extradata->data_size, 4);
+    p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
+    p_extra->nPortIndex = OMX_DirOutput;
+    p_extra->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataVideoLTRInfo;
+    p_extra->nDataSize = p_extradata->data_size;
+    memcpy(p_extra->data, p_extradata->data, p_extradata->data_size);
+}
+
+void venc_dev::append_extradata_none(OMX_OTHER_EXTRADATATYPE *p_extra)
+{
+    p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE), 4);
+    p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
+    p_extra->nPortIndex = OMX_DirOutput;
+    p_extra->eType = OMX_ExtraDataNone;
+    p_extra->nDataSize = 0;
+}
+
 bool venc_dev::handle_input_extradata(struct v4l2_buffer buf)
 {
     OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
@@ -925,6 +957,14 @@
 {
     OMX_BUFFERHEADERTYPE *p_bufhdr = (OMX_BUFFERHEADERTYPE *) buffer;
     OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
+    OMX_OTHER_EXTRADATATYPE *p_clientextra = NULL;
+    if(venc_handle->m_sExtraData) {
+        p_clientextra = (OMX_OTHER_EXTRADATATYPE * )
+            ((venc_handle->m_client_output_extradata_mem_ptr + index) ->pBuffer);
+    }
+    if (p_clientextra == NULL) {
+        DEBUG_PRINT_ERROR("Client Extradata buffers not allocated\n");
+    }
 
     if (!output_extradata_info.uaddr) {
         DEBUG_PRINT_ERROR("Extradata buffers not allocated\n");
@@ -954,31 +994,27 @@
         switch (p_extradata->type) {
             case MSM_VIDC_EXTRADATA_METADATA_MBI:
             {
-                OMX_U32 payloadSize = append_mbi_extradata(&p_extra->data, p_extradata);
-                p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + payloadSize, 4);
-                p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
-                p_extra->nPortIndex = OMX_DirOutput;
-                p_extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVideoEncoderMBInfo;
-                p_extra->nDataSize = payloadSize;
+                append_extradata_mbidata(p_extra, p_extradata);
+                if(p_clientextra) {
+                     append_extradata_mbidata(p_clientextra, p_extradata);
+                }
+                DEBUG_PRINT_LOW("MBI Extradata = 0x%x", *((OMX_U32 *)p_extra->data));
                 break;
             }
             case MSM_VIDC_EXTRADATA_METADATA_LTR:
             {
-                p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + p_extradata->data_size, 4);
-                p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
-                p_extra->nPortIndex = OMX_DirOutput;
-                p_extra->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataVideoLTRInfo;
-                p_extra->nDataSize = p_extradata->data_size;
-                memcpy(p_extra->data, p_extradata->data, p_extradata->data_size);
+                append_extradata_ltrinfo(p_extra, p_extradata);
+                if(p_clientextra) {
+                    append_extradata_ltrinfo(p_clientextra, p_extradata);
+                }
                 DEBUG_PRINT_LOW("LTRInfo Extradata = 0x%x", *((OMX_U32 *)p_extra->data));
                 break;
             }
             case MSM_VIDC_EXTRADATA_NONE:
-                p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE), 4);
-                p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
-                p_extra->nPortIndex = OMX_DirOutput;
-                p_extra->eType = OMX_ExtraDataNone;
-                p_extra->nDataSize = 0;
+                append_extradata_none(p_extra);
+                if(p_clientextra) {
+                    append_extradata_none(p_clientextra);
+                }
                 break;
             default:
                 /* No idea what this stuff is, just skip over it */
@@ -988,6 +1024,9 @@
         }
 
         p_extra = (OMX_OTHER_EXTRADATATYPE *)(((char *)p_extra) + p_extra->nSize);
+        if(p_clientextra) {
+            p_clientextra = (OMX_OTHER_EXTRADATATYPE *)(((char *)p_clientextra) + p_clientextra->nSize);
+        }
     } while (p_extradata->type != MSM_VIDC_EXTRADATA_NONE);
 
     /* Just for debugging: Traverse the list of extra datas  and spit it out onto log */
@@ -1924,6 +1963,7 @@
         output_extradata_info.buffer_size = extra_data_size;
         output_extradata_info.count = m_sOutput_buff_property.actualcount;
         output_extradata_info.size = output_extradata_info.buffer_size * output_extradata_info.count;
+        venc_handle->m_client_out_extradata_info.set_extradata_info(extra_data_size,m_sOutput_buff_property.actualcount);
     }
 
     return true;