From fe0421979380fd6306b2081d5d6985741e8d3d63 Mon Sep 17 00:00:00 2001 From: Jussi Saavalainen Date: Fri, 1 Feb 2013 14:26:27 +0200 Subject: [PATCH] Remove low-res frame ISP padding with software crop 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 | 15 ++++++++ gst/mfldv4l2cam/gstv4l2camsrc.h | 5 ++- gst/mfldv4l2cam/v4l2camsrc_calls.c | 64 +++++++++++++++++++++++++++++++++++ packaging/gst-plugins-atomisp.changes | 3 ++ 4 files changed, 86 insertions(+), 1 deletion(-) diff --git a/gst/mfldv4l2cam/gstv4l2camsrc.c b/gst/mfldv4l2cam/gstv4l2camsrc.c index e60e504..dcdee0e 100644 --- a/gst/mfldv4l2cam/gstv4l2camsrc.c +++ b/gst/mfldv4l2cam/gstv4l2camsrc.c @@ -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; diff --git a/gst/mfldv4l2cam/gstv4l2camsrc.h b/gst/mfldv4l2cam/gstv4l2camsrc.h index 61c978b..5108e04 100644 --- a/gst/mfldv4l2cam/gstv4l2camsrc.h +++ b/gst/mfldv4l2cam/gstv4l2camsrc.h @@ -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; }; diff --git a/gst/mfldv4l2cam/v4l2camsrc_calls.c b/gst/mfldv4l2cam/v4l2camsrc_calls.c index 8fc5cfe..55fe886 100644 --- a/gst/mfldv4l2cam/v4l2camsrc_calls.c +++ b/gst/mfldv4l2cam/v4l2camsrc_calls.c @@ -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) { diff --git a/packaging/gst-plugins-atomisp.changes b/packaging/gst-plugins-atomisp.changes index b88ae0f..e1e9129 100644 --- a/packaging/gst-plugins-atomisp.changes +++ b/packaging/gst-plugins-atomisp.changes @@ -1,3 +1,6 @@ +* Fri Feb 01 2013 Jussi Saavalainen 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 submit/tizen_2.0/20130128.132122@0e78adb - Rename package to gst-plugins-atomisp -- 2.7.4