mm-video: vidc: Support s3d framepacking information

- Client can enable framepacking extradata using extension
  index OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA.
- Client can get the framepacking information as part of
  extradata in output buffer.
- Client can also get the latest framepacking information
  via get_config() call using extension index
  OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO.

Change-Id: I47f15310f308676a2a4e0a2541715f851a0fbc22
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 f0e5a91..55d233b 100644
--- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp
+++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp
@@ -624,6 +624,7 @@
     memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
 #endif
     memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
+    memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
     drv_ctx.timestamp_adjust = false;
     drv_ctx.video_driver_fd = -1;
     m_vendor_config.pData = NULL;
@@ -3296,6 +3297,15 @@
                                    eRet = OMX_ErrorUnsupportedSetting;
                                }
                                break;
+        case OMX_QcomIndexParamVideoFramePackingExtradata:
+                               if (!secure_mode)
+                                   eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
+                                           ((QOMX_ENABLETYPE *)paramData)->bEnable);
+                               else {
+                                   DEBUG_PRINT_ERROR("\n Setting extradata in secure mode is not supported");
+                                   eRet = OMX_ErrorUnsupportedSetting;
+                               }
+                               break;
         case OMX_QcomIndexParamVideoDivx: {
                               QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
                           }
@@ -3555,7 +3565,8 @@
                                           if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
                                               OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
                                                   (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
-                                              h264_parser->get_frame_pack_data(configFmt);
+                                              memcpy(configFmt, &m_frame_pack_arrangement,
+                                                  sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
                                           } else {
                                               DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
                                           }
@@ -3799,6 +3810,8 @@
     return OMX_ErrorNotImplemented;
 }
 
+#define extn_equals(param, extn) (!strncmp(param, extn, strlen(extn)))
+
 /* ======================================================================
    FUNCTION
    omx_vdec::GetExtensionIndex
@@ -3820,24 +3833,28 @@
     if (m_state == OMX_StateInvalid) {
         DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
         return OMX_ErrorInvalidState;
-    } else if (!strncmp(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode",sizeof("OMX.QCOM.index.param.video.SyncFrameDecodingMode") - 1)) {
+    } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
-    } else if (!strncmp(paramName, "OMX.QCOM.index.param.IndexExtraData",sizeof("OMX.QCOM.index.param.IndexExtraData") - 1)) {
+    } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
+    } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
+        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
+    } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
+        *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
     }
 #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
-    else if (!strncmp(paramName,"OMX.google.android.index.enableAndroidNativeBuffers", sizeof("OMX.google.android.index.enableAndroidNativeBuffers") - 1)) {
+    else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
-    } else if (!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer2", sizeof("OMX.google.android.index.enableAndroidNativeBuffer2") - 1)) {
+    } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
-    } else if (!strncmp(paramName,"OMX.google.android.index.useAndroidNativeBuffer", sizeof("OMX.google.android.index.enableAndroidNativeBuffer") - 1)) {
+    } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
         DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
-    } else if (!strncmp(paramName,"OMX.google.android.index.getAndroidNativeBufferUsage", sizeof("OMX.google.android.index.getAndroidNativeBufferUsage") - 1)) {
+    } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
         *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
     }
 #endif
-    else if (!strncmp(paramName, "OMX.google.android.index.storeMetaDataInBuffers", sizeof("OMX.google.android.index.storeMetaDataInBuffers") - 1)) {
+    else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
         *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
     }
     else {
@@ -7593,6 +7610,10 @@
             DEBUG_PRINT_HIGH("Smooth streaming enabled extra_data_size=%d",
                     client_extra_data_size);
         }
+        if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
+            client_extra_data_size += OMX_FRAMEPACK_EXTRADATA_SIZE;
+            DEBUG_PRINT_HIGH("framepack 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
@@ -8028,7 +8049,9 @@
     struct msm_vidc_panscan_window_payload *panscan_payload = NULL;
     OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) +
         p_buf_hdr->nOffset;
+
     if (!drv_ctx.extradata_info.uaddr) {
+        DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
         return;
     }
     if (!secure_mode)
@@ -8051,6 +8074,7 @@
                 DEBUG_PRINT_LOW("Invalid extra data size");
                 break;
             }
+            DEBUG_PRINT_LOW("handle_extradata: eType = %d", data->eType);
             switch ((unsigned long)data->eType) {
                 case EXTRADATA_INTERLACE_VIDEO:
                     struct msm_vidc_interlace_payload *payload;
@@ -8130,6 +8154,14 @@
                         m_disp_vert_size = seqdisp_payload->disp_height;
                     }
                     break;
+                case EXTRADATA_S3D_FRAME_PACKING:
+                    struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
+                    s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)data->data;
+                    if (!secure_mode && (client_extradata & OMX_FRAMEPACK_EXTRADATA)) {
+                        append_framepack_extradata(p_extra, s3d_frame_packing_payload);
+                        p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
+                    }
+                    break;
                 default:
                     goto unrecognized_extradata;
             }
@@ -8178,7 +8210,8 @@
                 DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
                         " Quality of interlaced clips might be impacted.");
             }
-        } else if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
+        }
+        if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
             control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
@@ -8211,13 +8244,26 @@
                     DEBUG_PRINT_HIGH("Failed to set panscan extradata");
                 }
             }
-        } else if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
+        }
+        if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
             control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
             control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
             if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
                 DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
             }
         }
+        if (requested_extradata & OMX_FRAMEPACK_EXTRADATA) {
+            if (output_capability == V4L2_PIX_FMT_H264) {
+                DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
+                control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+                control.value =  V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
+                if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+                    DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
+                }
+            } else {
+                DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
+            }
+        }
     }
     ret = get_buffer_req(&drv_ctx.op_buf);
     return ret;
@@ -8303,6 +8349,48 @@
         }
 
         DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
+    } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
+        OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)extra->data;
+        DEBUG_PRINT_HIGH(
+                "------------------ Framepack Format ----------\n"
+                "                           id: %lu \n"
+                "                  cancel_flag: %lu \n"
+                "                         type: %lu \n"
+                " quincunx_sampling_flagFormat: %lu \n"
+                "  content_interpretation_type: %lu \n"
+                "  content_interpretation_type: %lu \n"
+                "        spatial_flipping_flag: %lu \n"
+                "          frame0_flipped_flag: %lu \n"
+                "             field_views_flag: %lu \n"
+                " current_frame_is_frame0_flag: %lu \n"
+                "   frame0_self_contained_flag: %lu \n"
+                "   frame1_self_contained_flag: %lu \n"
+                "       frame0_grid_position_x: %lu \n"
+                "       frame0_grid_position_y: %lu \n"
+                "       frame1_grid_position_x: %lu \n"
+                "       frame1_grid_position_y: %lu \n"
+                "                reserved_byte: %lu \n"
+                "            repetition_period: %lu \n"
+                "               extension_flag: %lu \n"
+                "================== End of Framepack ===========",
+                framepack->id,
+                framepack->cancel_flag,
+                framepack->type,
+                framepack->quincunx_sampling_flag,
+                framepack->content_interpretation_type,
+                framepack->spatial_flipping_flag,
+                framepack->frame0_flipped_flag,
+                framepack->field_views_flag,
+                framepack->current_frame_is_frame0_flag,
+                framepack->frame0_self_contained_flag,
+                framepack->frame1_self_contained_flag,
+                framepack->frame0_grid_position_x,
+                framepack->frame0_grid_position_y,
+                framepack->frame1_grid_position_x,
+                framepack->frame1_grid_position_y,
+                framepack->reserved_byte,
+                framepack->repetition_period,
+                framepack->extension_flag);
     } else if (extra->eType == OMX_ExtraDataNone) {
         DEBUG_PRINT_HIGH("========== End of Terminator ===========");
     } else {
@@ -8438,6 +8526,30 @@
             portDefn->format.video.nSliceHeight);
 }
 
+void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
+        struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
+{
+    OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
+    if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
+        DEBUG_PRINT_ERROR("frame packing size mismatch");
+        return;
+    }
+    extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
+    extra->nVersion.nVersion = OMX_SPEC_VERSION;
+    extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+    extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
+    extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
+    framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)extra->data;
+    framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
+    framepack->nVersion.nVersion = OMX_SPEC_VERSION;
+    framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+    memcpy(&framepack->id, s3d_frame_packing_payload,
+        sizeof(struct msm_vidc_s3d_frame_packing_payload));
+    memcpy(&m_frame_pack_arrangement, framepack,
+        sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
+    print_debug_extradata(extra);
+}
+
 void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
 {
     if (!client_extradata) {