mm-video: vidc: Add support for encoder deinterlacing

Venus FW supports deinterlacing for encoder. FW doesn't
support deinterlacing with rotation. Driver needs to make
sure that rotation and deinterlacing are not called together.
Client can enable and\or disable deinterlacing at run time.
This change adds encoder deinterlacing support.

Depends-on: 435602
Change-Id: I15e306b944f676a44ff9df4984ec631d92e245ae
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 435e3e1..46b751f 100644
--- a/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
+++ b/mm-video-v4l2/vidc/venc/inc/omx_video_base.h
@@ -576,6 +576,7 @@
         QOMX_VIDEO_CONFIG_LTRPERIOD_TYPE m_sConfigLTRPeriod;
         QOMX_VIDEO_CONFIG_LTRUSE_TYPE m_sConfigLTRUse;
         OMX_VIDEO_CONFIG_AVCINTRAPERIOD m_sConfigAVCIDRPeriod;
+        OMX_VIDEO_CONFIG_DEINTERLACE m_sConfigDeinterlace;
         OMX_U32 m_sExtraData;
         OMX_U32 m_input_msg_id;
 
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 50de0f6..73c26e1 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
@@ -260,6 +260,7 @@
         void free_extradata();
         bool handle_extradata(void *, int);
         int venc_set_format(int);
+        bool deinterlace_enabled;
     private:
         struct msm_venc_basecfg             m_sVenc_cfg;
         struct msm_venc_ratectrlcfg         rate_ctrl;
@@ -305,6 +306,7 @@
         bool venc_set_idr_period(OMX_U32 nPFrames, OMX_U32 nIDRPeriod);
         bool venc_reconfig_reqbufs();
         bool venc_set_vpe_rotation(OMX_S32 rotation_angle);
+        bool venc_set_deinterlace(OMX_U32 enable);
 #ifdef MAX_RES_1080P
         OMX_U32 pmem_free();
         OMX_U32 pmem_allocate(OMX_U32 size, OMX_U32 alignment, OMX_U32 count);
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 e9cc6f4..a5dfd44 100644
--- a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
+++ b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp
@@ -1864,6 +1864,14 @@
                 memcpy(pParam, &m_sConfigAVCIDRPeriod, sizeof(m_sConfigAVCIDRPeriod));
                 break;
             }
+        case OMX_IndexConfigCommonDeinterlace:
+            {
+                OMX_VIDEO_CONFIG_DEINTERLACE *pParam =
+                    reinterpret_cast<OMX_VIDEO_CONFIG_DEINTERLACE*>(configData);
+                DEBUG_PRINT_LOW("get_config: OMX_IndexConfigCommonDeinterlace");
+                memcpy(pParam, &m_sConfigDeinterlace, sizeof(m_sConfigDeinterlace));
+                break;
+            }
         default:
             DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
             return OMX_ErrorUnsupportedIndex;
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 6b9d43d..129026b 100644
--- a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
+++ b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp
@@ -407,6 +407,10 @@
     m_sParamLTRMode.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
     m_sParamLTRMode.eLTRMode = QOMX_VIDEO_LTRMode_Disable;
 
+    OMX_INIT_STRUCT(&m_sConfigDeinterlace, OMX_VIDEO_CONFIG_DEINTERLACE);
+    m_sConfigDeinterlace.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
+    m_sConfigDeinterlace.nEnable = OMX_FALSE;
+
     m_state                   = OMX_StateLoaded;
     m_sExtraData = 0;
 
@@ -1453,6 +1457,17 @@
                 memcpy(&m_sConfigAVCIDRPeriod, pParam, sizeof(m_sConfigAVCIDRPeriod));
                 break;
             }
+        case OMX_IndexConfigCommonDeinterlace:
+            {
+                OMX_VIDEO_CONFIG_DEINTERLACE *pParam = (OMX_VIDEO_CONFIG_DEINTERLACE*) configData;
+                DEBUG_PRINT_LOW("set_config: OMX_IndexConfigCommonDeinterlace");
+                if (!handle->venc_set_config(pParam, (OMX_INDEXTYPE)OMX_IndexConfigCommonDeinterlace)) {
+                    DEBUG_PRINT_ERROR("ERROR: Setting OMX_IndexConfigCommonDeinterlace failed");
+                    return OMX_ErrorUnsupportedSetting;
+                }
+                memcpy(&m_sConfigDeinterlace, pParam, sizeof(m_sConfigDeinterlace));
+                break;
+            }
         default:
             DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
             break;
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 d8930cb..f4bfacd 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
@@ -1428,7 +1428,10 @@
                 OMX_CONFIG_ROTATIONTYPE *config_rotation =
                     reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData);
                 OMX_U32 nFrameWidth;
-
+                if (true == deinterlace_enabled) {
+                    DEBUG_PRINT_ERROR("\nERROR: Rotation is not supported with deinterlacing\n");
+                    return false;
+                }
                 DEBUG_PRINT_HIGH("\nvenc_set_config: updating the new Dims");
                 nFrameWidth = m_sVenc_cfg.dvs_width;
                 m_sVenc_cfg.dvs_width  = m_sVenc_cfg.dvs_height;
@@ -1452,7 +1455,26 @@
                             "OMX_IndexConfigVideoAVCIntraPeriod failed");
                     return false;
                 }
-
+                break;
+            }
+        case OMX_IndexConfigCommonDeinterlace:
+            {
+                OMX_VIDEO_CONFIG_DEINTERLACE *deinterlace = (OMX_VIDEO_CONFIG_DEINTERLACE *) configData;
+                DEBUG_PRINT_LOW("\n venc_set_config: OMX_IndexConfigCommonDeinterlace");
+                if(deinterlace->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
+                    if (m_sVenc_cfg.dvs_width == m_sVenc_cfg.input_height &&
+                        m_sVenc_cfg.dvs_height == m_sVenc_cfg.input_width)
+                    {
+                        DEBUG_PRINT_ERROR("\nERROR: Deinterlace not supported with rotation");
+                        return false;
+                    }
+                    if(venc_set_deinterlace(deinterlace->nEnable) == false) {
+                        DEBUG_PRINT_ERROR("\nERROR: Setting Deinterlace failed");
+                        return false;
+                    }
+                } else {
+                DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexConfigCommonDeinterlace");
+                }
                 break;
             }
         default:
@@ -3039,6 +3061,28 @@
     return true;
 }
 
+bool venc_dev::venc_set_deinterlace(OMX_U32 enable)
+{
+    DEBUG_PRINT_LOW("\n venc_set_deinterlace: enable = %lu", enable);
+    struct v4l2_control control;
+    int rc;
+    control.id = V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE;
+    if (enable)
+        control.value = V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_ENABLED;
+    else
+        control.value = V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_ENABLED;
+
+    DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d\n", control.id, control.value);
+    rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
+    if (rc) {
+        DEBUG_PRINT_ERROR("Failed to set Deinterlcing control\n");
+        return false;
+    }
+    DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, value=%d\n", control.id, control.value);
+    deinterlace_enabled = true;
+    return true;
+}
+
 bool venc_dev::venc_set_vpe_rotation(OMX_S32 rotation_angle)
 {
     DEBUG_PRINT_LOW("\n venc_set_vpe_rotation: rotation angle = %ld", rotation_angle);