Remove low-res frame ISP padding with software crop
authorJussi Saavalainen <jussi.saavalainen@ixonos.com>
Fri, 1 Feb 2013 12:26:27 +0000 (14:26 +0200)
committerJussi Saavalainen <jussi.saavalainen@ixonos.com>
Fri, 1 Feb 2013 12:32:54 +0000 (14:32 +0200)
The ISP silently inserts padding up to next multiple of 32
horizontal pixels, so handle this by cropping the extras off
the buffer. Limit this to NV12 and width <320 for now.

Change-Id: I09e87a5fcbf78140170ae7fcde5006ca98f005f9

gst/mfldv4l2cam/gstv4l2camsrc.c
gst/mfldv4l2cam/gstv4l2camsrc.h
gst/mfldv4l2cam/v4l2camsrc_calls.c
packaging/gst-plugins-atomisp.changes

index e60e504..dcdee0e 100644 (file)
@@ -128,6 +128,7 @@ typedef enum
   PROP_DUMP_RAW,
   PROP_DUMP_IMAGE,
   PROP_DEBUG_FLAGS,
+  PROP_DISABLE_LOW_RES_CROP,
 } GstV4L2CamSrcProperties;
 
 
@@ -750,6 +751,7 @@ gboolean gst_v4l2camsrc_write_settings (GstCameraSrc * camsrc,
     GstPhotoSettings * photoconf, gboolean scene_override);
 gboolean
 gst_v4l2camsrc_set_flash_mode (GstCameraSrc *camsrc, int value);
+gboolean
 gst_v4l2camsrc_read_exif (GstCameraSrc *camsrc, 
     GstCameraControlExifInfo *exif_info);
 gboolean
@@ -968,6 +970,12 @@ gst_v4l2camsrc_class_init (GstMFLDV4l2CamSrcClass * klass)
           "Horisontal flip", FALSE,
           G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
+  g_object_class_install_property (gobject_class,
+      PROP_DISABLE_LOW_RES_CROP,
+      g_param_spec_boolean ("disable-low-res-crop", "disable low resolution crop",
+          "disable software crop on unsupported low resolution frame size", FALSE,
+          G_PARAM_READWRITE));
+
   camera_class->is_open = GST_DEBUG_FUNCPTR (gst_v4l2camsrc_is_open);
   camera_class->open = GST_DEBUG_FUNCPTR (gst_v4l2camsrc_open);
   camera_class->close = GST_DEBUG_FUNCPTR (gst_v4l2camsrc_close);
@@ -1120,6 +1128,7 @@ gst_v4l2camsrc_init (GstMFLDV4l2CamSrc * v4l2camsrc,
   v4l2camsrc->dump_image = FALSE;
   v4l2camsrc->raw_output_size = 0;
   v4l2camsrc->debug_flags = DEFAULT_DEBUG_FLAGS;
+  v4l2camsrc->disable_low_res_crop = FALSE;
 
   v4l2camsrc->device_mutex = g_mutex_new ();
 
@@ -1503,6 +1512,9 @@ gst_v4l2camsrc_set_property (GObject * object,
     case PROP_DEBUG_FLAGS:
       v4l2camsrc->debug_flags = g_value_get_flags (value);
       break;
+    case PROP_DISABLE_LOW_RES_CROP:
+      v4l2camsrc->disable_low_res_crop = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1679,6 +1691,9 @@ gst_v4l2camsrc_get_property (GObject * object,
     case PROP_DEBUG_FLAGS:
       g_value_set_flags (value, v4l2camsrc->debug_flags);
       break;
+    case PROP_DISABLE_LOW_RES_CROP:
+      g_value_set_boolean (value, v4l2camsrc->disable_low_res_crop);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
index 61c978b..5108e04 100644 (file)
@@ -248,8 +248,9 @@ struct _GstMFLDV4l2CamSrc {
   guint32 vf_fourcc;
 
   guint capture_w, capture_h;
+  guint32 expected_capture_w, expected_capture_h;
   guint capture_fps_n, capture_fps_d;
-  guint32 capture_fourcc;
+  guint32 capture_fourcc, expected_capture_fourcc;
 
   struct v4l2_capability vcap;  /* the video device's capabilities */
   struct v4l2_cropcap vcrop;    /* cropping & scaling capabilities */
@@ -296,6 +297,8 @@ struct _GstMFLDV4l2CamSrc {
   GstCameraInputSensor input_sensor;
   gboolean dump_image;
   GstCameraSrcDebugFlags debug_flags;
+
+  gboolean disable_low_res_crop;
 };
 
 
index 8fc5cfe..55fe886 100644 (file)
@@ -2027,6 +2027,47 @@ default_frame_sizes:
   return ret;
 }
 
+/* Crop to upper left corner of NV12 frame. */
+static gboolean crop_buffer_inplace_nv12(unsigned char *buf, unsigned in_w, unsigned in_h,
+                               unsigned out_w, unsigned out_h)
+{
+       unsigned rows;
+       unsigned char *in, *out;
+
+       if(in_w < out_w || in_h < out_h
+               || in_w % 4 || out_w % 4
+               || in_h % 4 || out_h % 4)
+               return FALSE;
+
+       in = buf; out = buf;
+       for(rows = 0; rows < out_h; ++rows) {
+               memmove(out, in, out_w);
+               in += in_w;
+               out += out_w;
+       }
+       in = buf + in_w * in_h;
+       for(rows = 0; rows < out_h / 2; ++rows) {
+               memmove(out, in, out_w);
+               in += in_w;
+               out += out_w;
+       }
+#if 0
+       /* B/W Marker to top left corner */
+#define put_dot(x,y,c) buf[(y)*out_w+x] = c
+       put_dot(0,0,0xff); put_dot(1,0,0x00); put_dot(2,0,0xff); put_dot(3,0,0x00); put_dot(4,0,0xff); put_dot(5,0,0x00); put_dot(6,0,0xff); put_dot(7,0,0x00);
+       put_dot(0,1,0x00); put_dot(1,1,0xff); put_dot(2,1,0x00); put_dot(3,1,0xff); put_dot(4,1,0x00); put_dot(5,1,0xff); put_dot(6,1,0x00); put_dot(7,1,0xff);
+       put_dot(0,2,0xff); put_dot(1,2,0x00);
+       put_dot(0,3,0x00); put_dot(1,3,0xff);
+       put_dot(0,4,0xff); put_dot(1,4,0x00);
+       put_dot(0,5,0x00); put_dot(1,5,0xff);
+       put_dot(0,6,0xff); put_dot(1,6,0x00);
+       put_dot(0,7,0x00); put_dot(1,7,0xff);
+#undef put_dot
+#endif
+
+       return TRUE;
+}
+
 /**
  * gst_v4l2camsrc_libmfld_grab_hq_frame:
  * @v4l2camsrc: #GstMFLDV4l2CamSrc object
@@ -2080,6 +2121,7 @@ gst_v4l2camsrc_grab_frame (GstCameraSrc * camsrc, GstBuffer ** buf,
   gboolean variable_frame_size = FALSE;  /* FIXME if we ever support JPEG etc */
   gint index;
   gint ret;
+  unsigned real_w;
 
   /* wait if all buffers are DQBuf */
   g_mutex_lock (v4l2camsrc->device_mutex);
@@ -2230,6 +2272,24 @@ gst_v4l2camsrc_grab_frame (GstCameraSrc * camsrc, GstBuffer ** buf,
   v4l2camsrc->pool->num_live_buffers++;
   v4l2camsrc->pool->queued[index] = 0;
 
+  /* SW workaround for ISP padding. */
+
+  if(v4l2camsrc->expected_capture_w < 320 && (v4l2camsrc->expected_capture_w % 32 != 0)
+      && v4l2camsrc->expected_capture_fourcc == V4L2_PIX_FMT_NV12
+      && !v4l2camsrc->disable_low_res_crop) {
+
+    real_w = (v4l2camsrc->expected_capture_w & ~31) + 32;
+
+    GST_LOG_OBJECT(v4l2camsrc, "Downscaling padded buffer with cropping (%u,%u) -> (%u,%u)",
+      real_w, v4l2camsrc->expected_capture_h, v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h);
+
+    if(!crop_buffer_inplace_nv12(GST_BUFFER_DATA(pool_buffer),
+        real_w, v4l2camsrc->expected_capture_h,
+        v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h)) {
+      GST_ERROR_OBJECT(v4l2camsrc,"Software crop failed");
+    }
+  }
+
   g_mutex_unlock (v4l2camsrc->pool->lock);
 
   /* this can change at every frame, esp. with jpeg */
@@ -2388,6 +2448,10 @@ gst_v4l2camsrc_set_capture (GstCameraSrc * camsrc, GstOperationMode mode,
 
   GST_DEBUG_OBJECT (v4l2camsrc, "mode = %d, try_only = %d", mode, try_only);
 
+  v4l2camsrc->expected_capture_w = *width;
+  v4l2camsrc->expected_capture_h = *height;
+  v4l2camsrc->expected_capture_fourcc = *pixelformat;
+
   if (mode == GST_PHOTOGRAPHY_OPERATION_MODE_PREVIEW) {
     return FALSE;
   } else if (mode == GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE) {
index b88ae0f..e1e9129 100644 (file)
@@ -1,3 +1,6 @@
+* Fri Feb 01 2013 Jussi Saavalainen <jussi.saavalainen@ixonos.com> accepted/tizen_2.0/20130128.180320@3e02944
+- Remove low-res frame ISP padding with software crop. TZSP-4269
+
 * Wed Jan 30 2013 Telle-Tiia Pitkänen <telle-tiia.pitkanen@ixonos.com> submit/tizen_2.0/20130128.132122@0e78adb
 - Rename package to gst-plugins-atomisp