Merge "mm-video-v4l2: raise onConfigUpdate Event on FBD"
diff --git a/mm-core/inc/OMX_Core.h b/mm-core/inc/OMX_Core.h
index 4a2f5db..6fa88c2 100644
--- a/mm-core/inc/OMX_Core.h
+++ b/mm-core/inc/OMX_Core.h
@@ -534,6 +534,20 @@
      *  fool-proof way to do that for video encoders.
      */
     OMX_EventDataSpaceChanged,
+
+    /**
+     * Event when a component has an updated configuration on output for the client to retrieve.
+     * |arg1| contains the port index (currently only output port is valid). |arg2| contains the
+     * index of the updated config.
+     *
+     * For config updates that's associated with one frame, the update should be applied to the
+     * next output frame that comes in EmptyBufferDone callback.
+     *
+     * Upon receiving this event, the client must call the corresponding OMX_GetConfig to retrieve
+     * the config update.
+     */
+    OMX_EventConfigUpdate,
+
     OMX_EventMax = 0x7FFFFFFF
 } OMX_EVENTTYPE;
 
diff --git a/mm-core/inc/OMX_QCOMExtns.h b/mm-core/inc/OMX_QCOMExtns.h
index 6d9006d..39b82d8 100644
--- a/mm-core/inc/OMX_QCOMExtns.h
+++ b/mm-core/inc/OMX_QCOMExtns.h
@@ -705,6 +705,8 @@
     OMX_QTIIndexParamNativeRecorder = 0x7F100008,
 
     OMX_QTIIndexParamVideoDecoderOutputFrameRate = 0x7F100009,
+    /*"OMX.google.android.index.describeHDR10PlusInfo"*/
+    OMX_QTIIndexConfigDescribeHDR10PlusInfo = 0x7F10000a,
 };
 
 /**
diff --git a/mm-core/inc/OMX_VideoExt.h b/mm-core/inc/OMX_VideoExt.h
index db48d3c..1d372d2 100644
--- a/mm-core/inc/OMX_VideoExt.h
+++ b/mm-core/inc/OMX_VideoExt.h
@@ -164,6 +164,7 @@
     // HDR profiles also support passing HDR metadata
     OMX_VIDEO_VP9Profile2HDR = 0x1000,
     OMX_VIDEO_VP9Profile3HDR = 0x2000,
+    OMX_VIDEO_VP9Profile2HDR10Plus = 0x4000,
     OMX_VIDEO_VP9ProfileUnknown = 0x6EFFFFFF,
     OMX_VIDEO_VP9ProfileMax = 0x7FFFFFFF
 } OMX_VIDEO_VP9PROFILETYPE;
diff --git a/mm-video-v4l2/vidc/common/src/vidc_common.cpp b/mm-video-v4l2/vidc/common/src/vidc_common.cpp
index 0db59ee..464504c 100644
--- a/mm-video-v4l2/vidc/common/src/vidc_common.cpp
+++ b/mm-video-v4l2/vidc/common/src/vidc_common.cpp
@@ -78,6 +78,7 @@
 pl_map profile_level_converter::profile_vp9_omx_to_v4l2 ({
             {OMX_VIDEO_VP9Profile0, V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_P0},
             {OMX_VIDEO_VP9Profile2HDR, V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_P2_10},
+            {OMX_VIDEO_VP9Profile2HDR10Plus, V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_P2_10},
         });
 
 pl_map profile_level_converter::profile_vp9_v4l2_to_omx ({});
diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
index 689a637..05b1ce5 100644
--- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
+++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
@@ -56,6 +56,7 @@
 #include "media/hardware/HardwareAPI.h"
 #include <unordered_map>
 #include <media/msm_media_info.h>
+#include <list>
 
 #include <linux/msm_ion.h>
 #if TARGET_ION_ABI_VERSION >= 2
@@ -415,6 +416,18 @@
 	unsigned long fps_numerator;
 };
 
+struct hdr10plusInfo {
+    bool is_new;
+    unsigned int cookie;
+    OMX_TICKS timestamp;
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_U32 nParamSize;
+    OMX_U32 nParamSizeUsed;
+    OMX_U8 payload[MAX_HDR10PLUSINFO_SIZE];
+};
+
 #ifdef USE_ION
 struct vdec_ion {
     int dev_fd;
@@ -1103,6 +1116,9 @@
         OMX_BUFFERHEADERTYPE  *m_client_output_extradata_mem_ptr;
         // number of input bitstream error frame count
         unsigned int m_inp_err_count;
+
+        pthread_mutex_t m_hdr10pluslock;
+        std::list<hdr10plusInfo> m_hdr10pluslist;
 #ifdef _ANDROID_
         // Timestamp list
         ts_arr_list           m_timestamp_list;
@@ -1130,6 +1146,8 @@
         // encapsulate the waiting states.
         uint64_t m_flags;
 
+        OMX_U32 m_etb_count;
+        OMX_TICKS m_etb_timestamp;
         // store I/P PORT state
         OMX_BOOL m_inp_bEnabled;
         // store O/P PORT state
@@ -1452,6 +1470,12 @@
         void get_preferred_color_aspects(ColorAspects& preferredColorAspects);
         void get_preferred_hdr_info(HDRStaticInfo& preferredHDRInfo);
         bool vdec_query_cap(struct v4l2_queryctrl &cap);
+        bool store_hdr10plusinfo(DescribeHDR10PlusInfoParams *hdr10plusinfo);
+        void update_hdr10plusinfo_cookie_using_timestamp(OMX_PTR cookie, OMX_TICKS timestamp);
+        void convert_hdr10plusinfo_to_metadata(OMX_PTR cookie, ColorMetaData &colorData);
+        void remove_hdr10plusinfo_using_cookie(OMX_PTR cookie);
+        void clear_hdr10plusinfo();
+        void get_hdr10plusinfo(DescribeHDR10PlusInfoParams *hdr10plusdata);
 public:
         bool is_down_scalar_enabled;
         bool m_is_split_mode;
diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
index cf2d0e5..09fea4b 100644
--- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
+++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
@@ -152,6 +152,16 @@
 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
 
+/*
+To enable sending vp9 hdr10plus metadata via private gralloc
+handle to display, define VP9_HDR10PLUS_GRALLOC_PATH_ENABLE
+as 1. This disables sending metadata via framework.
+To enable sending vp9 hdr10plus metadata via framework, define
+VP9_HDR10PLUS_GRALLOC_PATH_ENABLE as 0. This disables sending
+metadata via gralloc handle.
+*/
+#define VP9HDR10PLUS_SETMETADATA_ENABLE 1
+
 using namespace android;
 
 #ifdef HYPERVISOR
@@ -876,6 +886,7 @@
     pthread_mutex_init(&m_lock, NULL);
     pthread_mutex_init(&c_lock, NULL);
     pthread_mutex_init(&buf_lock, NULL);
+    pthread_mutex_init(&m_hdr10pluslock, NULL);
     sem_init(&m_cmd_lock,0,0);
     sem_init(&m_safe_flush, 0, 0);
     streaming[CAPTURE_PORT] =
@@ -921,6 +932,9 @@
     m_dither_config = DITHER_DISABLE;
 
     DEBUG_PRINT_HIGH("Dither config is %d", m_dither_config);
+    m_etb_count = 0;
+    m_etb_timestamp = 0;
+
     m_color_space = EXCEPT_BT2020;
 
     init_color_aspects_map();
@@ -1046,9 +1060,11 @@
 #else
     close(drv_ctx.video_driver_fd);
 #endif
+    clear_hdr10plusinfo();
     pthread_mutex_destroy(&m_lock);
     pthread_mutex_destroy(&c_lock);
     pthread_mutex_destroy(&buf_lock);
+    pthread_mutex_destroy(&m_hdr10pluslock);
     sem_destroy(&m_cmd_lock);
     if (perf_flag) {
         DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
@@ -1588,11 +1604,36 @@
                                         if (p2 != VDEC_S_SUCCESS) {
                                             DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_FBD failure");
                                             pThis->omx_report_error ();
-                                        } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
+                                            break;
+                                        }
+                                        if (pThis->fill_buffer_done(&pThis->m_cmp,
                                                     (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
                                             DEBUG_PRINT_ERROR("fill_buffer_done failure");
                                             pThis->omx_report_error ();
+                                            break;
                                         }
+#if !VP9HDR10PLUS_SETMETADATA_ENABLE
+                                        if (pThis->output_capability != V4L2_PIX_FMT_VP9)
+                                            break;
+
+                                        if (!pThis->m_cb.EventHandler) {
+                                            DEBUG_PRINT_ERROR("fill_buffer_done: null event handler");
+                                            break;
+                                        }
+                                        bool is_list_empty;
+                                        is_list_empty = false;
+                                        pthread_mutex_lock(&pThis->m_hdr10pluslock);
+                                        is_list_empty = pThis->m_hdr10pluslist.empty();
+                                        pthread_mutex_unlock(&pThis->m_hdr10pluslock);
+                                        if (!is_list_empty) {
+                                            DEBUG_PRINT_LOW("fill_buffer_done: event config update");
+                                            pThis->m_cb.EventHandler(&pThis->m_cmp,
+                                                    pThis->m_app_data,
+                                                    OMX_EventConfigUpdate,
+                                                    OMX_CORE_OUTPUT_PORT_INDEX,
+                                                    OMX_QTIIndexConfigDescribeHDR10PlusInfo, NULL);
+                                        }
+#endif
                                         break;
 
                 case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
@@ -3444,6 +3485,8 @@
             pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
                     OMX_EventCmdComplete,OMX_CommandFlush,
                     OMX_CORE_INPUT_PORT_INDEX,NULL );
+            //clear hdr10plusinfo list upon input flush done
+            clear_hdr10plusinfo();
         }
     }
 }
@@ -3533,9 +3576,10 @@
                              OMX_VIDEO_HEVCProfileMain10HDR10 };
     int mpeg2_profiles[2] = { OMX_VIDEO_MPEG2ProfileSimple,
                               OMX_VIDEO_MPEG2ProfileMain};
-    int vp9_profiles[3] = { OMX_VIDEO_VP9Profile0,
+    int vp9_profiles[4] = { OMX_VIDEO_VP9Profile0,
                             OMX_VIDEO_VP9Profile2,
-                            OMX_VIDEO_VP9Profile2HDR};
+                            OMX_VIDEO_VP9Profile2HDR,
+                            OMX_VIDEO_VP9Profile2HDR10Plus};
 
     if (!profileLevelType)
         return OMX_ErrorBadParameter;
@@ -5360,6 +5404,13 @@
 
             break;
         }
+        case OMX_QTIIndexConfigDescribeHDR10PlusInfo:
+        {
+            VALIDATE_OMX_PARAM_DATA(configData, DescribeHDR10PlusInfoParams);
+            DescribeHDR10PlusInfoParams *params = (DescribeHDR10PlusInfoParams *)configData;
+            get_hdr10plusinfo(params);
+            break;
+        }
         case OMX_IndexConfigAndroidVendorExtension:
         {
             VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
@@ -5558,6 +5609,13 @@
         memcpy(&m_client_hdr_info, params, sizeof(DescribeHDRStaticInfoParams));
         return ret;
 
+    } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeHDR10PlusInfo) {
+        VALIDATE_OMX_PARAM_DATA(configData, DescribeHDR10PlusInfoParams);
+        if (!store_hdr10plusinfo((DescribeHDR10PlusInfoParams *)configData)) {
+            DEBUG_PRINT_ERROR("Failed to set hdr10plus info");
+        }
+        return ret;
+
     } else if ((int)configIndex == (int)OMX_IndexConfigAndroidVendorExtension) {
         VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE);
 
@@ -5660,6 +5718,8 @@
         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeHDRColorInfo;
     } else if (extn_equals(paramName, "OMX.QTI.index.param.ClientConfiguredProfileLevel")) {
         *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamClientConfiguredProfileLevelForSufficiency;
+    } else if (extn_equals(paramName, "OMX.google.android.index.describeHDR10PlusInfo")) {
+        *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeHDR10PlusInfo;
     }else {
         DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
         return OMX_ErrorNotImplemented;
@@ -7378,14 +7438,21 @@
         buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
     }
 
-    DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
-            buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
+    m_etb_count++;
+    //To handle wrap around case. m_etb_count++ to ensure value is non-zero.
+    if (!m_etb_count)
+        m_etb_count++;
+    m_etb_timestamp = buffer->nTimeStamp;
+    DEBUG_PRINT_LOW("[ETB] nCnt(%u) BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
+            m_etb_count, buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
+    buffer->pMarkData = (OMX_PTR)(unsigned long)m_etb_count;
     if (arbitrary_bytes) {
         post_event ((unsigned long)hComp,(unsigned long)buffer,
                 OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
     } else {
         post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
     }
+
     time_stamp_dts.insert_timestamp(buffer);
     return OMX_ErrorNone;
 }
@@ -7436,7 +7503,7 @@
     /* return zero length and not an EOS buffer */
     if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
             ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
-        DEBUG_PRINT_HIGH("return zero legth buffer");
+        DEBUG_PRINT_HIGH("return zero length buffer");
         post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
                 OMX_COMPONENT_GENERATE_EBD);
         return OMX_ErrorNone;
@@ -7560,6 +7627,8 @@
         buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
     }
 
+    // update hdr10plusinfo list with cookie as pMarkData
+    update_hdr10plusinfo_cookie_using_timestamp(buffer->pMarkData, buffer->nTimeStamp);
 
     OMX_ERRORTYPE eRet = OMX_ErrorNone;
     buf.index = nPortIndex;
@@ -11521,6 +11590,10 @@
                 get_preferred_hdr_info(final_hdr_info);
                 convert_color_aspects_to_metadata(final_color_aspects, color_mdata);
                 convert_hdr_info_to_metadata(final_hdr_info, color_mdata);
+#if VP9HDR10PLUS_SETMETADATA_ENABLE
+                convert_hdr10plusinfo_to_metadata(p_buf_hdr->pMarkData, color_mdata);
+                remove_hdr10plusinfo_using_cookie(p_buf_hdr->pMarkData);
+#endif
                 print_debug_hdr_color_info_mdata(&color_mdata);
                 print_debug_hdr10plus_metadata(color_mdata);
                 set_colormetadata_in_handle(&color_mdata, buf_index);
@@ -13077,6 +13150,219 @@
     return rc;
 }
 
+bool omx_vdec::store_hdr10plusinfo(DescribeHDR10PlusInfoParams *hdr10plusdata)
+{
+    struct hdr10plusInfo metadata;
+
+    if (!hdr10plusdata) {
+        DEBUG_PRINT_ERROR("hdr10plus info not present");
+        return false;
+    }
+
+    if (hdr10plusdata->nParamSize > MAX_HDR10PLUSINFO_SIZE ||
+            hdr10plusdata->nParamSize < 1) {
+        DEBUG_PRINT_ERROR("Invalid hdr10plus metadata size %u", hdr10plusdata->nParamSize);
+        return false;
+    }
+
+    if (output_capability != V4L2_PIX_FMT_VP9) {
+        DEBUG_PRINT_ERROR("DescribeHDR10PlusInfoParams is not supported for %d codec",
+            output_capability);
+        return false;
+    }
+
+    memset(&metadata, 0, sizeof(struct hdr10plusInfo));
+    metadata.nSize = hdr10plusdata->nSize;
+    metadata.nVersion = hdr10plusdata->nVersion;
+    metadata.nPortIndex = hdr10plusdata->nPortIndex;
+    metadata.nParamSize = hdr10plusdata->nParamSize;
+    metadata.nParamSizeUsed = hdr10plusdata->nParamSizeUsed;
+    memcpy(metadata.payload, hdr10plusdata->nValue , hdr10plusdata->nParamSizeUsed);
+    metadata.is_new = true;
+
+    /*
+     * For the first setconfig, set the timestamp as zero. For
+     * the remaining, set the timestamp equal to previous
+     * etb timestamp + 1 to know this hdr10plus data arrived
+     * after previous etb.
+     */
+    if (m_etb_count) {
+        metadata.timestamp = m_etb_timestamp + 1;
+    }
+
+    pthread_mutex_lock(&m_hdr10pluslock);
+    DEBUG_PRINT_LOW("add hdr10plus info to the list with timestamp %lld and size %u",
+        metadata.timestamp, metadata.nParamSizeUsed);
+    m_hdr10pluslist.push_back(metadata);
+    pthread_mutex_unlock(&m_hdr10pluslock);
+
+    return true;
+}
+
+void omx_vdec::update_hdr10plusinfo_cookie_using_timestamp(OMX_PTR markdata, OMX_TICKS timestamp)
+{
+    std::list<hdr10plusInfo>::reverse_iterator iter;
+    unsigned int found = 0;
+    unsigned int cookie = (unsigned int)(unsigned long)markdata;
+    bool is_list_empty = false;
+
+    if (output_capability != V4L2_PIX_FMT_VP9)
+        return;
+
+    pthread_mutex_lock(&m_hdr10pluslock);
+    is_list_empty = m_hdr10pluslist.empty();
+    pthread_mutex_unlock(&m_hdr10pluslock);
+
+    if (is_list_empty) {
+        DEBUG_PRINT_HIGH("update_hdr10plusinfo_cookie_using_timestamp: hdr10plusinfo list is empty!");
+        return;
+    }
+    /*
+     * look for the hdr10plus data which has timestamp nearest and
+     * lower than the etb timestamp, we should not take the
+     * hdr10plus data which has the timestamp greater than etb timestamp.
+     */
+    pthread_mutex_lock(&m_hdr10pluslock);
+    iter = m_hdr10pluslist.rbegin();
+    while (iter != m_hdr10pluslist.rend()) {
+        if (iter->timestamp <= timestamp && iter->is_new) {
+            found++;
+            if (found == 1) {
+                iter->cookie = cookie;
+                iter->is_new = false;
+                DEBUG_PRINT_LOW("Cookie value %u stored in hdr10plus list with timestamp %lld, size %u",
+                    iter->cookie, iter->timestamp, iter->nParamSizeUsed);
+            }
+        }
+        iter++;
+    }
+    pthread_mutex_unlock(&m_hdr10pluslock);
+
+    if(found > 1)
+        DEBUG_PRINT_HIGH("Multiple hdr10plus data not expected. Continue with the latest");
+}
+
+void omx_vdec::convert_hdr10plusinfo_to_metadata(OMX_PTR markdata, ColorMetaData &colorData)
+{
+    std::list<hdr10plusInfo>::iterator iter;
+    unsigned int cookie = (unsigned int)(unsigned long)markdata;
+    bool is_list_empty = false;
+
+    if (output_capability != V4L2_PIX_FMT_VP9)
+        return;
+
+    pthread_mutex_lock(&m_hdr10pluslock);
+    is_list_empty = m_hdr10pluslist.empty();
+    pthread_mutex_unlock(&m_hdr10pluslock);
+
+    if (is_list_empty) {
+        DEBUG_PRINT_HIGH("convert_hdr10plusinfo_to_metadata: hdr10plusinfo list is empty!");
+        return;
+    }
+
+    pthread_mutex_lock(&m_hdr10pluslock);
+    iter = m_hdr10pluslist.begin();
+    while (iter != m_hdr10pluslist.end()) {
+        if (iter->cookie == cookie && !iter->is_new) {
+            colorData.dynamicMetaDataValid = true;
+            colorData.dynamicMetaDataLen = iter->nParamSizeUsed;
+            memcpy(colorData.dynamicMetaDataPayload, iter->payload,
+                iter->nParamSizeUsed);
+            DEBUG_PRINT_LOW("found hdr10plus metadata for cookie %u with timestamp %lld, size %u",
+                cookie, iter->timestamp, colorData.dynamicMetaDataLen);
+            break;
+        }
+        iter++;
+    }
+    pthread_mutex_unlock(&m_hdr10pluslock);
+}
+
+void omx_vdec::remove_hdr10plusinfo_using_cookie(OMX_PTR markdata)
+{
+    std::list<hdr10plusInfo>::iterator iter;
+    unsigned int cookie = (unsigned int)(unsigned long)markdata;
+    bool is_list_empty = false;
+
+    if (output_capability != V4L2_PIX_FMT_VP9)
+        return;
+
+    pthread_mutex_lock(&m_hdr10pluslock);
+    is_list_empty = m_hdr10pluslist.empty();
+    pthread_mutex_unlock(&m_hdr10pluslock);
+
+    if (is_list_empty) {
+        DEBUG_PRINT_HIGH("remove_hdr10plusinfo_using_cookie: hdr10plusinfo list is empty!");
+        return;
+    }
+
+    pthread_mutex_lock(&m_hdr10pluslock);
+    iter = m_hdr10pluslist.begin();
+    while (iter != m_hdr10pluslist.end()) {
+        if (iter->cookie == cookie && !iter->is_new) {
+            iter = m_hdr10pluslist.erase(iter);
+            DEBUG_PRINT_LOW("removed hdr10plusinfo from the list for the cookie %u", cookie);
+            break;
+        }
+        iter++;
+    }
+    pthread_mutex_unlock(&m_hdr10pluslock);
+}
+
+void omx_vdec::clear_hdr10plusinfo()
+{
+    bool is_list_empty = false;
+
+    if (output_capability != V4L2_PIX_FMT_VP9)
+        return;
+
+    pthread_mutex_lock(&m_hdr10pluslock);
+    is_list_empty = m_hdr10pluslist.empty();
+    pthread_mutex_unlock(&m_hdr10pluslock);
+
+    if (is_list_empty) {
+        DEBUG_PRINT_HIGH("clear_hdr10plusinfo: hdr10plusinfo list is empty!");
+        return;
+    }
+
+    pthread_mutex_lock(&m_hdr10pluslock);
+    m_hdr10pluslist.clear();
+    pthread_mutex_unlock(&m_hdr10pluslock);
+}
+
+void omx_vdec::get_hdr10plusinfo(DescribeHDR10PlusInfoParams *hdr10plusdata)
+{
+    std::list<hdr10plusInfo>::iterator iter;
+    bool is_list_empty = false;
+
+    if (output_capability != V4L2_PIX_FMT_VP9)
+        return;
+
+    pthread_mutex_lock(&m_hdr10pluslock);
+    is_list_empty = m_hdr10pluslist.empty();
+    pthread_mutex_unlock(&m_hdr10pluslock);
+
+    if (is_list_empty) {
+        DEBUG_PRINT_HIGH("get_hdr10plusinfo: hdr10plusinfo list is empty!");
+        return;
+    }
+
+    pthread_mutex_lock(&m_hdr10pluslock);
+    iter = m_hdr10pluslist.begin();
+    while (iter != m_hdr10pluslist.end()) {
+        if (!iter->is_new) {
+            hdr10plusdata->nParamSizeUsed = iter->nParamSizeUsed;
+            memcpy(hdr10plusdata->nValue, iter->payload,
+                iter->nParamSizeUsed);
+            DEBUG_PRINT_LOW("found hdr10plus metadata with timestamp %lld, size %u",
+                iter->timestamp, iter->nParamSizeUsed);
+            iter = m_hdr10pluslist.erase(iter);
+            break;
+        }
+        iter++;
+    }
+    pthread_mutex_unlock(&m_hdr10pluslock);
+}
+
 // No code beyond this !
 
 // inline import of vendor-extensions implementation