PROP_DUMP_RAW,
PROP_DUMP_IMAGE,
PROP_DEBUG_FLAGS,
+ PROP_DISABLE_LOW_RES_CROP,
} GstV4L2CamSrcProperties;
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
"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);
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 ();
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;
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;
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
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);
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 */
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) {