summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2009-10-14 17:58:45 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2009-10-14 17:59:29 +0200
commit804a6aab4ff4ecee28bb962bcda2f5a16fd24c5f (patch)
tree734a1ab4d60a969ead4710b4f8562e45f1ba180c
parentad87141865d28ab74514f6da1ce244755a890022 (diff)
v4l2src: various changesste-good-0.10.16
Use custom buffers for output. Add properties for color balance and other effects.
-rw-r--r--sys/v4l2/gstv4l2bufferpool.c63
-rw-r--r--sys/v4l2/gstv4l2bufferpool.h3
-rw-r--r--sys/v4l2/gstv4l2object.c8
-rw-r--r--sys/v4l2/gstv4l2src.c311
-rw-r--r--sys/v4l2/gstv4l2src.h18
-rw-r--r--sys/v4l2/gstv4l2xoverlay.h19
-rw-r--r--sys/v4l2/v4l2src_calls.c508
-rw-r--r--sys/v4l2/v4l2src_calls.h13
8 files changed, 918 insertions, 25 deletions
diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c
index 494f46d73..7c2094ce7 100644
--- a/sys/v4l2/gstv4l2bufferpool.c
+++ b/sys/v4l2/gstv4l2bufferpool.c
@@ -35,7 +35,7 @@
#include "gstv4l2sink.h"
#include "v4l2_calls.h"
#include "gst/gst-i18n-plugin.h"
-
+#include "gsticbvideo.h"
GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
#define GST_CAT_DEFAULT v4l2_debug
@@ -53,6 +53,7 @@ gst_v4l2_buffer_finalize (GstV4l2Buffer * buffer)
GstV4l2BufferPool *pool;
gboolean resuscitated = FALSE;
gint index;
+ gboolean need_copy = FALSE;
pool = buffer->pool;
@@ -82,8 +83,10 @@ gst_v4l2_buffer_finalize (GstV4l2Buffer * buffer)
if (resuscitated) {
/* FIXME: check that the caps didn't change */
- GST_LOG_OBJECT (pool->v4l2elem, "reviving buffer %p, %d", buffer, index);
- gst_buffer_ref (GST_BUFFER (buffer));
+ GST_LOG ("reviving buffer %p, %d", buffer, index);
+ if (G_UNLIKELY (need_copy))
+ gst_buffer_ref (GST_BUFFER (buffer));
+
GST_BUFFER_SIZE (buffer) = 0;
pool->buffers[index] = buffer;
}
@@ -94,13 +97,20 @@ gst_v4l2_buffer_finalize (GstV4l2Buffer * buffer)
GST_LOG_OBJECT (pool->v4l2elem, "buffer %p not recovered, unmapping",
buffer);
gst_mini_object_unref (GST_MINI_OBJECT (pool));
- v4l2_munmap ((void *) GST_BUFFER_DATA (buffer), buffer->vbuffer.length);
GST_MINI_OBJECT_CLASS (v4l2buffer_parent_class)->finalize (GST_MINI_OBJECT
(buffer));
}
}
+
+static void
+gst_icb_v4l2_buffer_finalize (GstICBVideoBuffer * buffer)
+{
+ gst_v4l2_buffer_finalize ((GstV4l2Buffer *) buffer->ctx);
+}
+
+
static void
gst_v4l2_buffer_class_init (gpointer g_class, gpointer class_data)
{
@@ -169,12 +179,14 @@ gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
GST_LOG_OBJECT (pool->v4l2elem, " length: %u", ret->vbuffer.length);
GST_LOG_OBJECT (pool->v4l2elem, " input: %u", ret->vbuffer.input);
- data = (guint8 *) v4l2_mmap (0, ret->vbuffer.length,
- PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
- ret->vbuffer.m.offset);
-
if (data == MAP_FAILED)
- goto mmap_failed;
+ /* get data from memory pool (this pool was previously reserved & mmap at gst_v4l2src_capture_init execution */
+ if (pool->memory == NULL)
+
+ if (data == MAP_FAILED)
+ goto mmap_failed;
+
+ data = (guint8 *) pool->memory + ret->vbuffer.index * ret->vbuffer.length;
GST_BUFFER_DATA (ret) = data;
GST_BUFFER_SIZE (ret) = ret->vbuffer.length;
@@ -316,6 +328,7 @@ gst_v4l2_buffer_pool_new (GstElement * v4l2elem, gint fd, gint num_buffers,
{
GstV4l2BufferPool *pool;
gint n;
+ gint pmem_fd = 0;
struct v4l2_requestbuffers breq;
pool = (GstV4l2BufferPool *) gst_mini_object_new (GST_TYPE_V4L2_BUFFER_POOL);
@@ -344,6 +357,16 @@ gst_v4l2_buffer_pool_new (GstElement * v4l2elem, gint fd, gint num_buffers,
if (breq.count < GST_V4L2_MIN_BUFFERS)
goto no_buffers;
+ /* the memory pool is reserved by pmem allocator */
+ pmem_fd = (int) breq.reserved[0]; /* pmem file descriptor */
+ pool->memorySize = (int) breq.reserved[1]; /* pmem memory size */
+ pool->memory =
+ (guint8 *) v4l2_mmap (0, pool->memorySize, PROT_READ | PROT_WRITE,
+ MAP_SHARED, pmem_fd, (off_t) 0);
+
+ if (pool->memory == NULL)
+ goto buffer_new_failed;
+
if (num_buffers != breq.count) {
GST_WARNING_OBJECT (v4l2elem, "using %u buffers instead", breq.count);
num_buffers = breq.count;
@@ -359,6 +382,7 @@ gst_v4l2_buffer_pool_new (GstElement * v4l2elem, gint fd, gint num_buffers,
/* now, map the buffers: */
for (n = 0; n < num_buffers; n++) {
pool->buffers[n] = gst_v4l2_buffer_new (pool, n, caps);
+
if (!pool->buffers[n])
goto buffer_new_failed;
pool->num_live_buffers++;
@@ -421,6 +445,10 @@ gst_v4l2_buffer_pool_destroy (GstV4l2BufferPool * pool)
GST_DEBUG_OBJECT (pool->v4l2elem, "destroy pool");
+ v4l2_munmap ((void *) pool->memory, pool->memorySize);
+ pool->memorySize = 0;
+ pool->memory = NULL;
+
/* after this point, no more buffers will be queued or dequeued; no buffer
* from pool->buffers that is NULL will be set to a buffer, and no buffer that
* is not NULL will be pushed out. */
@@ -495,10 +523,13 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool)
GstV4l2Object *v4l2object = get_v4l2_object (pool->v4l2elem);
GstV4l2Buffer *pool_buffer;
struct v4l2_buffer buffer;
+ video_frame_t frame = VIDEO_FRAME_INIT;
+ gint index;
memset (&buffer, 0x00, sizeof (buffer));
buffer.type = pool->type;
buffer.memory = V4L2_MEMORY_MMAP;
+ buffer.m.userptr = (unsigned long) &frame;
if (v4l2_ioctl (pool->video_fd, VIDIOC_DQBUF, &buffer) >= 0) {
@@ -508,7 +539,15 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool)
/* get our GstBuffer with that index from the pool, if the buffer was
* outstanding we have a serious problem.
*/
- pool_buffer = pool->buffers[buffer.index];
+ index = buffer.index;
+ frame.image.semiplanar.a.vbase_address =
+ GST_BUFFER_DATA (pool->buffers[index]);
+ pool_buffer =
+ gst_icbvideo_buffer_new (&frame, gst_icb_v4l2_buffer_finalize,
+ pool->buffers[index]);
+
+ gst_buffer_set_caps (GST_BUFFER (pool_buffer),
+ GST_BUFFER_CAPS (pool->buffers[index]));
if (pool_buffer == NULL) {
GST_ELEMENT_ERROR (pool->v4l2elem, RESOURCE, FAILED,
@@ -520,9 +559,9 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool)
}
GST_LOG_OBJECT (pool->v4l2elem,
- "grabbed frame %d (ix=%d), flags %08x, pool-ct=%d, buffer=%p",
+ "grabbed frame %d (ix=%d), flags %08x, pool-ct=%d, buffer=%p, data=%p",
buffer.sequence, buffer.index, buffer.flags, pool->num_live_buffers,
- pool_buffer);
+ pool_buffer, GST_BUFFER_DATA (pool_buffer));
pool->num_live_buffers++;
GST_DEBUG_OBJECT (pool->v4l2elem, "num_live_buffers++: %d",
diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h
index 36a42208c..3966b5856 100644
--- a/sys/v4l2/gstv4l2bufferpool.h
+++ b/sys/v4l2/gstv4l2bufferpool.h
@@ -64,6 +64,9 @@ struct _GstV4l2BufferPool
gint video_fd; /* a dup(2) of the v4l2object's video_fd */
guint buffer_count;
GstV4l2Buffer **buffers;
+
+ guint8* memory;
+ gint memorySize;
};
struct _GstV4l2Buffer {
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index f73ce2183..9aa2336d3 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -1200,13 +1200,13 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
break;
case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
fourcc = V4L2_PIX_FMT_NV12;
- outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
- outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
+ outsize = GST_ROUND_UP_16 (*w) * GST_ROUND_UP_16 (*h);
+ outsize += (GST_ROUND_UP_16 (*w) * *h) / 2;
break;
case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
fourcc = V4L2_PIX_FMT_NV21;
- outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
- outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
+ outsize = GST_ROUND_UP_16 (*w) * GST_ROUND_UP_16 (*h);
+ outsize += (GST_ROUND_UP_16 (*w) * *h) / 2;
break;
#ifdef V4L2_PIX_FMT_YVYU
case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c
index 463bef3a6..5b7fade38 100644
--- a/sys/v4l2/gstv4l2src.c
+++ b/sys/v4l2/gstv4l2src.c
@@ -79,7 +79,23 @@ enum
PROP_0,
V4L2_STD_OBJECT_PROPS,
PROP_QUEUE_SIZE,
- PROP_ALWAYS_COPY
+ PROP_ALWAYS_COPY,
+
+ /* additionnal properties for Stericsson sensors */
+ PROP_EFFECT,
+ PROP_HFLIP,
+ PROP_VFLIP,
+ PROP_BRIGHTNESS,
+ PROP_CONTRAST,
+ PROP_SATURATION,
+ PROP_ZOOM,
+ PROP_WB_MODE,
+ PROP_SCENE,
+ PROP_SENSITIVITY,
+ PROP_MET_EXP,
+ PROP_FOCUS_CTRL,
+ PROP_FOCUS_STATE,
+ PROP_FLICKER_MOD,
};
GST_IMPLEMENT_V4L2_PROBE_METHODS (GstV4l2SrcClass, gst_v4l2src);
@@ -221,6 +237,32 @@ gst_v4l2src_base_init (gpointer g_class)
gst_v4l2_object_get_all_caps ()));
}
+GType gst_v4l2src_effect_type = 0;
+const GEnumValue gst_icbvideo_v4l_effects[] = GST_ICB_EFFECT_LIST;
+#define DEFAULT_EFFECT 0 /* NO_FX */
+GType gst_v4l2src_wb_mode = 0;
+const GEnumValue gst_icbvideo_v4l_wb_mode[] = GST_ICB_WB_MODE_LIST;
+#define DEFAULT_WB_MODE 0 /* AUTO */
+GType gst_v4l2src_scene = 0;
+const GEnumValue gst_icbvideo_v4l_scene[] = GST_ICB_SCENE_LIST;
+#define DEFAULT_SCENE V4L2_CTRL_SCENE_AUTO
+GType gst_v4l2src_sensitivity = 0;
+const GEnumValue gst_icbvideo_v4l_sensitivity[] = GST_ICB_SENSITIVITY_LIST;
+#define DEFAULT_SENSITIVITY V4L2_CTRL_ISO_AUTO
+GType gst_v4l2src_metering_exposure = 0;
+const GEnumValue gst_icbvideo_v4l_metering_exposure[] = GST_ICB_MET_EXP_LIST;
+#define DEFAULT_MET_EXP V4L2_CTRL_MET_EXP_MATRIX
+GType gst_v4l2src_focus_ctrl = 0;
+const GEnumValue gst_icbvideo_v4l_focus_ctrl[] = GST_ICB_FOCUS_CTRL_LIST;
+#define DEFAULT_FOCUS_CTRL GST_ICB_FOCUS_CTRL_OFF
+GType gst_v4l2src_focus_state = 0;
+const GEnumValue gst_icbvideo_v4l_focus_state[] = GST_ICB_FOCUS_STATE_LIST;
+#define DEFAULT_FOCUS_STATE GST_ICB_FOCUS_STATE_NOT_FOCUSED
+GType gst_v4l2src_flicker_mod = 0;
+const GEnumValue gst_icbvideo_v4l_flicker_mod[] = GST_ICB_FLICKER_MOD_LIST;
+#define DEFAULT_FLICKER_MOD V4L2_CID_POWER_LINE_FREQUENCY_DISABLED
+
+
static void
gst_v4l2src_class_init (GstV4l2SrcClass * klass)
{
@@ -264,6 +306,126 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass)
basesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_v4l2src_negotiate);
pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_v4l2src_create);
+
+ /* additionnal properties for Stericsson sensors */
+ if (!gst_v4l2src_effect_type) {
+ gst_v4l2src_effect_type =
+ g_enum_register_static ("GstV4l2SrcEffects", gst_icbvideo_v4l_effects);
+ }
+
+ if (!gst_v4l2src_wb_mode) {
+
+ gst_v4l2src_wb_mode =
+ g_enum_register_static ("GstV4l2SrcWhiteBalanceMode",
+ gst_icbvideo_v4l_wb_mode);
+ }
+
+ if (!gst_v4l2src_scene) {
+
+ gst_v4l2src_scene =
+ g_enum_register_static ("GstV4l2SrcScene", gst_icbvideo_v4l_scene);
+ }
+
+ if (!gst_v4l2src_sensitivity) {
+
+ gst_v4l2src_sensitivity =
+ g_enum_register_static ("GstV4l2SrcSensitivity",
+ gst_icbvideo_v4l_sensitivity);
+ }
+
+ if (!gst_v4l2src_metering_exposure) {
+
+ gst_v4l2src_metering_exposure =
+ g_enum_register_static ("GstV4l2SrcMeteringExposure",
+ gst_icbvideo_v4l_metering_exposure);
+ }
+
+ if (!gst_v4l2src_focus_ctrl) {
+
+ gst_v4l2src_focus_ctrl =
+ g_enum_register_static ("GstV4l2SrcFocusCtrl",
+ gst_icbvideo_v4l_focus_ctrl);
+ }
+
+ if (!gst_v4l2src_focus_state) {
+
+ gst_v4l2src_focus_state =
+ g_enum_register_static ("GstV4l2SrcFocusState",
+ gst_icbvideo_v4l_focus_state);
+ }
+
+
+ if (!gst_v4l2src_flicker_mod) {
+
+ gst_v4l2src_flicker_mod =
+ g_enum_register_static ("GstV4l2SrcFlickerMod",
+ gst_icbvideo_v4l_flicker_mod);
+ }
+
+ g_object_class_install_property (gobject_class, PROP_EFFECT,
+ g_param_spec_enum ("effect", "Effect", "Effect of the source",
+ gst_v4l2src_effect_type, DEFAULT_EFFECT, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_WB_MODE,
+ g_param_spec_enum ("wb", "White_balance_mode",
+ "White balancemode of the source", gst_v4l2src_wb_mode,
+ DEFAULT_WB_MODE, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_HFLIP,
+ g_param_spec_boolean ("hflip", "Horizontal Flip",
+ "Horizontal Flip : camera configuration", 0, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_VFLIP,
+ g_param_spec_boolean ("vflip", "Vertical Flip",
+ "Vertical Flip : camera configuration", 0, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
+ g_param_spec_int ("brightness", "Brightness",
+ "Brightness : camera configuration", GST_ICB_BRIGHTNESS_MIN,
+ GST_ICB_BRIGHTNESS_MAX, GST_ICB_BRIGHTNESS_DEFAULT,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_CONTRAST,
+ g_param_spec_int ("contrast", "Contrast",
+ "Contrast : camera configuration", GST_ICB_CONTRAST_MIN,
+ GST_ICB_CONTRAST_MAX, GST_ICB_CONTRAST_DEFAULT, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_SATURATION,
+ g_param_spec_int ("saturation", "Saturation",
+ "Saturation : camera configuration", GST_ICB_SATURATION_MIN,
+ GST_ICB_SATURATION_MAX, GST_ICB_SATURATION_DEFAULT,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_ZOOM,
+ g_param_spec_double ("zoom", "Zoom",
+ "Zoom : camera configuration", 1.0, 4.0, 1.0, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_SCENE,
+ g_param_spec_enum ("scene", "Scene", "Scene of the source",
+ gst_v4l2src_scene, DEFAULT_SCENE, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_SENSITIVITY,
+ g_param_spec_enum ("sensitivity", "Sensitivity",
+ "Sensitivity of the source", gst_v4l2src_sensitivity,
+ DEFAULT_SENSITIVITY, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_MET_EXP,
+ g_param_spec_enum ("metering_exposure", "Metering exposure",
+ "metering exposure mode", gst_v4l2src_metering_exposure,
+ DEFAULT_MET_EXP, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_FOCUS_CTRL,
+ g_param_spec_enum ("focus control", "Focus control", "Lens focus control",
+ gst_v4l2src_focus_ctrl, DEFAULT_FOCUS_CTRL, G_PARAM_WRITABLE));
+
+ g_object_class_install_property (gobject_class, PROP_FOCUS_STATE,
+ g_param_spec_enum ("focus state", "Focus state", "Lens focus state",
+ gst_v4l2src_focus_state, DEFAULT_FOCUS_STATE, G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_FLICKER_MOD,
+ g_param_spec_enum ("flicker mode", "Flicker mode", "Flicker mode",
+ gst_v4l2src_flicker_mod, DEFAULT_FLICKER_MOD, G_PARAM_READWRITE));
+
}
static void
@@ -286,6 +448,18 @@ gst_v4l2src_init (GstV4l2Src * v4l2src, GstV4l2SrcClass * klass)
v4l2src->fps_d = 0;
v4l2src->fps_n = 0;
+ v4l2src->hflip = FALSE;
+ v4l2src->hflip = FALSE;
+ v4l2src->brightness = GST_ICB_BRIGHTNESS_DEFAULT;
+ v4l2src->contrast = GST_ICB_CONTRAST_DEFAULT;
+ v4l2src->saturation = GST_ICB_SATURATION_DEFAULT;
+ v4l2src->zoom = 1.0;
+ v4l2src->effect = DEFAULT_EFFECT;
+ v4l2src->wb_mode = DEFAULT_WB_MODE;
+ v4l2src->scene = DEFAULT_SCENE;
+ v4l2src->sensitivity = DEFAULT_SENSITIVITY;
+ v4l2src->metering_exposure = DEFAULT_MET_EXP;
+
}
@@ -308,6 +482,20 @@ gst_v4l2src_finalize (GstV4l2Src * v4l2src)
gst_v4l2_object_destroy (v4l2src->v4l2object);
G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (v4l2src));
+
+}
+
+
+/* looks for the nick name from value ; return NULL if not found */
+char *
+gst_v4l2src_get_enum_nick_from_value (GEnumValue * table, gint value)
+{
+ while (table->value_nick != NULL) {
+ if (table->value == value)
+ return (char *) table->value_nick;
+ table++;
+ }
+ return NULL;
}
@@ -326,6 +514,62 @@ gst_v4l2src_set_property (GObject * object,
case PROP_ALWAYS_COPY:
v4l2src->always_copy = g_value_get_boolean (value);
break;
+ case PROP_EFFECT:
+ v4l2src->effect = g_value_get_enum (value);
+ gst_v4l2src_capture_set_effect (v4l2src,
+ gst_v4l2src_get_enum_nick_from_value ((GEnumValue *)
+ gst_icbvideo_v4l_effects, v4l2src->effect));
+ break;
+ case PROP_WB_MODE:
+ v4l2src->wb_mode = g_value_get_enum (value);
+ gst_v4l2src_capture_set_white_balance_mode (v4l2src,
+ gst_v4l2src_get_enum_nick_from_value ((GEnumValue *)
+ gst_icbvideo_v4l_wb_mode, v4l2src->wb_mode));
+ break;
+ case PROP_HFLIP:
+ v4l2src->hflip = g_value_get_boolean (value);
+ gst_v4l2src_capture_set_control (v4l2src, PROP_HFLIP);
+ break;
+ case PROP_VFLIP:
+ v4l2src->vflip = g_value_get_boolean (value);
+ gst_v4l2src_capture_set_control (v4l2src, PROP_VFLIP);
+ break;
+ case PROP_BRIGHTNESS:
+ v4l2src->brightness = g_value_get_int (value);
+ gst_v4l2src_capture_set_control (v4l2src, PROP_BRIGHTNESS);
+ break;
+ case PROP_CONTRAST:
+ v4l2src->contrast = g_value_get_int (value);
+ gst_v4l2src_capture_set_control (v4l2src, PROP_CONTRAST);
+ break;
+ case PROP_SATURATION:
+ v4l2src->saturation = g_value_get_int (value);
+ gst_v4l2src_capture_set_control (v4l2src, PROP_SATURATION);
+ break;
+ case PROP_ZOOM:
+ v4l2src->zoom = g_value_get_double (value);
+ gst_v4l2src_capture_set_zoom (v4l2src);
+ break;
+ case PROP_SCENE:
+ v4l2src->scene = g_value_get_enum (value);
+ gst_v4l2src_capture_set_control (v4l2src, PROP_SCENE);
+ break;
+ case PROP_SENSITIVITY:
+ v4l2src->sensitivity = g_value_get_enum (value);
+ gst_v4l2src_capture_set_control (v4l2src, PROP_SENSITIVITY);
+ break;
+ case PROP_MET_EXP:
+ v4l2src->metering_exposure = g_value_get_enum (value);
+ gst_v4l2src_capture_set_control (v4l2src, PROP_MET_EXP);
+ break;
+ case PROP_FOCUS_CTRL:
+ v4l2src->focus_ctrl = g_value_get_enum (value);
+ gst_v4l2src_capture_set_control (v4l2src, PROP_FOCUS_CTRL);
+ break;
+ case PROP_FLICKER_MOD:
+ v4l2src->flicker_mod = g_value_get_enum (value);
+ gst_v4l2src_capture_set_control (v4l2src, PROP_FLICKER_MOD);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -349,6 +593,55 @@ gst_v4l2src_get_property (GObject * object,
case PROP_ALWAYS_COPY:
g_value_set_boolean (value, v4l2src->always_copy);
break;
+ case PROP_EFFECT:
+ g_value_set_enum (value, v4l2src->effect);
+ break;
+ case PROP_WB_MODE:
+ g_value_set_enum (value, v4l2src->wb_mode);
+ break;
+ case PROP_HFLIP:
+ gst_v4l2src_capture_get_control (v4l2src, PROP_HFLIP);
+ g_value_set_boolean (value, v4l2src->hflip);
+ break;
+ case PROP_VFLIP:
+ gst_v4l2src_capture_get_control (v4l2src, PROP_VFLIP);
+ g_value_set_boolean (value, v4l2src->vflip);
+ break;
+ case PROP_BRIGHTNESS:
+ gst_v4l2src_capture_get_control (v4l2src, PROP_BRIGHTNESS);
+ g_value_set_int (value, v4l2src->brightness);
+ break;
+ case PROP_CONTRAST:
+ gst_v4l2src_capture_get_control (v4l2src, PROP_CONTRAST);
+ g_value_set_int (value, v4l2src->contrast);
+ break;
+ case PROP_SATURATION:
+ gst_v4l2src_capture_get_control (v4l2src, PROP_SATURATION);
+ g_value_set_int (value, v4l2src->saturation);
+ break;
+ case PROP_ZOOM:
+ g_value_set_double (value, v4l2src->zoom);
+ break;
+ case PROP_SCENE:
+ gst_v4l2src_capture_get_control (v4l2src, PROP_SCENE);
+ g_value_set_enum (value, v4l2src->scene);
+ break;
+ case PROP_SENSITIVITY:
+ gst_v4l2src_capture_get_control (v4l2src, PROP_SENSITIVITY);
+ g_value_set_enum (value, v4l2src->sensitivity);
+ break;
+ case PROP_MET_EXP:
+ gst_v4l2src_capture_get_control (v4l2src, PROP_MET_EXP);
+ g_value_set_enum (value, v4l2src->metering_exposure);
+ break;
+ case PROP_FOCUS_STATE:
+ gst_v4l2src_capture_get_control (v4l2src, PROP_FOCUS_STATE);
+ g_value_set_enum (value, v4l2src->focus_state);
+ break;
+ case PROP_FLICKER_MOD:
+ gst_v4l2src_capture_get_control (v4l2src, PROP_FLICKER_MOD);
+ g_value_set_enum (value, v4l2src->flicker_mod);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -617,6 +910,22 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
if (!gst_v4l2src_capture_init (v4l2src, caps))
return FALSE;
+ if (!gst_v4l2src_capture_set_all_controls (v4l2src))
+ return FALSE;
+
+ if (!gst_v4l2src_capture_set_effect (v4l2src,
+ gst_v4l2src_get_enum_nick_from_value ((GEnumValue *)
+ gst_icbvideo_v4l_effects, v4l2src->effect)))
+ return FALSE;
+
+ if (!gst_v4l2src_capture_set_white_balance_mode (v4l2src,
+ gst_v4l2src_get_enum_nick_from_value ((GEnumValue *)
+ gst_icbvideo_v4l_wb_mode, v4l2src->wb_mode)))
+ return FALSE;
+
+ if (!gst_v4l2src_capture_set_zoom (v4l2src))
+ return FALSE;
+
if (!gst_v4l2src_capture_start (v4l2src))
return FALSE;
diff --git a/sys/v4l2/gstv4l2src.h b/sys/v4l2/gstv4l2src.h
index fef3f108c..4e52dc3c3 100644
--- a/sys/v4l2/gstv4l2src.h
+++ b/sys/v4l2/gstv4l2src.h
@@ -26,6 +26,7 @@
#include <gstv4l2object.h>
#include <gstv4l2bufferpool.h>
+#include "gsticbvideo.h"
GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
@@ -80,6 +81,23 @@ struct _GstV4l2Src
guint64 offset;
gint fps_d, fps_n; /* framerate if device is open */
+ /* additionnal properties */
+ gboolean hflip; /* horizontal flip */
+ gboolean vflip; /* vertical flip */
+ gint brightness;
+ gint contrast;
+ gint saturation;
+ gdouble zoom;
+
+ GstIcbEffect effect; /* prop effect */
+ GstIcbWbMode wb_mode; /* prop white balance mode */
+ gint scene;
+ gint sensitivity;
+ gint metering_exposure;
+ gint flicker_mod;
+ gint focus_ctrl;
+ gint focus_state;
+ gint focus_step;
};
struct _GstV4l2SrcClass
diff --git a/sys/v4l2/gstv4l2xoverlay.h b/sys/v4l2/gstv4l2xoverlay.h
index 3d15ce90a..0185ebf2a 100644
--- a/sys/v4l2/gstv4l2xoverlay.h
+++ b/sys/v4l2/gstv4l2xoverlay.h
@@ -24,7 +24,11 @@
#ifndef __GST_V4L2_X_OVERLAY_H__
#define __GST_V4L2_X_OVERLAY_H__
+#define NO_X11 /* PLA hack */
+
+#ifndef NO_X11
#include <X11/X.h>
+#endif
#include <gst/gst.h>
#include <gst/interfaces/xoverlay.h>
@@ -37,6 +41,7 @@ void gst_v4l2_xoverlay_start (GstV4l2Object *v4l2object);
void gst_v4l2_xoverlay_stop (GstV4l2Object *v4l2object);
void gst_v4l2_xoverlay_interface_init (GstXOverlayClass * klass);
+#ifndef NO_X11
void gst_v4l2_xoverlay_set_xwindow_id (GstV4l2Object * v4l2object,
XID xwindow_id);
@@ -60,5 +65,19 @@ interface_as_function ## _xoverlay_interface_init (GstXOverlayClass * klass) \
gst_v4l2_xoverlay_interface_init(klass); \
} \
+#else
+
+#define GST_IMPLEMENT_V4L2_XOVERLAY_METHODS(Type, interface_as_function) \
+ \
+static void \
+interface_as_function ## _xoverlay_interface_init (GstXOverlayClass * klass) \
+{ \
+ /* default virtual functions */ \
+ klass->set_xwindow_id = interface_as_function ## _xoverlay_set_xwindow_id; \
+ \
+ gst_v4l2_xoverlay_interface_init(klass); \
+} \
+
+#endif /* NO_X11 */
#endif /* __GST_V4L2_X_OVERLAY_H__ */
diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c
index d8e365f9a..d87bdf4f1 100644
--- a/sys/v4l2/v4l2src_calls.c
+++ b/sys/v4l2/v4l2src_calls.c
@@ -44,12 +44,38 @@
#include "gstv4l2tuner.h"
#include "gstv4l2bufferpool.h"
+#include "gsticbvideo.h"
#include "gst/gst-i18n-plugin.h"
GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
#define GST_CAT_DEFAULT v4l2src_debug
+enum
+{
+ PROP_0,
+ V4L2_STD_OBJECT_PROPS,
+ PROP_QUEUE_SIZE,
+ PROP_ALWAYS_COPY,
+
+ /* additionnal properties for PNX sensors */
+ PROP_EFFECT,
+ PROP_HFLIP,
+ PROP_VFLIP,
+ PROP_BRIGHTNESS,
+ PROP_CONTRAST,
+ PROP_SATURATION,
+ PROP_ZOOM,
+ PROP_WB_MODE,
+ PROP_SCENE,
+ PROP_SENSITIVITY,
+ PROP_MET_EXP,
+ PROP_FOCUS_CTRL,
+ PROP_FOCUS_STATE,
+ PROP_FLICKER_MOD,
+};
+
+
/* lalala... */
#define GST_V4L2_SET_ACTIVE(element) (element)->buffer = GINT_TO_POINTER (-1)
#define GST_V4L2_SET_INACTIVE(element) (element)->buffer = NULL
@@ -125,6 +151,7 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
}
pool_buffer = GST_BUFFER (gst_v4l2_buffer_pool_dqbuf (pool));
+
if (pool_buffer)
break;
@@ -156,6 +183,8 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
need_copy = v4l2src->always_copy
|| !gst_v4l2_buffer_pool_available_buffers (pool);
+ need_copy = FALSE;
+
if (G_UNLIKELY (need_copy)) {
*buf = gst_buffer_copy (pool_buffer);
GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY);
@@ -226,14 +255,9 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat,
goto done;
}
- /* Note: V4L2 provides the frame interval, we have the frame rate */
- if (fractions_are_equal (stream.parm.capture.timeperframe.numerator,
- stream.parm.capture.timeperframe.denominator, fps_d, fps_n)) {
- GST_LOG_OBJECT (v4l2src, "Desired framerate already set");
- v4l2src->fps_n = fps_n;
- v4l2src->fps_d = fps_d;
- goto done;
- }
+ /* initialize default values */
+ v4l2src->fps_n = stream.parm.capture.timeperframe.numerator;
+ v4l2src->fps_d = stream.parm.capture.timeperframe.denominator;
/* We want to change the frame rate, so check whether we can. Some cheap USB
* cameras don't have the capability */
@@ -416,3 +440,471 @@ gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
return TRUE;
}
+
+/******************************************************
+ * gst_v4l2src_capture_set_all_controls():
+ * set control on capture device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_set_all_controls (GstV4l2Src * v4l2src)
+{
+ struct v4l2_control control;
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_DEBUG_OBJECT (v4l2src, "set controls on capture device");
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_HFLIP;
+ control.value = v4l2src->hflip;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_HFLIP");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_VFLIP;
+ control.value = v4l2src->vflip;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_VFLIP");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_SCENE;
+ control.value = v4l2src->scene;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SCENE");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_SENSITIVITY;
+ control.value = v4l2src->sensitivity;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SENSITIVITY");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_MET_EXP;
+ control.value = v4l2src->metering_exposure;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_MET_EXP");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_BRIGHTNESS;
+ control.value = v4l2src->brightness;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_BRIGHTNESS");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_CONTRAST;
+ control.value = v4l2src->contrast;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_CONTRAST");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_SATURATION;
+ control.value = v4l2src->saturation;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SATURATION");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_FOCUS_AUTO;
+ control.value = v4l2src->focus_ctrl;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_FOCUS_AUTO");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_POWER_LINE_FREQUENCY;
+ control.value = v4l2src->flicker_mod;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_POWER_LINE_FREQUENCY");
+ }
+
+ return TRUE;
+}
+
+/******************************************************
+ * gst_v4l2src_capture_set_control():
+ * set a specific control on capture device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_set_control (GstV4l2Src * v4l2src, guint prop_id)
+{
+ struct v4l2_control control;
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_DEBUG_OBJECT (v4l2src, "set control on capture device");
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+
+ switch (prop_id) {
+ case PROP_HFLIP:
+ control.id = V4L2_CID_HFLIP;
+ control.value = v4l2src->hflip;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_HFLIP");
+ }
+ break;
+ case PROP_VFLIP:
+ control.id = V4L2_CID_VFLIP;
+ control.value = v4l2src->vflip;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_VFLIP");
+ }
+ break;
+ case PROP_BRIGHTNESS:
+ control.id = V4L2_CID_BRIGHTNESS;
+ control.value = v4l2src->brightness;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_BRIGHTNESS");
+ }
+ break;
+ case PROP_CONTRAST:
+ control.id = V4L2_CID_CONTRAST;
+ control.value = v4l2src->contrast;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_CONTRAST");
+ }
+ break;
+ case PROP_SATURATION:
+ control.id = V4L2_CID_SATURATION;
+ control.value = v4l2src->saturation;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SATURATION");
+ }
+ break;
+ case PROP_SCENE:
+ control.id = V4L2_CID_SCENE;
+ control.value = v4l2src->scene;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SCENE");
+ }
+ break;
+ case PROP_SENSITIVITY:
+ control.id = V4L2_CID_SENSITIVITY;
+ control.value = v4l2src->sensitivity;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SENSITIVITY");
+ }
+ break;
+ case PROP_MET_EXP:
+ control.id = V4L2_CID_MET_EXP;
+ control.value = v4l2src->metering_exposure;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_MET_EXP");
+ }
+ break;
+ case PROP_FOCUS_CTRL:
+ control.id = V4L2_CID_FOCUS_AUTO;
+ control.value = v4l2src->focus_ctrl;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_FOCUS_AUTO");
+ }
+ break;
+ case PROP_FLICKER_MOD:
+ control.id = V4L2_CID_POWER_LINE_FREQUENCY;
+ control.value = v4l2src->flicker_mod;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src,
+ "failed to set V4L2_CID_POWER_LINE_FREQUENCY");
+ }
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+/******************************************************
+ * gst_v4l2src_capture_get_control():
+ * get a specific control on capture device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_get_control (GstV4l2Src * v4l2src, guint prop_id)
+{
+ struct v4l2_control control;
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_DEBUG_OBJECT (v4l2src, "set control on capture device");
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+
+ switch (prop_id) {
+ case PROP_HFLIP:
+ control.id = V4L2_CID_HFLIP;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_HFLIP");
+ }
+ v4l2src->hflip = control.value;
+ break;
+ case PROP_VFLIP:
+ control.id = V4L2_CID_VFLIP;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_VFLIP");
+ }
+ v4l2src->vflip = control.value;
+ break;
+ case PROP_BRIGHTNESS:
+ control.id = V4L2_CID_BRIGHTNESS;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_BRIGHTNESS");
+ }
+ v4l2src->brightness = control.value;
+ break;
+ case PROP_CONTRAST:
+ control.id = V4L2_CID_CONTRAST;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_CONTRAST");
+ }
+ v4l2src->contrast = control.value;
+ break;
+ case PROP_SATURATION:
+ control.id = V4L2_CID_SATURATION;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SATURATION");
+ }
+ v4l2src->saturation = control.value;
+ break;
+ case PROP_SCENE:
+ control.id = V4L2_CID_SCENE;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SCENE");
+ }
+ v4l2src->scene = control.value;
+ break;
+ case PROP_SENSITIVITY:
+ control.id = V4L2_CID_SENSITIVITY;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SENSITIVITY");
+ }
+ v4l2src->sensitivity = control.value;
+ break;
+ case PROP_MET_EXP:
+ control.id = V4L2_CID_MET_EXP;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_MET_EXP");
+ }
+ v4l2src->metering_exposure = control.value;
+ break;
+ case PROP_FOCUS_STATE:
+ control.id = V4L2_CID_FOCUS_AUTO;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_FOCUS_AUTO");
+ }
+ v4l2src->focus_ctrl = control.value;
+ break;
+ case PROP_FLICKER_MOD:
+ control.id = V4L2_CID_POWER_LINE_FREQUENCY;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src,
+ "failed to set V4L2_CID_POWER_LINE_FREQUENCY");
+ }
+ v4l2src->flicker_mod = control.value;
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+
+/******************************************************
+ * gst_v4l2src_capture_set_effect():
+ * set effect on capture device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_set_effect (GstV4l2Src * v4l2src, gchar * effect_name)
+{
+ struct v4l2_efx v4l2_effect;
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_DEBUG_OBJECT (v4l2src, "set effect on capture device");
+
+ memset (&v4l2_effect, 0, sizeof (struct v4l2_efx));
+ sprintf (v4l2_effect.efx_name, "%s", effect_name);
+ GST_DEBUG_OBJECT (v4l2src, "set effect: %s", effect_name);
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_EFX, &v4l2_effect) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set effect");
+ }
+
+ return TRUE;
+}
+
+/******************************************************
+ * gst_v4l2src_capture_set_white_balance_mode():
+ * set white_balance mode on capture device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_set_white_balance_mode (GstV4l2Src * v4l2src,
+ gchar * wb_mode_name)
+{
+ struct v4l2_wb_mode wb_mode;
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_DEBUG_OBJECT (v4l2src, "set white balance on capture device");
+
+ memset (&wb_mode, 0, sizeof (struct v4l2_efx));
+ sprintf (wb_mode.wb_mode_name, "%s", wb_mode_name);
+ GST_DEBUG_OBJECT (v4l2src, "set white balance mode: %s", wb_mode_name);
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_WBMODE, &wb_mode) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set white balance");
+ }
+
+ return TRUE;
+}
+
+/******************************************************
+ * gst_v4l2src_capture_set_zoom():
+ * set zoom value mode on capture device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_set_zoom (GstV4l2Src * v4l2src)
+{
+ double zoom_max = 1.0;
+ struct v4l2_crop crop;
+ struct v4l2_cropcap cropcap;
+
+#define min(a,b) ((a) > (b) ? (b) : (a))
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_DEBUG_OBJECT (v4l2src, "set ZOOM on capture device");
+
+
+ /* get crop cap */
+ memset (&cropcap, 0, sizeof (struct v4l2_cropcap));
+ cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_CROPCAP, &cropcap) < 0) {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
+ ("failed to get crop caps"));
+ return FALSE;
+ }
+ GST_DEBUG_OBJECT (v4l2src, "defrect: w:%d h:%d l:%d t:%d",
+ cropcap.defrect.width, cropcap.defrect.height,
+ cropcap.defrect.left, cropcap.defrect.top);
+ GST_DEBUG_OBJECT (v4l2src, "bounds: w:%d h:%d l:%d t:%d",
+ cropcap.bounds.width, cropcap.bounds.height,
+ cropcap.bounds.left, cropcap.bounds.top);
+
+ /* limit zoom to zoomax */
+ zoom_max = cropcap.defrect.width / cropcap.bounds.width;
+ v4l2src->zoom = min (v4l2src->zoom, zoom_max);
+ GST_DEBUG_OBJECT (v4l2src, "set zoom: %f (zoom max:%f)", v4l2src->zoom,
+ zoom_max);
+
+ /* set croppping zone */
+ memset (&crop, 0, sizeof (struct v4l2_crop));
+ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ crop.c.width = cropcap.defrect.width / v4l2src->zoom;
+ crop.c.height = cropcap.defrect.height / v4l2src->zoom;
+ /* center crop */
+ crop.c.left =
+ (cropcap.defrect.width + cropcap.defrect.left * 2 - crop.c.width) / 2;
+ crop.c.top =
+ (cropcap.defrect.height + cropcap.defrect.top * 2 - crop.c.height) / 2;
+ GST_DEBUG_OBJECT (v4l2src, "=> CROP: w:%d h:%d l:%d t:%d", crop.c.width,
+ crop.c.height, crop.c.left, crop.c.top);
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CROP, &crop) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "Crop setting failed");
+ }
+
+ return TRUE;
+}
+
+/*
+ */
+static gboolean
+gst_v4l2src_get_nearest_size (GstV4l2Src * v4l2src, guint32 pixelformat,
+ gint * width, gint * height)
+{
+ struct v4l2_format fmt;
+ int fd;
+ int r;
+
+ g_return_val_if_fail (width != NULL, FALSE);
+ g_return_val_if_fail (height != NULL, FALSE);
+
+ GST_LOG_OBJECT (v4l2src,
+ "getting nearest size to %dx%d with format %" GST_FOURCC_FORMAT,
+ *width, *height, GST_FOURCC_ARGS (pixelformat));
+
+ fd = v4l2src->v4l2object->video_fd;
+
+ /* get size delimiters */
+ memset (&fmt, 0, sizeof (fmt));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+ fmt.fmt.pix.pixelformat = pixelformat;
+ fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+ r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
+ if (r < 0 && errno == EINVAL) {
+ /* try again with progressive video */
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+ fmt.fmt.pix.pixelformat = pixelformat;
+ fmt.fmt.pix.field = V4L2_FIELD_NONE;
+ r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
+ }
+
+ if (r < 0) {
+ /* The driver might not implement TRY_FMT, in which case we will try
+ S_FMT to probe */
+ if (errno != ENOTTY)
+ return FALSE;
+
+ /* Only try S_FMT if we're not actively capturing yet, which we shouldn't
+ be, because we're still probing */
+ if (GST_V4L2_IS_ACTIVE (v4l2src->v4l2object))
+ return FALSE;
+
+ GST_LOG_OBJECT (v4l2src,
+ "Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
+
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+
+ r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
+ if (r < 0 && errno == EINVAL) {
+ /* try again with progressive video */
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+ fmt.fmt.pix.pixelformat = pixelformat;
+ fmt.fmt.pix.field = V4L2_FIELD_NONE;
+ r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
+ }
+
+ if (r < 0)
+ return FALSE;
+ }
+
+ GST_LOG_OBJECT (v4l2src,
+ "got nearest size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
+
+ *width = fmt.fmt.pix.width;
+ *height = fmt.fmt.pix.height;
+
+ return TRUE;
+}
diff --git a/sys/v4l2/v4l2src_calls.h b/sys/v4l2/v4l2src_calls.h
index 1fc7411fa..aee775417 100644
--- a/sys/v4l2/v4l2src_calls.h
+++ b/sys/v4l2/v4l2src_calls.h
@@ -41,5 +41,18 @@ GstFlowReturn gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer **buf)
gboolean gst_v4l2src_capture_stop (GstV4l2Src * v4l2src);
gboolean gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src);
+gboolean gst_v4l2src_capture_set_effect (GstV4l2Src * v4l2src, gchar* effect_name);
+gboolean gst_v4l2src_capture_set_white_balance_mode (GstV4l2Src * v4l2src, gchar* wb_mode_name);
+gboolean gst_v4l2src_capture_set_all_controls (GstV4l2Src * v4l2src);
+gboolean gst_v4l2src_capture_set_control (GstV4l2Src * v4l2src, guint prop_id);
+gboolean gst_v4l2src_capture_get_control (GstV4l2Src * v4l2src, guint prop_id);
+
+gboolean gst_v4l2src_capture_set_zoom (GstV4l2Src * v4l2src);
+
+gboolean gst_v4l2src_fill_format_list (GstV4l2Src * v4l2src);
+gboolean gst_v4l2src_clear_format_list (GstV4l2Src * v4l2src);
+
+GstCaps* gst_v4l2src_probe_caps_for_format (GstV4l2Src * v4l2src, guint32 pixelformat,
+ const GstStructure *template);
#endif /* __V4L2SRC_CALLS_H__ */