mm-video-v4l2: vdec: add frame QP request as extra data

Provides frame level QP information. For H264 it is the slice level QP
averaged over whole frame. For all other codecs its frame level QP.
To get the extra data use the standard OpenMAX IL for custom indexes:
Request the index value using: "OMX.QCOM.index.param.video.QPExtradata"
Or directly using the index OMX_QcomIndexParamVideoQPExtraData

Change-Id: Id36820d4b62c7c582c41b72b5811e56d58d2038e
diff --git a/mm-core/inc/OMX_QCOMExtns.h b/mm-core/inc/OMX_QCOMExtns.h
index 2b5cfa3..1c74c16 100644
--- a/mm-core/inc/OMX_QCOMExtns.h
+++ b/mm-core/inc/OMX_QCOMExtns.h
@@ -1,5 +1,5 @@
 /*--------------------------------------------------------------------------
-Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+Copyright (c) 2009-2014, 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:
@@ -419,6 +419,9 @@
 
     /* google smooth-streaming support */
     OMX_QcomIndexParamVideoAdaptivePlaybackMode = 0x7F00002E,
+
+    /* "OMX.QCOM.index.param.video.QPExtradata" */
+    OMX_QcomIndexParamVideoQPExtraData = 0x7F00002F,
 };
 
 /**
@@ -840,6 +843,11 @@
   OMX_U32 extension_flag;
 } OMX_QCOM_FRAME_PACK_ARRANGEMENT;
 
+typedef struct OMX_QCOM_EXTRADATA_QP
+{
+   OMX_U32        nQP;
+} OMX_QCOM_EXTRADATA_QP;
+
 typedef struct OMX_QCOM_EXTRADATA_FRAMEINFO
 {
    // common frame meta data. interlace related info removed
@@ -883,18 +891,19 @@
 
 typedef enum OMX_QCOM_EXTRADATATYPE
 {
-   OMX_ExtraDataFrameInfo = 0x7F000001,
-   OMX_ExtraDataH264 = 0x7F000002,
-   OMX_ExtraDataVC1 = 0x7F000003,
-   OMX_ExtraDataFrameDimension = 0x7F000004,
-   OMX_ExtraDataVideoEncoderSliceInfo = 0x7F000005,
-   OMX_ExtraDataConcealMB = 0x7F000006,
-   OMX_ExtraDataInterlaceFormat = 0x7F000007,
-   OMX_ExtraDataPortDef = 0x7F000008,
-   OMX_ExtraDataMP2ExtnData = 0x7F000009,
-   OMX_ExtraDataMP2UserData = 0x7F00000a,
-   OMX_ExtraDataVideoLTRInfo = 0x7F00000b,
-   OMX_ExtraDataFramePackingArrangement = 0x7F00000c,
+    OMX_ExtraDataFrameInfo =               0x7F000001,
+    OMX_ExtraDataH264 =                    0x7F000002,
+    OMX_ExtraDataVC1 =                     0x7F000003,
+    OMX_ExtraDataFrameDimension =          0x7F000004,
+    OMX_ExtraDataVideoEncoderSliceInfo =   0x7F000005,
+    OMX_ExtraDataConcealMB =               0x7F000006,
+    OMX_ExtraDataInterlaceFormat =         0x7F000007,
+    OMX_ExtraDataPortDef =                 0x7F000008,
+    OMX_ExtraDataMP2ExtnData =             0x7F000009,
+    OMX_ExtraDataMP2UserData =             0x7F00000a,
+    OMX_ExtraDataVideoLTRInfo =            0x7F00000b,
+    OMX_ExtraDataFramePackingArrangement = 0x7F00000c,
+    OMX_ExtraDataQP =                      0x7F00000d,
 } OMX_QCOM_EXTRADATATYPE;
 
 typedef struct  OMX_STREAMINTERLACEFORMATTYPE {
@@ -1112,6 +1121,7 @@
 #define OMX_QCOM_INDEX_PARAM_INDEXEXTRADATA "OMX.QCOM.index.param.IndexExtraData"
 #define OMX_QCOM_INDEX_PARAM_VIDEO_SLICEDELIVERYMODE "OMX.QCOM.index.param.SliceDeliveryMode"
 #define OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA "OMX.QCOM.index.param.video.FramePackingExtradata"
+#define OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA "OMX.QCOM.index.param.video.QPExtradata"
 #define OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO "OMX.QCOM.index.config.video.FramePackingInfo"
 
 typedef enum {
diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
index b7e4f33..619fb20 100644
--- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
+++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h
@@ -186,6 +186,7 @@
 #define OMX_PORTDEF_EXTRADATA   0x00080000
 #define OMX_EXTNUSER_EXTRADATA  0x00100000
 #define OMX_FRAMEPACK_EXTRADATA 0x00400000
+#define OMX_QP_EXTRADATA        0x00800000
 #define DRIVER_EXTRADATA_MASK   0x0000FFFF
 
 #define OMX_INTERLACE_EXTRADATA_SIZE ((sizeof(OMX_OTHER_EXTRADATATYPE) +\
@@ -196,6 +197,8 @@
             sizeof(OMX_PARAM_PORTDEFINITIONTYPE) + 3)&(~3))
 #define OMX_FRAMEPACK_EXTRADATA_SIZE ((sizeof(OMX_OTHER_EXTRADATATYPE) +\
             sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT) + 3)&(~3))
+#define OMX_QP_EXTRADATA_SIZE ((sizeof(OMX_OTHER_EXTRADATATYPE) +\
+            sizeof(OMX_QCOM_EXTRADATA_QP) + 3)&(~3))
 
 //  Define next macro with required values to enable default extradata,
 //    VDEC_EXTRADATA_MB_ERROR_MAP
@@ -661,6 +664,8 @@
                 OMX_OTHER_EXTRADATATYPE *p_concealmb, OMX_U8 *conceal_mb_data);
         void append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
                 struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload);
+        void append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
+                struct msm_vidc_frame_qp_payload *qp_payload);
         void insert_demux_addr_offset(OMX_U32 address_offset);
         void extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr);
         OMX_ERRORTYPE handle_demux_data(OMX_BUFFERHEADERTYPE *buf_hdr);
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 982bf6d..b342d6e 100644
--- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp
+++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp
@@ -3400,10 +3400,20 @@
                                    eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
                                            ((QOMX_ENABLETYPE *)paramData)->bEnable);
                                else {
-                                   DEBUG_PRINT_ERROR("\n Setting extradata in secure mode is not supported");
+                                   DEBUG_PRINT_ERROR("secure mode setting not supported");
                                    eRet = OMX_ErrorUnsupportedSetting;
                                }
                                break;
+        case OMX_QcomIndexParamVideoQPExtraData: {
+                                   if (!secure_mode)
+                                       eRet = enable_extradata(OMX_QP_EXTRADATA, false,
+                                               ((QOMX_ENABLETYPE *)paramData)->bEnable);
+                                   else {
+                                       DEBUG_PRINT_ERROR("secure mode setting not supported");
+                                       eRet = OMX_ErrorUnsupportedSetting;
+                                   }
+                                   break;
+                               }
         case OMX_QcomIndexParamVideoDivx: {
                               QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
                           }
@@ -3649,6 +3659,8 @@
                  eRet = OMX_ErrorUnsupportedIndex;
              }
     }
+    if (eRet != OMX_ErrorNone)
+        DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
     return eRet;
 }
 
@@ -3990,6 +4002,8 @@
         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
     } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
+    } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
+        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
     }
 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
     else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
@@ -7838,6 +7852,11 @@
             client_extra_data_size += OMX_FRAMEPACK_EXTRADATA_SIZE;
             DEBUG_PRINT_HIGH("framepack extradata enabled");
         }
+        if (client_extradata & OMX_QP_EXTRADATA) {
+            client_extra_data_size += OMX_QP_EXTRADATA_SIZE;
+            DEBUG_PRINT_HIGH("QP extradata enabled");
+        }
+
         if (client_extra_data_size) {
             client_extra_data_size += sizeof(OMX_OTHER_EXTRADATATYPE); //Space for terminator
             buf_size = ((buf_size + 3)&(~3)); //Align extradata start address to 64Bit
@@ -8400,6 +8419,14 @@
                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
                     }
                     break;
+                case EXTRADATA_FRAME_QP:
+                    struct msm_vidc_frame_qp_payload *qp_payload;
+                    qp_payload = (struct msm_vidc_frame_qp_payload*)data->data;
+                    if (!secure_mode && (client_extradata & OMX_QP_EXTRADATA)) {
+                        append_qp_extradata(p_extra, qp_payload);
+                        p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
+                    }
+                    break;
                 default:
                     goto unrecognized_extradata;
             }
@@ -8502,6 +8529,13 @@
                 DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
             }
         }
+        if (requested_extradata & OMX_QP_EXTRADATA) {
+            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+            control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
+            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+                DEBUG_PRINT_HIGH("Failed to set QP extradata");
+            }
+        }
     }
     ret = get_buffer_req(&drv_ctx.op_buf);
     return ret;
@@ -8629,6 +8663,13 @@
                 framepack->reserved_byte,
                 framepack->repetition_period,
                 framepack->extension_flag);
+    } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
+        OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)extra->data;
+        DEBUG_PRINT_HIGH(
+                "---- QP (Frame quantization parameter) ----\n"
+                "    Frame QP: %lu \n"
+                "================ End of QP ================\n",
+                qp->nQP);
     } else if (extra->eType == OMX_ExtraDataNone) {
         DEBUG_PRINT_HIGH("========== End of Terminator ===========");
     } else {
@@ -8788,6 +8829,24 @@
     print_debug_extradata(extra);
 }
 
+void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
+            struct msm_vidc_frame_qp_payload *qp_payload)
+{
+    OMX_QCOM_EXTRADATA_QP * qp = NULL;
+    if (!qp_payload) {
+        DEBUG_PRINT_ERROR("QP payload is NULL");
+        return;
+    }
+    extra->nSize = OMX_QP_EXTRADATA_SIZE;
+    extra->nVersion.nVersion = OMX_SPEC_VERSION;
+    extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+    extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
+    extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
+    qp = (OMX_QCOM_EXTRADATA_QP *)extra->data;
+    qp->nQP = qp_payload->frame_qp;
+    print_debug_extradata(extra);
+}
+
 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
 {
     if (!client_extradata) {