3 * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
4 * 2006 Edgard Lima <edgard.lima@indt.org.br>
5 * 2008-2010 Nokia Corporation <multimedia@maemo.org>
6 * 2010 Intel Corporation
8 * v4l2camsrc.c - system calls
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
30 #include <sys/types.h>
33 #include <sys/ioctl.h>
40 /* Needed on older Solaris Nevada builds (72 at least) */
42 #include <sys/ioccom.h>
45 #include <gst/camera/gstmfldcameracolorbalance.h>
46 #include <gst/controller/gstcontroller.h>
48 #include "v4l2camsrc_calls.h"
49 #include <atomisp_v4l2.h>
52 GST_DEBUG_CATEGORY_EXTERN (gst_v4l2camsrc_debug);
53 #define GST_CAT_DEFAULT gst_v4l2camsrc_debug
55 extern guint gst_camerasrc_signals[CAMERA_IN_LAST_SIGNAL];
57 static const gint gst_v4l2camsrc_capture_map[] = {
58 CAM_VIEWFINDER_MODE_VIEWFINDER,
59 CAM_VIEWFINDER_MODE_STILL_CAPTURE,
60 CAM_VIEWFINDER_MODE_VIDEO_RECORD,
64 static const gint gst_v4l2camsrc_effect_map[] = {
65 CAM_GENERAL_EFFECT_TYPE_NORMAL,
66 CAM_GENERAL_EFFECT_TYPE_SEPIA,
67 CAM_GENERAL_EFFECT_TYPE_NEGATIVE,
68 CAM_GENERAL_EFFECT_TYPE_GRAYSCALE,
69 CAM_GENERAL_EFFECT_TYPE_NORMAL,
70 CAM_GENERAL_EFFECT_TYPE_VIVID,
71 CAM_GENERAL_EFFECT_TYPE_NORMAL,
72 CAM_GENERAL_EFFECT_TYPE_NORMAL,
73 CAM_GENERAL_EFFECT_TYPE_NORMAL,
74 CAM_GENERAL_EFFECT_TYPE_SKY_BLUE,
75 CAM_GENERAL_EFFECT_TYPE_GRASS_GREEN,
76 CAM_GENERAL_EFFECT_TYPE_SKIN_WHITEN,
80 static const gint gst_v4l2camsrc_wb_map[] = {
82 CAM_AWB_MODE_DAYLIGHT,
85 CAM_AWB_MODE_TUNGSTEN,
86 CAM_AWB_MODE_FLUORESCENT,
91 static gint find_item (const gint table[], const gint item);
92 /* Define this to use memory locking for video buffers */
93 /* #define USE_MLOCK */
96 #define GST_V4L2CAMSRC_SET_ACTIVE(element) (element)->buffer = GINT_TO_POINTER (-1)
97 #define GST_V4L2CAMSRC_SET_INACTIVE(element) (element)->buffer = NULL
99 /* On some systems MAP_FAILED seems to be missing */
101 #define MAP_FAILED ((caddr_t) -1)
104 #define RESIZER_MAX_DOWNSCALE_FACTOR 4
105 #define V4L2CAMSRC_POLL_TIMEOUT (20 * GST_SECOND)
107 #define GST_TYPE_V4L2CAMSRC_BUFFER (gst_v4l2camsrc_buffer_get_type())
108 #define GST_IS_V4L2CAMSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2CAMSRC_BUFFER))
109 #define GST_V4L2CAMSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2CAMSRC_BUFFER, GstV4l2Buffer))
111 /* Local functions */
113 gst_v4l2camsrc_get_nearest_size (GstMFLDV4l2CamSrc * v4l2camsrc,
114 guint32 pixelformat, gint * width, gint * height);
115 static void gst_v4l2camsrc_buffer_pool_destroy (GstMFLDV4l2CamSrcBufferPool *
116 pool, GstMFLDV4l2CamSrc * v4l2camsrc);
117 static gboolean gst_v4l2camsrc_update_cropping (GstMFLDV4l2CamSrc * v4l2camsrc,
118 gint width, gint height, gfloat zoom);
120 gst_v4l2camsrc_check_focus_status (GstMFLDV4l2CamSrc * v4l2camsrc,
121 GstCameraFocusStatus *fs, gboolean detailed);
123 static gboolean gst_v4l2camsrc_libmfldcam_init (GstMFLDV4l2CamSrc * v4l2camsrc);
124 static gboolean gst_v4l2camsrc_libmfldcam_deinit (GstMFLDV4l2CamSrc *
131 static GstBufferClass *v4l2buffer_parent_class = NULL;
134 gst_v4l2camsrc_buffer_finalize (GstV4l2Buffer * buffer)
136 GstMFLDV4l2CamSrcBufferPool *pool;
137 gboolean resuscitated = FALSE;
138 struct v4l2_buffer *vbuffer;
142 vbuffer = (struct v4l2_buffer *) buffer->vbuffer;
143 index = vbuffer->index;
145 GST_LOG ("finalizing buffer %p %d", buffer, index);
147 g_mutex_lock (pool->lock);
148 if (GST_BUFFER_SIZE (buffer) != 0)
149 /* BUFFER_SIZE is only set if the frame was dequeued */
150 pool->num_live_buffers--;
153 if (pool->is_vaapi_sharing && buffer->gbuffer)
154 GST_BUFFER_DATA(buffer) = GST_BUFFER_DATA(buffer->gbuffer);
155 if (ioctl (pool->video_fd, VIDIOC_QBUF, vbuffer) < 0) {
156 GST_WARNING ("could not requeue buffer %p %d", buffer, index);
158 /* FIXME: check that the caps didn't change */
159 GST_LOG ("reviving buffer %p, %d", buffer, index);
160 gst_buffer_ref (GST_BUFFER (buffer));
161 GST_BUFFER_SIZE (buffer) = 0;
162 pool->buffers[index] = buffer;
163 pool->queued[index] = 1;
164 g_cond_signal (pool->data_cond);
168 GST_LOG ("the pool is shutting down");
170 g_mutex_unlock (pool->lock);
173 GST_LOG ("buffer %p not recovered, unmapping", buffer);
174 if (buffer->use_mmap)
175 munmap ((void *) GST_BUFFER_DATA (buffer), vbuffer->length);
176 gst_mini_object_unref (GST_MINI_OBJECT (pool));
178 if (!buffer->use_mmap) {
179 if (buffer->gbuffer) {
180 /* It was allocated with gst_pad_alloc_buffer */
181 /* FIXME temporal fix for double free error */
182 if (pool->is_vaapi_sharing)
183 gst_buffer_unref (buffer->gbuffer);
184 buffer->gbuffer = NULL;
186 /* It was allocated with posix_memalign */
187 free (GST_BUFFER_DATA (buffer));
191 GST_BUFFER_DATA (buffer) = NULL;
193 g_free (buffer->vbuffer);
195 GST_LOG ("free v4l2buffer");
196 GST_MINI_OBJECT_CLASS (v4l2buffer_parent_class)->finalize (GST_MINI_OBJECT
202 gst_v4l2camsrc_buffer_class_init (gpointer g_class, gpointer class_data)
204 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
206 v4l2buffer_parent_class = g_type_class_peek_parent (g_class);
208 mini_object_class->finalize =
209 (GstMiniObjectFinalizeFunction) gst_v4l2camsrc_buffer_finalize;
213 gst_v4l2camsrc_buffer_get_type (void)
215 static GType _gst_v4l2camsrc_buffer_type;
217 if (G_UNLIKELY (_gst_v4l2camsrc_buffer_type == 0)) {
218 static const GTypeInfo v4l2camsrc_buffer_info = {
219 sizeof (GstBufferClass),
222 gst_v4l2camsrc_buffer_class_init,
225 sizeof (GstV4l2Buffer),
230 _gst_v4l2camsrc_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
231 "GstCameraBuffer", &v4l2camsrc_buffer_info, 0);
233 return _gst_v4l2camsrc_buffer_type;
236 static GstV4l2Buffer *
237 gst_v4l2camsrc_buffer_new (GstMFLDV4l2CamSrcBufferPool * pool,
238 GstCameraSrc * camsrc, guint index, GstCaps * caps)
240 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
241 GstV4l2Buffer *ret = NULL;
242 GstFlowReturn flow_ret;
243 GstBuffer *buf_cap_signal2 = NULL; /*output main buffer for capture signal*/
244 struct v4l2_buffer *vbuffer;
246 ret = (GstV4l2Buffer *) gst_mini_object_new (GST_TYPE_V4L2CAMSRC_BUFFER);
247 ret->use_mmap = v4l2camsrc->use_mmap;
248 vbuffer = ret->vbuffer = g_new0 (struct v4l2_buffer, 1);
249 GST_LOG ("creating buffer %u, %p in pool %p", index, ret, pool);
251 (GstMFLDV4l2CamSrcBufferPool *)
252 gst_mini_object_ref (GST_MINI_OBJECT (pool));
254 vbuffer->index = index;
255 vbuffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
257 if (v4l2camsrc->use_mmap)
258 vbuffer->memory = V4L2_MEMORY_MMAP;
260 vbuffer->memory = V4L2_MEMORY_USERPTR;
262 vbuffer->length = v4l2camsrc->frame_byte_size;
265 if (ioctl (pool->video_fd, VIDIOC_QUERYBUF, vbuffer) < 0)
266 goto querybuf_failed;
268 if (v4l2camsrc->use_mmap) {
270 data = (guint8 *) mmap (0, vbuffer->length,
271 PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd, vbuffer->m.offset);
272 if (data == MAP_FAILED)
274 GST_BUFFER_DATA (ret) = (guint8 *) data;
277 if (v4l2camsrc->capture_mode == GST_CAMERA_SRC_CAPTURE_MODE_STILL) {
280 /* alloc buffer for capture callback */
281 buf_cap_signal2 = gst_buffer_new ();
283 GST_BUFFER_DATA(buf_cap_signal2) = NULL;
284 GST_BUFFER_SIZE(buf_cap_signal2) = 0;
285 GST_BUFFER_CAPS(buf_cap_signal2) = gst_caps_new_simple("video/x-raw-yuv",
286 "format", GST_TYPE_FOURCC, v4l2camsrc->capture_fourcc,
287 "width", G_TYPE_INT, v4l2camsrc->capture_w,
288 "height", G_TYPE_INT,v4l2camsrc->capture_h,
291 GST_LOG_OBJECT (camsrc, "CALL: usrptr callback");
292 g_signal_emit( G_OBJECT (camsrc),
293 gst_camerasrc_signals[CAMERA_IN_SIGNAL_STILL_USRPTR_BUFFER],
297 if (GST_BUFFER_DATA(buf_cap_signal2) == NULL)
298 goto usrptr_alloc_failed;
300 GST_LOG_OBJECT (camsrc, "RETURN: usrptr callback: buf=%p, size=%d",
301 GST_BUFFER_DATA(buf_cap_signal2), GST_BUFFER_SIZE(buf_cap_signal2));
302 GST_BUFFER_DATA (ret) = GST_BUFFER_DATA(buf_cap_signal2);
303 gst_buffer_unref(buf_cap_signal2);
306 if (gst_pad_is_linked (GST_BASE_SRC_PAD (v4l2camsrc))) {
307 GST_LOG ("using pad_alloc, size=%d", v4l2camsrc->frame_byte_size);
308 GST_LOG ("ALLOC CAPS: %" GST_PTR_FORMAT, caps);
311 gst_pad_alloc_buffer_and_set_caps (GST_BASE_SRC_PAD (v4l2camsrc), 0LL,
312 v4l2camsrc->frame_byte_size, caps, &ret->gbuffer);
313 if (flow_ret != GST_FLOW_OK)
314 goto pad_alloc_failed;
315 GST_BUFFER_DATA (ret) = ret->gbuffer->data;
319 GST_LOG ("using posix_memalign");
320 if (posix_memalign (&data, getpagesize (), vbuffer->length) != 0) {
321 goto memalign_failed;
323 GST_BUFFER_DATA (ret) = (guint8 *) data;
328 GST_BUFFER_SIZE (ret) = v4l2camsrc->frame_byte_size;
329 GST_BUFFER_FLAG_SET (ret, GST_BUFFER_FLAG_READONLY);
330 gst_buffer_set_caps (GST_BUFFER (ret), caps);
333 GST_DEBUG ("mlocking buffer data");
334 if (mlock ((void *) GST_BUFFER_DATA (ret), v4l2camsrc->frame_byte_size) == -1)
338 /* mlocking succeeded, now we can set the pointer to vbuffer. The existence
339 * of this pointer will be used later to determine if the munlock() is
341 if (!v4l2camsrc->use_mmap)
342 vbuffer->m.userptr = (unsigned int) GST_BUFFER_DATA (ret);
346 GST_LOG (" index: %u", vbuffer->index);
347 GST_LOG (" type: %d", vbuffer->type);
348 GST_LOG (" bytesused: %u", vbuffer->bytesused);
349 GST_LOG (" flags: %08x", vbuffer->flags);
350 GST_LOG (" field: %d", vbuffer->field);
351 GST_LOG (" memory: %d", vbuffer->memory);
352 if (vbuffer->memory == V4L2_MEMORY_MMAP)
353 GST_LOG (" MMAP offset: %p", vbuffer->m.offset);
354 else if (vbuffer->memory == V4L2_MEMORY_USERPTR)
355 GST_LOG (" user address: %p", vbuffer->m.userptr);
356 GST_LOG (" length: %u", vbuffer->length);
357 GST_LOG (" input: %u", vbuffer->input);
366 GST_WARNING ("Failed to mlock memory: %s", g_strerror (errno));
367 gst_buffer_unref (GST_BUFFER (ret));
374 gint errnosave = errno;
376 GST_WARNING ("Failed QUERYBUF: %s", g_strerror (errnosave));
377 gst_buffer_unref (GST_BUFFER (ret));
384 GST_WARNING ("Failed to posix_memalign a buffer");
390 GST_WARNING ("Failed to pad_alloc_buffer: %s",
391 gst_flow_get_name (flow_ret));
397 GST_WARNING ("Failed to alloc usrptr buffer");
403 gint errnosave = errno;
404 GST_WARNING ("Failed to mmap: %s", g_strerror (errnosave));
405 gst_buffer_unref (GST_BUFFER (ret));
413 #define GST_TYPE_V4L2CAMSRC_BUFFER_POOL (gst_v4l2camsrc_buffer_pool_get_type())
414 #define GST_IS_V4L2CAMSRC_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2CAMSRC_BUFFER_POOL))
415 #define GST_V4L2CAMSRC_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2CAMSRC_BUFFER_POOL, GstMFLDV4l2CamSrcBufferPool))
417 static GstMiniObjectClass *buffer_pool_parent_class = NULL;
420 gst_v4l2camsrc_buffer_pool_finalize (GstMFLDV4l2CamSrcBufferPool * pool)
422 g_mutex_free (pool->lock);
425 if (pool->video_fd >= 0)
426 close (pool->video_fd);
429 g_free (pool->buffers);
430 pool->buffers = NULL;
434 g_free (pool->queued);
438 g_cond_free (pool->data_cond);
439 pool->data_cond = NULL;
441 GST_MINI_OBJECT_CLASS (buffer_pool_parent_class)->finalize (GST_MINI_OBJECT
448 gst_v4l2camsrc_buffer_pool_init (GstMFLDV4l2CamSrcBufferPool * pool,
451 pool->lock = g_mutex_new ();
452 pool->running = FALSE;
453 pool->num_live_buffers = 0;
454 pool->data_cond = g_cond_new ();
455 pool->is_vaapi_sharing = FALSE;
461 gst_v4l2camsrc_buffer_pool_class_init (gpointer g_class, gpointer class_data)
463 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
465 buffer_pool_parent_class = g_type_class_peek_parent (g_class);
467 mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
468 gst_v4l2camsrc_buffer_pool_finalize;
474 gst_v4l2camsrc_buffer_pool_get_type (void)
476 static GType _gst_v4l2camsrc_buffer_pool_type;
478 if (G_UNLIKELY (_gst_v4l2camsrc_buffer_pool_type == 0)) {
479 static const GTypeInfo v4l2camsrc_buffer_pool_info = {
480 sizeof (GstBufferClass),
483 gst_v4l2camsrc_buffer_pool_class_init,
486 sizeof (GstMFLDV4l2CamSrcBufferPool),
488 (GInstanceInitFunc) gst_v4l2camsrc_buffer_pool_init,
491 _gst_v4l2camsrc_buffer_pool_type =
492 g_type_register_static (GST_TYPE_MINI_OBJECT,
493 "GstMFLDV4l2CamSrcBufferPool", &v4l2camsrc_buffer_pool_info, 0);
495 return _gst_v4l2camsrc_buffer_pool_type;
500 static GstMFLDV4l2CamSrcBufferPool *
501 gst_v4l2camsrc_buffer_pool_new (GstCameraSrc * camsrc, gint fd,
504 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
505 GstMFLDV4l2CamSrcBufferPool *pool;
508 pool = (GstMFLDV4l2CamSrcBufferPool *)
509 gst_mini_object_new (GST_TYPE_V4L2CAMSRC_BUFFER_POOL);
511 pool->video_fd = dup (fd);
512 if (pool->video_fd < 0)
515 GstStructure *structure = gst_caps_get_structure (caps, 0);
516 if (structure && gst_structure_has_name(structure, "video/x-vaapi-sharing"))
517 pool->is_vaapi_sharing = TRUE;
519 pool->buffer_count = v4l2camsrc->num_buffers;
520 pool->buffers = g_new0 (GstV4l2Buffer *, pool->buffer_count);
521 pool->queued = g_new0 (guint, pool->buffer_count);
523 for (n = 0; n < pool->buffer_count; n++) {
524 pool->buffers[n] = gst_v4l2camsrc_buffer_new (pool, camsrc, n, caps);
525 GST_LOG ("buffer ref is %d", GST_MINI_OBJECT_REFCOUNT (pool->buffers[n]));
526 if (!pool->buffers[n])
527 goto buffer_new_failed;
535 gint errnosave = errno;
537 gst_v4l2camsrc_buffer_pool_destroy (pool, v4l2camsrc);
545 gint errnosave = errno;
547 GST_LOG ("creating a new buffer failed");
548 gst_mini_object_unref (GST_MINI_OBJECT (pool));
559 gst_v4l2camsrc_buffer_pool_activate (GstMFLDV4l2CamSrcBufferPool * pool,
560 GstMFLDV4l2CamSrc * v4l2camsrc)
564 g_mutex_lock (pool->lock);
566 for (n = 0; n < pool->buffer_count; n++) {
568 struct v4l2_buffer *buf;
570 buf = (struct v4l2_buffer *) pool->buffers[n]->vbuffer;
572 GST_LOG ("enqueue pool buffer %d", n);
574 if (ioctl (pool->video_fd, VIDIOC_QBUF, buf) < 0)
579 pool->running = TRUE;
581 g_mutex_unlock (pool->lock);
588 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
589 ("Could not enqueue buffers in device '%s'.",
590 v4l2camsrc->videodev),
591 ("enqueing buffer %d/%d failed: %s",
592 n, v4l2camsrc->num_buffers, g_strerror (errno)));
593 g_mutex_unlock (pool->lock);
598 /* requeue buffers that are writable again */
599 /* FIXME: This isn't needed anymore. Buffers are re-queued automatically
600 * when they are finalized, so there is no need to wait for them separately */
602 gst_v4l2_buffer_pool_update (GstMFLDV4l2CamSrcBufferPool * pool,
603 GstMFLDV4l2CamSrc * v4l2camsrc)
608 g_mutex_lock (pool->lock);
610 for (n = 0; n < pool->buffer_count; n++) {
611 if (!pool->queued[n]) {
612 GST_LOG ("buffer %d is dequeued", n);
617 /* if all the buffers are dequeued, wait */
618 if (ref == v4l2camsrc->num_buffers) {
619 GST_LOG ("no free buffers available");
620 g_cond_wait (pool->data_cond, pool->lock);
623 g_mutex_unlock (pool->lock);
625 return (ref != v4l2camsrc->num_buffers) ? TRUE : FALSE;
631 gst_v4l2camsrc_buffer_pool_destroy (GstMFLDV4l2CamSrcBufferPool * pool,
632 GstMFLDV4l2CamSrc * v4l2camsrc)
636 g_mutex_lock (pool->lock);
637 pool->running = FALSE;
638 g_mutex_unlock (pool->lock);
640 GST_DEBUG ("destroy pool");
642 /* after this point, no more buffers will be queued or dequeued; no buffer
643 * from pool->buffers that is NULL will be set to a buffer, and no buffer that
644 * is not NULL will be pushed out. */
646 /* miniobjects have no dispose, so they can't break ref-cycles, as buffers ref
647 * the pool, we need to unref the buffer to properly finalize te pool */
648 for (n = 0; n < pool->buffer_count; n++) {
651 g_mutex_lock (pool->lock);
652 buf = GST_BUFFER (pool->buffers[n]);
653 g_mutex_unlock (pool->lock);
657 if (pool->buffers[n].m.userptr) {
658 GST_DEBUG ("munlocking buffer data");
659 munlock ((void *) pool->buffers[n].m.userptr,
660 v4l2camsrc->frame_byte_size);
663 /* we own the ref if the buffer is in pool->buffers; drop it. */
664 gst_buffer_unref (buf);
667 pool->is_vaapi_sharing = FALSE;
668 gst_mini_object_unref (GST_MINI_OBJECT (pool));
671 /******************************************************
672 * gst_v4l2camsrc_get_capture_capabilities():
673 * get the device's capturing capabilities
674 * return value: TRUE on success, FALSE on error
675 ******************************************************/
677 gst_v4l2camsrc_get_capture_capabilities (GstMFLDV4l2CamSrc * v4l2camsrc)
679 GST_DEBUG_OBJECT (v4l2camsrc, "getting capabilities");
681 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
684 if (ioctl (v4l2camsrc->video_fd, VIDIOC_QUERYCAP, &v4l2camsrc->vcap) < 0)
687 GST_LOG_OBJECT (v4l2camsrc, "driver: '%s'", v4l2camsrc->vcap.driver);
688 GST_LOG_OBJECT (v4l2camsrc, "card: '%s'", v4l2camsrc->vcap.card);
689 GST_LOG_OBJECT (v4l2camsrc, "bus_info: '%s'", v4l2camsrc->vcap.bus_info);
690 GST_LOG_OBJECT (v4l2camsrc, "version: %08x", v4l2camsrc->vcap.version);
691 GST_LOG_OBJECT (v4l2camsrc, "capabilites: %08x",
692 v4l2camsrc->vcap.capabilities);
699 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
700 ("Error getting capabilities for device '%s': "
701 "It isn't a v4l2 driver. Check if it is a v4l1 driver.",
702 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
708 /******************************************************
709 * gst_v4l2camsrc_set_input_sensor():
710 * set which sensor is the input of ISP
711 * return value: TRUE on success, FALSE on error
712 ******************************************************/
714 gst_v4l2camsrc_set_input_sensor (GstMFLDV4l2CamSrc * v4l2camsrc)
716 V4L2CameraInputSensor select_sensor;
718 GST_DEBUG_OBJECT (v4l2camsrc, "setting input sensor");
720 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
723 if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_PRIMARY)
724 select_sensor = V2L2_CAMERA_INPUT_SENSOR_PRIMARY;
726 select_sensor =V2L2_CAMERA_INPUT_SENSOR_SECONDARY;
728 if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_INPUT,
732 GST_LOG_OBJECT (v4l2camsrc, "set input sensor to: %d",
740 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
741 ("Error setting input for device '%s': ",
742 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
748 get_supported_mmfw_control (GstMFLDV4l2CamSrc * v4l2camsrc, struct v4l2_queryctrl *control)
751 GST_DEBUG_OBJECT (v4l2camsrc, "set private control (%x)", control->id);
753 for (i = 0; i < N_MMFW_CONTROLS; i++) {
754 if (mmfw_wb_controls[i].id == control->id) {
755 *control = mmfw_wb_controls[i];
763 /******************************************************
764 * gst_v4l2camsrc_fill_lists():
765 * fill the lists of enumerations
766 * return value: TRUE on success, FALSE on error
767 ******************************************************/
769 gst_v4l2camsrc_fill_lists (GstMFLDV4l2CamSrc * v4l2camsrc)
773 GST_DEBUG_OBJECT (v4l2camsrc, "getting enumerations");
774 GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
776 GST_DEBUG_OBJECT (v4l2camsrc, " controls+menus");
777 /* and lastly, controls+menus (if appropriate) */
778 for (n = V4L2_CID_BASE;; n++) {
779 struct v4l2_queryctrl control = { 0, };
780 GstCameraSrcColorBalanceChannel *v4l2channel;
782 GstColorBalanceChannel *channel;
784 /* when we reached the last official CID, continue with private CIDs */
785 if (n == V4L2_CID_LASTP1) {
786 GST_DEBUG_OBJECT (v4l2camsrc, "checking private CIDs");
787 n = V4L2_CID_PRIVATE_BASE;
788 /* FIXME: We are still not handling private controls. We need a
789 new GstInterface to export those controls */
791 GST_DEBUG_OBJECT (v4l2camsrc, "private ID");
796 if( n > SOURCE_PRIV_BASE) {
797 if( n > MM_CAM_SOURCE_PRIV_LAST)
800 get_supported_mmfw_control(v4l2camsrc, &control);
802 else if (ioctl (v4l2camsrc->video_fd, VIDIOC_QUERYCTRL, &control) < 0) {
803 if (errno == EINVAL) {
804 if (n < V4L2_CID_PRIVATE_BASE)
805 /* continue so that we also check private controls */
810 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
811 ("Failed getting controls attributes on device '%s.'",
812 v4l2camsrc->videodev),
813 ("Failed querying control %d on device '%s'. (%d - %s)",
814 n, v4l2camsrc->videodev, errno, strerror (errno)));
818 if (control.flags & V4L2_CTRL_FLAG_DISABLED)
822 case V4L2_CID_BRIGHTNESS:
823 case V4L2_CID_CONTRAST:
824 case V4L2_CID_SATURATION:
826 case V4L2_CID_BLACK_LEVEL:
827 case V4L2_CID_AUTO_WHITE_BALANCE:
828 case V4L2_CID_DO_WHITE_BALANCE:
829 case V4L2_CID_RED_BALANCE:
830 case V4L2_CID_BLUE_BALANCE:
832 case V4L2_CID_EXPOSURE:
833 case V4L2_CID_AUTOGAIN:
835 case V4L2_CID_COLORFX:
836 case MM_CAM_FILTER_WB_SOURCE_PRIV:
837 case MM_CAM_FILTER_COLOR_TONE_SOURCE_PRIV:
838 /* we only handle these for now (why?) */
842 case V4L2_CID_HCENTER:
843 case V4L2_CID_VCENTER:
844 #ifdef V4L2_CID_PAN_RESET
845 case V4L2_CID_PAN_RESET:
847 #ifdef V4L2_CID_TILT_RESET
848 case V4L2_CID_TILT_RESET:
850 /* not handled here, handled by VideoOrientation interface */
853 case V4L2_CID_AUDIO_VOLUME:
854 case V4L2_CID_AUDIO_BALANCE:
855 case V4L2_CID_AUDIO_BASS:
856 case V4L2_CID_AUDIO_TREBLE:
857 case V4L2_CID_AUDIO_MUTE:
858 case V4L2_CID_AUDIO_LOUDNESS:
859 /* FIXME: We should implement GstMixer interface */
862 GST_DEBUG_OBJECT (v4l2camsrc,
863 "ControlID %s (%x) unhandled, FIXME", control.name, n);
870 GST_DEBUG_OBJECT (v4l2camsrc, "Adding ControlID %s (%x)", control.name, n);
872 g_object_new (GST_TYPE_CAMERA_SRC_COLOR_BALANCE_CHANNEL, NULL);
873 channel = GST_COLOR_BALANCE_CHANNEL (v4l2channel);
874 channel->label = g_strdup ((const gchar *) control.name);
878 switch (control.type) {
879 case V4L2_CTRL_TYPE_INTEGER:
880 channel->min_value = control.minimum;
881 channel->max_value = control.maximum;
883 case V4L2_CTRL_TYPE_BOOLEAN:
884 channel->min_value = FALSE;
885 channel->max_value = TRUE;
888 /* FIXME we should find out how to handle V4L2_CTRL_TYPE_BUTTON.
889 BUTTON controls like V4L2_CID_DO_WHITE_BALANCE can just be set (1) or
890 unset (0), but can't be queried */
891 GST_DEBUG_OBJECT (v4l2camsrc,
892 "Control with non supported type %s (%x), type=%d",
893 control.name, n, control.type);
894 channel->min_value = channel->max_value = 0;
898 gst_camerasrc_add_color_channel (GST_CAMERA_SRC (v4l2camsrc), channel);
901 GST_DEBUG_OBJECT (v4l2camsrc, "done");
905 /******************************************************
906 * gst_v4l2camsrc_open():
907 * open the video device (v4l2camsrc->videodev)
908 * return value: TRUE on success, FALSE on error
909 ******************************************************/
911 gst_v4l2camsrc_open (GstCameraSrc * camsrc)
914 GstPollFD pollfd = GST_POLL_FD_INIT;
916 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
918 GST_DEBUG_OBJECT (v4l2camsrc, "Trying to open device %s",
919 v4l2camsrc->videodev);
921 GST_V4L2CAMSRC_CHECK_NOT_OPEN (v4l2camsrc);
922 GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
924 /* be sure we have a device */
925 if (!v4l2camsrc->videodev)
926 v4l2camsrc->videodev = g_strdup ("/dev/video");
928 /* check if it is a device */
929 if (stat (v4l2camsrc->videodev, &st) == -1)
932 if (!S_ISCHR (st.st_mode))
935 /* open the device */
936 v4l2camsrc->video_fd =
937 open (v4l2camsrc->videodev, O_RDWR /* | O_NONBLOCK */ );
939 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
942 /* get capabilities, error will be posted */
943 if (!gst_v4l2camsrc_get_capture_capabilities (v4l2camsrc))
946 /* get capabilities, error will be posted */
947 if (!gst_v4l2camsrc_set_input_sensor (v4l2camsrc))
950 /* do we need to be a capture device? */
951 if (GST_IS_V4L2CAMSRC (v4l2camsrc) &&
952 !(v4l2camsrc->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
955 /* Before iterating enumerations, clear the parent's color channel list */
956 gst_camerasrc_clear_color_channels (camsrc);
958 /* create enumerations, posts errors. */
959 if (!gst_v4l2camsrc_fill_lists (v4l2camsrc))
962 GST_INFO_OBJECT (v4l2camsrc,
963 "Opened device '%s' (%s) successfully",
964 v4l2camsrc->vcap.card, v4l2camsrc->videodev);
966 pollfd.fd = v4l2camsrc->video_fd;
967 gst_poll_add_fd (v4l2camsrc->poll, &pollfd);
968 gst_poll_fd_ctl_read (v4l2camsrc->poll, &pollfd, TRUE);
970 gst_v4l2camsrc_libmfldcam_init (v4l2camsrc);
977 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
978 ("Cannot identify device '%s'.", v4l2camsrc->videodev),
984 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
985 ("This isn't a device '%s'.", v4l2camsrc->videodev), GST_ERROR_SYSTEM);
990 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, OPEN_READ_WRITE,
991 ("Could not open device '%s' for reading and writing.",
992 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
997 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
998 ("Device '%s' is not a capture device.",
999 v4l2camsrc->videodev),
1000 ("Capabilities: 0x%x", v4l2camsrc->vcap.capabilities));
1005 if (GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc)) {
1007 close (v4l2camsrc->video_fd);
1008 v4l2camsrc->video_fd = -1;
1015 /******************************************************
1016 * gst_v4l2camsrc_close():
1017 * close the video device (v4l2camsrc->video_fd)
1018 * return value: TRUE on success, FALSE on error
1019 ******************************************************/
1021 gst_v4l2camsrc_close (GstCameraSrc * camsrc)
1023 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1025 GstPollFD pollfd = GST_POLL_FD_INIT;
1027 GST_DEBUG_OBJECT (v4l2camsrc, "Trying to close %s", v4l2camsrc->videodev);
1029 GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
1030 GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
1033 gst_v4l2camsrc_libmfldcam_deinit (v4l2camsrc);
1035 close (v4l2camsrc->video_fd);
1036 pollfd.fd = v4l2camsrc->video_fd;
1037 gst_poll_remove_fd (v4l2camsrc->poll, &pollfd);
1038 v4l2camsrc->video_fd = -1;
1043 /******************************************************
1044 * gst_v4l2camsrc_get_attribute():
1045 * try to get the value of one specific attribute
1046 * return value: TRUE on success, FALSE on error
1047 ******************************************************/
1049 gst_v4l2camsrc_get_attribute (GstCameraSrc * camsrc,
1050 int attribute_num, int *value)
1052 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1054 struct v4l2_control control;
1058 GST_DEBUG_OBJECT (v4l2camsrc, "getting value of attribute %d", attribute_num);
1060 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
1063 control.id = attribute_num;
1065 if (control.id > SOURCE_PRIV_BASE) {
1066 switch (control.id) {
1067 case MM_CAM_FILTER_WB_SOURCE_PRIV:
1068 err = cam_feature_get (v4l2camsrc->video_fd, CAM_AWB_MODE, &tmp_value);
1069 *value = find_item (gst_v4l2camsrc_wb_map, tmp_value);
1071 case MM_CAM_FILTER_COLOR_TONE_SOURCE_PRIV:
1072 err = cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE, &tmp_value);
1073 *value = find_item (gst_v4l2camsrc_effect_map, tmp_value);
1080 if (ioctl (v4l2camsrc->video_fd, VIDIOC_G_CTRL, &control) < 0)
1082 *value = control.value;
1089 struct v4l2_ext_controls controls;
1090 struct v4l2_ext_control control;
1092 controls.ctrl_class = V4L2_CTRL_CLASS_USER;
1094 controls.controls = &control;
1096 control.id = attribute_num;
1098 if (ioctl (v4l2camsrc->video_fd, VIDIOC_G_EXT_CTRLS, &controls) < 0)
1101 *value = control.value;
1110 GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1111 ("Failed to get value for control %d on device '%s'.",
1112 attribute_num, v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1117 /******************************************************
1118 * gst_v4l2camsrc_set_attribute():
1119 * try to set the value of one specific attribute
1120 * return value: TRUE on success, FALSE on error
1121 ******************************************************/
1123 gst_v4l2camsrc_set_attribute (GstCameraSrc * camsrc,
1124 int attribute_num, const int value)
1126 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1127 struct v4l2_control control;
1129 GST_DEBUG_OBJECT (v4l2camsrc, "setting value of attribute %d to %d",
1130 attribute_num, value);
1132 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
1135 control.id = attribute_num;
1136 control.value = value;
1137 if (control.id > SOURCE_PRIV_BASE) {
1138 switch (control.id) {
1139 case MM_CAM_FILTER_WB_SOURCE_PRIV:
1140 cam_feature_set (v4l2camsrc->video_fd, CAM_AWB_MODE, gst_v4l2camsrc_wb_map[value]);
1142 case MM_CAM_FILTER_COLOR_TONE_SOURCE_PRIV:
1143 cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE, gst_v4l2camsrc_effect_map[value]);
1151 if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_CTRL, &control) < 0)
1158 struct v4l2_ext_controls controls;
1159 struct v4l2_ext_control control;
1161 controls.ctrl_class = V4L2_CTRL_CLASS_USER;
1163 controls.controls = &control;
1165 control.id = attribute_num;
1166 control.value = value;
1168 if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_EXT_CTRLS, &controls) < 0)
1177 GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1178 ("Failed to set value %d for control %d on device '%s'.",
1179 value, attribute_num, v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1185 /* complete made up ranking, the values themselves are meaningless */
1186 #define YUV_BASE_RANK 1000
1187 #define JPEG_BASE_RANK 500
1188 #define DV_BASE_RANK 200
1189 #define RGB_BASE_RANK 100
1190 #define YUV_ODD_BASE_RANK 50
1191 #define RGB_ODD_BASE_RANK 25
1192 #define BAYER_BASE_RANK 15
1193 #define S910_BASE_RANK 10
1194 #define GREY_BASE_RANK 5
1195 #define PWC_BASE_RANK 1
1197 /* This flag is already used by libv4l2 although
1198 * it was added to the Linux kernel in 2.6.32
1200 #ifndef V4L2_FMT_FLAG_EMULATED
1201 #define V4L2_FMT_FLAG_EMULATED 0x0002
1205 gst_v4l2camsrc_format_get_rank (const struct v4l2_fmtdesc *fmt)
1207 guint32 fourcc = fmt->pixelformat;
1208 gboolean emulated = ((fmt->flags & V4L2_FMT_FLAG_EMULATED) != 0);
1212 case V4L2_PIX_FMT_MJPEG:
1213 rank = JPEG_BASE_RANK;
1215 case V4L2_PIX_FMT_JPEG:
1216 rank = JPEG_BASE_RANK + 1;
1218 case V4L2_PIX_FMT_MPEG: /* MPEG */
1219 rank = JPEG_BASE_RANK + 2;
1222 case V4L2_PIX_FMT_RGB332:
1223 case V4L2_PIX_FMT_RGB555:
1224 case V4L2_PIX_FMT_RGB555X:
1225 case V4L2_PIX_FMT_RGB565:
1226 case V4L2_PIX_FMT_RGB565X:
1227 rank = RGB_ODD_BASE_RANK;
1230 case V4L2_PIX_FMT_RGB24:
1231 case V4L2_PIX_FMT_BGR24:
1232 rank = RGB_BASE_RANK - 1;
1235 case V4L2_PIX_FMT_RGB32:
1236 case V4L2_PIX_FMT_BGR32:
1237 rank = RGB_BASE_RANK;
1240 case V4L2_PIX_FMT_GREY: /* 8 Greyscale */
1241 rank = GREY_BASE_RANK;
1244 case V4L2_PIX_FMT_NV12: /* 12 Y/CbCr 4:2:0 */
1245 case V4L2_PIX_FMT_NV21: /* 12 Y/CrCb 4:2:0 */
1246 case V4L2_PIX_FMT_YYUV: /* 16 YUV 4:2:2 */
1247 case V4L2_PIX_FMT_HI240: /* 8 8-bit color */
1248 case V4L2_PIX_FMT_NV16: /* 16 bit YUV 422, Y, UV plane */
1249 rank = YUV_ODD_BASE_RANK;
1251 case V4L2_PIX_FMT_YUV444: /* YUV 444, 24 bits per pixel */
1252 rank = YUV_BASE_RANK + 0;
1254 case V4L2_PIX_FMT_YVU410: /* YVU9, 9 bits per pixel */
1255 rank = YUV_BASE_RANK + 3;
1257 case V4L2_PIX_FMT_YUV410: /* YUV9, 9 bits per pixel */
1258 rank = YUV_BASE_RANK + 2;
1260 case V4L2_PIX_FMT_YUV420: /* I420, 12 bits per pixel */
1261 rank = YUV_BASE_RANK + 7;
1263 case V4L2_PIX_FMT_YUYV: /* YUY2, 16 bits per pixel */
1264 rank = YUV_BASE_RANK + 10;
1266 case V4L2_PIX_FMT_YVU420: /* YV12, 12 bits per pixel */
1267 rank = YUV_BASE_RANK + 6;
1269 case V4L2_PIX_FMT_UYVY: /* UYVY, 16 bits per pixel */
1270 rank = YUV_BASE_RANK + 9;
1272 case V4L2_PIX_FMT_Y41P: /* Y41P, 12 bits per pixel */
1273 rank = YUV_BASE_RANK + 5;
1275 case V4L2_PIX_FMT_YUV411P: /* Y41B, 12 bits per pixel */
1276 rank = YUV_BASE_RANK + 4;
1278 case V4L2_PIX_FMT_YUV422P: /* Y42B, 16 bits per pixel */
1279 rank = YUV_BASE_RANK + 8;
1282 case V4L2_PIX_FMT_DV:
1283 rank = DV_BASE_RANK;
1286 case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */
1290 case V4L2_PIX_FMT_SBGGR8:
1291 case V4L2_PIX_FMT_SRGGB8:
1292 case V4L2_PIX_FMT_SGBRG8:
1293 case V4L2_PIX_FMT_SGRBG10:
1294 case V4L2_PIX_FMT_SRGGB10:
1295 case V4L2_PIX_FMT_SGBRG10:
1296 rank = BAYER_BASE_RANK;
1299 #ifdef V4L2_PIX_FMT_SN9C10X
1300 case V4L2_PIX_FMT_SN9C10X:
1301 rank = S910_BASE_RANK;
1305 #ifdef V4L2_PIX_FMT_PWC1
1306 case V4L2_PIX_FMT_PWC1:
1307 rank = PWC_BASE_RANK;
1310 #ifdef V4L2_PIX_FMT_PWC2
1311 case V4L2_PIX_FMT_PWC2:
1312 rank = PWC_BASE_RANK;
1317 GST_LOG("Don't know how to rank pixelformat %" GST_FOURCC_FORMAT,
1318 GST_FOURCC_ARGS(fourcc));
1323 /* All ranks are below 1<<15 so a shift by 15
1324 * will a) make all non-emulated formats larger
1325 * than emulated and b) will not overflow
1334 gst_v4l2camsrc_format_cmp_func (gconstpointer a, gconstpointer b)
1336 const struct v4l2_fmtdesc *fa = a;
1337 const struct v4l2_fmtdesc *fb = b;
1339 if (fa->pixelformat == fb->pixelformat)
1342 return gst_v4l2camsrc_format_get_rank (fb) -
1343 gst_v4l2camsrc_format_get_rank (fa);
1346 static gboolean is_supported_pixelformat(guint32 fourcc)
1348 if(fourcc == V4L2_PIX_FMT_NV12
1349 || fourcc == V4L2_PIX_FMT_YUV420
1350 || fourcc == V4L2_PIX_FMT_SGRBG10)
1355 /******************************************************
1356 * gst_v4l2camsrc_fill_format_list():
1357 * create list of supported capture formats
1358 * return value: TRUE on success, FALSE on error
1359 ******************************************************/
1361 gst_v4l2camsrc_fill_format_list (GstMFLDV4l2CamSrc * v4l2camsrc)
1364 struct v4l2_fmtdesc *format;
1366 GST_DEBUG_OBJECT (v4l2camsrc, "getting src format enumerations");
1368 /* format enumeration */
1370 format = g_new0 (struct v4l2_fmtdesc, 1);
1373 format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1375 if (ioctl (v4l2camsrc->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
1376 if (errno == EINVAL) {
1378 break; /* end of enumeration */
1383 if(!is_supported_pixelformat(format->pixelformat)) {
1384 GST_LOG_OBJECT(v4l2camsrc, " (skipping format %" GST_FOURCC_FORMAT ")",GST_FOURCC_ARGS (format->pixelformat));
1388 GST_LOG_OBJECT (v4l2camsrc, "index: %u", format->index);
1389 GST_LOG_OBJECT (v4l2camsrc, "type: %d", format->type);
1390 GST_LOG_OBJECT (v4l2camsrc, "flags: %08x", format->flags);
1391 GST_LOG_OBJECT (v4l2camsrc, "description: '%s'", format->description);
1392 GST_LOG_OBJECT (v4l2camsrc, "pixelformat: %" GST_FOURCC_FORMAT,
1393 GST_FOURCC_ARGS (format->pixelformat));
1395 /* sort formats according to our preference; we do this, because caps
1396 * are probed in the order the formats are in the list, and the order of
1397 * formats in the final probed caps matters for things like fixation */
1398 v4l2camsrc->formats = g_slist_insert_sorted (v4l2camsrc->formats, format,
1399 (GCompareFunc) gst_v4l2camsrc_format_cmp_func);
1402 GST_DEBUG_OBJECT (v4l2camsrc, "got %d format(s)", n);
1409 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1410 ("Failed to enumerate possible video formats device '%s' can work with",
1411 v4l2camsrc->videodev),
1412 ("Failed to get number %d in pixelformat enumeration for %s. (%d - %s)",
1413 n, v4l2camsrc->videodev, errno, g_strerror (errno)));
1419 /******************************************************
1420 * gst_v4l2camsrc_clear_format_list():
1421 * free list of supported capture formats
1422 * return value: TRUE on success, FALSE on error
1423 ******************************************************/
1425 gst_v4l2camsrc_clear_format_list (GstMFLDV4l2CamSrc * v4l2camsrc)
1427 g_slist_foreach (v4l2camsrc->formats, (GFunc) g_free, NULL);
1428 g_slist_free (v4l2camsrc->formats);
1429 v4l2camsrc->formats = NULL;
1434 /* The frame interval enumeration code first appeared in Linux 2.6.19. */
1435 #ifdef VIDIOC_ENUM_FRAMEINTERVALS
1436 static GstStructure *
1437 gst_v4l2camsrc_probe_caps_for_format_and_size (GstMFLDV4l2CamSrc * v4l2camsrc,
1438 guint32 pixelformat,
1439 guint32 width, guint32 height, const GstStructure * template)
1441 gint fd = v4l2camsrc->video_fd;
1442 struct v4l2_frmivalenum ival;
1445 GValue rates = { 0, };
1447 memset (&ival, 0, sizeof (struct v4l2_frmivalenum));
1449 ival.pixel_format = pixelformat;
1451 ival.height = height;
1453 GST_LOG_OBJECT (v4l2camsrc, "get frame interval for %ux%u, %"
1454 GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat));
1456 /* keep in mind that v4l2 gives us frame intervals (durations); we invert the
1457 * fraction to get framerate */
1458 if (ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0)
1459 goto enum_frameintervals_failed;
1461 if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
1462 GValue rate = { 0, };
1464 g_value_init (&rates, GST_TYPE_LIST);
1465 g_value_init (&rate, GST_TYPE_FRACTION);
1468 num = ival.discrete.numerator;
1469 denom = ival.discrete.denominator;
1471 if (num > G_MAXINT || denom > G_MAXINT) {
1472 /* let us hope we don't get here... */
1477 GST_LOG_OBJECT (v4l2camsrc, "adding discrete framerate: %d/%d",
1480 /* swap to get the framerate */
1481 gst_value_set_fraction (&rate, denom, num);
1482 gst_value_list_append_value (&rates, &rate);
1485 } while (ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
1487 /* FIXME MASSIVE UGLY HACK: Pretend to support 30/1 fps always */
1488 gst_value_set_fraction(&rate, 30, 1);
1489 gst_value_list_append_value(&rates, &rate);
1491 } else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
1492 GValue min = { 0, };
1493 GValue step = { 0, };
1494 GValue max = { 0, };
1495 gboolean added = FALSE;
1496 guint32 minnum, mindenom;
1497 guint32 maxnum, maxdenom;
1499 g_value_init (&rates, GST_TYPE_LIST);
1501 g_value_init (&min, GST_TYPE_FRACTION);
1502 g_value_init (&step, GST_TYPE_FRACTION);
1503 g_value_init (&max, GST_TYPE_FRACTION);
1506 minnum = ival.stepwise.min.numerator;
1507 mindenom = ival.stepwise.min.denominator;
1508 if (minnum > G_MAXINT || mindenom > G_MAXINT) {
1512 GST_LOG_OBJECT (v4l2camsrc, "stepwise min frame interval: %d/%d", minnum,
1514 gst_value_set_fraction (&min, minnum, mindenom);
1517 maxnum = ival.stepwise.max.numerator;
1518 maxdenom = ival.stepwise.max.denominator;
1519 if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
1524 GST_LOG_OBJECT (v4l2camsrc, "stepwise max frame interval: %d/%d", maxnum,
1526 gst_value_set_fraction (&max, maxnum, maxdenom);
1529 num = ival.stepwise.step.numerator;
1530 denom = ival.stepwise.step.denominator;
1531 if (num > G_MAXINT || denom > G_MAXINT) {
1536 if (num == 0 || denom == 0) {
1537 /* in this case we have a wrong fraction or no step, set the step to max
1538 * so that we only add the min value in the loop below */
1543 /* since we only have gst_value_fraction_subtract and not add, negate the
1545 GST_LOG_OBJECT (v4l2camsrc, "stepwise step frame interval: %d/%d",
1548 gst_value_set_fraction (&step, -num, denom);
1550 while (gst_value_compare (&min, &max) <= 0) {
1551 GValue rate = { 0, };
1553 num = gst_value_get_fraction_numerator (&min);
1554 denom = gst_value_get_fraction_denominator (&min);
1555 GST_LOG_OBJECT (v4l2camsrc, "adding stepwise framerate: %d/%d",
1558 /* invert to get the framerate */
1559 g_value_init (&rate, GST_TYPE_FRACTION);
1560 gst_value_set_fraction (&rate, denom, num);
1561 gst_value_list_append_value (&rates, &rate);
1564 /* we're actually adding because step was negated above. This is because
1565 * there is no _add function... */
1566 if (!gst_value_fraction_subtract (&min, &min, &step)) {
1567 GST_WARNING_OBJECT (v4l2camsrc, "could not step fraction!");
1572 /* no range was added, leave the default range from the template */
1573 GST_WARNING_OBJECT (v4l2camsrc, "no range added, leaving default");
1574 g_value_unset (&rates);
1576 } else if (ival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
1577 guint32 maxnum, maxdenom;
1579 g_value_init (&rates, GST_TYPE_FRACTION_RANGE);
1581 num = ival.stepwise.min.numerator;
1582 denom = ival.stepwise.min.denominator;
1583 if (num > G_MAXINT || denom > G_MAXINT) {
1588 maxnum = ival.stepwise.max.numerator;
1589 maxdenom = ival.stepwise.max.denominator;
1590 if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
1595 GST_LOG_OBJECT (v4l2camsrc, "continuous frame interval %d/%d to %d/%d",
1596 maxdenom, maxnum, denom, num);
1598 gst_value_set_fraction_range_full (&rates, maxdenom, maxnum, denom, num);
1604 s = gst_structure_copy (template);
1605 /* https://projects.maemo.org/bugzilla/show_bug.cgi?id=105590 */
1606 gst_structure_set (s,
1607 "width", G_TYPE_INT, (gint) width,
1608 "height", G_TYPE_INT, (gint) height, NULL);
1610 if (G_IS_VALUE (&rates)) {
1611 /* only change the framerate on the template when we have a valid probed new
1613 gst_structure_set_value (s, "framerate", &rates);
1614 g_value_unset (&rates);
1619 enum_frameintervals_failed:
1621 GST_DEBUG_OBJECT (v4l2camsrc,
1622 "Unable to enumerate intervals for %" GST_FOURCC_FORMAT "@%ux%u",
1623 GST_FOURCC_ARGS (pixelformat), width, height);
1628 /* I don't see how this is actually an error, we ignore the format then */
1629 GST_WARNING_OBJECT (v4l2camsrc,
1630 "Unknown frame interval type at %" GST_FOURCC_FORMAT "@%ux%u: %u",
1631 GST_FOURCC_ARGS (pixelformat), width, height, ival.type);
1635 #endif /* defined VIDIOC_ENUM_FRAMEINTERVALS */
1641 compare_resolutions (gconstpointer a, gconstpointer b)
1643 GstStructure *as = (GstStructure *) a;
1644 GstStructure *bs = (GstStructure *) b;
1645 gint aw, bw, ah, bh;
1647 gst_structure_get_int (as, "width", &aw);
1648 gst_structure_get_int (bs, "width", &bw);
1649 gst_structure_get_int (as, "height", &ah);
1650 gst_structure_get_int (bs, "height", &bh);
1652 /* FIXME: What is the best way to compare resolutions if their aspect
1653 * ratio isn't the same? */
1654 return ((aw - bw) + (ah - bh));
1661 fractions_are_equal (gint num1, gint den1, gint num2, gint den2)
1663 GValue fraction1 = { 0, }, fraction2 = {
1666 g_value_init (&fraction1, GST_TYPE_FRACTION);
1667 g_value_init (&fraction2, GST_TYPE_FRACTION);
1668 gst_value_set_fraction (&fraction1, num1, den1);
1669 gst_value_set_fraction (&fraction2, num2, den2);
1670 /* we know we don't have to unset the values in this case */
1671 return (gst_value_compare (&fraction1, &fraction2) == GST_VALUE_EQUAL);
1675 gst_v4l2camsrc_get_frame_size (guint32 fourcc, guint * w, guint * h)
1680 case V4L2_PIX_FMT_YUV420:
1681 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1682 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1684 case V4L2_PIX_FMT_YUYV:
1685 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1687 case V4L2_PIX_FMT_Y41P:
1688 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1690 case V4L2_PIX_FMT_UYVY:
1691 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1693 case V4L2_PIX_FMT_YVU420:
1694 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1695 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1697 case V4L2_PIX_FMT_YUV411P:
1698 outsize = GST_ROUND_UP_4 (*w) * *h;
1699 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
1701 case V4L2_PIX_FMT_YUV422P:
1702 outsize = GST_ROUND_UP_4 (*w) * *h;
1703 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
1705 case V4L2_PIX_FMT_NV12:
1706 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1707 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1709 case V4L2_PIX_FMT_NV21:
1710 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1711 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1721 gst_v4l2camsrc_configure_device (GstMFLDV4l2CamSrc * v4l2camsrc,
1722 guint32 * pixelformat, guint * width, guint * height,
1723 guint * fps_n, guint * fps_d)
1725 gint fd = v4l2camsrc->video_fd;
1726 struct v4l2_format format;
1727 struct v4l2_streamparm stream;
1728 gboolean ret = TRUE;
1730 GST_DEBUG_OBJECT (v4l2camsrc, "Configuring device to %dx%d, format "
1731 "%" GST_FOURCC_FORMAT, *width, *height, GST_FOURCC_ARGS (*pixelformat));
1733 GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
1735 memset (&format, 0x00, sizeof (struct v4l2_format));
1736 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1738 if (ioctl (fd, VIDIOC_G_FMT, &format) < 0)
1739 goto get_fmt_failed;
1741 if (v4l2camsrc->dump_raw)
1742 format.type = V4L2_BUF_TYPE_PRIVATE;
1744 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1745 format.fmt.pix.width = *width;
1746 format.fmt.pix.height = *height;
1747 format.fmt.pix.pixelformat = *pixelformat;
1748 /* request whole frames; change when gstreamer supports interlaced video
1749 * (INTERLACED mode returns frames where the fields have already been
1750 * combined, there are other modes for requesting fields individually) */
1751 format.fmt.pix.field = V4L2_FIELD_INTERLACED;
1753 if (ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
1754 if (errno != EINVAL)
1755 goto set_fmt_failed;
1757 /* try again with progressive video */
1758 format.fmt.pix.width = *width;
1759 format.fmt.pix.height = *height;
1760 format.fmt.pix.pixelformat = *pixelformat;
1761 format.fmt.pix.field = V4L2_FIELD_NONE;
1762 if (ioctl (fd, VIDIOC_S_FMT, &format) < 0)
1763 goto set_fmt_failed;
1766 if (v4l2camsrc->dump_raw)
1767 v4l2camsrc->raw_output_size = format.fmt.pix.priv;
1769 if (format.fmt.pix.width != *width || format.fmt.pix.height != *height)
1770 goto invalid_dimensions;
1772 if (format.fmt.pix.pixelformat != *pixelformat)
1773 goto invalid_pixelformat;
1775 memset (&stream, 0x00, sizeof (struct v4l2_streamparm));
1776 stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1777 if (ioctl (fd, VIDIOC_G_PARM, &stream) < 0) {
1778 GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1779 ("Could not get parameters on device '%s'",
1780 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1784 if (fps_n == NULL || fps_d == NULL) {
1785 GST_LOG_OBJECT (v4l2camsrc, "Framerate will not be set");
1789 GST_LOG_OBJECT (v4l2camsrc, "Desired framerate: %u/%u", *fps_n, *fps_d);
1791 /* Note: V4L2 provides the frame interval, we have the frame rate */
1792 if (stream.parm.capture.timeperframe.denominator &&
1793 fractions_are_equal (stream.parm.capture.timeperframe.numerator,
1794 stream.parm.capture.timeperframe.denominator, *fps_d, *fps_n)) {
1795 GST_LOG_OBJECT (v4l2camsrc, "Desired framerate already set, nothing to do");
1799 /* We want to change the frame rate, so check whether we can. Some cheap USB
1800 * cameras don't have the capability */
1801 if ((stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
1802 GST_DEBUG_OBJECT (v4l2camsrc, "Not setting framerate (not supported)");
1806 GST_LOG_OBJECT (v4l2camsrc, "Setting framerate to %u/%u", *fps_n, *fps_d);
1808 /* Note: V4L2 wants the frame interval, we have the frame rate */
1809 stream.parm.capture.timeperframe.numerator = *fps_d;
1810 stream.parm.capture.timeperframe.denominator = *fps_n;
1812 /* some cheap USB cam's won't accept any change */
1813 if (ioctl (fd, VIDIOC_S_PARM, &stream) < 0) {
1814 GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1815 ("Video input device did not accept new frame rate setting."),
1820 GST_INFO_OBJECT (v4l2camsrc, "Set frame interval to %u/%u",
1821 stream.parm.capture.timeperframe.numerator,
1822 stream.parm.capture.timeperframe.denominator);
1824 cam_set_frame_rate( ((gfloat)stream.parm.capture.timeperframe.denominator / stream.parm.capture.timeperframe.numerator));
1827 v4l2camsrc->max_zoom_factor = 10.0;
1828 v4l2camsrc->frame_byte_size = gst_v4l2camsrc_get_frame_size (*pixelformat,
1830 /* v4l2camsrc->frame_byte_size = GST_ROUND_UP_2 (*width) * 2 * (*height); */
1832 if (v4l2camsrc->bayer_downscaling) {
1833 struct v4l2_crop crop;
1834 memset (&v4l2camsrc->vcrop, 0, sizeof (struct v4l2_cropcap));
1835 v4l2camsrc->vcrop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1836 if (ioctl (v4l2camsrc->video_fd, VIDIOC_CROPCAP, &v4l2camsrc->vcrop) < 0) {
1837 GST_DEBUG_OBJECT (v4l2camsrc, "Failed to query crop cap");
1841 crop.c = v4l2camsrc->vcrop.defrect; /* reset to default */
1842 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1843 if (-1 == ioctl (fd, VIDIOC_S_CROP, &crop)) {
1846 GST_DEBUG_OBJECT (v4l2camsrc, "Crop not support\n");
1849 GST_DEBUG_OBJECT (v4l2camsrc, "Crop failed\n");
1858 v4l2camsrc->crop_supported = TRUE;
1860 GST_DEBUG_OBJECT (v4l2camsrc, "got cropping bounds: x:%d, y:%d, w:%d, h:%d",
1861 v4l2camsrc->vcrop.bounds.left,
1862 v4l2camsrc->vcrop.bounds.top,
1863 v4l2camsrc->vcrop.bounds.width, v4l2camsrc->vcrop.bounds.height);
1865 GST_DEBUG_OBJECT (v4l2camsrc, "cropping defrect: x:%d, y:%d, w:%d, h:%d",
1866 v4l2camsrc->vcrop.defrect.left,
1867 v4l2camsrc->vcrop.defrect.top,
1868 v4l2camsrc->vcrop.defrect.width, v4l2camsrc->vcrop.defrect.height);
1870 gst_v4l2camsrc_update_cropping (v4l2camsrc, *width, *height, 1.0);
1874 cam_set_capture_fmt (v4l2camsrc->video_fd, *width, *height, *pixelformat);
1881 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1882 ("Device '%s' does not support video capture",
1883 v4l2camsrc->videodev),
1884 ("Call to G_FMT failed: (%s)", g_strerror (errno)));
1889 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1890 ("Device '%s' cannot capture at %dx%d",
1891 v4l2camsrc->videodev, *width, *height),
1892 ("Call to S_FMT failed for %" GST_FOURCC_FORMAT " @ %dx%d: %s",
1893 GST_FOURCC_ARGS (*pixelformat), *width, *height,
1894 g_strerror (errno)));
1899 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1900 ("Device '%s' cannot capture at %dx%d",
1901 v4l2camsrc->videodev, *width, *height),
1902 ("Tried to capture at %dx%d, but device returned size %dx%d",
1903 *width, *height, format.fmt.pix.width, format.fmt.pix.height));
1906 invalid_pixelformat:
1908 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1909 ("Device '%s' cannot capture in the specified format",
1910 v4l2camsrc->videodev),
1911 ("Tried to capture in %" GST_FOURCC_FORMAT
1912 ", but device returned format" " %" GST_FOURCC_FORMAT,
1913 GST_FOURCC_ARGS (*pixelformat),
1914 GST_FOURCC_ARGS (format.fmt.pix.pixelformat)));
1919 static gboolean resolution_is_supported(int w, int h)
1921 return (w % 4) == 0 && (h % 4) == 0;
1924 #define probe_and_add_for_w_h(w, h) \
1926 GST_LOG(" w=%lu h=%lu",w,h); \
1927 tmp = gst_v4l2camsrc_probe_caps_for_format_and_size(v4l2camsrc, \
1928 pixelformat, w, h, template); \
1930 res = g_list_prepend(res, tmp); \
1934 static GList *build_caps_list(GstMFLDV4l2CamSrc * v4l2camsrc,
1935 guint32 pixelformat, const GstStructure * template,
1936 struct v4l2_frmsizeenum *size)
1938 GstStructure *tmp = NULL;
1940 long wl,wh,hl,hh,ws,hs;
1942 wl = size->stepwise.min_width; wh = size->stepwise.max_width; ws = size->stepwise.step_width;
1943 hl = size->stepwise.min_height; hh = size->stepwise.max_height; hs = size->stepwise.step_height;
1945 probe_and_add_for_w_h(wl, hl);
1946 probe_and_add_for_w_h(wh, hh);
1948 tmp = gst_structure_copy(template);
1949 gst_structure_set (tmp,
1950 "width", GST_TYPE_INT_RANGE, wl, wh,
1951 "height", GST_TYPE_INT_RANGE, hl, hh,
1953 res = g_list_prepend(res, tmp);
1960 * gst_v4l2camsrc_probe_caps_for_format:
1961 * @v4l2camsrc: #GstMFLDV4l2CamSrc object
1962 * @pixelformat: pixel format fourcc
1963 * @template: GstStructure template to be used for generating the caps
1965 * Creates GstCaps object which describes the supported caps of the device.
1967 * Returns: GStCaps containing supported video resolutions.
1970 gst_v4l2camsrc_probe_caps_for_format (GstMFLDV4l2CamSrc * v4l2camsrc,
1971 guint32 pixelformat, const GstStructure * template)
1973 GstCaps *ret = gst_caps_new_empty ();
1974 gint min_w, max_w, min_h, max_h;
1977 #ifdef VIDIOC_ENUM_FRAMESIZES
1979 gint fd = v4l2camsrc->video_fd;
1980 struct v4l2_frmsizeenum size;
1981 GList *results = NULL;
1984 memset (&size, 0, sizeof (struct v4l2_frmsizeenum));
1986 size.pixel_format = pixelformat;
1988 if (ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0)
1989 goto enum_framesizes_failed;
1991 if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
1993 w = MIN (size.discrete.width, G_MAXINT);
1994 h = MIN (size.discrete.height, G_MAXINT);
1996 if(resolution_is_supported(w, h)) {
1997 tmp = gst_v4l2camsrc_probe_caps_for_format_and_size (v4l2camsrc,
1998 pixelformat, w, h, template);
2001 results = g_list_prepend (results, tmp);
2005 } while (ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
2006 } else if(size.type == V4L2_FRMSIZE_TYPE_STEPWISE
2007 || size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
2008 results = build_caps_list(v4l2camsrc, pixelformat, template, &size);
2013 /* Sort the resolutions from smallest to largest */
2014 results = g_list_sort (results, compare_resolutions);
2016 while (results != NULL) {
2017 tmp = GST_STRUCTURE (results->data);
2019 gst_caps_merge_structure (ret, tmp);
2021 results = g_list_delete_link (results, results);
2024 if (gst_caps_is_empty (ret))
2025 goto enum_framesizes_no_results;
2030 enum_framesizes_failed:
2032 /* I don't see how this is actually an error */
2033 GST_DEBUG_OBJECT (v4l2camsrc,
2034 "Failed to enumerate frame sizes for pixelformat %" GST_FOURCC_FORMAT
2035 " (%s)", GST_FOURCC_ARGS (pixelformat), g_strerror (errno));
2036 goto default_frame_sizes;
2038 enum_framesizes_no_results:
2040 /* it's possible that VIDIOC_ENUM_FRAMESIZES is defined but the driver in
2041 * question doesn't actually support it yet */
2042 GST_DEBUG_OBJECT (v4l2camsrc, "No results for pixelformat %"
2043 GST_FOURCC_FORMAT " enumerating frame sizes, trying fallback",
2044 GST_FOURCC_ARGS (pixelformat));
2045 goto default_frame_sizes;
2049 GST_WARNING_OBJECT (v4l2camsrc,
2050 "Unknown frame sizeenum type for pixelformat %" GST_FOURCC_FORMAT
2051 ": %u", GST_FOURCC_ARGS (pixelformat), size.type);
2052 goto default_frame_sizes;
2055 #endif /* defined VIDIOC_ENUM_FRAMESIZES */
2057 default_frame_sizes:
2060 max_w = max_h = GST_CAMERA_SRC_MAX_SIZE;
2061 if (!gst_v4l2camsrc_get_nearest_size (v4l2camsrc, pixelformat,
2063 GST_WARNING_OBJECT (v4l2camsrc,
2064 "Could not probe minimum capture size for pixelformat %"
2065 GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2067 if (!gst_v4l2camsrc_get_nearest_size (v4l2camsrc, pixelformat,
2069 GST_WARNING_OBJECT (v4l2camsrc,
2070 "Could not probe maximum capture size for pixelformat %"
2071 GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2074 tmp = gst_structure_copy (template);
2075 gst_structure_set (tmp,
2076 "width", GST_TYPE_INT_RANGE, min_w, max_w,
2077 "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL);
2078 gst_caps_append_structure (ret, tmp);
2083 static void draw_corner_markers_nv12(unsigned char *buf, unsigned w, unsigned h)
2086 #define put_dot(x,y) buf[(x)+w*(y)] = (((x+y)&0x01)?0x00:0xff)
2088 for(j = 0; j < 4; ++j)
2089 for(i = 0; i < 8; ++i) {
2090 put_dot(i, j); put_dot(w-1-i, j);
2091 put_dot(j, i); put_dot(j, h-1-i);
2092 put_dot(i, h-1-j); put_dot(w-1-i, h-1-j);
2093 put_dot(w-1-j, i); put_dot(w-1-j, h-1-i);
2098 /* Crop to upper left corner of NV12 frame. */
2099 static gboolean crop_buffer_inplace_nv12(unsigned char *buf, unsigned in_w, unsigned in_h,
2100 unsigned out_w, unsigned out_h)
2103 unsigned char *in, *out;
2105 if(in_w < out_w || in_h < out_h
2106 || in_w % 4 || out_w % 4
2107 || in_h % 4 || out_h % 4)
2110 in = buf; out = buf;
2111 for(rows = 0; rows < out_h; ++rows) {
2112 memmove(out, in, out_w);
2116 in = buf + in_w * in_h;
2117 for(rows = 0; rows < out_h / 2; ++rows) {
2118 memmove(out, in, out_w);
2127 * gst_v4l2camsrc_libmfld_grab_hq_frame:
2128 * @v4l2camsrc: #GstMFLDV4l2CamSrc object
2129 * @buf: Pointer to v4l2_buffer where to place the image frame
2131 * Grab a High-Quality image by using libmfldcam.
2133 * Returns: TRUE if capture succeeds, FALSE otherwise
2136 gst_v4l2camsrc_libmfld_grab_hq_frame (GstMFLDV4l2CamSrc * v4l2camsrc,
2137 struct v4l2_buffer * buffer)
2141 struct cam_capture_settings st;
2143 st.mmap = v4l2camsrc->use_mmap;
2144 st.ae_awb_af = v4l2camsrc->ae_awb_af_enabled;
2145 st.dump_raw = v4l2camsrc->dump_raw;
2146 st.raw_output_size = v4l2camsrc->raw_output_size;
2147 st.dump_image = v4l2camsrc->dump_image;
2149 err = cam_capture_frames (v4l2camsrc->video_fd, buffer, &st);
2150 if (v4l2camsrc->ae_awb_af_enabled)
2151 mfldcam_3a_start ();
2152 ret = (err == CAM_ERR_NONE);
2157 /******************************************************
2158 * gst_v4l2camsrc_grab_frame ():
2159 * grab a frame for capturing
2160 * return value: GST_FLOW_OK, GST_FLOW_WRONG_STATE or GST_FLOW_ERROR
2161 ******************************************************/
2163 gst_v4l2camsrc_grab_frame (GstCameraSrc * camsrc, GstBuffer ** buf,
2164 GstCameraCapturePhase phase)
2166 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2168 #define NUM_TRIALS 5000
2169 struct v4l2_buffer buffer;
2170 gint32 trials = NUM_TRIALS;
2171 GstBuffer *pool_buffer;
2172 gboolean need_copy = v4l2camsrc->use_copy;
2173 gboolean variable_frame_size = FALSE; /* FIXME if we ever support JPEG etc */
2178 /* wait if all buffers are DQBuf */
2179 g_mutex_lock (v4l2camsrc->device_mutex);
2180 gst_v4l2_buffer_pool_update (v4l2camsrc->pool, v4l2camsrc);
2181 g_mutex_unlock (v4l2camsrc->device_mutex);
2183 memset (&buffer, 0x00, sizeof (buffer));
2184 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2186 if (v4l2camsrc->use_mmap)
2187 buffer.memory = V4L2_MEMORY_MMAP;
2189 buffer.memory = V4L2_MEMORY_USERPTR;
2191 if (phase == GST_CAMERA_CAPTURE) {
2192 gst_camerasrc_send_capture_start_message (camsrc);
2196 ret = gst_poll_wait (v4l2camsrc->poll, V4L2CAMSRC_POLL_TIMEOUT);
2197 if (G_UNLIKELY (ret < 0)) {
2200 if (errno != EAGAIN && errno != EINTR)
2204 if (G_UNLIKELY (ret == 0)) {
2207 g_mutex_lock (v4l2camsrc->device_mutex);
2208 ret = gst_v4l2camsrc_libmfld_grab_hq_frame (v4l2camsrc, &buffer);
2209 g_mutex_unlock (v4l2camsrc->device_mutex);
2214 GST_WARNING_OBJECT (v4l2camsrc,
2215 "problem grabbing frame %d (ix=%d), trials=%d, pool-ct=%d, buf.flags=%d",
2216 buffer.sequence, buffer.index, trials,
2217 GST_MINI_OBJECT_REFCOUNT (v4l2camsrc->pool), buffer.flags);
2219 /* if the sync() got interrupted, we can retry */
2222 GST_WARNING_OBJECT (v4l2camsrc,
2223 "Non-blocking I/O has been selected using O_NONBLOCK and"
2224 " no buffer was in the outgoing queue. device %s",
2225 v4l2camsrc->videodev);
2232 GST_INFO_OBJECT (v4l2camsrc,
2233 "VIDIOC_DQBUF failed due to an internal error."
2234 " Can also indicate temporary problems like signal loss."
2235 " Note the driver might dequeue an (empty) buffer despite"
2236 " returning an error, or even stop capturing."
2237 " device %s", v4l2camsrc->videodev);
2238 /* have we de-queued a buffer ? */
2239 if (!(buffer.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
2241 if ((buffer.index >= 0) && (buffer.index < v4l2camsrc->breq.count)) {
2242 GST_DEBUG_OBJECT (v4l2camsrc, "reenqueing buffer (ix=%ld)", buffer.index);
2243 gst_v4l2camsrc_queue_frame (v4l2camsrc, buffer.index);
2247 GST_DEBUG_OBJECT (v4l2camsrc, "reenqueing buffer");
2248 /* FIXME: this is not a good idea, as drivers usualy return the buffer
2249 * with index-number set to 0, thus the re-enque will fail unless it
2250 * was incidentialy 0.
2251 * We could try to re-enque all buffers without handling the ioctl
2255 if (ioctl (v4l2camsrc->video_fd, VIDIOC_QBUF, &buffer) < 0) {
2263 GST_WARNING_OBJECT (v4l2camsrc,
2264 "could not sync on a buffer on device %s", v4l2camsrc->videodev);
2267 GST_WARNING_OBJECT (v4l2camsrc,
2268 "Grabbing frame got interrupted on %s. No expected reason.",
2269 v4l2camsrc->videodev);
2273 /* check nr. of attempts to capture */
2274 if (--trials == -1) {
2275 goto too_many_trials;
2277 memset (&buffer, 0x00, sizeof (buffer));
2278 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2279 if (v4l2camsrc->use_mmap)
2280 buffer.memory = V4L2_MEMORY_MMAP;
2282 buffer.memory = V4L2_MEMORY_USERPTR;
2286 if (phase == GST_CAMERA_CAPTURE) {
2287 gst_camerasrc_send_capture_stop_message (camsrc);
2289 /* Send the CAF status message */
2290 GstCameraFocusStatus focus_status;
2292 lret = gst_v4l2camsrc_check_focus_status(v4l2camsrc, &focus_status, FALSE);
2294 GST_LOG_OBJECT (v4l2camsrc, "CAF status: %d", focus_status.status);
2295 if (focus_status.status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS )
2296 gst_camerasrc_send_af_status(GST_CAMERA_SRC (v4l2camsrc) ,CAMERASRC_AUTO_FOCUS_RESULT_FOCUSED);
2297 else if (focus_status.status == GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL )
2298 gst_camerasrc_send_af_status(GST_CAMERA_SRC (v4l2camsrc) ,CAMERASRC_AUTO_FOCUS_RESULT_FAILED);
2300 GST_WARNING_OBJECT (v4l2camsrc, "CAF status erronous: %d send as failed", focus_status.status);
2301 gst_camerasrc_send_af_status(GST_CAMERA_SRC (v4l2camsrc) ,CAMERASRC_AUTO_FOCUS_RESULT_FAILED);
2307 g_mutex_lock (v4l2camsrc->pool->lock);
2309 index = buffer.index;
2311 /* get our GstBuffer with that index from the pool, if the buffer is
2312 * in use (NULL) we have a serious problem (should only be possible in mmap
2314 pool_buffer = GST_BUFFER (v4l2camsrc->pool->buffers[index]);
2316 if (G_UNLIKELY (pool_buffer == NULL))
2319 GST_LOG_OBJECT (v4l2camsrc, "grabbed buffer %p at index %d (refct = %d)",
2320 pool_buffer, index, GST_MINI_OBJECT_REFCOUNT (pool_buffer));
2322 /* ref the buffer and requeue, when if becomes writable again */
2323 v4l2camsrc->pool->buffers[index] = NULL;
2324 v4l2camsrc->pool->num_live_buffers++;
2325 v4l2camsrc->pool->queued[index] = 0;
2327 /* SW workaround for ISP padding. */
2329 if(v4l2camsrc->expected_capture_w < 320 && (v4l2camsrc->expected_capture_w % 32 != 0)
2330 && v4l2camsrc->expected_capture_fourcc == V4L2_PIX_FMT_NV12
2331 && !v4l2camsrc->disable_low_res_crop) {
2333 real_w = (v4l2camsrc->expected_capture_w & ~31) + 32;
2335 GST_LOG_OBJECT(v4l2camsrc, "Downscaling padded buffer with cropping (%u,%u) -> (%u,%u)",
2336 real_w, v4l2camsrc->expected_capture_h, v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h);
2338 if(!crop_buffer_inplace_nv12(GST_BUFFER_DATA(pool_buffer),
2339 real_w, v4l2camsrc->expected_capture_h,
2340 v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h)) {
2341 GST_ERROR_OBJECT(v4l2camsrc,"Software crop failed");
2345 if(v4l2camsrc->draw_corner_markers)
2346 draw_corner_markers_nv12(GST_BUFFER_DATA(pool_buffer),
2347 v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h);
2349 g_mutex_unlock (v4l2camsrc->pool->lock);
2351 /* this can change at every frame, esp. with jpeg */
2352 if(variable_frame_size)
2353 GST_BUFFER_SIZE (pool_buffer) = buffer.bytesused;
2355 GST_BUFFER_SIZE (pool_buffer) = v4l2camsrc->frame_byte_size;
2357 GST_BUFFER_OFFSET (pool_buffer) = v4l2camsrc->offset++;
2358 GST_BUFFER_OFFSET_END (pool_buffer) = v4l2camsrc->offset;
2360 /* timestamps, LOCK to get clock and base time. */
2363 GstClockTime timestamp;
2365 GST_OBJECT_LOCK (v4l2camsrc);
2366 if ((clock = GST_ELEMENT_CLOCK (v4l2camsrc))) {
2367 /* we have a clock, get base time and ref clock */
2368 timestamp = GST_ELEMENT (v4l2camsrc)->base_time;
2369 gst_object_ref (clock);
2371 /* no clock, can't set timestamps */
2372 timestamp = GST_CLOCK_TIME_NONE;
2374 GST_OBJECT_UNLOCK (v4l2camsrc);
2377 GstClockTime latency;
2379 /* the time now is the time of the clock minus the base time */
2380 timestamp = gst_clock_get_time (clock) - timestamp;
2381 gst_object_unref (clock);
2384 gst_util_uint64_scale_int (GST_SECOND, camsrc->fps_d, camsrc->fps_n);
2386 if (timestamp > latency)
2387 timestamp -= latency;
2390 GST_BUFFER_DURATION (pool_buffer) = latency;
2392 /* activate settings for next frame (Code from v4l2src) */
2393 if (GST_CLOCK_TIME_IS_VALID (camsrc->duration)) {
2394 v4l2camsrc->ctrl_time += camsrc->duration;
2396 v4l2camsrc->ctrl_time = timestamp;
2398 gst_object_sync_values (G_OBJECT (camsrc), v4l2camsrc->ctrl_time);
2400 /* FIXME: use the timestamp from the buffer itself! */
2401 GST_BUFFER_TIMESTAMP (pool_buffer) = timestamp;
2404 if (G_UNLIKELY (need_copy)) {
2405 GST_DEBUG_OBJECT (v4l2camsrc, "copying buffer");
2406 *buf = gst_buffer_copy (pool_buffer);
2407 GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY);
2408 /* this will requeue */
2409 gst_buffer_unref (pool_buffer);
2411 if (v4l2camsrc->pool->is_vaapi_sharing)
2412 GST_BUFFER_DATA(pool_buffer) = (GST_V4L2CAMSRC_BUFFER(pool_buffer))->gbuffer;
2416 GST_LOG_OBJECT (v4l2camsrc,
2417 "grabbed frame %d (ix=%d), flags %08x, pool-ct=%d", buffer.sequence,
2418 buffer.index, buffer.flags, v4l2camsrc->pool->num_live_buffers);
2425 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ, (NULL),
2426 ("select error %d: %s (%d)", ret, g_strerror (errno), errno));
2427 return GST_FLOW_ERROR;
2431 GST_DEBUG ("stop called");
2432 return GST_FLOW_WRONG_STATE;
2436 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2437 ("Failed trying to get video frames from device '%s'.",
2438 v4l2camsrc->videodev),
2439 ("The buffer type is not supported, or the index is out of bounds,"
2440 " or no buffers have been allocated yet, or the userptr"
2441 " or length are invalid. device %s", v4l2camsrc->videodev));
2442 return GST_FLOW_ERROR;
2446 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2447 ("Failed trying to get video frames from device '%s'. Not enough memory.",
2448 v4l2camsrc->videodev), ("insufficient memory to enqueue a user "
2449 "pointer buffer. device %s.", v4l2camsrc->videodev));
2450 return GST_FLOW_ERROR;
2454 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2455 ("Failed trying to get video frames from device '%s'.",
2456 v4l2camsrc->videodev),
2457 ("Failed after %d tries. device %s. system error: %s",
2458 NUM_TRIALS, v4l2camsrc->videodev, g_strerror (errno)));
2459 return GST_FLOW_ERROR;
2463 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2464 ("Failed trying to get video frames from device '%s'.",
2465 v4l2camsrc->videodev),
2466 ("No free buffers found in the pool at index %d.", index));
2467 g_mutex_unlock (v4l2camsrc->pool->lock);
2468 return GST_FLOW_ERROR;
2473 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, WRITE,
2474 ("Could not exchange data with device '%s'.",
2475 v4l2camsrc->videodev),
2476 ("Error queueing buffer on device %s. system error: %s",
2477 v4l2camsrc->videodev, g_strerror (errno)));
2478 return GST_FLOW_ERROR;
2483 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2484 ("Timeout when trying to get video frames from device '%s'.",
2485 v4l2camsrc->videodev), NULL);
2486 return GST_FLOW_ERROR;
2491 /******************************************************
2492 * gst_v4l2camsrc_set_capture():
2493 * set capture parameters for certain operation mode
2494 * return value: TRUE on success, FALSE on error
2495 ******************************************************/
2497 gst_v4l2camsrc_set_capture (GstCameraSrc * camsrc, GstOperationMode mode,
2498 gboolean try_only, guint32 * pixelformat, guint * width, guint * height,
2499 guint * fps_n, guint * fps_d)
2501 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2502 cam_err_t err = CAM_ERR_NONE;
2503 gboolean ret = TRUE;
2505 GST_DEBUG_OBJECT (v4l2camsrc, "mode = %d, try_only = %d", mode, try_only);
2507 v4l2camsrc->expected_capture_w = *width;
2508 v4l2camsrc->expected_capture_h = *height;
2509 v4l2camsrc->expected_capture_fourcc = *pixelformat;
2511 if (mode == GST_PHOTOGRAPHY_OPERATION_MODE_PREVIEW) {
2513 } else if (mode == GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE) {
2514 GST_DEBUG_OBJECT (v4l2camsrc, "Image capture: %dx%d, format "
2515 "%" GST_FOURCC_FORMAT, *width, *height, GST_FOURCC_ARGS (*pixelformat));
2518 /* Round width & height down to be dividable by 8 */
2519 *width = (*width) & ~7;
2520 *height = (*height) & ~7;
2523 ret = gst_v4l2camsrc_configure_device (v4l2camsrc, pixelformat,
2524 width, height, fps_n, fps_d);
2526 v4l2camsrc->tmp_num_buffers = v4l2camsrc->num_buffers;
2527 v4l2camsrc->num_buffers = 1;
2529 v4l2camsrc->capture_w = *width;
2530 v4l2camsrc->capture_h = *height;
2531 if (fps_n && fps_d) {
2532 v4l2camsrc->capture_fps_n = *fps_n;
2533 v4l2camsrc->capture_fps_d = *fps_d;
2535 v4l2camsrc->capture_fourcc = *pixelformat;
2538 /* VIEWFINDER mode */
2539 /* FIXME: handle try_only mode */
2541 v4l2camsrc->num_buffers = v4l2camsrc->tmp_num_buffers;
2543 ret = gst_v4l2camsrc_configure_device (v4l2camsrc, pixelformat,
2544 width, height, fps_n, fps_d);
2546 v4l2camsrc->vf_w = *width;
2547 v4l2camsrc->vf_h = *height;
2548 v4l2camsrc->vf_fourcc = *pixelformat;
2549 if (fps_n && fps_d) {
2550 v4l2camsrc->vf_fps_n = *fps_n;
2551 v4l2camsrc->vf_fps_d = *fps_d;
2554 if (err != CAM_ERR_NONE)
2560 /******************************************************
2561 * gst_v4l2camsrc_capture_start():
2562 * Start capturing frames from the device
2563 * return value: TRUE on success, FALSE on error
2564 ******************************************************/
2566 gst_v4l2camsrc_capture_start (GstCameraSrc * camsrc, GstCaps * caps)
2568 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2570 gint fd = v4l2camsrc->video_fd;
2571 struct v4l2_requestbuffers breq;
2572 gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2573 cam_capture_mode_t cam_mode;
2576 v4l2camsrc->offset = 0;
2578 /* activate settings for first frame */
2579 v4l2camsrc->ctrl_time = 0;
2580 gst_object_sync_values (G_OBJECT (camsrc), v4l2camsrc->ctrl_time);
2582 memset (&breq, 0, sizeof (struct v4l2_requestbuffers));
2584 GST_DEBUG_OBJECT (v4l2camsrc, "initializing the capture system");
2586 GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
2587 GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
2589 if (!(v4l2camsrc->vcap.capabilities & V4L2_CAP_STREAMING))
2590 goto no_capture_method;
2592 GST_DEBUG_OBJECT (v4l2camsrc, "STREAMING, requesting %d CAPTURE buffers",
2593 v4l2camsrc->num_buffers);
2595 err = cam_driver_set_mipi_interrupt(fd,1);
2596 if (err != CAM_ERR_NONE)
2597 GST_DEBUG_OBJECT (v4l2camsrc, "MIPI interrupt enable FAILED !");
2599 breq.count = v4l2camsrc->num_buffers;
2600 breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2602 if(v4l2camsrc->use_mmap && GST_CAPS_IS_SIMPLE(caps)) {
2603 GstStructure *st = gst_caps_get_structure(caps, 0);
2604 if(g_str_has_prefix(gst_structure_get_name(st), "video/x-vaapi-sharing")) {
2605 v4l2camsrc->use_mmap = FALSE;
2606 GST_WARNING_OBJECT(v4l2camsrc, "mmap is not supported with VA shared buffer, turning off");
2610 if (v4l2camsrc->use_mmap)
2611 breq.memory = V4L2_MEMORY_MMAP;
2613 breq.memory = V4L2_MEMORY_USERPTR;
2615 if (ioctl (fd, VIDIOC_REQBUFS, &breq) < 0)
2616 goto reqbufs_failed;
2618 GST_LOG_OBJECT (v4l2camsrc, " count: %u", breq.count);
2619 GST_LOG_OBJECT (v4l2camsrc, " type: %d", breq.type);
2620 GST_LOG_OBJECT (v4l2camsrc, " memory: %d", breq.memory);
2622 if (breq.count < GST_V4L2CAMSRC_MIN_BUFFERS)
2625 if (v4l2camsrc->num_buffers != breq.count) {
2626 GST_WARNING_OBJECT (v4l2camsrc, "using %u buffers instead", breq.count);
2627 v4l2camsrc->num_buffers = breq.count;
2628 g_object_notify (G_OBJECT (v4l2camsrc), "queue-size");
2631 /* Map the buffers */
2632 GST_LOG_OBJECT (v4l2camsrc, "initiating buffer pool");
2634 if (!(v4l2camsrc->pool =
2635 gst_v4l2camsrc_buffer_pool_new (camsrc, fd, caps)))
2636 goto buffer_pool_new_failed;
2638 GST_INFO_OBJECT (v4l2camsrc, "capturing buffers");
2640 GST_V4L2CAMSRC_SET_ACTIVE (v4l2camsrc);
2642 GST_DEBUG_OBJECT (v4l2camsrc, "starting the capturing");
2643 GST_V4L2CAMSRC_CHECK_ACTIVE (v4l2camsrc);
2645 if (!gst_v4l2camsrc_buffer_pool_activate (v4l2camsrc->pool, v4l2camsrc))
2646 goto pool_activate_failed;
2648 if (ioctl (fd, VIDIOC_STREAMON, &type) < 0)
2649 goto streamon_failed;
2651 v4l2camsrc->is_active = TRUE;
2652 GST_DEBUG_OBJECT (v4l2camsrc, "STREAMON called");
2654 /* Update the focus only when the Sensor is stream on */
2655 if (v4l2camsrc->focus_updated) {
2656 cam_driver_set_focus_posi(v4l2camsrc->video_fd, v4l2camsrc->focus_posi);
2657 v4l2camsrc->focus_updated = FALSE;
2660 if (v4l2camsrc->zoom_updated) {
2661 gst_v4l2camsrc_libmfldcam_set_zoom(v4l2camsrc, v4l2camsrc->zoom_factor);
2662 v4l2camsrc->zoom_updated = FALSE;
2665 cam_mode = find_item (gst_v4l2camsrc_capture_map,v4l2camsrc->capture_mode);
2666 cam_set_capture_mode (v4l2camsrc->video_fd, cam_mode);
2673 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2674 ("Could not get buffers from device '%s'.",
2675 v4l2camsrc->videodev),
2676 ("error requesting %d buffers: %s",
2677 v4l2camsrc->num_buffers, g_strerror (errno)));
2678 cam_driver_set_mipi_interrupt(fd, 0);
2683 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2684 ("Could not get enough buffers from device '%s'.",
2685 v4l2camsrc->videodev),
2686 ("we received %d from device '%s', we want at least %d",
2687 breq.count, v4l2camsrc->videodev, GST_V4L2CAMSRC_MIN_BUFFERS));
2688 cam_driver_set_mipi_interrupt(fd, 0);
2691 buffer_pool_new_failed:
2693 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2694 ("Could not map buffers from device '%s'",
2695 v4l2camsrc->videodev),
2696 ("Failed to create buffer pool: %s", g_strerror (errno)));
2697 cam_driver_set_mipi_interrupt(fd, 0);
2702 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2703 ("The driver of device '%s' does not support streaming. ",
2704 v4l2camsrc->videodev), (NULL));
2705 cam_driver_set_mipi_interrupt(fd, 0);
2708 pool_activate_failed:
2710 /* already errored */
2711 cam_driver_set_mipi_interrupt(fd, 0);
2716 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, OPEN_READ,
2717 ("Error starting streaming capture from device '%s'.",
2718 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
2719 cam_driver_set_mipi_interrupt(fd, 0);
2724 /******************************************************
2725 * gst_v4l2camsrc_capture_stop():
2726 * stop streaming capture
2727 * return value: TRUE on success, FALSE on error
2728 ******************************************************/
2730 gst_v4l2camsrc_capture_stop (GstCameraSrc * camsrc)
2732 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2733 struct v4l2_requestbuffers breq;
2734 gint fd = v4l2camsrc->video_fd;
2737 gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2739 memset(&breq, 0, sizeof(struct v4l2_requestbuffers));
2741 GST_DEBUG_OBJECT (v4l2camsrc, "stopping capturing");
2743 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc)) {
2746 if (!GST_V4L2CAMSRC_IS_ACTIVE (v4l2camsrc)) {
2750 err = cam_driver_set_mipi_interrupt(fd,0);
2751 if (err != CAM_ERR_NONE)
2752 GST_DEBUG_OBJECT (v4l2camsrc, "MIPI interrupt disable FAILED !");
2754 /* we actually need to sync on all queued buffers but not
2755 * on the non-queued ones */
2756 if (ioctl (v4l2camsrc->video_fd, VIDIOC_STREAMOFF, &type) < 0)
2757 goto streamoff_failed;
2759 GST_DEBUG_OBJECT (v4l2camsrc, "STREAMOFF called");
2762 breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2763 if(v4l2camsrc->use_mmap)
2764 breq.memory = V4L2_MEMORY_MMAP;
2766 breq.memory = V4L2_MEMORY_USERPTR;
2768 GST_DEBUG_OBJECT (v4l2camsrc, "REQUEST 0 to finalize buffer");
2770 if(ioctl(v4l2camsrc->video_fd, VIDIOC_REQBUFS, &breq) < 0)
2771 GST_DEBUG_OBJECT (v4l2camsrc, "Failed to REQUEST 0 to finalize buffer");
2774 if (v4l2camsrc->pool) {
2775 gst_v4l2camsrc_buffer_pool_destroy (v4l2camsrc->pool, v4l2camsrc);
2776 v4l2camsrc->pool = NULL;
2779 GST_V4L2CAMSRC_SET_INACTIVE (v4l2camsrc);
2780 v4l2camsrc->is_active = FALSE;
2788 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, CLOSE,
2789 ("Error stopping streaming capture from device '%s'.",
2790 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
2798 gst_v4l2camsrc_get_nearest_size (GstMFLDV4l2CamSrc * v4l2camsrc,
2799 guint32 pixelformat, gint * width, gint * height)
2801 struct v4l2_format fmt;
2805 g_return_val_if_fail (width != NULL, FALSE);
2806 g_return_val_if_fail (height != NULL, FALSE);
2808 GST_LOG_OBJECT (v4l2camsrc,
2809 "getting nearest size to %dx%d with format %" GST_FOURCC_FORMAT,
2810 *width, *height, GST_FOURCC_ARGS (pixelformat));
2812 fd = v4l2camsrc->video_fd;
2814 /* get size delimiters */
2815 memset (&fmt, 0, sizeof (fmt));
2816 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2817 fmt.fmt.pix.width = *width;
2818 fmt.fmt.pix.height = *height;
2819 fmt.fmt.pix.pixelformat = pixelformat;
2820 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
2822 /* FIXME: Disable TRY_FMT check, driver is not returning anything useful yet */
2824 r = ioctl (fd, VIDIOC_TRY_FMT, &fmt);
2825 if (r < 0 && errno == EINVAL) {
2826 /* try again with progressive video */
2827 fmt.fmt.pix.width = *width;
2828 fmt.fmt.pix.height = *height;
2829 fmt.fmt.pix.pixelformat = pixelformat;
2830 fmt.fmt.pix.field = V4L2_FIELD_NONE;
2831 r = ioctl (fd, VIDIOC_TRY_FMT, &fmt);
2835 /* The driver might not implement TRY_FMT, in which case we will try
2837 if (errno != ENOTTY)
2841 /* Only try S_FMT if we're not actively capturing yet, which we shouldn't
2842 be, because we're still probing */
2843 if (GST_V4L2CAMSRC_IS_ACTIVE (v4l2camsrc))
2847 GST_LOG_OBJECT (v4l2camsrc,
2848 "Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
2851 fmt.fmt.pix.width = *width;
2852 fmt.fmt.pix.height = *height;
2854 r = ioctl (fd, VIDIOC_S_FMT, &fmt);
2855 if (r < 0 && errno == EINVAL) {
2856 /* try again with progressive video */
2857 fmt.fmt.pix.width = *width;
2858 fmt.fmt.pix.height = *height;
2859 fmt.fmt.pix.pixelformat = pixelformat;
2860 fmt.fmt.pix.field = V4L2_FIELD_NONE;
2861 r = ioctl (fd, VIDIOC_S_FMT, &fmt);
2870 GST_LOG_OBJECT (v4l2camsrc,
2871 "got nearest size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
2873 *width = fmt.fmt.pix.width;
2874 *height = fmt.fmt.pix.height;
2880 /******************************************************
2881 * gst_v4l2camsrc_set_crop():
2882 * set cropping bounds
2883 * return value: TRUE on success, FALSE on error
2884 ******************************************************/
2886 gst_v4l2camsrc_set_crop (GstMFLDV4l2CamSrc * v4l2camsrc,
2887 gint x, gint y, gint w, gint h)
2889 gboolean ret = FALSE;
2890 struct v4l2_crop scrop;
2891 struct v4l2_crop gcrop;
2892 gint cx, cy, cw, ch;
2895 fd = v4l2camsrc->video_fd;
2896 cx = v4l2camsrc->vcrop.bounds.left;
2897 cy = v4l2camsrc->vcrop.bounds.top;
2898 cw = v4l2camsrc->vcrop.bounds.width;
2899 ch = v4l2camsrc->vcrop.bounds.height;
2901 memset (&scrop, 0, sizeof (scrop));
2902 scrop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2904 /* Make sure that cropping area stays inside the crop boundaries */
2905 scrop.c.left = x > cx ? x : cx;
2906 scrop.c.top = y > cy ? y : cy;
2907 scrop.c.width = (scrop.c.left + w) < (cx + cw) ? w : cx + cw - scrop.c.left;
2908 scrop.c.height = (scrop.c.top + h) < (cy + ch) ? h : cy + ch - scrop.c.top;
2910 GST_DEBUG_OBJECT (v4l2camsrc,
2911 "Crop request: left = %d, top = %d, w = %d, h = %d",
2912 scrop.c.left, scrop.c.top, scrop.c.width, scrop.c.height);
2914 g_mutex_lock (v4l2camsrc->device_mutex);
2916 if (-1 == ioctl (fd, VIDIOC_S_CROP, &scrop) && errno != EINVAL) {
2920 if (-1 == ioctl (fd, VIDIOC_G_CROP, &gcrop)) {
2924 g_mutex_unlock (v4l2camsrc->device_mutex);
2926 GST_DEBUG_OBJECT (v4l2camsrc,
2927 "Crop selected: left = %d, top = %d, w = %d, h = %d",
2928 gcrop.c.left, gcrop.c.top, gcrop.c.width, gcrop.c.height);
2931 if (gcrop.c.left != scrop.c.left || gcrop.c.top != scrop.c.top ||
2932 gcrop.c.width != scrop.c.width || gcrop.c.height != scrop.c.height) {
2933 goto crop_not_supported;
2945 g_mutex_unlock (v4l2camsrc->device_mutex);
2946 GST_DEBUG_OBJECT (v4l2camsrc, "VIDIOC_S_CROP not supported");
2950 g_mutex_unlock (v4l2camsrc->device_mutex);
2951 GST_DEBUG_OBJECT (v4l2camsrc, "VIDIOC_G_CROP not supported");
2956 g_mutex_unlock (v4l2camsrc->device_mutex);
2957 GST_DEBUG_OBJECT (v4l2camsrc, "Given crop value not accepted");
2963 /******************************************************
2964 * gst_v4l2camsrc_update_cropping():
2965 * update cropping area according to width, height and zoom factors.
2966 * return value: TRUE on success, FALSE on error
2967 ******************************************************/
2969 gst_v4l2camsrc_update_cropping (GstMFLDV4l2CamSrc * v4l2camsrc, gint width,
2970 gint height, gfloat zoom)
2972 gfloat sensor_ar, reso_ar;
2973 gint crop_x, crop_y, crop_w, crop_h;
2975 g_return_val_if_fail (width != 0, FALSE);
2976 g_return_val_if_fail (height != 0, FALSE);
2977 g_return_val_if_fail (zoom != 0, FALSE);
2979 if (zoom < 1.0 || zoom > v4l2camsrc->max_zoom_factor) {
2980 GST_DEBUG_OBJECT (v4l2camsrc, "invalid zoom = %.2f", zoom);
2983 if (!v4l2camsrc->crop_supported) {
2984 GST_DEBUG_OBJECT (v4l2camsrc, "crop not supported");
2988 sensor_ar = v4l2camsrc->vcrop.defrect.width /
2989 v4l2camsrc->vcrop.defrect.height;
2990 reso_ar = width / height;
2992 if (sensor_ar > reso_ar) {
2993 crop_w = (width * v4l2camsrc->vcrop.defrect.height / height) / zoom;
2994 crop_h = MAX (v4l2camsrc->vcrop.defrect.height, height) / zoom;
2996 crop_w = MAX (v4l2camsrc->vcrop.defrect.width, width) / zoom;
2997 crop_h = (height * v4l2camsrc->vcrop.defrect.width / width) / zoom;
3000 crop_x = ABS ((v4l2camsrc->vcrop.defrect.width - crop_w) / 2);
3001 crop_y = ABS ((v4l2camsrc->vcrop.defrect.height - crop_h) / 2);
3003 GST_LOG_OBJECT (v4l2camsrc, "set cropping: x: %d, y: %d, w: %d, h: %d",
3004 crop_x, crop_y, crop_w, crop_h);
3006 return gst_v4l2camsrc_set_crop (v4l2camsrc, crop_x, crop_y, crop_w, crop_h);
3009 /***************************************************************************
3010 * New MFLD Camera Code ****************************************************
3011 * *************************************************************************/
3013 /* These map tables help to adapt the general photography interface to
3014 * different device implementations.
3016 * Table index = Enumeration value from GstPhotography
3017 * Table value = Device/Implementation -specific setting value
3020 static const gint gst_v4l2camsrc_scene_map[] = {
3021 999, /* GST_PHOTOGRAPHY_SCENE_MODE_MANUAL */
3022 CAM_GENERAL_SCENE_MODE_CLOSEUP,
3023 CAM_GENERAL_SCENE_MODE_PORTRAIT,
3024 CAM_GENERAL_SCENE_MODE_LANDSCAPE,
3025 CAM_GENERAL_SCENE_MODE_SPORT,
3026 CAM_GENERAL_SCENE_MODE_NIGHT,
3027 CAM_GENERAL_SCENE_MODE_AUTO,
3031 static const gint gst_v4l2camsrc_flash_map[] = {
3032 CAM_LIGHT_FLASH_MODE_AUTO,
3033 CAM_LIGHT_FLASH_MODE_OFF,
3034 CAM_LIGHT_FLASH_MODE_ON,
3035 CAM_LIGHT_FLASH_MODE_FILL_IN,
3036 CAM_LIGHT_FLASH_MODE_RED_EYE,
3040 static const gint gst_v4l2camsrc_focus_map[] = {
3041 CAM_FOCUS_MODE_AUTO, /* GST_PHOTOGRAPHY_FOCUS_MODE_AUTO = 0 */
3042 CAM_FOCUS_MODE_MACRO, /* GST_PHOTOGRAPHY_FOCUS_MODE_MACRO */
3043 CAM_FOCUS_MODE_TOUCH_AUTO, /* GST_PHOTOGRAPHY_FOCUS_MODE_PORTRAIT */
3044 CAM_FOCUS_MODE_FULL, /* GST_PHOTOGRAPHY_FOCUS_MODE_INFINITY */
3045 CAM_FOCUS_MODE_AUTO, /* GST_PHOTOGRAPHY_FOCUS_MODE_HYPERFOCAL */
3046 CAM_FOCUS_MODE_FULL, /* GST_PHOTOGRAPHY_FOCUS_MODE_EXTENDED */
3047 CAM_FOCUS_MODE_CONTINUOUS, /* GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_NORMAL */
3048 CAM_FOCUS_MODE_CONTINUOUS, /* GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_EXTENDED */
3052 static const gint gst_v4l2camsrc_flicker_map[] = {
3053 CAM_GENERAL_FLICKER_REDUCTION_MODE_OFF, /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF = 0 */
3054 CAM_GENERAL_FLICKER_REDUCTION_MODE_50HZ, /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ */
3055 CAM_GENERAL_FLICKER_REDUCTION_MODE_60HZ, /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_60HZ */
3056 CAM_GENERAL_FLICKER_REDUCTION_MODE_AUTO, /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO */
3060 static const gint gst_v4l2camsrc_iso_map[][2] = {
3061 {CAM_EXPOSURE_ISO_VALUE_1600, 1600},
3062 {CAM_EXPOSURE_ISO_VALUE_800, 800},
3063 {CAM_EXPOSURE_ISO_VALUE_400, 400},
3064 {CAM_EXPOSURE_ISO_VALUE_200, 200},
3065 {CAM_EXPOSURE_ISO_VALUE_100, 100},
3066 {CAM_EXPOSURE_ISO_VALUE_AUTO, 0}
3069 static const gint gst_v4l2camsrc_focus_status_map[][2] =
3071 { GST_PHOTOGRAPHY_FOCUS_STATUS_NONE, CAM_FOCUS_STATUS_IDLE },
3072 { GST_PHOTOGRAPHY_FOCUS_STATUS_RUNNING, CAM_FOCUS_STATUS_RUNNING },
3073 { GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS, CAM_FOCUS_STATUS_SUCCESS },
3074 { GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL, CAM_FOCUS_STATUS_FAIL },
3078 static const gchar *cameralib_error_map[] = {
3085 "CAM_ERR_DEPRECATED",
3086 "CAM_ERR_INVALID_STATE",
3095 static cam_exposure_iso_value_t
3096 gst_v4l2camsrc_libmfld_map_iso (guint iso)
3100 while (gst_v4l2camsrc_iso_map[i][1] != 0) {
3101 if (iso >= gst_v4l2camsrc_iso_map[i][1]) {
3107 return gst_v4l2camsrc_iso_map[i][1];
3115 gst_v4l2camsrc_libmfld_reverse_map_iso (cam_exposure_iso_value_t iso)
3119 while (gst_v4l2camsrc_iso_map[i][1] != 0) {
3120 if (iso == gst_v4l2camsrc_iso_map[i][0]) {
3126 return gst_v4l2camsrc_iso_map[i][1];
3129 static const gint gst_v4l2camsrc_shakerisk_map[] = {
3130 GST_PHOTOGRAPHY_SHAKE_RISK_LOW, /* CAM_EXPOSURE_SHAKE_RISK_LOW = 0 */
3131 GST_PHOTOGRAPHY_SHAKE_RISK_MEDIUM, /* CAM_EXPOSURE_SHAKE_RISK_MEDIUM */
3132 GST_PHOTOGRAPHY_SHAKE_RISK_HIGH, /* CAM_EXPOSURE_SHAKE_RISK_HIGH */
3136 * Return index of the item in the table.
3139 find_item (const gint table[], const gint item)
3143 while (table[i] != -1) {
3144 if (table[i] == item)
3152 gst_v4l2camsrc_read_settings (GstCameraSrc * camsrc,
3153 GstPhotoSettings * photoconf)
3155 GstMFLDV4l2CamSrc *v4l2camsrc;
3156 gint32 wbmode, effect, scene, flash, focus;
3158 gint32 ev, iso, aperture, exposure, noise_reduction;
3161 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3163 g_mutex_lock (v4l2camsrc->device_mutex);
3165 if (!v4l2camsrc->initialized) {
3166 GST_DEBUG ("Device not initialized");
3167 g_mutex_unlock (v4l2camsrc->device_mutex);
3171 GST_DEBUG ("Retrieving settings from camera");
3173 err = cam_feature_get (v4l2camsrc->video_fd, CAM_AWB_MODE, &wbmode);
3174 if (err != CAM_ERR_NONE) {
3175 GST_DEBUG ("CAM_AWB_MODE query failed: %s", cameralib_error_map[err]);
3180 cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE, &effect);
3181 if (err != CAM_ERR_NONE) {
3182 GST_DEBUG ("CAM_GENERAL_EFFECT_TYPE query failed: %s",
3183 cameralib_error_map[err]);
3187 err = cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_SCENE_MODE, &scene);
3188 if (err != CAM_ERR_NONE) {
3189 GST_DEBUG ("CAM_GENERAL_SCENE_MODE query failed: %s",
3190 cameralib_error_map[err]);
3194 err = cam_feature_get (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE, &flash);
3195 if (err != CAM_ERR_NONE) {
3196 GST_DEBUG ("CAM_LIGHT_FLASH_MODE query failed: %s",
3197 cameralib_error_map[err]);
3201 err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION, &ev);
3202 if (err != CAM_ERR_NONE) {
3203 GST_DEBUG ("CAM_EXPOSURE_COMPENSATION query failed: %s",
3204 cameralib_error_map[err]);
3208 err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE, &iso);
3209 if (err != CAM_ERR_NONE) {
3210 GST_DEBUG ("CAM_EXPOSURE_ISO_VALUE query failed: %s",
3211 cameralib_error_map[err]);
3215 err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_APERTURE,
3217 if (err != CAM_ERR_NONE) {
3218 GST_DEBUG ("CAM_EXPOSURE_MANUAL_APERTURE query failed: %s",
3219 cameralib_error_map[err]);
3224 cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_TIME,
3226 if (err != CAM_ERR_NONE) {
3227 GST_DEBUG ("CAM_EXPOSURE_MANUAL_TIME query failed: %s",
3228 cameralib_error_map[err]);
3232 err = cam_feature_get (v4l2camsrc->video_fd, CAM_FOCUS_MODE, &focus);
3233 if (err != CAM_ERR_NONE) {
3234 GST_DEBUG ("CAM_FOCUS_MODE query failed: %s", cameralib_error_map[err]);
3239 cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_FLICKER_REDUCTION_MODE,
3241 if (err != CAM_ERR_NONE) {
3242 GST_DEBUG ("CAM_GENERAL_FLICKER_REDUCTION_MODE query failed: %s",
3243 cameralib_error_map[err]);
3248 cam_feature_get (v4l2camsrc->video_fd, CAM_NOISE_REDUCTION_MODE,
3250 if (err != CAM_ERR_NONE) {
3251 GST_DEBUG ("CAM_NOISE_REDUCTION query failed: %s",
3252 cameralib_error_map[err]);
3256 photoconf->wb_mode = find_item (gst_v4l2camsrc_wb_map, wbmode);
3257 photoconf->tone_mode = find_item (gst_v4l2camsrc_effect_map, effect);
3258 photoconf->scene_mode = find_item (gst_v4l2camsrc_scene_map, scene);
3259 photoconf->flash_mode = find_item (gst_v4l2camsrc_flash_map, flash);
3260 photoconf->focus_mode = find_item (gst_v4l2camsrc_focus_map, focus);
3261 photoconf->flicker_mode = find_item (gst_v4l2camsrc_flicker_map, flicker);
3263 photoconf->ev_compensation = (gfloat) ev / 10;
3264 photoconf->iso_speed = gst_v4l2camsrc_libmfld_map_iso (iso);
3265 photoconf->aperture = aperture;
3266 photoconf->exposure = exposure;
3267 photoconf->noise_reduction = noise_reduction;
3269 GST_DEBUG ("Scene mode ext: %d, lib: %d", photoconf->scene_mode, scene);
3270 GST_DEBUG ("Focus mode ext: %d, lib: %d", photoconf->focus_mode, focus);
3271 GST_DEBUG ("Flash mode ext: %d, lib: %d", photoconf->flash_mode, flash);
3272 GST_DEBUG ("ISO: %d, EV_comp: %f (%d)", iso, photoconf->ev_compensation, ev);
3274 g_mutex_unlock (v4l2camsrc->device_mutex);
3281 g_mutex_unlock (v4l2camsrc->device_mutex);
3286 gst_v4l2camsrc_read_exif (GstCameraSrc * camsrc,
3287 GstCameraControlExifInfo *exif_info)
3289 GstMFLDV4l2CamSrc *v4l2camsrc;
3291 struct atomisp_makernote_info maker_note;
3294 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3297 if (!v4l2camsrc->initialized) {
3298 GST_DEBUG ("Device not initialized");
3301 buf = (unsigned char *)&maker_note;
3303 GST_DEBUG ("Retrieving makernote from atomisp");
3304 err = cam_get_makernote (v4l2camsrc->video_fd, buf, 0);
3310 exif_info->focal_len_numerator = maker_note.focal_length >> 16;
3311 exif_info->focal_len_denominator = maker_note.focal_length & 0xFFFF;
3312 /* Aperture value (f_num) */
3313 exif_info->aperture_f_num_numerator = maker_note.f_number_curr >> 16;
3314 exif_info->aperture_f_num_denominator = maker_note.f_number_curr & 0xFFFF;
3315 /* isp major, minor,patch level */
3316 exif_info->software_used = v4l2camsrc->vcap.version;
3317 exif_info->colorspace = 65535; /* Uncalibrated (=65535) */
3318 exif_info->metering_mode = 1; /* Average */
3319 cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE, &exif_info->iso);
3321 //* TODO complete exif info */
3322 exif_info->exposure_time_denominator = 0;
3323 exif_info->exposure_time_numerator = 0;
3325 exif_info->shutter_speed_numerator = 0;
3326 exif_info->shutter_speed_denominator = 0;
3327 exif_info->brigtness_numerator = 0;
3328 exif_info->brightness_denominator = 0;
3329 exif_info->flash = cam_is_flash_used();
3330 GST_DEBUG ("Focal lenght numerator : %d", exif_info->focal_len_numerator);
3331 GST_DEBUG ("Focal lenght denominator : %d", exif_info->focal_len_denominator);
3332 GST_DEBUG ("F num numerator : %d", exif_info->aperture_f_num_numerator);
3333 GST_DEBUG ("F num denominator : %d", exif_info->aperture_f_num_denominator);
3334 GST_DEBUG ("flash used : %d", exif_info->flash);
3341 g_mutex_unlock (v4l2camsrc->device_mutex);
3347 gst_v4l2camsrc_set_flash_mode (GstCameraSrc * camsrc,
3350 GstMFLDV4l2CamSrc *v4l2camsrc;
3355 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3357 g_mutex_lock (v4l2camsrc->device_mutex);
3359 if (!v4l2camsrc->initialized) {
3360 GST_DEBUG ("Device not initialized");
3361 g_mutex_unlock (v4l2camsrc->device_mutex);
3366 case GST_CAMERA_STROBE_CAP_NONE:
3367 case GST_CAMERA_STROBE_CAP_OFF:
3368 flash = CAM_LIGHT_FLASH_MODE_OFF;
3370 case GST_CAMERA_STROBE_CAP_ON:
3371 flash = CAM_LIGHT_FLASH_MODE_ON;
3373 case GST_CAMERA_STROBE_CAP_AUTO:
3374 flash = CAM_LIGHT_FLASH_MODE_AUTO;
3376 case GST_CAMERA_STROBE_CAP_REDEYE:
3377 flash = CAM_LIGHT_FLASH_MODE_RED_EYE;
3380 flash = CAM_LIGHT_FLASH_MODE_OFF;
3384 GST_DEBUG_OBJECT (v4l2camsrc, "Set flash mode: %d",flash);
3385 err= cam_feature_set (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE,
3391 g_mutex_unlock (v4l2camsrc->device_mutex);
3398 g_mutex_unlock (v4l2camsrc->device_mutex);
3404 gst_v4l2camsrc_write_settings (GstCameraSrc * camsrc,
3405 GstPhotoSettings * photoconf, gboolean scene_override)
3407 GstMFLDV4l2CamSrc *v4l2camsrc;
3408 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3409 GST_DEBUG ("Write settings to libmfldcamd");
3411 g_mutex_lock (v4l2camsrc->device_mutex);
3413 if (!v4l2camsrc->initialized) {
3414 g_mutex_unlock (v4l2camsrc->device_mutex);
3415 GST_DEBUG ("Device not initialized");
3419 if (scene_override &&
3420 photoconf->scene_mode != GST_PHOTOGRAPHY_SCENE_MODE_MANUAL) {
3421 /* If scene override flag is set, we just leave the new settings in use */
3422 GST_DEBUG ("SCENE OVERRIDE, ext=%d", photoconf->scene_mode);
3423 cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_SCENE_MODE,
3424 gst_v4l2camsrc_scene_map[photoconf->scene_mode]);
3426 GST_DEBUG ("Normal settings");
3427 cam_feature_set (v4l2camsrc->video_fd, CAM_AWB_MODE,
3428 gst_v4l2camsrc_wb_map[photoconf->wb_mode]);
3430 cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE,
3431 gst_v4l2camsrc_effect_map[photoconf->tone_mode]);
3433 cam_feature_set (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE,
3434 gst_v4l2camsrc_flash_map[photoconf->flash_mode]);
3436 /* These will set exposure mode to MANUAL, is value is != 0 */
3437 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_TIME,
3438 photoconf->exposure);
3439 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_APERTURE,
3440 photoconf->aperture);
3442 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION,
3443 (gint) (photoconf->ev_compensation * 10));
3445 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE,
3446 gst_v4l2camsrc_libmfld_reverse_map_iso (photoconf->iso_speed));
3448 cam_feature_set (v4l2camsrc->video_fd, CAM_FOCUS_MODE,
3449 gst_v4l2camsrc_focus_map[photoconf->focus_mode]);
3451 cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_FLICKER_REDUCTION_MODE,
3452 gst_v4l2camsrc_flicker_map[photoconf->flicker_mode]);
3454 cam_feature_set (v4l2camsrc->video_fd, CAM_NOISE_REDUCTION_MODE,
3455 photoconf->noise_reduction);
3457 g_mutex_unlock (v4l2camsrc->device_mutex);
3463 gst_v4l2camsrc_set_AeAafwindow (GstCameraSrc * camsrc, GstCameraSrc3a_window window)
3465 GstMFLDV4l2CamSrc *v4l2camsrc;
3466 gboolean ret = TRUE;
3468 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3470 GST_DEBUG_OBJECT(v4l2camsrc,"ae-af-window-setting: x_left:%d, x_right:%d,"
3471 "y_bottom:%d, y_top:%d, weight:%d.\n",
3472 window.x_left,window.x_right,
3473 window.y_bottom, window.y_top,
3476 v4l2camsrc->af_window = v4l2camsrc->ae_window = *(GstCameraWindow*)&window;
3478 if (v4l2camsrc->is_active) {
3479 g_mutex_lock (v4l2camsrc->device_mutex);
3480 cam_set_af_ae_window((advci_window *) (&v4l2camsrc->af_window));
3481 g_mutex_unlock (v4l2camsrc->device_mutex);
3488 gst_v4l2camsrc_set_autofocus (GstCameraSrc * camsrc, gboolean on)
3490 GstMFLDV4l2CamSrc *v4l2camsrc;
3491 gboolean ret = FALSE;
3492 cam_err_t err = CAM_ERR_NONE;
3494 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3495 g_mutex_lock (v4l2camsrc->device_mutex);
3496 err= cam_set_autofocus(on);
3497 ret = (err == CAM_ERR_NONE);
3498 g_mutex_unlock (v4l2camsrc->device_mutex);
3500 GST_DEBUG ("setting autofocus: %s", ret ? "ok" : "failed");
3507 gst_v4l2camsrc_get_capabilities (GstCameraSrc * camsrc)
3511 pcaps = GST_PHOTOGRAPHY_CAPS_ZOOM | GST_PHOTOGRAPHY_CAPS_EV_COMP |
3512 GST_PHOTOGRAPHY_CAPS_WB_MODE | GST_PHOTOGRAPHY_CAPS_TONE |
3513 GST_PHOTOGRAPHY_CAPS_SCENE | GST_PHOTOGRAPHY_CAPS_FLASH |
3514 GST_PHOTOGRAPHY_CAPS_FOCUS | GST_PHOTOGRAPHY_CAPS_APERTURE |
3515 GST_PHOTOGRAPHY_CAPS_EXPOSURE | GST_PHOTOGRAPHY_CAPS_SHAKE |
3516 GST_PHOTOGRAPHY_CAPS_ISO_SPEED;
3525 gst_v4l2camsrc_check_focus_status (GstMFLDV4l2CamSrc * v4l2camsrc,
3526 GstCameraFocusStatus *fs, gboolean detailed)
3528 gboolean ret = FALSE;
3529 cam_focus_status_t status;
3532 GST_DEBUG_OBJECT (v4l2camsrc, "Retrieving focus status");
3534 update = cam_checkfocus_status (&status, (v4l2camsrc->debug_flags & GST_CAMERASRC_DEBUG_FLAGS_AUTO_FOCUS));
3536 if (update == TRUE) {
3537 fs->status = cam_find_item_new (gst_v4l2camsrc_focus_status_map, status, TRUE);
3540 GST_DEBUG_OBJECT (v4l2camsrc, "Focus status: %d", fs->status);
3546 gst_v4l2camsrc_set_capture_mode (GstCameraSrc * camsrc,
3547 GstCameraSrcCaptureMode mode)
3549 GstMFLDV4l2CamSrc *v4l2camsrc;
3550 gboolean ret = FALSE;
3551 int err; //cam_err_t err;
3552 cam_capture_mode_t cam_mode;
3553 static const gchar *cmodes[] = { "VIEWFINDER", "STILL", "VIDEO" };
3554 struct v4l2_streamparm parm;
3558 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3560 fd = v4l2camsrc->video_fd;
3562 cam_mode = find_item (gst_v4l2camsrc_capture_map, mode);
3564 g_mutex_lock (v4l2camsrc->device_mutex);
3566 if (v4l2camsrc->initialized) {
3567 v4l2camsrc->capture_mode = mode;
3568 GST_DEBUG ("Setting isp capture mode: %s", cmodes[mode]);
3569 memset (&parm, 0x00, sizeof (struct v4l2_streamparm));
3571 parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3572 err = ioctl(fd, VIDIOC_G_PARM, &parm);
3574 GST_DEBUG("Unable to get frame rate: %s (%d).\n",
3575 strerror(errno), errno);
3578 GST_DEBUG("Current frame rate: %u/%u\n",
3579 parm.parm.capture.timeperframe.numerator,
3580 parm.parm.capture.timeperframe.denominator);
3582 GST_DEBUG("Current run mode: %04x\n", parm.parm.capture.capturemode);
3585 case GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER:
3586 binary = CI_MODE_PREVIEW;
3588 case GST_CAMERA_SRC_CAPTURE_MODE_STILL:
3589 binary = CI_MODE_STILL_CAPTURE;
3591 case GST_CAMERA_SRC_CAPTURE_MODE_VIDEO:
3592 binary = CI_MODE_VIDEO;
3595 binary = CI_MODE_PREVIEW;
3598 parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3599 parm.parm.capture.capturemode = binary;
3601 GST_DEBUG("New run mode: %04x\n", parm.parm.capture.capturemode);
3603 if (ioctl (fd, VIDIOC_S_PARM, &parm) < 0) {
3604 GST_DEBUG("Switch Mode failed !\n");
3608 GST_DEBUG_OBJECT (v4l2camsrc, "Setting capture mode done: %s",
3609 ret ? "OK" : "FAIL");
3612 GST_DEBUG_OBJECT (v4l2camsrc, "Device not initialized");
3616 g_mutex_unlock (v4l2camsrc->device_mutex);
3621 gboolean gst_v4l2camsrc_set_strobe_state (GstCameraSrc * camsrc,
3625 GstMFLDV4l2CamSrc *v4l2camsrc;
3627 cam_err_t err = CAM_ERR_NONE;
3629 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3630 fd = v4l2camsrc->video_fd;
3632 err = cam_set_flash (fd, state);
3633 return(err == CAM_ERR_NONE);
3636 gst_libmfldcam_capture_correction_update (GstMFLDV4l2CamSrc * v4l2camsrc)
3638 int fd = v4l2camsrc->video_fd;
3641 if (!v4l2camsrc->cc_updated)
3644 if (v4l2camsrc->gdc_enabled)
3645 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_GDC, TRUE);
3647 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_GDC, FALSE);
3652 if (v4l2camsrc->cac_enabled)
3653 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_CAC, TRUE);
3655 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_CAC, FALSE);
3660 if (v4l2camsrc->dvs_enabled)
3661 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_DVS, TRUE);
3663 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_DVS, FALSE);
3668 if (v4l2camsrc->ee_enabled)
3669 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_EE, TRUE);
3671 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_EE, FALSE);
3676 if (v4l2camsrc->sc_enabled)
3677 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_SC, TRUE);
3679 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_SC, FALSE);
3684 if (v4l2camsrc->blc_enabled)
3685 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BLC, TRUE);
3687 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BLC, FALSE);
3689 if (v4l2camsrc->bpd_enabled)
3690 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BPD, TRUE);
3692 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BPD, FALSE);
3697 v4l2camsrc->cc_updated = FALSE;
3706 GST_WARNING_OBJECT (v4l2camsrc, "Set capture correction failed \n");
3712 * gst_v4l2camsrc_libmfldcam_set_zoom:
3713 * @v4l2camsrc: #GstMFLDV4l2CamSrc object.
3714 * @zoom: Desired zoom factor.
3716 * Set the zoom factor for captured image.
3718 * Returns: TRUE on success.
3721 gst_v4l2camsrc_libmfldcam_set_zoom (GstMFLDV4l2CamSrc * v4l2camsrc, gfloat zoom)
3723 cam_err_t err = CAM_ERR_NONE;
3726 GST_DEBUG_OBJECT (v4l2camsrc, "ZOOM: %f", zoom);
3728 err = cam_set_zoom (v4l2camsrc->video_fd, zoom);
3729 /* ret = err == CAM_ERR_NONE; */
3732 GST_DEBUG_OBJECT (v4l2camsrc, "Setting zoom: %s", ret ? "SUCCESS" : "FAIL");
3738 gst_v4l2camsrc_libmfldcam_get_makernote (GstMFLDV4l2CamSrc * v4l2camsrc, unsigned char *buf, unsigned size)
3740 cam_err_t err = CAM_ERR_NONE;
3742 GST_DEBUG_OBJECT (v4l2camsrc, "%s, !!!!!!line:%d\n", __func__, __LINE__);
3744 err = cam_get_makernote (v4l2camsrc->video_fd, buf, size);
3749 gst_v4l2camsrc_libmfldcam_get_focus_posi(GstMFLDV4l2CamSrc * v4l2camsrc, unsigned *posi)
3751 cam_err_t err = CAM_ERR_NONE;
3752 err = cam_get_focus_posi(v4l2camsrc->video_fd, posi);
3753 if(err != CAM_ERR_NONE)
3760 * @v4l2camsrc: #GstMFLDV4l2CamSrc object
3762 * configure driver default settings and set the opened ISP fd to libmfldcam
3765 gst_v4l2camsrc_libmfldcam_init (GstMFLDV4l2CamSrc * v4l2camsrc)
3768 struct v4l2_input input;
3772 memset(&input, 0, sizeof(input));
3773 if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_PRIMARY)
3774 input.index = V2L2_CAMERA_INPUT_SENSOR_PRIMARY;
3776 input.index = V2L2_CAMERA_INPUT_SENSOR_SECONDARY;
3778 ret = ioctl(v4l2camsrc->video_fd, VIDIOC_ENUMINPUT, &input);
3782 name = (char*)input.name;
3783 space = strchr(name, ' ');
3785 name[space - name] = '\0';
3787 GST_DEBUG_OBJECT (v4l2camsrc, "sensor name %s", name);
3789 err = cam_driver_init (v4l2camsrc->video_fd, name);
3791 if (err != CAM_ERR_NONE) {
3792 GST_WARNING ("libmfldcam initialization failed");
3795 if (v4l2camsrc->cc_updated)
3796 gst_libmfldcam_capture_correction_update (v4l2camsrc);
3798 if (v4l2camsrc->gamma_updated) {
3799 cam_set_tone_control (v4l2camsrc->video_fd, CAM_GAMMA_VALUE,
3801 cam_set_tone_control (v4l2camsrc->video_fd, CAM_BRIGHTNESS_VALUE,
3803 cam_set_tone_control (v4l2camsrc->video_fd, CAM_CONTRAST_VALUE,
3805 v4l2camsrc->gamma_updated = FALSE;
3808 /* Set the default settings here */
3810 GST_DEBUG_OBJECT (v4l2camsrc, "Configure default settings %s",
3811 v4l2camsrc->videodev);
3813 gst_v4l2camsrc_set_attribute (GST_CAMERA_SRC (v4l2camsrc),V4L2_CID_VFLIP,v4l2camsrc->vflip);
3814 if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_SECONDARY) {
3815 gst_v4l2camsrc_set_attribute (GST_CAMERA_SRC (v4l2camsrc),V4L2_CID_HFLIP,v4l2camsrc->hflip);
3816 gst_v4l2camsrc_set_attribute (GST_CAMERA_SRC (v4l2camsrc),V4L2_CID_POWER_LINE_FREQUENCY,CAM_GENERAL_FLICKER_REDUCTION_MODE_50HZ);
3819 v4l2camsrc->initialized = TRUE;
3820 v4l2camsrc->is_open = TRUE;
3825 gst_v4l2camsrc_libmfldcam_deinit (GstMFLDV4l2CamSrc * v4l2camsrc)
3827 //FIXME : determin whether is it initialized
3829 err = cam_driver_deinit (v4l2camsrc->video_fd);
3830 if (err != CAM_ERR_NONE) {
3831 GST_WARNING ("libmfldcam initialization failed");
3835 v4l2camsrc->is_open = FALSE;