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 case MM_CAM_FILTER_BRIGHTNESS_SOURCE_PRIV:
839 /* we only handle these for now (why?) */
843 case V4L2_CID_HCENTER:
844 case V4L2_CID_VCENTER:
845 #ifdef V4L2_CID_PAN_RESET
846 case V4L2_CID_PAN_RESET:
848 #ifdef V4L2_CID_TILT_RESET
849 case V4L2_CID_TILT_RESET:
851 /* not handled here, handled by VideoOrientation interface */
854 case V4L2_CID_AUDIO_VOLUME:
855 case V4L2_CID_AUDIO_BALANCE:
856 case V4L2_CID_AUDIO_BASS:
857 case V4L2_CID_AUDIO_TREBLE:
858 case V4L2_CID_AUDIO_MUTE:
859 case V4L2_CID_AUDIO_LOUDNESS:
860 /* FIXME: We should implement GstMixer interface */
863 GST_DEBUG_OBJECT (v4l2camsrc,
864 "ControlID %s (%x) unhandled, FIXME", control.name, n);
871 GST_DEBUG_OBJECT (v4l2camsrc, "Adding ControlID %s (%x)", control.name, n);
873 g_object_new (GST_TYPE_CAMERA_SRC_COLOR_BALANCE_CHANNEL, NULL);
874 channel = GST_COLOR_BALANCE_CHANNEL (v4l2channel);
875 channel->label = g_strdup ((const gchar *) control.name);
879 switch (control.type) {
880 case V4L2_CTRL_TYPE_INTEGER:
881 channel->min_value = control.minimum;
882 channel->max_value = control.maximum;
884 case V4L2_CTRL_TYPE_BOOLEAN:
885 channel->min_value = FALSE;
886 channel->max_value = TRUE;
889 /* FIXME we should find out how to handle V4L2_CTRL_TYPE_BUTTON.
890 BUTTON controls like V4L2_CID_DO_WHITE_BALANCE can just be set (1) or
891 unset (0), but can't be queried */
892 GST_DEBUG_OBJECT (v4l2camsrc,
893 "Control with non supported type %s (%x), type=%d",
894 control.name, n, control.type);
895 channel->min_value = channel->max_value = 0;
899 gst_camerasrc_add_color_channel (GST_CAMERA_SRC (v4l2camsrc), channel);
902 GST_DEBUG_OBJECT (v4l2camsrc, "done");
906 /******************************************************
907 * gst_v4l2camsrc_open():
908 * open the video device (v4l2camsrc->videodev)
909 * return value: TRUE on success, FALSE on error
910 ******************************************************/
912 gst_v4l2camsrc_open (GstCameraSrc * camsrc)
915 GstPollFD pollfd = GST_POLL_FD_INIT;
917 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
919 GST_DEBUG_OBJECT (v4l2camsrc, "Trying to open device %s",
920 v4l2camsrc->videodev);
922 GST_V4L2CAMSRC_CHECK_NOT_OPEN (v4l2camsrc);
923 GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
925 /* be sure we have a device */
926 if (!v4l2camsrc->videodev)
927 v4l2camsrc->videodev = g_strdup ("/dev/video");
929 /* check if it is a device */
930 if (stat (v4l2camsrc->videodev, &st) == -1)
933 if (!S_ISCHR (st.st_mode))
936 /* open the device */
937 v4l2camsrc->video_fd =
938 open (v4l2camsrc->videodev, O_RDWR /* | O_NONBLOCK */ );
940 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
943 /* get capabilities, error will be posted */
944 if (!gst_v4l2camsrc_get_capture_capabilities (v4l2camsrc))
947 /* get capabilities, error will be posted */
948 if (!gst_v4l2camsrc_set_input_sensor (v4l2camsrc))
951 /* do we need to be a capture device? */
952 if (GST_IS_V4L2CAMSRC (v4l2camsrc) &&
953 !(v4l2camsrc->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
956 /* Before iterating enumerations, clear the parent's color channel list */
957 gst_camerasrc_clear_color_channels (camsrc);
959 /* create enumerations, posts errors. */
960 if (!gst_v4l2camsrc_fill_lists (v4l2camsrc))
963 GST_INFO_OBJECT (v4l2camsrc,
964 "Opened device '%s' (%s) successfully",
965 v4l2camsrc->vcap.card, v4l2camsrc->videodev);
967 pollfd.fd = v4l2camsrc->video_fd;
968 gst_poll_add_fd (v4l2camsrc->poll, &pollfd);
969 gst_poll_fd_ctl_read (v4l2camsrc->poll, &pollfd, TRUE);
971 gst_v4l2camsrc_libmfldcam_init (v4l2camsrc);
978 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
979 ("Cannot identify device '%s'.", v4l2camsrc->videodev),
985 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
986 ("This isn't a device '%s'.", v4l2camsrc->videodev), GST_ERROR_SYSTEM);
991 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, OPEN_READ_WRITE,
992 ("Could not open device '%s' for reading and writing.",
993 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
998 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
999 ("Device '%s' is not a capture device.",
1000 v4l2camsrc->videodev),
1001 ("Capabilities: 0x%x", v4l2camsrc->vcap.capabilities));
1006 if (GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc)) {
1008 close (v4l2camsrc->video_fd);
1009 v4l2camsrc->video_fd = -1;
1016 /******************************************************
1017 * gst_v4l2camsrc_close():
1018 * close the video device (v4l2camsrc->video_fd)
1019 * return value: TRUE on success, FALSE on error
1020 ******************************************************/
1022 gst_v4l2camsrc_close (GstCameraSrc * camsrc)
1024 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1026 GstPollFD pollfd = GST_POLL_FD_INIT;
1028 GST_DEBUG_OBJECT (v4l2camsrc, "Trying to close %s", v4l2camsrc->videodev);
1030 GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
1031 GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
1034 gst_v4l2camsrc_libmfldcam_deinit (v4l2camsrc);
1036 close (v4l2camsrc->video_fd);
1037 pollfd.fd = v4l2camsrc->video_fd;
1038 gst_poll_remove_fd (v4l2camsrc->poll, &pollfd);
1039 v4l2camsrc->video_fd = -1;
1044 /******************************************************
1045 * gst_v4l2camsrc_get_attribute():
1046 * try to get the value of one specific attribute
1047 * return value: TRUE on success, FALSE on error
1048 ******************************************************/
1050 gst_v4l2camsrc_get_attribute (GstCameraSrc * camsrc,
1051 int attribute_num, int *value)
1053 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1055 struct v4l2_control control;
1059 GST_DEBUG_OBJECT (v4l2camsrc, "getting value of attribute %d", attribute_num);
1061 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
1064 control.id = attribute_num;
1066 if (control.id > SOURCE_PRIV_BASE) {
1067 switch (control.id) {
1068 case MM_CAM_FILTER_WB_SOURCE_PRIV:
1069 err = cam_feature_get (v4l2camsrc->video_fd, CAM_AWB_MODE, &tmp_value);
1070 *value = find_item (gst_v4l2camsrc_wb_map, tmp_value);
1072 case MM_CAM_FILTER_COLOR_TONE_SOURCE_PRIV:
1073 err = cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE, &tmp_value);
1074 *value = find_item (gst_v4l2camsrc_effect_map, tmp_value);
1076 case MM_CAM_FILTER_BRIGHTNESS_SOURCE_PRIV:
1077 err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION, &tmp_value);
1086 if (ioctl (v4l2camsrc->video_fd, VIDIOC_G_CTRL, &control) < 0)
1088 *value = control.value;
1095 struct v4l2_ext_controls controls;
1096 struct v4l2_ext_control control;
1098 controls.ctrl_class = V4L2_CTRL_CLASS_USER;
1100 controls.controls = &control;
1102 control.id = attribute_num;
1104 if (ioctl (v4l2camsrc->video_fd, VIDIOC_G_EXT_CTRLS, &controls) < 0)
1107 *value = control.value;
1116 GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1117 ("Failed to get value for control %d on device '%s'.",
1118 attribute_num, v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1123 /******************************************************
1124 * gst_v4l2camsrc_set_attribute():
1125 * try to set the value of one specific attribute
1126 * return value: TRUE on success, FALSE on error
1127 ******************************************************/
1129 gst_v4l2camsrc_set_attribute (GstCameraSrc * camsrc,
1130 int attribute_num, const int value)
1132 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1133 struct v4l2_control control;
1135 GST_DEBUG_OBJECT (v4l2camsrc, "setting value of attribute %d to %d",
1136 attribute_num, value);
1138 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
1141 control.id = attribute_num;
1142 control.value = value;
1143 if (control.id > SOURCE_PRIV_BASE) {
1144 switch (control.id) {
1145 case MM_CAM_FILTER_WB_SOURCE_PRIV:
1146 cam_feature_set (v4l2camsrc->video_fd, CAM_AWB_MODE, gst_v4l2camsrc_wb_map[value]);
1148 case MM_CAM_FILTER_COLOR_TONE_SOURCE_PRIV:
1149 cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE, gst_v4l2camsrc_effect_map[value]);
1151 case MM_CAM_FILTER_BRIGHTNESS_SOURCE_PRIV:
1152 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION, value);
1159 if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_CTRL, &control) < 0)
1166 struct v4l2_ext_controls controls;
1167 struct v4l2_ext_control control;
1169 controls.ctrl_class = V4L2_CTRL_CLASS_USER;
1171 controls.controls = &control;
1173 control.id = attribute_num;
1174 control.value = value;
1176 if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_EXT_CTRLS, &controls) < 0)
1185 GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1186 ("Failed to set value %d for control %d on device '%s'.",
1187 value, attribute_num, v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1193 /* complete made up ranking, the values themselves are meaningless */
1194 #define YUV_BASE_RANK 1000
1195 #define JPEG_BASE_RANK 500
1196 #define DV_BASE_RANK 200
1197 #define RGB_BASE_RANK 100
1198 #define YUV_ODD_BASE_RANK 50
1199 #define RGB_ODD_BASE_RANK 25
1200 #define BAYER_BASE_RANK 15
1201 #define S910_BASE_RANK 10
1202 #define GREY_BASE_RANK 5
1203 #define PWC_BASE_RANK 1
1205 /* This flag is already used by libv4l2 although
1206 * it was added to the Linux kernel in 2.6.32
1208 #ifndef V4L2_FMT_FLAG_EMULATED
1209 #define V4L2_FMT_FLAG_EMULATED 0x0002
1213 gst_v4l2camsrc_format_get_rank (const struct v4l2_fmtdesc *fmt)
1215 guint32 fourcc = fmt->pixelformat;
1216 gboolean emulated = ((fmt->flags & V4L2_FMT_FLAG_EMULATED) != 0);
1220 case V4L2_PIX_FMT_MJPEG:
1221 rank = JPEG_BASE_RANK;
1223 case V4L2_PIX_FMT_JPEG:
1224 rank = JPEG_BASE_RANK + 1;
1226 case V4L2_PIX_FMT_MPEG: /* MPEG */
1227 rank = JPEG_BASE_RANK + 2;
1230 case V4L2_PIX_FMT_RGB332:
1231 case V4L2_PIX_FMT_RGB555:
1232 case V4L2_PIX_FMT_RGB555X:
1233 case V4L2_PIX_FMT_RGB565:
1234 case V4L2_PIX_FMT_RGB565X:
1235 rank = RGB_ODD_BASE_RANK;
1238 case V4L2_PIX_FMT_RGB24:
1239 case V4L2_PIX_FMT_BGR24:
1240 rank = RGB_BASE_RANK - 1;
1243 case V4L2_PIX_FMT_RGB32:
1244 case V4L2_PIX_FMT_BGR32:
1245 rank = RGB_BASE_RANK;
1248 case V4L2_PIX_FMT_GREY: /* 8 Greyscale */
1249 rank = GREY_BASE_RANK;
1252 case V4L2_PIX_FMT_NV12: /* 12 Y/CbCr 4:2:0 */
1253 case V4L2_PIX_FMT_NV21: /* 12 Y/CrCb 4:2:0 */
1254 case V4L2_PIX_FMT_YYUV: /* 16 YUV 4:2:2 */
1255 case V4L2_PIX_FMT_HI240: /* 8 8-bit color */
1256 case V4L2_PIX_FMT_NV16: /* 16 bit YUV 422, Y, UV plane */
1257 rank = YUV_ODD_BASE_RANK;
1259 case V4L2_PIX_FMT_YUV444: /* YUV 444, 24 bits per pixel */
1260 rank = YUV_BASE_RANK + 0;
1262 case V4L2_PIX_FMT_YVU410: /* YVU9, 9 bits per pixel */
1263 rank = YUV_BASE_RANK + 3;
1265 case V4L2_PIX_FMT_YUV410: /* YUV9, 9 bits per pixel */
1266 rank = YUV_BASE_RANK + 2;
1268 case V4L2_PIX_FMT_YUV420: /* I420, 12 bits per pixel */
1269 rank = YUV_BASE_RANK + 7;
1271 case V4L2_PIX_FMT_YUYV: /* YUY2, 16 bits per pixel */
1272 rank = YUV_BASE_RANK + 10;
1274 case V4L2_PIX_FMT_YVU420: /* YV12, 12 bits per pixel */
1275 rank = YUV_BASE_RANK + 6;
1277 case V4L2_PIX_FMT_UYVY: /* UYVY, 16 bits per pixel */
1278 rank = YUV_BASE_RANK + 9;
1280 case V4L2_PIX_FMT_Y41P: /* Y41P, 12 bits per pixel */
1281 rank = YUV_BASE_RANK + 5;
1283 case V4L2_PIX_FMT_YUV411P: /* Y41B, 12 bits per pixel */
1284 rank = YUV_BASE_RANK + 4;
1286 case V4L2_PIX_FMT_YUV422P: /* Y42B, 16 bits per pixel */
1287 rank = YUV_BASE_RANK + 8;
1290 case V4L2_PIX_FMT_DV:
1291 rank = DV_BASE_RANK;
1294 case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */
1298 case V4L2_PIX_FMT_SBGGR8:
1299 case V4L2_PIX_FMT_SRGGB8:
1300 case V4L2_PIX_FMT_SGBRG8:
1301 case V4L2_PIX_FMT_SGRBG10:
1302 case V4L2_PIX_FMT_SRGGB10:
1303 case V4L2_PIX_FMT_SGBRG10:
1304 rank = BAYER_BASE_RANK;
1307 #ifdef V4L2_PIX_FMT_SN9C10X
1308 case V4L2_PIX_FMT_SN9C10X:
1309 rank = S910_BASE_RANK;
1313 #ifdef V4L2_PIX_FMT_PWC1
1314 case V4L2_PIX_FMT_PWC1:
1315 rank = PWC_BASE_RANK;
1318 #ifdef V4L2_PIX_FMT_PWC2
1319 case V4L2_PIX_FMT_PWC2:
1320 rank = PWC_BASE_RANK;
1325 GST_LOG("Don't know how to rank pixelformat %" GST_FOURCC_FORMAT,
1326 GST_FOURCC_ARGS(fourcc));
1331 /* All ranks are below 1<<15 so a shift by 15
1332 * will a) make all non-emulated formats larger
1333 * than emulated and b) will not overflow
1342 gst_v4l2camsrc_format_cmp_func (gconstpointer a, gconstpointer b)
1344 const struct v4l2_fmtdesc *fa = a;
1345 const struct v4l2_fmtdesc *fb = b;
1347 if (fa->pixelformat == fb->pixelformat)
1350 return gst_v4l2camsrc_format_get_rank (fb) -
1351 gst_v4l2camsrc_format_get_rank (fa);
1354 static gboolean is_supported_pixelformat(guint32 fourcc)
1356 if(fourcc == V4L2_PIX_FMT_NV12
1357 || fourcc == V4L2_PIX_FMT_YUV420
1358 || fourcc == V4L2_PIX_FMT_SGRBG10)
1363 /******************************************************
1364 * gst_v4l2camsrc_fill_format_list():
1365 * create list of supported capture formats
1366 * return value: TRUE on success, FALSE on error
1367 ******************************************************/
1369 gst_v4l2camsrc_fill_format_list (GstMFLDV4l2CamSrc * v4l2camsrc)
1372 struct v4l2_fmtdesc *format;
1374 GST_DEBUG_OBJECT (v4l2camsrc, "getting src format enumerations");
1376 /* format enumeration */
1378 format = g_new0 (struct v4l2_fmtdesc, 1);
1381 format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1383 if (ioctl (v4l2camsrc->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
1384 if (errno == EINVAL) {
1386 break; /* end of enumeration */
1391 if(!is_supported_pixelformat(format->pixelformat)) {
1392 GST_LOG_OBJECT(v4l2camsrc, " (skipping format %" GST_FOURCC_FORMAT ")",GST_FOURCC_ARGS (format->pixelformat));
1396 GST_LOG_OBJECT (v4l2camsrc, "index: %u", format->index);
1397 GST_LOG_OBJECT (v4l2camsrc, "type: %d", format->type);
1398 GST_LOG_OBJECT (v4l2camsrc, "flags: %08x", format->flags);
1399 GST_LOG_OBJECT (v4l2camsrc, "description: '%s'", format->description);
1400 GST_LOG_OBJECT (v4l2camsrc, "pixelformat: %" GST_FOURCC_FORMAT,
1401 GST_FOURCC_ARGS (format->pixelformat));
1403 /* sort formats according to our preference; we do this, because caps
1404 * are probed in the order the formats are in the list, and the order of
1405 * formats in the final probed caps matters for things like fixation */
1406 v4l2camsrc->formats = g_slist_insert_sorted (v4l2camsrc->formats, format,
1407 (GCompareFunc) gst_v4l2camsrc_format_cmp_func);
1410 GST_DEBUG_OBJECT (v4l2camsrc, "got %d format(s)", n);
1417 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1418 ("Failed to enumerate possible video formats device '%s' can work with",
1419 v4l2camsrc->videodev),
1420 ("Failed to get number %d in pixelformat enumeration for %s. (%d - %s)",
1421 n, v4l2camsrc->videodev, errno, g_strerror (errno)));
1427 /******************************************************
1428 * gst_v4l2camsrc_clear_format_list():
1429 * free list of supported capture formats
1430 * return value: TRUE on success, FALSE on error
1431 ******************************************************/
1433 gst_v4l2camsrc_clear_format_list (GstMFLDV4l2CamSrc * v4l2camsrc)
1435 g_slist_foreach (v4l2camsrc->formats, (GFunc) g_free, NULL);
1436 g_slist_free (v4l2camsrc->formats);
1437 v4l2camsrc->formats = NULL;
1442 /* The frame interval enumeration code first appeared in Linux 2.6.19. */
1443 #ifdef VIDIOC_ENUM_FRAMEINTERVALS
1444 static GstStructure *
1445 gst_v4l2camsrc_probe_caps_for_format_and_size (GstMFLDV4l2CamSrc * v4l2camsrc,
1446 guint32 pixelformat,
1447 guint32 width, guint32 height, const GstStructure * template)
1449 gint fd = v4l2camsrc->video_fd;
1450 struct v4l2_frmivalenum ival;
1453 GValue rates = { 0, };
1455 memset (&ival, 0, sizeof (struct v4l2_frmivalenum));
1457 ival.pixel_format = pixelformat;
1459 ival.height = height;
1461 GST_LOG_OBJECT (v4l2camsrc, "get frame interval for %ux%u, %"
1462 GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat));
1464 /* keep in mind that v4l2 gives us frame intervals (durations); we invert the
1465 * fraction to get framerate */
1466 if (ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0)
1467 goto enum_frameintervals_failed;
1469 if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
1470 GValue rate = { 0, };
1472 g_value_init (&rates, GST_TYPE_LIST);
1473 g_value_init (&rate, GST_TYPE_FRACTION);
1476 num = ival.discrete.numerator;
1477 denom = ival.discrete.denominator;
1479 if (num > G_MAXINT || denom > G_MAXINT) {
1480 /* let us hope we don't get here... */
1485 GST_LOG_OBJECT (v4l2camsrc, "adding discrete framerate: %d/%d",
1488 /* swap to get the framerate */
1489 gst_value_set_fraction (&rate, denom, num);
1490 gst_value_list_append_value (&rates, &rate);
1493 } while (ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
1495 /* FIXME MASSIVE UGLY HACK: Pretend to support 30/1 fps always */
1496 gst_value_set_fraction(&rate, 30, 1);
1497 gst_value_list_append_value(&rates, &rate);
1499 } else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
1500 GValue min = { 0, };
1501 GValue step = { 0, };
1502 GValue max = { 0, };
1503 gboolean added = FALSE;
1504 guint32 minnum, mindenom;
1505 guint32 maxnum, maxdenom;
1507 g_value_init (&rates, GST_TYPE_LIST);
1509 g_value_init (&min, GST_TYPE_FRACTION);
1510 g_value_init (&step, GST_TYPE_FRACTION);
1511 g_value_init (&max, GST_TYPE_FRACTION);
1514 minnum = ival.stepwise.min.numerator;
1515 mindenom = ival.stepwise.min.denominator;
1516 if (minnum > G_MAXINT || mindenom > G_MAXINT) {
1520 GST_LOG_OBJECT (v4l2camsrc, "stepwise min frame interval: %d/%d", minnum,
1522 gst_value_set_fraction (&min, minnum, mindenom);
1525 maxnum = ival.stepwise.max.numerator;
1526 maxdenom = ival.stepwise.max.denominator;
1527 if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
1532 GST_LOG_OBJECT (v4l2camsrc, "stepwise max frame interval: %d/%d", maxnum,
1534 gst_value_set_fraction (&max, maxnum, maxdenom);
1537 num = ival.stepwise.step.numerator;
1538 denom = ival.stepwise.step.denominator;
1539 if (num > G_MAXINT || denom > G_MAXINT) {
1544 if (num == 0 || denom == 0) {
1545 /* in this case we have a wrong fraction or no step, set the step to max
1546 * so that we only add the min value in the loop below */
1551 /* since we only have gst_value_fraction_subtract and not add, negate the
1553 GST_LOG_OBJECT (v4l2camsrc, "stepwise step frame interval: %d/%d",
1556 gst_value_set_fraction (&step, -num, denom);
1558 while (gst_value_compare (&min, &max) <= 0) {
1559 GValue rate = { 0, };
1561 num = gst_value_get_fraction_numerator (&min);
1562 denom = gst_value_get_fraction_denominator (&min);
1563 GST_LOG_OBJECT (v4l2camsrc, "adding stepwise framerate: %d/%d",
1566 /* invert to get the framerate */
1567 g_value_init (&rate, GST_TYPE_FRACTION);
1568 gst_value_set_fraction (&rate, denom, num);
1569 gst_value_list_append_value (&rates, &rate);
1572 /* we're actually adding because step was negated above. This is because
1573 * there is no _add function... */
1574 if (!gst_value_fraction_subtract (&min, &min, &step)) {
1575 GST_WARNING_OBJECT (v4l2camsrc, "could not step fraction!");
1580 /* no range was added, leave the default range from the template */
1581 GST_WARNING_OBJECT (v4l2camsrc, "no range added, leaving default");
1582 g_value_unset (&rates);
1584 } else if (ival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
1585 guint32 maxnum, maxdenom;
1587 g_value_init (&rates, GST_TYPE_FRACTION_RANGE);
1589 num = ival.stepwise.min.numerator;
1590 denom = ival.stepwise.min.denominator;
1591 if (num > G_MAXINT || denom > G_MAXINT) {
1596 maxnum = ival.stepwise.max.numerator;
1597 maxdenom = ival.stepwise.max.denominator;
1598 if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
1603 GST_LOG_OBJECT (v4l2camsrc, "continuous frame interval %d/%d to %d/%d",
1604 maxdenom, maxnum, denom, num);
1606 gst_value_set_fraction_range_full (&rates, maxdenom, maxnum, denom, num);
1612 s = gst_structure_copy (template);
1613 /* https://projects.maemo.org/bugzilla/show_bug.cgi?id=105590 */
1614 gst_structure_set (s,
1615 "width", G_TYPE_INT, (gint) width,
1616 "height", G_TYPE_INT, (gint) height, NULL);
1618 if (G_IS_VALUE (&rates)) {
1619 /* only change the framerate on the template when we have a valid probed new
1621 gst_structure_set_value (s, "framerate", &rates);
1622 g_value_unset (&rates);
1627 enum_frameintervals_failed:
1629 GST_DEBUG_OBJECT (v4l2camsrc,
1630 "Unable to enumerate intervals for %" GST_FOURCC_FORMAT "@%ux%u",
1631 GST_FOURCC_ARGS (pixelformat), width, height);
1636 /* I don't see how this is actually an error, we ignore the format then */
1637 GST_WARNING_OBJECT (v4l2camsrc,
1638 "Unknown frame interval type at %" GST_FOURCC_FORMAT "@%ux%u: %u",
1639 GST_FOURCC_ARGS (pixelformat), width, height, ival.type);
1643 #endif /* defined VIDIOC_ENUM_FRAMEINTERVALS */
1649 compare_resolutions (gconstpointer a, gconstpointer b)
1651 GstStructure *as = (GstStructure *) a;
1652 GstStructure *bs = (GstStructure *) b;
1653 gint aw, bw, ah, bh;
1655 gst_structure_get_int (as, "width", &aw);
1656 gst_structure_get_int (bs, "width", &bw);
1657 gst_structure_get_int (as, "height", &ah);
1658 gst_structure_get_int (bs, "height", &bh);
1660 /* FIXME: What is the best way to compare resolutions if their aspect
1661 * ratio isn't the same? */
1662 return ((aw - bw) + (ah - bh));
1669 fractions_are_equal (gint num1, gint den1, gint num2, gint den2)
1671 GValue fraction1 = { 0, }, fraction2 = {
1674 g_value_init (&fraction1, GST_TYPE_FRACTION);
1675 g_value_init (&fraction2, GST_TYPE_FRACTION);
1676 gst_value_set_fraction (&fraction1, num1, den1);
1677 gst_value_set_fraction (&fraction2, num2, den2);
1678 /* we know we don't have to unset the values in this case */
1679 return (gst_value_compare (&fraction1, &fraction2) == GST_VALUE_EQUAL);
1683 gst_v4l2camsrc_get_frame_size (guint32 fourcc, guint * w, guint * h)
1688 case V4L2_PIX_FMT_YUV420:
1689 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1690 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1692 case V4L2_PIX_FMT_YUYV:
1693 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1695 case V4L2_PIX_FMT_Y41P:
1696 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1698 case V4L2_PIX_FMT_UYVY:
1699 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1701 case V4L2_PIX_FMT_YVU420:
1702 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1703 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1705 case V4L2_PIX_FMT_YUV411P:
1706 outsize = GST_ROUND_UP_4 (*w) * *h;
1707 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
1709 case V4L2_PIX_FMT_YUV422P:
1710 outsize = GST_ROUND_UP_4 (*w) * *h;
1711 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
1713 case V4L2_PIX_FMT_NV12:
1714 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1715 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1717 case V4L2_PIX_FMT_NV21:
1718 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1719 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1729 gst_v4l2camsrc_configure_device (GstMFLDV4l2CamSrc * v4l2camsrc,
1730 guint32 * pixelformat, guint * width, guint * height,
1731 guint * fps_n, guint * fps_d)
1733 gint fd = v4l2camsrc->video_fd;
1734 struct v4l2_format format;
1735 struct v4l2_streamparm stream;
1736 gboolean ret = TRUE;
1738 GST_DEBUG_OBJECT (v4l2camsrc, "Configuring device to %dx%d, format "
1739 "%" GST_FOURCC_FORMAT, *width, *height, GST_FOURCC_ARGS (*pixelformat));
1741 GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
1743 memset (&format, 0x00, sizeof (struct v4l2_format));
1744 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1746 if (ioctl (fd, VIDIOC_G_FMT, &format) < 0)
1747 goto get_fmt_failed;
1749 if (v4l2camsrc->dump_raw)
1750 format.type = V4L2_BUF_TYPE_PRIVATE;
1752 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1753 format.fmt.pix.width = *width;
1754 format.fmt.pix.height = *height;
1755 format.fmt.pix.pixelformat = *pixelformat;
1756 /* request whole frames; change when gstreamer supports interlaced video
1757 * (INTERLACED mode returns frames where the fields have already been
1758 * combined, there are other modes for requesting fields individually) */
1759 format.fmt.pix.field = V4L2_FIELD_INTERLACED;
1761 if (ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
1762 if (errno != EINVAL)
1763 goto set_fmt_failed;
1765 /* try again with progressive video */
1766 format.fmt.pix.width = *width;
1767 format.fmt.pix.height = *height;
1768 format.fmt.pix.pixelformat = *pixelformat;
1769 format.fmt.pix.field = V4L2_FIELD_NONE;
1770 if (ioctl (fd, VIDIOC_S_FMT, &format) < 0)
1771 goto set_fmt_failed;
1774 if (v4l2camsrc->dump_raw)
1775 v4l2camsrc->raw_output_size = format.fmt.pix.priv;
1777 if (format.fmt.pix.width != *width || format.fmt.pix.height != *height)
1778 goto invalid_dimensions;
1780 if (format.fmt.pix.pixelformat != *pixelformat)
1781 goto invalid_pixelformat;
1783 memset (&stream, 0x00, sizeof (struct v4l2_streamparm));
1784 stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1785 if (ioctl (fd, VIDIOC_G_PARM, &stream) < 0) {
1786 GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1787 ("Could not get parameters on device '%s'",
1788 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1792 if (fps_n == NULL || fps_d == NULL) {
1793 GST_LOG_OBJECT (v4l2camsrc, "Framerate will not be set");
1797 GST_LOG_OBJECT (v4l2camsrc, "Desired framerate: %u/%u", *fps_n, *fps_d);
1799 /* Note: V4L2 provides the frame interval, we have the frame rate */
1800 if (stream.parm.capture.timeperframe.denominator &&
1801 fractions_are_equal (stream.parm.capture.timeperframe.numerator,
1802 stream.parm.capture.timeperframe.denominator, *fps_d, *fps_n)) {
1803 GST_LOG_OBJECT (v4l2camsrc, "Desired framerate already set, nothing to do");
1807 /* We want to change the frame rate, so check whether we can. Some cheap USB
1808 * cameras don't have the capability */
1809 if ((stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
1810 GST_DEBUG_OBJECT (v4l2camsrc, "Not setting framerate (not supported)");
1814 GST_LOG_OBJECT (v4l2camsrc, "Setting framerate to %u/%u", *fps_n, *fps_d);
1816 /* Note: V4L2 wants the frame interval, we have the frame rate */
1817 stream.parm.capture.timeperframe.numerator = *fps_d;
1818 stream.parm.capture.timeperframe.denominator = *fps_n;
1820 /* some cheap USB cam's won't accept any change */
1821 if (ioctl (fd, VIDIOC_S_PARM, &stream) < 0) {
1822 GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1823 ("Video input device did not accept new frame rate setting."),
1828 GST_INFO_OBJECT (v4l2camsrc, "Set frame interval to %u/%u",
1829 stream.parm.capture.timeperframe.numerator,
1830 stream.parm.capture.timeperframe.denominator);
1832 cam_set_frame_rate( ((gfloat)stream.parm.capture.timeperframe.denominator / stream.parm.capture.timeperframe.numerator));
1835 v4l2camsrc->max_zoom_factor = 10.0;
1836 v4l2camsrc->frame_byte_size = gst_v4l2camsrc_get_frame_size (*pixelformat,
1838 /* v4l2camsrc->frame_byte_size = GST_ROUND_UP_2 (*width) * 2 * (*height); */
1840 if (v4l2camsrc->bayer_downscaling) {
1841 struct v4l2_crop crop;
1842 memset (&v4l2camsrc->vcrop, 0, sizeof (struct v4l2_cropcap));
1843 v4l2camsrc->vcrop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1844 if (ioctl (v4l2camsrc->video_fd, VIDIOC_CROPCAP, &v4l2camsrc->vcrop) < 0) {
1845 GST_DEBUG_OBJECT (v4l2camsrc, "Failed to query crop cap");
1849 crop.c = v4l2camsrc->vcrop.defrect; /* reset to default */
1850 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1851 if (-1 == ioctl (fd, VIDIOC_S_CROP, &crop)) {
1854 GST_DEBUG_OBJECT (v4l2camsrc, "Crop not support\n");
1857 GST_DEBUG_OBJECT (v4l2camsrc, "Crop failed\n");
1866 v4l2camsrc->crop_supported = TRUE;
1868 GST_DEBUG_OBJECT (v4l2camsrc, "got cropping bounds: x:%d, y:%d, w:%d, h:%d",
1869 v4l2camsrc->vcrop.bounds.left,
1870 v4l2camsrc->vcrop.bounds.top,
1871 v4l2camsrc->vcrop.bounds.width, v4l2camsrc->vcrop.bounds.height);
1873 GST_DEBUG_OBJECT (v4l2camsrc, "cropping defrect: x:%d, y:%d, w:%d, h:%d",
1874 v4l2camsrc->vcrop.defrect.left,
1875 v4l2camsrc->vcrop.defrect.top,
1876 v4l2camsrc->vcrop.defrect.width, v4l2camsrc->vcrop.defrect.height);
1878 gst_v4l2camsrc_update_cropping (v4l2camsrc, *width, *height, 1.0);
1882 cam_set_capture_fmt (v4l2camsrc->video_fd, *width, *height, *pixelformat);
1889 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1890 ("Device '%s' does not support video capture",
1891 v4l2camsrc->videodev),
1892 ("Call to G_FMT failed: (%s)", g_strerror (errno)));
1897 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1898 ("Device '%s' cannot capture at %dx%d",
1899 v4l2camsrc->videodev, *width, *height),
1900 ("Call to S_FMT failed for %" GST_FOURCC_FORMAT " @ %dx%d: %s",
1901 GST_FOURCC_ARGS (*pixelformat), *width, *height,
1902 g_strerror (errno)));
1907 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1908 ("Device '%s' cannot capture at %dx%d",
1909 v4l2camsrc->videodev, *width, *height),
1910 ("Tried to capture at %dx%d, but device returned size %dx%d",
1911 *width, *height, format.fmt.pix.width, format.fmt.pix.height));
1914 invalid_pixelformat:
1916 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1917 ("Device '%s' cannot capture in the specified format",
1918 v4l2camsrc->videodev),
1919 ("Tried to capture in %" GST_FOURCC_FORMAT
1920 ", but device returned format" " %" GST_FOURCC_FORMAT,
1921 GST_FOURCC_ARGS (*pixelformat),
1922 GST_FOURCC_ARGS (format.fmt.pix.pixelformat)));
1927 static gboolean resolution_is_supported(int w, int h)
1929 return (w % 4) == 0 && (h % 4) == 0;
1932 #define probe_and_add_for_w_h(w, h) \
1934 GST_LOG(" w=%lu h=%lu",w,h); \
1935 tmp = gst_v4l2camsrc_probe_caps_for_format_and_size(v4l2camsrc, \
1936 pixelformat, w, h, template); \
1938 res = g_list_prepend(res, tmp); \
1942 static GList *build_caps_list(GstMFLDV4l2CamSrc * v4l2camsrc,
1943 guint32 pixelformat, const GstStructure * template,
1944 struct v4l2_frmsizeenum *size)
1946 GstStructure *tmp = NULL;
1948 long wl,wh,hl,hh,ws,hs;
1950 wl = size->stepwise.min_width; wh = size->stepwise.max_width; ws = size->stepwise.step_width;
1951 hl = size->stepwise.min_height; hh = size->stepwise.max_height; hs = size->stepwise.step_height;
1953 probe_and_add_for_w_h(wl, hl);
1954 probe_and_add_for_w_h(wh, hh);
1956 tmp = gst_structure_copy(template);
1957 gst_structure_set (tmp,
1958 "width", GST_TYPE_INT_RANGE, wl, wh,
1959 "height", GST_TYPE_INT_RANGE, hl, hh,
1961 res = g_list_prepend(res, tmp);
1968 * gst_v4l2camsrc_probe_caps_for_format:
1969 * @v4l2camsrc: #GstMFLDV4l2CamSrc object
1970 * @pixelformat: pixel format fourcc
1971 * @template: GstStructure template to be used for generating the caps
1973 * Creates GstCaps object which describes the supported caps of the device.
1975 * Returns: GStCaps containing supported video resolutions.
1978 gst_v4l2camsrc_probe_caps_for_format (GstMFLDV4l2CamSrc * v4l2camsrc,
1979 guint32 pixelformat, const GstStructure * template)
1981 GstCaps *ret = gst_caps_new_empty ();
1982 gint min_w, max_w, min_h, max_h;
1985 #ifdef VIDIOC_ENUM_FRAMESIZES
1987 gint fd = v4l2camsrc->video_fd;
1988 struct v4l2_frmsizeenum size;
1989 GList *results = NULL;
1992 memset (&size, 0, sizeof (struct v4l2_frmsizeenum));
1994 size.pixel_format = pixelformat;
1996 if (ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0)
1997 goto enum_framesizes_failed;
1999 if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
2001 w = MIN (size.discrete.width, G_MAXINT);
2002 h = MIN (size.discrete.height, G_MAXINT);
2004 if(resolution_is_supported(w, h)) {
2005 tmp = gst_v4l2camsrc_probe_caps_for_format_and_size (v4l2camsrc,
2006 pixelformat, w, h, template);
2009 results = g_list_prepend (results, tmp);
2013 } while (ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
2014 } else if(size.type == V4L2_FRMSIZE_TYPE_STEPWISE
2015 || size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
2016 results = build_caps_list(v4l2camsrc, pixelformat, template, &size);
2021 /* Sort the resolutions from smallest to largest */
2022 results = g_list_sort (results, compare_resolutions);
2024 while (results != NULL) {
2025 tmp = GST_STRUCTURE (results->data);
2027 gst_caps_merge_structure (ret, tmp);
2029 results = g_list_delete_link (results, results);
2032 if (gst_caps_is_empty (ret))
2033 goto enum_framesizes_no_results;
2038 enum_framesizes_failed:
2040 /* I don't see how this is actually an error */
2041 GST_DEBUG_OBJECT (v4l2camsrc,
2042 "Failed to enumerate frame sizes for pixelformat %" GST_FOURCC_FORMAT
2043 " (%s)", GST_FOURCC_ARGS (pixelformat), g_strerror (errno));
2044 goto default_frame_sizes;
2046 enum_framesizes_no_results:
2048 /* it's possible that VIDIOC_ENUM_FRAMESIZES is defined but the driver in
2049 * question doesn't actually support it yet */
2050 GST_DEBUG_OBJECT (v4l2camsrc, "No results for pixelformat %"
2051 GST_FOURCC_FORMAT " enumerating frame sizes, trying fallback",
2052 GST_FOURCC_ARGS (pixelformat));
2053 goto default_frame_sizes;
2057 GST_WARNING_OBJECT (v4l2camsrc,
2058 "Unknown frame sizeenum type for pixelformat %" GST_FOURCC_FORMAT
2059 ": %u", GST_FOURCC_ARGS (pixelformat), size.type);
2060 goto default_frame_sizes;
2063 #endif /* defined VIDIOC_ENUM_FRAMESIZES */
2065 default_frame_sizes:
2068 max_w = max_h = GST_CAMERA_SRC_MAX_SIZE;
2069 if (!gst_v4l2camsrc_get_nearest_size (v4l2camsrc, pixelformat,
2071 GST_WARNING_OBJECT (v4l2camsrc,
2072 "Could not probe minimum capture size for pixelformat %"
2073 GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2075 if (!gst_v4l2camsrc_get_nearest_size (v4l2camsrc, pixelformat,
2077 GST_WARNING_OBJECT (v4l2camsrc,
2078 "Could not probe maximum capture size for pixelformat %"
2079 GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2082 tmp = gst_structure_copy (template);
2083 gst_structure_set (tmp,
2084 "width", GST_TYPE_INT_RANGE, min_w, max_w,
2085 "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL);
2086 gst_caps_append_structure (ret, tmp);
2091 static void draw_corner_markers_nv12(unsigned char *buf, unsigned w, unsigned h)
2094 #define put_dot(x,y) buf[(x)+w*(y)] = (((x+y)&0x01)?0x00:0xff)
2096 for(j = 0; j < 4; ++j)
2097 for(i = 0; i < 8; ++i) {
2098 put_dot(i, j); put_dot(w-1-i, j);
2099 put_dot(j, i); put_dot(j, h-1-i);
2100 put_dot(i, h-1-j); put_dot(w-1-i, h-1-j);
2101 put_dot(w-1-j, i); put_dot(w-1-j, h-1-i);
2106 /* Crop to upper left corner of NV12 frame. */
2107 static gboolean crop_buffer_inplace_nv12(unsigned char *buf, unsigned in_w, unsigned in_h,
2108 unsigned out_w, unsigned out_h)
2111 unsigned char *in, *out;
2113 if(in_w < out_w || in_h < out_h
2114 || in_w % 4 || out_w % 4
2115 || in_h % 4 || out_h % 4)
2118 in = buf; out = buf;
2119 for(rows = 0; rows < out_h; ++rows) {
2120 memmove(out, in, out_w);
2124 in = buf + in_w * in_h;
2125 for(rows = 0; rows < out_h / 2; ++rows) {
2126 memmove(out, in, out_w);
2135 * gst_v4l2camsrc_libmfld_grab_hq_frame:
2136 * @v4l2camsrc: #GstMFLDV4l2CamSrc object
2137 * @buf: Pointer to v4l2_buffer where to place the image frame
2139 * Grab a High-Quality image by using libmfldcam.
2141 * Returns: TRUE if capture succeeds, FALSE otherwise
2144 gst_v4l2camsrc_libmfld_grab_hq_frame (GstMFLDV4l2CamSrc * v4l2camsrc,
2145 struct v4l2_buffer * buffer)
2149 struct cam_capture_settings st;
2151 st.mmap = v4l2camsrc->use_mmap;
2152 st.ae_awb_af = v4l2camsrc->ae_awb_af_enabled;
2153 st.dump_raw = v4l2camsrc->dump_raw;
2154 st.raw_output_size = v4l2camsrc->raw_output_size;
2155 st.dump_image = v4l2camsrc->dump_image;
2157 err = cam_capture_frames (v4l2camsrc->video_fd, buffer, &st);
2158 if (v4l2camsrc->ae_awb_af_enabled)
2159 mfldcam_3a_start ();
2160 ret = (err == CAM_ERR_NONE);
2165 /******************************************************
2166 * gst_v4l2camsrc_grab_frame ():
2167 * grab a frame for capturing
2168 * return value: GST_FLOW_OK, GST_FLOW_WRONG_STATE or GST_FLOW_ERROR
2169 ******************************************************/
2171 gst_v4l2camsrc_grab_frame (GstCameraSrc * camsrc, GstBuffer ** buf,
2172 GstCameraCapturePhase phase)
2174 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2176 #define NUM_TRIALS 5000
2177 struct v4l2_buffer buffer;
2178 gint32 trials = NUM_TRIALS;
2179 GstBuffer *pool_buffer;
2180 gboolean need_copy = v4l2camsrc->use_copy;
2181 gboolean variable_frame_size = FALSE; /* FIXME if we ever support JPEG etc */
2186 /* wait if all buffers are DQBuf */
2187 g_mutex_lock (v4l2camsrc->device_mutex);
2188 gst_v4l2_buffer_pool_update (v4l2camsrc->pool, v4l2camsrc);
2189 g_mutex_unlock (v4l2camsrc->device_mutex);
2191 memset (&buffer, 0x00, sizeof (buffer));
2192 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2194 if (v4l2camsrc->use_mmap)
2195 buffer.memory = V4L2_MEMORY_MMAP;
2197 buffer.memory = V4L2_MEMORY_USERPTR;
2199 if (phase == GST_CAMERA_CAPTURE) {
2200 gst_camerasrc_send_capture_start_message (camsrc);
2204 ret = gst_poll_wait (v4l2camsrc->poll, V4L2CAMSRC_POLL_TIMEOUT);
2205 if (G_UNLIKELY (ret < 0)) {
2208 if (errno != EAGAIN && errno != EINTR)
2212 if (G_UNLIKELY (ret == 0)) {
2215 g_mutex_lock (v4l2camsrc->device_mutex);
2216 ret = gst_v4l2camsrc_libmfld_grab_hq_frame (v4l2camsrc, &buffer);
2217 g_mutex_unlock (v4l2camsrc->device_mutex);
2222 GST_WARNING_OBJECT (v4l2camsrc,
2223 "problem grabbing frame %d (ix=%d), trials=%d, pool-ct=%d, buf.flags=%d",
2224 buffer.sequence, buffer.index, trials,
2225 GST_MINI_OBJECT_REFCOUNT (v4l2camsrc->pool), buffer.flags);
2227 /* if the sync() got interrupted, we can retry */
2230 GST_WARNING_OBJECT (v4l2camsrc,
2231 "Non-blocking I/O has been selected using O_NONBLOCK and"
2232 " no buffer was in the outgoing queue. device %s",
2233 v4l2camsrc->videodev);
2240 GST_INFO_OBJECT (v4l2camsrc,
2241 "VIDIOC_DQBUF failed due to an internal error."
2242 " Can also indicate temporary problems like signal loss."
2243 " Note the driver might dequeue an (empty) buffer despite"
2244 " returning an error, or even stop capturing."
2245 " device %s", v4l2camsrc->videodev);
2246 /* have we de-queued a buffer ? */
2247 if (!(buffer.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
2249 if ((buffer.index >= 0) && (buffer.index < v4l2camsrc->breq.count)) {
2250 GST_DEBUG_OBJECT (v4l2camsrc, "reenqueing buffer (ix=%ld)", buffer.index);
2251 gst_v4l2camsrc_queue_frame (v4l2camsrc, buffer.index);
2255 GST_DEBUG_OBJECT (v4l2camsrc, "reenqueing buffer");
2256 /* FIXME: this is not a good idea, as drivers usualy return the buffer
2257 * with index-number set to 0, thus the re-enque will fail unless it
2258 * was incidentialy 0.
2259 * We could try to re-enque all buffers without handling the ioctl
2263 if (ioctl (v4l2camsrc->video_fd, VIDIOC_QBUF, &buffer) < 0) {
2271 GST_WARNING_OBJECT (v4l2camsrc,
2272 "could not sync on a buffer on device %s", v4l2camsrc->videodev);
2275 GST_WARNING_OBJECT (v4l2camsrc,
2276 "Grabbing frame got interrupted on %s. No expected reason.",
2277 v4l2camsrc->videodev);
2281 /* check nr. of attempts to capture */
2282 if (--trials == -1) {
2283 goto too_many_trials;
2285 memset (&buffer, 0x00, sizeof (buffer));
2286 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2287 if (v4l2camsrc->use_mmap)
2288 buffer.memory = V4L2_MEMORY_MMAP;
2290 buffer.memory = V4L2_MEMORY_USERPTR;
2294 if (phase == GST_CAMERA_CAPTURE) {
2295 gst_camerasrc_send_capture_stop_message (camsrc);
2297 /* Send the CAF status message */
2298 GstCameraFocusStatus focus_status;
2300 lret = gst_v4l2camsrc_check_focus_status(v4l2camsrc, &focus_status, FALSE);
2302 GST_LOG_OBJECT (v4l2camsrc, "CAF status: %d", focus_status.status);
2303 if (focus_status.status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS )
2304 gst_camerasrc_send_af_status(GST_CAMERA_SRC (v4l2camsrc) ,CAMERASRC_AUTO_FOCUS_RESULT_FOCUSED);
2305 else if (focus_status.status == GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL )
2306 gst_camerasrc_send_af_status(GST_CAMERA_SRC (v4l2camsrc) ,CAMERASRC_AUTO_FOCUS_RESULT_FAILED);
2308 GST_WARNING_OBJECT (v4l2camsrc, "CAF status erronous: %d send as failed", focus_status.status);
2309 gst_camerasrc_send_af_status(GST_CAMERA_SRC (v4l2camsrc) ,CAMERASRC_AUTO_FOCUS_RESULT_FAILED);
2315 g_mutex_lock (v4l2camsrc->pool->lock);
2317 index = buffer.index;
2319 /* get our GstBuffer with that index from the pool, if the buffer is
2320 * in use (NULL) we have a serious problem (should only be possible in mmap
2322 pool_buffer = GST_BUFFER (v4l2camsrc->pool->buffers[index]);
2324 if (G_UNLIKELY (pool_buffer == NULL))
2327 GST_LOG_OBJECT (v4l2camsrc, "grabbed buffer %p at index %d (refct = %d)",
2328 pool_buffer, index, GST_MINI_OBJECT_REFCOUNT (pool_buffer));
2330 /* ref the buffer and requeue, when if becomes writable again */
2331 v4l2camsrc->pool->buffers[index] = NULL;
2332 v4l2camsrc->pool->num_live_buffers++;
2333 v4l2camsrc->pool->queued[index] = 0;
2335 /* SW workaround for ISP padding. */
2337 if(v4l2camsrc->expected_capture_w < 320 && (v4l2camsrc->expected_capture_w % 32 != 0)
2338 && v4l2camsrc->expected_capture_fourcc == V4L2_PIX_FMT_NV12
2339 && !v4l2camsrc->disable_low_res_crop) {
2341 real_w = (v4l2camsrc->expected_capture_w & ~31) + 32;
2343 GST_LOG_OBJECT(v4l2camsrc, "Downscaling padded buffer with cropping (%u,%u) -> (%u,%u)",
2344 real_w, v4l2camsrc->expected_capture_h, v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h);
2346 if(!crop_buffer_inplace_nv12(GST_BUFFER_DATA(pool_buffer),
2347 real_w, v4l2camsrc->expected_capture_h,
2348 v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h)) {
2349 GST_ERROR_OBJECT(v4l2camsrc,"Software crop failed");
2353 if(v4l2camsrc->draw_corner_markers)
2354 draw_corner_markers_nv12(GST_BUFFER_DATA(pool_buffer),
2355 v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h);
2357 g_mutex_unlock (v4l2camsrc->pool->lock);
2359 /* this can change at every frame, esp. with jpeg */
2360 if(variable_frame_size)
2361 GST_BUFFER_SIZE (pool_buffer) = buffer.bytesused;
2363 GST_BUFFER_SIZE (pool_buffer) = v4l2camsrc->frame_byte_size;
2365 GST_BUFFER_OFFSET (pool_buffer) = v4l2camsrc->offset++;
2366 GST_BUFFER_OFFSET_END (pool_buffer) = v4l2camsrc->offset;
2368 /* timestamps, LOCK to get clock and base time. */
2371 GstClockTime timestamp;
2373 GST_OBJECT_LOCK (v4l2camsrc);
2374 if ((clock = GST_ELEMENT_CLOCK (v4l2camsrc))) {
2375 /* we have a clock, get base time and ref clock */
2376 timestamp = GST_ELEMENT (v4l2camsrc)->base_time;
2377 gst_object_ref (clock);
2379 /* no clock, can't set timestamps */
2380 timestamp = GST_CLOCK_TIME_NONE;
2382 GST_OBJECT_UNLOCK (v4l2camsrc);
2385 GstClockTime latency;
2387 /* the time now is the time of the clock minus the base time */
2388 timestamp = gst_clock_get_time (clock) - timestamp;
2389 gst_object_unref (clock);
2392 gst_util_uint64_scale_int (GST_SECOND, camsrc->fps_d, camsrc->fps_n);
2394 if (timestamp > latency)
2395 timestamp -= latency;
2398 GST_BUFFER_DURATION (pool_buffer) = latency;
2400 /* activate settings for next frame (Code from v4l2src) */
2401 if (GST_CLOCK_TIME_IS_VALID (camsrc->duration)) {
2402 v4l2camsrc->ctrl_time += camsrc->duration;
2404 v4l2camsrc->ctrl_time = timestamp;
2406 gst_object_sync_values (G_OBJECT (camsrc), v4l2camsrc->ctrl_time);
2408 /* FIXME: use the timestamp from the buffer itself! */
2409 GST_BUFFER_TIMESTAMP (pool_buffer) = timestamp;
2412 if (G_UNLIKELY (need_copy)) {
2413 GST_DEBUG_OBJECT (v4l2camsrc, "copying buffer");
2414 *buf = gst_buffer_copy (pool_buffer);
2415 GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY);
2416 /* this will requeue */
2417 gst_buffer_unref (pool_buffer);
2419 if (v4l2camsrc->pool->is_vaapi_sharing)
2420 GST_BUFFER_DATA(pool_buffer) = (GST_V4L2CAMSRC_BUFFER(pool_buffer))->gbuffer;
2424 GST_LOG_OBJECT (v4l2camsrc,
2425 "grabbed frame %d (ix=%d), flags %08x, pool-ct=%d", buffer.sequence,
2426 buffer.index, buffer.flags, v4l2camsrc->pool->num_live_buffers);
2433 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ, (NULL),
2434 ("select error %d: %s (%d)", ret, g_strerror (errno), errno));
2435 return GST_FLOW_ERROR;
2439 GST_DEBUG ("stop called");
2440 return GST_FLOW_WRONG_STATE;
2444 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2445 ("Failed trying to get video frames from device '%s'.",
2446 v4l2camsrc->videodev),
2447 ("The buffer type is not supported, or the index is out of bounds,"
2448 " or no buffers have been allocated yet, or the userptr"
2449 " or length are invalid. 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'. Not enough memory.",
2456 v4l2camsrc->videodev), ("insufficient memory to enqueue a user "
2457 "pointer buffer. device %s.", v4l2camsrc->videodev));
2458 return GST_FLOW_ERROR;
2462 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2463 ("Failed trying to get video frames from device '%s'.",
2464 v4l2camsrc->videodev),
2465 ("Failed after %d tries. device %s. system error: %s",
2466 NUM_TRIALS, v4l2camsrc->videodev, g_strerror (errno)));
2467 return GST_FLOW_ERROR;
2471 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2472 ("Failed trying to get video frames from device '%s'.",
2473 v4l2camsrc->videodev),
2474 ("No free buffers found in the pool at index %d.", index));
2475 g_mutex_unlock (v4l2camsrc->pool->lock);
2476 return GST_FLOW_ERROR;
2481 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, WRITE,
2482 ("Could not exchange data with device '%s'.",
2483 v4l2camsrc->videodev),
2484 ("Error queueing buffer on device %s. system error: %s",
2485 v4l2camsrc->videodev, g_strerror (errno)));
2486 return GST_FLOW_ERROR;
2491 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2492 ("Timeout when trying to get video frames from device '%s'.",
2493 v4l2camsrc->videodev), NULL);
2494 return GST_FLOW_ERROR;
2499 /******************************************************
2500 * gst_v4l2camsrc_set_capture():
2501 * set capture parameters for certain operation mode
2502 * return value: TRUE on success, FALSE on error
2503 ******************************************************/
2505 gst_v4l2camsrc_set_capture (GstCameraSrc * camsrc, GstOperationMode mode,
2506 gboolean try_only, guint32 * pixelformat, guint * width, guint * height,
2507 guint * fps_n, guint * fps_d)
2509 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2510 cam_err_t err = CAM_ERR_NONE;
2511 gboolean ret = TRUE;
2513 GST_DEBUG_OBJECT (v4l2camsrc, "mode = %d, try_only = %d", mode, try_only);
2515 v4l2camsrc->expected_capture_w = *width;
2516 v4l2camsrc->expected_capture_h = *height;
2517 v4l2camsrc->expected_capture_fourcc = *pixelformat;
2519 if (mode == GST_PHOTOGRAPHY_OPERATION_MODE_PREVIEW) {
2521 } else if (mode == GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE) {
2522 GST_DEBUG_OBJECT (v4l2camsrc, "Image capture: %dx%d, format "
2523 "%" GST_FOURCC_FORMAT, *width, *height, GST_FOURCC_ARGS (*pixelformat));
2526 /* Round width & height down to be dividable by 8 */
2527 *width = (*width) & ~7;
2528 *height = (*height) & ~7;
2531 ret = gst_v4l2camsrc_configure_device (v4l2camsrc, pixelformat,
2532 width, height, fps_n, fps_d);
2534 v4l2camsrc->tmp_num_buffers = v4l2camsrc->num_buffers;
2535 v4l2camsrc->num_buffers = 1;
2537 v4l2camsrc->capture_w = *width;
2538 v4l2camsrc->capture_h = *height;
2539 if (fps_n && fps_d) {
2540 v4l2camsrc->capture_fps_n = *fps_n;
2541 v4l2camsrc->capture_fps_d = *fps_d;
2543 v4l2camsrc->capture_fourcc = *pixelformat;
2546 /* VIEWFINDER mode */
2547 /* FIXME: handle try_only mode */
2549 v4l2camsrc->num_buffers = v4l2camsrc->tmp_num_buffers;
2551 ret = gst_v4l2camsrc_configure_device (v4l2camsrc, pixelformat,
2552 width, height, fps_n, fps_d);
2554 v4l2camsrc->vf_w = *width;
2555 v4l2camsrc->vf_h = *height;
2556 v4l2camsrc->vf_fourcc = *pixelformat;
2557 if (fps_n && fps_d) {
2558 v4l2camsrc->vf_fps_n = *fps_n;
2559 v4l2camsrc->vf_fps_d = *fps_d;
2562 if (err != CAM_ERR_NONE)
2568 /******************************************************
2569 * gst_v4l2camsrc_capture_start():
2570 * Start capturing frames from the device
2571 * return value: TRUE on success, FALSE on error
2572 ******************************************************/
2574 gst_v4l2camsrc_capture_start (GstCameraSrc * camsrc, GstCaps * caps)
2576 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2578 gint fd = v4l2camsrc->video_fd;
2579 struct v4l2_requestbuffers breq;
2580 gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2581 cam_capture_mode_t cam_mode;
2584 v4l2camsrc->offset = 0;
2586 /* activate settings for first frame */
2587 v4l2camsrc->ctrl_time = 0;
2588 gst_object_sync_values (G_OBJECT (camsrc), v4l2camsrc->ctrl_time);
2590 memset (&breq, 0, sizeof (struct v4l2_requestbuffers));
2592 GST_DEBUG_OBJECT (v4l2camsrc, "initializing the capture system");
2594 GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
2595 GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
2597 if (!(v4l2camsrc->vcap.capabilities & V4L2_CAP_STREAMING))
2598 goto no_capture_method;
2600 GST_DEBUG_OBJECT (v4l2camsrc, "STREAMING, requesting %d CAPTURE buffers",
2601 v4l2camsrc->num_buffers);
2603 err = cam_driver_set_mipi_interrupt(fd,1);
2604 if (err != CAM_ERR_NONE)
2605 GST_DEBUG_OBJECT (v4l2camsrc, "MIPI interrupt enable FAILED !");
2607 breq.count = v4l2camsrc->num_buffers;
2608 breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2610 if(v4l2camsrc->use_mmap && GST_CAPS_IS_SIMPLE(caps)) {
2611 GstStructure *st = gst_caps_get_structure(caps, 0);
2612 if(g_str_has_prefix(gst_structure_get_name(st), "video/x-vaapi-sharing")) {
2613 v4l2camsrc->use_mmap = FALSE;
2614 GST_WARNING_OBJECT(v4l2camsrc, "mmap is not supported with VA shared buffer, turning off");
2618 if (v4l2camsrc->use_mmap)
2619 breq.memory = V4L2_MEMORY_MMAP;
2621 breq.memory = V4L2_MEMORY_USERPTR;
2623 if (ioctl (fd, VIDIOC_REQBUFS, &breq) < 0)
2624 goto reqbufs_failed;
2626 GST_LOG_OBJECT (v4l2camsrc, " count: %u", breq.count);
2627 GST_LOG_OBJECT (v4l2camsrc, " type: %d", breq.type);
2628 GST_LOG_OBJECT (v4l2camsrc, " memory: %d", breq.memory);
2630 if (breq.count < GST_V4L2CAMSRC_MIN_BUFFERS)
2633 if (v4l2camsrc->num_buffers != breq.count) {
2634 GST_WARNING_OBJECT (v4l2camsrc, "using %u buffers instead", breq.count);
2635 v4l2camsrc->num_buffers = breq.count;
2636 g_object_notify (G_OBJECT (v4l2camsrc), "queue-size");
2639 /* Map the buffers */
2640 GST_LOG_OBJECT (v4l2camsrc, "initiating buffer pool");
2642 if (!(v4l2camsrc->pool =
2643 gst_v4l2camsrc_buffer_pool_new (camsrc, fd, caps)))
2644 goto buffer_pool_new_failed;
2646 GST_INFO_OBJECT (v4l2camsrc, "capturing buffers");
2648 GST_V4L2CAMSRC_SET_ACTIVE (v4l2camsrc);
2650 GST_DEBUG_OBJECT (v4l2camsrc, "starting the capturing");
2651 GST_V4L2CAMSRC_CHECK_ACTIVE (v4l2camsrc);
2653 if (!gst_v4l2camsrc_buffer_pool_activate (v4l2camsrc->pool, v4l2camsrc))
2654 goto pool_activate_failed;
2656 if (ioctl (fd, VIDIOC_STREAMON, &type) < 0)
2657 goto streamon_failed;
2659 v4l2camsrc->is_active = TRUE;
2660 GST_DEBUG_OBJECT (v4l2camsrc, "STREAMON called");
2662 /* Update the focus only when the Sensor is stream on */
2663 if (v4l2camsrc->focus_updated) {
2664 cam_driver_set_focus_posi(v4l2camsrc->video_fd, v4l2camsrc->focus_posi);
2665 v4l2camsrc->focus_updated = FALSE;
2668 if (v4l2camsrc->zoom_updated) {
2669 gst_v4l2camsrc_libmfldcam_set_zoom(v4l2camsrc, v4l2camsrc->zoom_factor);
2670 v4l2camsrc->zoom_updated = FALSE;
2673 cam_mode = find_item (gst_v4l2camsrc_capture_map,v4l2camsrc->capture_mode);
2674 cam_set_capture_mode (v4l2camsrc->video_fd, cam_mode);
2681 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2682 ("Could not get buffers from device '%s'.",
2683 v4l2camsrc->videodev),
2684 ("error requesting %d buffers: %s",
2685 v4l2camsrc->num_buffers, g_strerror (errno)));
2686 cam_driver_set_mipi_interrupt(fd, 0);
2691 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2692 ("Could not get enough buffers from device '%s'.",
2693 v4l2camsrc->videodev),
2694 ("we received %d from device '%s', we want at least %d",
2695 breq.count, v4l2camsrc->videodev, GST_V4L2CAMSRC_MIN_BUFFERS));
2696 cam_driver_set_mipi_interrupt(fd, 0);
2699 buffer_pool_new_failed:
2701 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2702 ("Could not map buffers from device '%s'",
2703 v4l2camsrc->videodev),
2704 ("Failed to create buffer pool: %s", g_strerror (errno)));
2705 cam_driver_set_mipi_interrupt(fd, 0);
2710 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2711 ("The driver of device '%s' does not support streaming. ",
2712 v4l2camsrc->videodev), (NULL));
2713 cam_driver_set_mipi_interrupt(fd, 0);
2716 pool_activate_failed:
2718 /* already errored */
2719 cam_driver_set_mipi_interrupt(fd, 0);
2724 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, OPEN_READ,
2725 ("Error starting streaming capture from device '%s'.",
2726 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
2727 cam_driver_set_mipi_interrupt(fd, 0);
2732 /******************************************************
2733 * gst_v4l2camsrc_capture_stop():
2734 * stop streaming capture
2735 * return value: TRUE on success, FALSE on error
2736 ******************************************************/
2738 gst_v4l2camsrc_capture_stop (GstCameraSrc * camsrc)
2740 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2741 struct v4l2_requestbuffers breq;
2742 gint fd = v4l2camsrc->video_fd;
2745 gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2747 memset(&breq, 0, sizeof(struct v4l2_requestbuffers));
2749 GST_DEBUG_OBJECT (v4l2camsrc, "stopping capturing");
2751 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc)) {
2754 if (!GST_V4L2CAMSRC_IS_ACTIVE (v4l2camsrc)) {
2758 err = cam_driver_set_mipi_interrupt(fd,0);
2759 if (err != CAM_ERR_NONE)
2760 GST_DEBUG_OBJECT (v4l2camsrc, "MIPI interrupt disable FAILED !");
2762 /* we actually need to sync on all queued buffers but not
2763 * on the non-queued ones */
2764 if (ioctl (v4l2camsrc->video_fd, VIDIOC_STREAMOFF, &type) < 0)
2765 goto streamoff_failed;
2767 GST_DEBUG_OBJECT (v4l2camsrc, "STREAMOFF called");
2770 breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2771 if(v4l2camsrc->use_mmap)
2772 breq.memory = V4L2_MEMORY_MMAP;
2774 breq.memory = V4L2_MEMORY_USERPTR;
2776 GST_DEBUG_OBJECT (v4l2camsrc, "REQUEST 0 to finalize buffer");
2778 if(ioctl(v4l2camsrc->video_fd, VIDIOC_REQBUFS, &breq) < 0)
2779 GST_DEBUG_OBJECT (v4l2camsrc, "Failed to REQUEST 0 to finalize buffer");
2782 if (v4l2camsrc->pool) {
2783 gst_v4l2camsrc_buffer_pool_destroy (v4l2camsrc->pool, v4l2camsrc);
2784 v4l2camsrc->pool = NULL;
2787 GST_V4L2CAMSRC_SET_INACTIVE (v4l2camsrc);
2788 v4l2camsrc->is_active = FALSE;
2796 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, CLOSE,
2797 ("Error stopping streaming capture from device '%s'.",
2798 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
2806 gst_v4l2camsrc_get_nearest_size (GstMFLDV4l2CamSrc * v4l2camsrc,
2807 guint32 pixelformat, gint * width, gint * height)
2809 struct v4l2_format fmt;
2813 g_return_val_if_fail (width != NULL, FALSE);
2814 g_return_val_if_fail (height != NULL, FALSE);
2816 GST_LOG_OBJECT (v4l2camsrc,
2817 "getting nearest size to %dx%d with format %" GST_FOURCC_FORMAT,
2818 *width, *height, GST_FOURCC_ARGS (pixelformat));
2820 fd = v4l2camsrc->video_fd;
2822 /* get size delimiters */
2823 memset (&fmt, 0, sizeof (fmt));
2824 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2825 fmt.fmt.pix.width = *width;
2826 fmt.fmt.pix.height = *height;
2827 fmt.fmt.pix.pixelformat = pixelformat;
2828 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
2830 /* FIXME: Disable TRY_FMT check, driver is not returning anything useful yet */
2832 r = ioctl (fd, VIDIOC_TRY_FMT, &fmt);
2833 if (r < 0 && errno == EINVAL) {
2834 /* try again with progressive video */
2835 fmt.fmt.pix.width = *width;
2836 fmt.fmt.pix.height = *height;
2837 fmt.fmt.pix.pixelformat = pixelformat;
2838 fmt.fmt.pix.field = V4L2_FIELD_NONE;
2839 r = ioctl (fd, VIDIOC_TRY_FMT, &fmt);
2843 /* The driver might not implement TRY_FMT, in which case we will try
2845 if (errno != ENOTTY)
2849 /* Only try S_FMT if we're not actively capturing yet, which we shouldn't
2850 be, because we're still probing */
2851 if (GST_V4L2CAMSRC_IS_ACTIVE (v4l2camsrc))
2855 GST_LOG_OBJECT (v4l2camsrc,
2856 "Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
2859 fmt.fmt.pix.width = *width;
2860 fmt.fmt.pix.height = *height;
2862 r = ioctl (fd, VIDIOC_S_FMT, &fmt);
2863 if (r < 0 && errno == EINVAL) {
2864 /* try again with progressive video */
2865 fmt.fmt.pix.width = *width;
2866 fmt.fmt.pix.height = *height;
2867 fmt.fmt.pix.pixelformat = pixelformat;
2868 fmt.fmt.pix.field = V4L2_FIELD_NONE;
2869 r = ioctl (fd, VIDIOC_S_FMT, &fmt);
2878 GST_LOG_OBJECT (v4l2camsrc,
2879 "got nearest size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
2881 *width = fmt.fmt.pix.width;
2882 *height = fmt.fmt.pix.height;
2888 /******************************************************
2889 * gst_v4l2camsrc_set_crop():
2890 * set cropping bounds
2891 * return value: TRUE on success, FALSE on error
2892 ******************************************************/
2894 gst_v4l2camsrc_set_crop (GstMFLDV4l2CamSrc * v4l2camsrc,
2895 gint x, gint y, gint w, gint h)
2897 gboolean ret = FALSE;
2898 struct v4l2_crop scrop;
2899 struct v4l2_crop gcrop;
2900 gint cx, cy, cw, ch;
2903 fd = v4l2camsrc->video_fd;
2904 cx = v4l2camsrc->vcrop.bounds.left;
2905 cy = v4l2camsrc->vcrop.bounds.top;
2906 cw = v4l2camsrc->vcrop.bounds.width;
2907 ch = v4l2camsrc->vcrop.bounds.height;
2909 memset (&scrop, 0, sizeof (scrop));
2910 scrop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2912 /* Make sure that cropping area stays inside the crop boundaries */
2913 scrop.c.left = x > cx ? x : cx;
2914 scrop.c.top = y > cy ? y : cy;
2915 scrop.c.width = (scrop.c.left + w) < (cx + cw) ? w : cx + cw - scrop.c.left;
2916 scrop.c.height = (scrop.c.top + h) < (cy + ch) ? h : cy + ch - scrop.c.top;
2918 GST_DEBUG_OBJECT (v4l2camsrc,
2919 "Crop request: left = %d, top = %d, w = %d, h = %d",
2920 scrop.c.left, scrop.c.top, scrop.c.width, scrop.c.height);
2922 g_mutex_lock (v4l2camsrc->device_mutex);
2924 if (-1 == ioctl (fd, VIDIOC_S_CROP, &scrop) && errno != EINVAL) {
2928 if (-1 == ioctl (fd, VIDIOC_G_CROP, &gcrop)) {
2932 g_mutex_unlock (v4l2camsrc->device_mutex);
2934 GST_DEBUG_OBJECT (v4l2camsrc,
2935 "Crop selected: left = %d, top = %d, w = %d, h = %d",
2936 gcrop.c.left, gcrop.c.top, gcrop.c.width, gcrop.c.height);
2939 if (gcrop.c.left != scrop.c.left || gcrop.c.top != scrop.c.top ||
2940 gcrop.c.width != scrop.c.width || gcrop.c.height != scrop.c.height) {
2941 goto crop_not_supported;
2953 g_mutex_unlock (v4l2camsrc->device_mutex);
2954 GST_DEBUG_OBJECT (v4l2camsrc, "VIDIOC_S_CROP not supported");
2958 g_mutex_unlock (v4l2camsrc->device_mutex);
2959 GST_DEBUG_OBJECT (v4l2camsrc, "VIDIOC_G_CROP not supported");
2964 g_mutex_unlock (v4l2camsrc->device_mutex);
2965 GST_DEBUG_OBJECT (v4l2camsrc, "Given crop value not accepted");
2971 /******************************************************
2972 * gst_v4l2camsrc_update_cropping():
2973 * update cropping area according to width, height and zoom factors.
2974 * return value: TRUE on success, FALSE on error
2975 ******************************************************/
2977 gst_v4l2camsrc_update_cropping (GstMFLDV4l2CamSrc * v4l2camsrc, gint width,
2978 gint height, gfloat zoom)
2980 gfloat sensor_ar, reso_ar;
2981 gint crop_x, crop_y, crop_w, crop_h;
2983 g_return_val_if_fail (width != 0, FALSE);
2984 g_return_val_if_fail (height != 0, FALSE);
2985 g_return_val_if_fail (zoom != 0, FALSE);
2987 if (zoom < 1.0 || zoom > v4l2camsrc->max_zoom_factor) {
2988 GST_DEBUG_OBJECT (v4l2camsrc, "invalid zoom = %.2f", zoom);
2991 if (!v4l2camsrc->crop_supported) {
2992 GST_DEBUG_OBJECT (v4l2camsrc, "crop not supported");
2996 sensor_ar = v4l2camsrc->vcrop.defrect.width /
2997 v4l2camsrc->vcrop.defrect.height;
2998 reso_ar = width / height;
3000 if (sensor_ar > reso_ar) {
3001 crop_w = (width * v4l2camsrc->vcrop.defrect.height / height) / zoom;
3002 crop_h = MAX (v4l2camsrc->vcrop.defrect.height, height) / zoom;
3004 crop_w = MAX (v4l2camsrc->vcrop.defrect.width, width) / zoom;
3005 crop_h = (height * v4l2camsrc->vcrop.defrect.width / width) / zoom;
3008 crop_x = ABS ((v4l2camsrc->vcrop.defrect.width - crop_w) / 2);
3009 crop_y = ABS ((v4l2camsrc->vcrop.defrect.height - crop_h) / 2);
3011 GST_LOG_OBJECT (v4l2camsrc, "set cropping: x: %d, y: %d, w: %d, h: %d",
3012 crop_x, crop_y, crop_w, crop_h);
3014 return gst_v4l2camsrc_set_crop (v4l2camsrc, crop_x, crop_y, crop_w, crop_h);
3017 /***************************************************************************
3018 * New MFLD Camera Code ****************************************************
3019 * *************************************************************************/
3021 /* These map tables help to adapt the general photography interface to
3022 * different device implementations.
3024 * Table index = Enumeration value from GstPhotography
3025 * Table value = Device/Implementation -specific setting value
3028 static const gint gst_v4l2camsrc_scene_map[] = {
3029 999, /* GST_PHOTOGRAPHY_SCENE_MODE_MANUAL */
3030 CAM_GENERAL_SCENE_MODE_CLOSEUP,
3031 CAM_GENERAL_SCENE_MODE_PORTRAIT,
3032 CAM_GENERAL_SCENE_MODE_LANDSCAPE,
3033 CAM_GENERAL_SCENE_MODE_SPORT,
3034 CAM_GENERAL_SCENE_MODE_NIGHT,
3035 CAM_GENERAL_SCENE_MODE_AUTO,
3039 static const gint gst_v4l2camsrc_flash_map[] = {
3040 CAM_LIGHT_FLASH_MODE_AUTO,
3041 CAM_LIGHT_FLASH_MODE_OFF,
3042 CAM_LIGHT_FLASH_MODE_ON,
3043 CAM_LIGHT_FLASH_MODE_FILL_IN,
3044 CAM_LIGHT_FLASH_MODE_RED_EYE,
3048 static const gint gst_v4l2camsrc_focus_map[] = {
3049 CAM_FOCUS_MODE_AUTO, /* GST_PHOTOGRAPHY_FOCUS_MODE_AUTO = 0 */
3050 CAM_FOCUS_MODE_MACRO, /* GST_PHOTOGRAPHY_FOCUS_MODE_MACRO */
3051 CAM_FOCUS_MODE_TOUCH_AUTO, /* GST_PHOTOGRAPHY_FOCUS_MODE_PORTRAIT */
3052 CAM_FOCUS_MODE_FULL, /* GST_PHOTOGRAPHY_FOCUS_MODE_INFINITY */
3053 CAM_FOCUS_MODE_AUTO, /* GST_PHOTOGRAPHY_FOCUS_MODE_HYPERFOCAL */
3054 CAM_FOCUS_MODE_FULL, /* GST_PHOTOGRAPHY_FOCUS_MODE_EXTENDED */
3055 CAM_FOCUS_MODE_CONTINUOUS, /* GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_NORMAL */
3056 CAM_FOCUS_MODE_CONTINUOUS, /* GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_EXTENDED */
3060 static const gint gst_v4l2camsrc_flicker_map[] = {
3061 CAM_GENERAL_FLICKER_REDUCTION_MODE_OFF, /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF = 0 */
3062 CAM_GENERAL_FLICKER_REDUCTION_MODE_50HZ, /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ */
3063 CAM_GENERAL_FLICKER_REDUCTION_MODE_60HZ, /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_60HZ */
3064 CAM_GENERAL_FLICKER_REDUCTION_MODE_AUTO, /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO */
3068 static const gint gst_v4l2camsrc_iso_map[][2] = {
3069 {CAM_EXPOSURE_ISO_VALUE_1600, 1600},
3070 {CAM_EXPOSURE_ISO_VALUE_800, 800},
3071 {CAM_EXPOSURE_ISO_VALUE_400, 400},
3072 {CAM_EXPOSURE_ISO_VALUE_200, 200},
3073 {CAM_EXPOSURE_ISO_VALUE_100, 100},
3074 {CAM_EXPOSURE_ISO_VALUE_AUTO, 0}
3077 static const gint gst_v4l2camsrc_focus_status_map[][2] =
3079 { GST_PHOTOGRAPHY_FOCUS_STATUS_NONE, CAM_FOCUS_STATUS_IDLE },
3080 { GST_PHOTOGRAPHY_FOCUS_STATUS_RUNNING, CAM_FOCUS_STATUS_RUNNING },
3081 { GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS, CAM_FOCUS_STATUS_SUCCESS },
3082 { GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL, CAM_FOCUS_STATUS_FAIL },
3086 static const gchar *cameralib_error_map[] = {
3093 "CAM_ERR_DEPRECATED",
3094 "CAM_ERR_INVALID_STATE",
3103 static cam_exposure_iso_value_t
3104 gst_v4l2camsrc_libmfld_map_iso (guint iso)
3108 while (gst_v4l2camsrc_iso_map[i][1] != 0) {
3109 if (iso >= gst_v4l2camsrc_iso_map[i][1]) {
3115 return gst_v4l2camsrc_iso_map[i][1];
3123 gst_v4l2camsrc_libmfld_reverse_map_iso (cam_exposure_iso_value_t iso)
3127 while (gst_v4l2camsrc_iso_map[i][1] != 0) {
3128 if (iso == gst_v4l2camsrc_iso_map[i][0]) {
3134 return gst_v4l2camsrc_iso_map[i][1];
3137 static const gint gst_v4l2camsrc_shakerisk_map[] = {
3138 GST_PHOTOGRAPHY_SHAKE_RISK_LOW, /* CAM_EXPOSURE_SHAKE_RISK_LOW = 0 */
3139 GST_PHOTOGRAPHY_SHAKE_RISK_MEDIUM, /* CAM_EXPOSURE_SHAKE_RISK_MEDIUM */
3140 GST_PHOTOGRAPHY_SHAKE_RISK_HIGH, /* CAM_EXPOSURE_SHAKE_RISK_HIGH */
3144 * Return index of the item in the table.
3147 find_item (const gint table[], const gint item)
3151 while (table[i] != -1) {
3152 if (table[i] == item)
3160 gst_v4l2camsrc_read_settings (GstCameraSrc * camsrc,
3161 GstPhotoSettings * photoconf)
3163 GstMFLDV4l2CamSrc *v4l2camsrc;
3164 gint32 wbmode, effect, scene, flash, focus;
3166 gint32 ev, iso, aperture, exposure, noise_reduction;
3169 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3171 g_mutex_lock (v4l2camsrc->device_mutex);
3173 if (!v4l2camsrc->initialized) {
3174 GST_DEBUG ("Device not initialized");
3175 g_mutex_unlock (v4l2camsrc->device_mutex);
3179 GST_DEBUG ("Retrieving settings from camera");
3181 err = cam_feature_get (v4l2camsrc->video_fd, CAM_AWB_MODE, &wbmode);
3182 if (err != CAM_ERR_NONE) {
3183 GST_DEBUG ("CAM_AWB_MODE query failed: %s", cameralib_error_map[err]);
3188 cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE, &effect);
3189 if (err != CAM_ERR_NONE) {
3190 GST_DEBUG ("CAM_GENERAL_EFFECT_TYPE query failed: %s",
3191 cameralib_error_map[err]);
3195 err = cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_SCENE_MODE, &scene);
3196 if (err != CAM_ERR_NONE) {
3197 GST_DEBUG ("CAM_GENERAL_SCENE_MODE query failed: %s",
3198 cameralib_error_map[err]);
3202 err = cam_feature_get (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE, &flash);
3203 if (err != CAM_ERR_NONE) {
3204 GST_DEBUG ("CAM_LIGHT_FLASH_MODE query failed: %s",
3205 cameralib_error_map[err]);
3209 err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION, &ev);
3210 if (err != CAM_ERR_NONE) {
3211 GST_DEBUG ("CAM_EXPOSURE_COMPENSATION query failed: %s",
3212 cameralib_error_map[err]);
3215 err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE, &iso);
3216 if (err != CAM_ERR_NONE) {
3217 GST_DEBUG ("CAM_EXPOSURE_ISO_VALUE query failed: %s",
3218 cameralib_error_map[err]);
3222 err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_APERTURE,
3224 if (err != CAM_ERR_NONE) {
3225 GST_DEBUG ("CAM_EXPOSURE_MANUAL_APERTURE query failed: %s",
3226 cameralib_error_map[err]);
3231 cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_TIME,
3233 if (err != CAM_ERR_NONE) {
3234 GST_DEBUG ("CAM_EXPOSURE_MANUAL_TIME query failed: %s",
3235 cameralib_error_map[err]);
3239 err = cam_feature_get (v4l2camsrc->video_fd, CAM_FOCUS_MODE, &focus);
3240 if (err != CAM_ERR_NONE) {
3241 GST_DEBUG ("CAM_FOCUS_MODE query failed: %s", cameralib_error_map[err]);
3246 cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_FLICKER_REDUCTION_MODE,
3248 if (err != CAM_ERR_NONE) {
3249 GST_DEBUG ("CAM_GENERAL_FLICKER_REDUCTION_MODE query failed: %s",
3250 cameralib_error_map[err]);
3255 cam_feature_get (v4l2camsrc->video_fd, CAM_NOISE_REDUCTION_MODE,
3257 if (err != CAM_ERR_NONE) {
3258 GST_DEBUG ("CAM_NOISE_REDUCTION query failed: %s",
3259 cameralib_error_map[err]);
3263 photoconf->wb_mode = find_item (gst_v4l2camsrc_wb_map, wbmode);
3264 photoconf->tone_mode = find_item (gst_v4l2camsrc_effect_map, effect);
3265 photoconf->scene_mode = find_item (gst_v4l2camsrc_scene_map, scene);
3266 photoconf->flash_mode = find_item (gst_v4l2camsrc_flash_map, flash);
3267 photoconf->focus_mode = find_item (gst_v4l2camsrc_focus_map, focus);
3268 photoconf->flicker_mode = find_item (gst_v4l2camsrc_flicker_map, flicker);
3270 photoconf->ev_compensation = (gfloat) ev;
3271 photoconf->iso_speed = gst_v4l2camsrc_libmfld_map_iso (iso);
3272 photoconf->aperture = aperture;
3273 photoconf->exposure = exposure;
3274 photoconf->noise_reduction = noise_reduction;
3276 GST_DEBUG ("Scene mode ext: %d, lib: %d", photoconf->scene_mode, scene);
3277 GST_DEBUG ("Focus mode ext: %d, lib: %d", photoconf->focus_mode, focus);
3278 GST_DEBUG ("Flash mode ext: %d, lib: %d", photoconf->flash_mode, flash);
3279 GST_DEBUG ("ISO: %d, EV_comp: %f (%d)", iso, photoconf->ev_compensation, ev);
3281 g_mutex_unlock (v4l2camsrc->device_mutex);
3288 g_mutex_unlock (v4l2camsrc->device_mutex);
3293 gst_v4l2camsrc_read_exif (GstCameraSrc * camsrc,
3294 GstCameraControlExifInfo *exif_info)
3296 GstMFLDV4l2CamSrc *v4l2camsrc;
3298 struct atomisp_makernote_info maker_note;
3301 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3304 if (!v4l2camsrc->initialized) {
3305 GST_DEBUG ("Device not initialized");
3308 buf = (unsigned char *)&maker_note;
3310 GST_DEBUG ("Retrieving makernote from atomisp");
3311 err = cam_get_makernote (v4l2camsrc->video_fd, buf, 0);
3317 exif_info->focal_len_numerator = maker_note.focal_length >> 16;
3318 exif_info->focal_len_denominator = maker_note.focal_length & 0xFFFF;
3319 /* Aperture value (f_num) */
3320 exif_info->aperture_f_num_numerator = maker_note.f_number_curr >> 16;
3321 exif_info->aperture_f_num_denominator = maker_note.f_number_curr & 0xFFFF;
3322 /* isp major, minor,patch level */
3323 exif_info->software_used = v4l2camsrc->vcap.version;
3324 exif_info->colorspace = 65535; /* Uncalibrated (=65535) */
3325 exif_info->metering_mode = 1; /* Average */
3326 cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE, &exif_info->iso);
3328 //* TODO complete exif info */
3329 exif_info->exposure_time_denominator = 0;
3330 exif_info->exposure_time_numerator = 0;
3332 exif_info->shutter_speed_numerator = 0;
3333 exif_info->shutter_speed_denominator = 0;
3334 exif_info->brigtness_numerator = 0;
3335 exif_info->brightness_denominator = 0;
3336 exif_info->flash = cam_is_flash_used();
3337 GST_DEBUG ("Focal lenght numerator : %d", exif_info->focal_len_numerator);
3338 GST_DEBUG ("Focal lenght denominator : %d", exif_info->focal_len_denominator);
3339 GST_DEBUG ("F num numerator : %d", exif_info->aperture_f_num_numerator);
3340 GST_DEBUG ("F num denominator : %d", exif_info->aperture_f_num_denominator);
3341 GST_DEBUG ("flash used : %d", exif_info->flash);
3348 g_mutex_unlock (v4l2camsrc->device_mutex);
3354 gst_v4l2camsrc_set_flash_mode (GstCameraSrc * camsrc,
3357 GstMFLDV4l2CamSrc *v4l2camsrc;
3362 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3364 g_mutex_lock (v4l2camsrc->device_mutex);
3366 if (!v4l2camsrc->initialized) {
3367 GST_DEBUG ("Device not initialized");
3368 g_mutex_unlock (v4l2camsrc->device_mutex);
3373 case GST_CAMERA_STROBE_CAP_NONE:
3374 case GST_CAMERA_STROBE_CAP_OFF:
3375 flash = CAM_LIGHT_FLASH_MODE_OFF;
3377 case GST_CAMERA_STROBE_CAP_ON:
3378 flash = CAM_LIGHT_FLASH_MODE_ON;
3380 case GST_CAMERA_STROBE_CAP_AUTO:
3381 flash = CAM_LIGHT_FLASH_MODE_AUTO;
3383 case GST_CAMERA_STROBE_CAP_REDEYE:
3384 flash = CAM_LIGHT_FLASH_MODE_RED_EYE;
3387 flash = CAM_LIGHT_FLASH_MODE_OFF;
3391 GST_DEBUG_OBJECT (v4l2camsrc, "Set flash mode: %d",flash);
3392 err= cam_feature_set (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE,
3398 g_mutex_unlock (v4l2camsrc->device_mutex);
3405 g_mutex_unlock (v4l2camsrc->device_mutex);
3411 gst_v4l2camsrc_write_settings (GstCameraSrc * camsrc,
3412 GstPhotoSettings * photoconf, gboolean scene_override)
3414 GstMFLDV4l2CamSrc *v4l2camsrc;
3415 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3416 GST_DEBUG ("Write settings to libmfldcamd");
3418 g_mutex_lock (v4l2camsrc->device_mutex);
3420 if (!v4l2camsrc->initialized) {
3421 g_mutex_unlock (v4l2camsrc->device_mutex);
3422 GST_DEBUG ("Device not initialized");
3426 if (scene_override &&
3427 photoconf->scene_mode != GST_PHOTOGRAPHY_SCENE_MODE_MANUAL) {
3428 /* If scene override flag is set, we just leave the new settings in use */
3429 GST_DEBUG ("SCENE OVERRIDE, ext=%d", photoconf->scene_mode);
3430 cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_SCENE_MODE,
3431 gst_v4l2camsrc_scene_map[photoconf->scene_mode]);
3433 GST_DEBUG ("Normal settings");
3434 cam_feature_set (v4l2camsrc->video_fd, CAM_AWB_MODE,
3435 gst_v4l2camsrc_wb_map[photoconf->wb_mode]);
3437 cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE,
3438 gst_v4l2camsrc_effect_map[photoconf->tone_mode]);
3440 cam_feature_set (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE,
3441 gst_v4l2camsrc_flash_map[photoconf->flash_mode]);
3443 /* These will set exposure mode to MANUAL, is value is != 0 */
3444 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_TIME,
3445 photoconf->exposure);
3446 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_APERTURE,
3447 photoconf->aperture);
3449 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION,
3450 (gint) (photoconf->ev_compensation));
3452 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE,
3453 gst_v4l2camsrc_libmfld_reverse_map_iso (photoconf->iso_speed));
3455 cam_feature_set (v4l2camsrc->video_fd, CAM_FOCUS_MODE,
3456 gst_v4l2camsrc_focus_map[photoconf->focus_mode]);
3458 cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_FLICKER_REDUCTION_MODE,
3459 gst_v4l2camsrc_flicker_map[photoconf->flicker_mode]);
3461 cam_feature_set (v4l2camsrc->video_fd, CAM_NOISE_REDUCTION_MODE,
3462 photoconf->noise_reduction);
3464 g_mutex_unlock (v4l2camsrc->device_mutex);
3470 gst_v4l2camsrc_set_AeAafwindow (GstCameraSrc * camsrc, GstCameraSrc3a_window window)
3472 GstMFLDV4l2CamSrc *v4l2camsrc;
3473 gboolean ret = TRUE;
3475 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3477 GST_DEBUG_OBJECT(v4l2camsrc,"ae-af-window-setting: x_left:%d, x_right:%d,"
3478 "y_bottom:%d, y_top:%d, weight:%d.\n",
3479 window.x_left,window.x_right,
3480 window.y_bottom, window.y_top,
3483 v4l2camsrc->af_window = v4l2camsrc->ae_window = *(GstCameraWindow*)&window;
3485 if (v4l2camsrc->is_active) {
3486 g_mutex_lock (v4l2camsrc->device_mutex);
3487 cam_set_af_ae_window((advci_window *) (&v4l2camsrc->af_window));
3488 g_mutex_unlock (v4l2camsrc->device_mutex);
3495 gst_v4l2camsrc_set_autofocus (GstCameraSrc * camsrc, gboolean on)
3497 GstMFLDV4l2CamSrc *v4l2camsrc;
3498 gboolean ret = FALSE;
3499 cam_err_t err = CAM_ERR_NONE;
3501 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3502 g_mutex_lock (v4l2camsrc->device_mutex);
3503 err= cam_set_autofocus(on);
3504 ret = (err == CAM_ERR_NONE);
3505 g_mutex_unlock (v4l2camsrc->device_mutex);
3507 GST_DEBUG ("setting autofocus: %s", ret ? "ok" : "failed");
3514 gst_v4l2camsrc_get_capabilities (GstCameraSrc * camsrc)
3518 pcaps = GST_PHOTOGRAPHY_CAPS_ZOOM | GST_PHOTOGRAPHY_CAPS_EV_COMP |
3519 GST_PHOTOGRAPHY_CAPS_WB_MODE | GST_PHOTOGRAPHY_CAPS_TONE |
3520 GST_PHOTOGRAPHY_CAPS_SCENE | GST_PHOTOGRAPHY_CAPS_FLASH |
3521 GST_PHOTOGRAPHY_CAPS_FOCUS | GST_PHOTOGRAPHY_CAPS_APERTURE |
3522 GST_PHOTOGRAPHY_CAPS_EXPOSURE | GST_PHOTOGRAPHY_CAPS_SHAKE |
3523 GST_PHOTOGRAPHY_CAPS_ISO_SPEED;
3532 gst_v4l2camsrc_check_focus_status (GstMFLDV4l2CamSrc * v4l2camsrc,
3533 GstCameraFocusStatus *fs, gboolean detailed)
3535 gboolean ret = FALSE;
3536 cam_focus_status_t status;
3539 GST_DEBUG_OBJECT (v4l2camsrc, "Retrieving focus status");
3541 update = cam_checkfocus_status (&status, (v4l2camsrc->debug_flags & GST_CAMERASRC_DEBUG_FLAGS_AUTO_FOCUS));
3543 if (update == TRUE) {
3544 fs->status = cam_find_item_new (gst_v4l2camsrc_focus_status_map, status, TRUE);
3547 GST_DEBUG_OBJECT (v4l2camsrc, "Focus status: %d", fs->status);
3553 gst_v4l2camsrc_set_capture_mode (GstCameraSrc * camsrc,
3554 GstCameraSrcCaptureMode mode)
3556 GstMFLDV4l2CamSrc *v4l2camsrc;
3557 gboolean ret = FALSE;
3558 int err; //cam_err_t err;
3559 cam_capture_mode_t cam_mode;
3560 static const gchar *cmodes[] = { "VIEWFINDER", "STILL", "VIDEO" };
3561 struct v4l2_streamparm parm;
3565 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3567 fd = v4l2camsrc->video_fd;
3569 cam_mode = find_item (gst_v4l2camsrc_capture_map, mode);
3571 g_mutex_lock (v4l2camsrc->device_mutex);
3573 if (v4l2camsrc->initialized) {
3574 v4l2camsrc->capture_mode = mode;
3575 GST_DEBUG ("Setting isp capture mode: %s", cmodes[mode]);
3576 memset (&parm, 0x00, sizeof (struct v4l2_streamparm));
3578 parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3579 err = ioctl(fd, VIDIOC_G_PARM, &parm);
3581 GST_DEBUG("Unable to get frame rate: %s (%d).\n",
3582 strerror(errno), errno);
3585 GST_DEBUG("Current frame rate: %u/%u\n",
3586 parm.parm.capture.timeperframe.numerator,
3587 parm.parm.capture.timeperframe.denominator);
3589 GST_DEBUG("Current run mode: %04x\n", parm.parm.capture.capturemode);
3592 case GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER:
3593 binary = CI_MODE_PREVIEW;
3595 case GST_CAMERA_SRC_CAPTURE_MODE_STILL:
3596 binary = CI_MODE_STILL_CAPTURE;
3598 case GST_CAMERA_SRC_CAPTURE_MODE_VIDEO:
3599 binary = CI_MODE_VIDEO;
3602 binary = CI_MODE_PREVIEW;
3605 parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3606 parm.parm.capture.capturemode = binary;
3608 GST_DEBUG("New run mode: %04x\n", parm.parm.capture.capturemode);
3610 if (ioctl (fd, VIDIOC_S_PARM, &parm) < 0) {
3611 GST_DEBUG("Switch Mode failed !\n");
3615 GST_DEBUG_OBJECT (v4l2camsrc, "Setting capture mode done: %s",
3616 ret ? "OK" : "FAIL");
3619 GST_DEBUG_OBJECT (v4l2camsrc, "Device not initialized");
3623 g_mutex_unlock (v4l2camsrc->device_mutex);
3628 gboolean gst_v4l2camsrc_set_strobe_state (GstCameraSrc * camsrc,
3632 GstMFLDV4l2CamSrc *v4l2camsrc;
3634 cam_err_t err = CAM_ERR_NONE;
3636 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3637 fd = v4l2camsrc->video_fd;
3639 err = cam_set_flash (fd, state);
3640 return(err == CAM_ERR_NONE);
3643 gst_libmfldcam_capture_correction_update (GstMFLDV4l2CamSrc * v4l2camsrc)
3645 int fd = v4l2camsrc->video_fd;
3648 if (!v4l2camsrc->cc_updated)
3651 if (v4l2camsrc->gdc_enabled)
3652 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_GDC, TRUE);
3654 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_GDC, FALSE);
3659 if (v4l2camsrc->cac_enabled)
3660 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_CAC, TRUE);
3662 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_CAC, FALSE);
3667 if (v4l2camsrc->dvs_enabled)
3668 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_DVS, TRUE);
3670 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_DVS, FALSE);
3675 if (v4l2camsrc->ee_enabled)
3676 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_EE, TRUE);
3678 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_EE, FALSE);
3683 if (v4l2camsrc->sc_enabled)
3684 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_SC, TRUE);
3686 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_SC, FALSE);
3691 if (v4l2camsrc->blc_enabled)
3692 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BLC, TRUE);
3694 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BLC, FALSE);
3696 if (v4l2camsrc->bpd_enabled)
3697 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BPD, TRUE);
3699 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BPD, FALSE);
3704 v4l2camsrc->cc_updated = FALSE;
3713 GST_WARNING_OBJECT (v4l2camsrc, "Set capture correction failed \n");
3719 * gst_v4l2camsrc_libmfldcam_set_zoom:
3720 * @v4l2camsrc: #GstMFLDV4l2CamSrc object.
3721 * @zoom: Desired zoom factor.
3723 * Set the zoom factor for captured image.
3725 * Returns: TRUE on success.
3728 gst_v4l2camsrc_libmfldcam_set_zoom (GstMFLDV4l2CamSrc * v4l2camsrc, gfloat zoom)
3730 cam_err_t err = CAM_ERR_NONE;
3733 GST_DEBUG_OBJECT (v4l2camsrc, "ZOOM: %f", zoom);
3735 err = cam_set_zoom (v4l2camsrc->video_fd, zoom);
3736 /* ret = err == CAM_ERR_NONE; */
3739 GST_DEBUG_OBJECT (v4l2camsrc, "Setting zoom: %s", ret ? "SUCCESS" : "FAIL");
3745 gst_v4l2camsrc_libmfldcam_get_makernote (GstMFLDV4l2CamSrc * v4l2camsrc, unsigned char *buf, unsigned size)
3747 cam_err_t err = CAM_ERR_NONE;
3749 GST_DEBUG_OBJECT (v4l2camsrc, "%s, !!!!!!line:%d\n", __func__, __LINE__);
3751 err = cam_get_makernote (v4l2camsrc->video_fd, buf, size);
3756 gst_v4l2camsrc_libmfldcam_get_focus_posi(GstMFLDV4l2CamSrc * v4l2camsrc, unsigned *posi)
3758 cam_err_t err = CAM_ERR_NONE;
3759 err = cam_get_focus_posi(v4l2camsrc->video_fd, posi);
3760 if(err != CAM_ERR_NONE)
3767 * @v4l2camsrc: #GstMFLDV4l2CamSrc object
3769 * configure driver default settings and set the opened ISP fd to libmfldcam
3772 gst_v4l2camsrc_libmfldcam_init (GstMFLDV4l2CamSrc * v4l2camsrc)
3775 struct v4l2_input input;
3779 memset(&input, 0, sizeof(input));
3780 if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_PRIMARY)
3781 input.index = V2L2_CAMERA_INPUT_SENSOR_PRIMARY;
3783 input.index = V2L2_CAMERA_INPUT_SENSOR_SECONDARY;
3785 ret = ioctl(v4l2camsrc->video_fd, VIDIOC_ENUMINPUT, &input);
3789 name = (char*)input.name;
3790 space = strchr(name, ' ');
3792 name[space - name] = '\0';
3794 GST_DEBUG_OBJECT (v4l2camsrc, "sensor name %s", name);
3796 err = cam_driver_init (v4l2camsrc->video_fd, name);
3798 if (err != CAM_ERR_NONE) {
3799 GST_WARNING ("libmfldcam initialization failed");
3802 if (v4l2camsrc->cc_updated)
3803 gst_libmfldcam_capture_correction_update (v4l2camsrc);
3805 if (v4l2camsrc->gamma_updated) {
3806 cam_set_tone_control (v4l2camsrc->video_fd, CAM_GAMMA_VALUE,
3808 cam_set_tone_control (v4l2camsrc->video_fd, CAM_BRIGHTNESS_VALUE,
3810 cam_set_tone_control (v4l2camsrc->video_fd, CAM_CONTRAST_VALUE,
3812 v4l2camsrc->gamma_updated = FALSE;
3815 /* Set the default settings here */
3817 GST_DEBUG_OBJECT (v4l2camsrc, "Configure default settings %s",
3818 v4l2camsrc->videodev);
3820 gst_v4l2camsrc_set_attribute (GST_CAMERA_SRC (v4l2camsrc),V4L2_CID_VFLIP,v4l2camsrc->vflip);
3821 if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_SECONDARY) {
3822 gst_v4l2camsrc_set_attribute (GST_CAMERA_SRC (v4l2camsrc),V4L2_CID_HFLIP,v4l2camsrc->hflip);
3823 gst_v4l2camsrc_set_attribute (GST_CAMERA_SRC (v4l2camsrc),V4L2_CID_POWER_LINE_FREQUENCY,CAM_GENERAL_FLICKER_REDUCTION_MODE_50HZ);
3826 v4l2camsrc->initialized = TRUE;
3827 v4l2camsrc->is_open = TRUE;
3832 gst_v4l2camsrc_libmfldcam_deinit (GstMFLDV4l2CamSrc * v4l2camsrc)
3834 //FIXME : determin whether is it initialized
3836 err = cam_driver_deinit (v4l2camsrc->video_fd);
3837 if (err != CAM_ERR_NONE) {
3838 GST_WARNING ("libmfldcam initialization failed");
3842 v4l2camsrc->is_open = FALSE;