mm-video-v4l2: vdec: add input frame bits info as extradata

Provides information regarding number of bits in the frame (i.e. frame
size expressed in bits) and also the number of bits in frame header
(i.e. frame header size expressed in bits). Number of bits in header is
reported as:
For H264, sum of all slice headers bits for all the slices in the frame.
For all other codecs is the number of bits in the frame header.
To get the extra data use the standard OpenMAX IL for custom indexes:
Request the index value using:
"OMX.QCOM.index.param.video.InputBitsInfoExtradata"
Or directly using the index:
OMX_QcomIndexParamVideoInputBitsInfoExtraData

Change-Id: I69808a221b1c0de7012fddaa14c4b92bf92992af
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 b342d6e..8193a52 100644
--- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp
+++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp
@@ -3414,6 +3414,16 @@
                                    }
                                    break;
                                }
+        case OMX_QcomIndexParamVideoInputBitsInfoExtraData: {
+                                   if (!secure_mode)
+                                       eRet = enable_extradata(OMX_BITSINFO_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;
                           }
@@ -4004,6 +4014,8 @@
         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
     } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
+    } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
+        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
     }
 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
     else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
@@ -7856,6 +7868,10 @@
             client_extra_data_size += OMX_QP_EXTRADATA_SIZE;
             DEBUG_PRINT_HIGH("QP extradata enabled");
         }
+        if (client_extradata & OMX_BITSINFO_EXTRADATA) {
+            client_extra_data_size += OMX_BITSINFO_EXTRADATA_SIZE;
+            DEBUG_PRINT_HIGH("Input bits info extradata enabled");
+        }
 
         if (client_extra_data_size) {
             client_extra_data_size += sizeof(OMX_OTHER_EXTRADATATYPE); //Space for terminator
@@ -8427,6 +8443,14 @@
                         p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
                     }
                     break;
+                case EXTRADATA_FRAME_BITS_INFO:
+                    struct msm_vidc_frame_bits_info_payload *bits_info_payload;
+                    bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)data->data;
+                    if (!secure_mode && (client_extradata & OMX_BITSINFO_EXTRADATA)) {
+                        append_bitsinfo_extradata(p_extra, bits_info_payload);
+                        p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
+                    }
+                    break;
                 default:
                     goto unrecognized_extradata;
             }
@@ -8536,6 +8560,13 @@
                 DEBUG_PRINT_HIGH("Failed to set QP extradata");
             }
         }
+        if (requested_extradata & OMX_BITSINFO_EXTRADATA) {
+            control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+            control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO;
+            if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+                DEBUG_PRINT_HIGH("Failed to set frame bits info extradata");
+            }
+        }
     }
     ret = get_buffer_req(&drv_ctx.op_buf);
     return ret;
@@ -8670,6 +8701,14 @@
                 "    Frame QP: %lu \n"
                 "================ End of QP ================\n",
                 qp->nQP);
+    } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
+        OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)extra->data;
+        DEBUG_PRINT_HIGH(
+                "--------- Input bits information --------\n"
+                "    Header bits: %lu \n"
+                "     Frame bits: %lu \n"
+                "===== End of Input bits information =====\n",
+                bits->header_bits, bits->frame_bits);
     } else if (extra->eType == OMX_ExtraDataNone) {
         DEBUG_PRINT_HIGH("========== End of Terminator ===========");
     } else {
@@ -8847,6 +8886,25 @@
     print_debug_extradata(extra);
 }
 
+void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
+            struct msm_vidc_frame_bits_info_payload *bits_payload)
+{
+    OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
+    if (!bits_payload) {
+        DEBUG_PRINT_ERROR("bits info payload is NULL");
+        return;
+    }
+    extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
+    extra->nVersion.nVersion = OMX_SPEC_VERSION;
+    extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+    extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
+    extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
+    bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)extra->data;
+    bits->frame_bits = bits_payload->frame_bits;
+    bits->header_bits = bits_payload->header_bits;
+    print_debug_extradata(extra);
+}
+
 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
 {
     if (!client_extradata) {