mm-video: vidc: Adds support for extradata

Adds support for frame rate, recovery point
sei, conceal mb, panscan window and time stamp
extradata types.

Change-Id: Ie86084476978b267d62d97c513a7978c6c655f07
Signed-off-by: Praneeth Paladugu <ppaladug@codeaurora.org>
diff --git a/mm-video/vidc/vdec/src/omx_vdec_msm8974.cpp b/mm-video/vidc/vdec/src/omx_vdec_msm8974.cpp
index bfea061..faf85a9 100644
--- a/mm-video/vidc/vdec/src/omx_vdec_msm8974.cpp
+++ b/mm-video/vidc/vdec/src/omx_vdec_msm8974.cpp
@@ -131,14 +131,6 @@
 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power);  num = q >> power; den = 0x1 << (16 - power); }
 #define EXTRADATA_IDX(__num_planes) (__num_planes  - 1)
 
-typedef enum INTERLACE_TYPE {
-  INTERLACE_FRAME_PROGRESSIVE = 0x01,
-  INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST = 0x02,
-  INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST = 0x04,
-  INTERLACE_FRAME_TOPFIELDFIRST = 0x08,
-  INTERLACE_FRAME_BOTTOMFIELDFIRST = 0x10,
-};
-
 #define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA)
 void* async_message_thread (void *input)
 {
@@ -6918,7 +6910,17 @@
         output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
 	// output_respbuf->time_stamp = vdec_msg->msgdata.output_frame.time_stamp;
 	// output_respbuf->flags = vdec_msg->msgdata.output_frame.flags;
-	// output_respbuf->pic_type = vdec_msg->msgdata.output_frame.pic_type;
+        if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME)
+        {
+          output_respbuf->pic_type = PICTURE_TYPE_I;
+        }
+        if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME)
+        {
+          output_respbuf->pic_type = PICTURE_TYPE_P;
+        }
+        if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
+          output_respbuf->pic_type = PICTURE_TYPE_B;
+        }
 	// output_respbuf->interlaced_format = vdec_msg->msgdata.output_frame.interlaced_format;
 
         if (omx->output_use_buffer)
@@ -8279,30 +8281,14 @@
 
 void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
 {
-  struct extradata_interlace_video_payload {
-    OMX_U32 format;
-  };
-
-  typedef enum DRIVER_EXTRADATA_TYPE {
-    EXTRADATA_NONE = 0x00000000,
-    EXTRADATA_MB_QUANTIZATION = 0x00000001,
-    EXTRADATA_INTERLACE_VIDEO = 0x00000002,
-    EXTRADATA_VC1_FRAMEDISP = 0x00000003,
-    EXTRADATA_VC1_SEQDISP = 0x00000004,
-    EXTRADATA_TIMESTAMP = 0x00000005,
-    EXTRADATA_S3D_FRAME_PACKING = 0x00000006,
-    EXTRADATA_EOSNAL_DETECTED = 0x00000007,
-    EXTRADATA_MULTISLICE_INFO = 0x7F100000,
-    EXTRADATA_NUM_CONCEALED_MB = 0x7F100001,
-    EXTRADATA_INDEX = 0x7F100002,
-    EXTRADATA_METADATA_FILLER = 0x7FE00002,
-  };
   OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL;
   OMX_U32 num_conceal_MB = 0;
-  OMX_S64 ts_in_sei = 0;
   OMX_U32 frame_rate = 0;
   OMX_U32 consumed_len = 0;
+  OMX_U32 num_MB_in_frame;
+  OMX_U32 recovery_sei_flags = 1;
   int buf_index = p_buf_hdr - m_out_mem_ptr;
+  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) {
     return;
@@ -8313,7 +8299,6 @@
   if ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))
     p_extra = NULL;
   OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
-
   if (data) {
     while((consumed_len < drv_ctx.extradata_info.buffer_size)
         && (data->eType != EXTRADATA_NONE)) {
@@ -8323,11 +8308,18 @@
       }
       switch(data->eType) {
       case EXTRADATA_INTERLACE_VIDEO:
-        struct extradata_interlace_video_payload *payload;
-        payload = (struct extradata_interlace_video_payload *)data->data;
+        struct msm_vidc_interlace_payload *payload;
+        payload = (struct msm_vidc_interlace_payload *)data->data;
         if (payload->format != INTERLACE_FRAME_PROGRESSIVE) {
           int enable = 1;
-          setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
+          OMX_U32 mbaff = 0;
+          mbaff = (h264_parser)? (h264_parser->is_mbaff()): false;
+          if ((payload->format == INTERLACE_FRAME_PROGRESSIVE)  && !mbaff)
+            drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
+          else
+            drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
+          if(m_enable_android_native_buffers)
+            setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
               PP_PARAM_INTERLACED, (void*)&enable);
         }
         if (!secure_mode && (client_extradata & OMX_INTERLACE_EXTRADATA)) {
@@ -8335,12 +8327,46 @@
           p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
         }
         break;
+      case EXTRADATA_FRAME_RATE:
+        struct msm_vidc_framerate_payload *frame_rate_payload;
+        frame_rate_payload = (struct msm_vidc_framerate_payload *)data->data;
+        frame_rate = frame_rate_payload->frame_rate;
+      break;
+      case EXTRADATA_TIMESTAMP:
+        struct msm_vidc_ts_payload *time_stamp_payload;
+        time_stamp_payload = (struct msm_vidc_ts_payload *)data->data;
+      break;
+      case EXTRADATA_NUM_CONCEALED_MB:
+        struct msm_vidc_concealmb_payload *conceal_mb_payload;
+        conceal_mb_payload = (struct msm_vidc_concealmb_payload *)data->data;
+        num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
+                     (drv_ctx.video_resolution.frame_height + 15)) >> 8;
+        num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
+      break;
+      case EXTRADATA_RECOVERY_POINT_SEI:
+        struct msm_vidc_recoverysei_payload *recovery_sei_payload;
+        recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)data->data;
+        recovery_sei_flags = recovery_sei_payload->flags;
+       if (recovery_sei_flags != FRAME_RECONSTRUCTION_CORRECT) {
+        p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
+        DEBUG_PRINT_HIGH("***************************************************\n");
+        DEBUG_PRINT_HIGH("Extradata: OMX_BUFFERFLAG_DATACORRUPT Received\n");
+        DEBUG_PRINT_HIGH("***************************************************\n");
+       }
+      break;
+      case EXTRADATA_PANSCAN_WINDOW:
+        panscan_payload = (struct msm_vidc_panscan_window_payload *)data->data;
+        break;
       default:
         goto unrecognized_extradata;
       }
       consumed_len += data->nSize;
       data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
     }
+    if (!secure_mode && (client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
+      append_frame_info_extradata(p_extra,
+        num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
+        panscan_payload);}
   }
 unrecognized_extradata:
   if(!secure_mode && client_extradata)
@@ -8376,6 +8402,35 @@
         DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
             " Quality of interlaced clips might be impacted.\n");
       }
+    } else 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)) {
+        DEBUG_PRINT_HIGH("Failed to set framerate extradata\n");
+      }
+      control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+      control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
+      if(ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+        DEBUG_PRINT_HIGH("Failed to set concealed MB extradata\n");
+      }
+      control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+      control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
+      if(ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+        DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata\n");
+      }
+      control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+      control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
+      if(ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+        DEBUG_PRINT_HIGH("Failed to set panscan extradata\n");
+      }
+    } else 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\n");
+      }
     }
   }
   return ret;
@@ -8511,10 +8566,14 @@
 
 
 void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
-    OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_S64 timestamp, OMX_U32 frame_rate,
-	vdec_aspectratioinfo *aspect_ratio_info)
+    OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate,
+        struct msm_vidc_panscan_window_payload *panscan_payload)
 {
   OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
+  struct msm_vidc_panscan_window *panscan_window;
+  if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
+        return;
+  }
   extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
   extra->nVersion.nVersion = OMX_SPEC_VERSION;
   extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
@@ -8541,15 +8600,22 @@
     frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
   else
     frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
-  memset(&frame_info->panScan,0,sizeof(frame_info->panScan));
   memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
-  if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264)
-  {
-    h264_parser->fill_pan_scan_data(&frame_info->panScan, timestamp);
-    h264_parser->fill_aspect_ratio_info(&frame_info->aspectRatio);
-  }
   frame_info->nConcealedMacroblocks = num_conceal_mb;
   frame_info->nFrameRate = frame_rate;
+  frame_info->panScan.numWindows = 0;
+  if(panscan_payload) {
+  frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
+  panscan_window = &panscan_payload->wnd[0];
+  for (int i = 0; i < frame_info->panScan.numWindows; i++)
+    {
+      frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
+      frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
+      frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
+      frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
+      panscan_window++;
+    }
+  }
   print_debug_extradata(extra);
 }