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 #define GST_V4L2CAMSRC_SECOND_VIDEO_DEFAULT_NAME "/dev/video1"
57 extern guint gst_camerasrc_signals[CAMERA_IN_LAST_SIGNAL];
59 static const gint gst_v4l2camsrc_capture_map[] = {
60 CAM_VIEWFINDER_MODE_VIEWFINDER,
61 CAM_VIEWFINDER_MODE_STILL_CAPTURE,
62 CAM_VIEWFINDER_MODE_VIDEO_RECORD,
66 static const gint gst_v4l2camsrc_effect_map[] = {
67 CAM_GENERAL_EFFECT_TYPE_NORMAL,
68 CAM_GENERAL_EFFECT_TYPE_SEPIA,
69 CAM_GENERAL_EFFECT_TYPE_NEGATIVE,
70 CAM_GENERAL_EFFECT_TYPE_GRAYSCALE,
71 CAM_GENERAL_EFFECT_TYPE_NORMAL,
72 CAM_GENERAL_EFFECT_TYPE_VIVID,
73 CAM_GENERAL_EFFECT_TYPE_NORMAL,
74 CAM_GENERAL_EFFECT_TYPE_NORMAL,
75 CAM_GENERAL_EFFECT_TYPE_NORMAL,
76 CAM_GENERAL_EFFECT_TYPE_SKY_BLUE,
77 CAM_GENERAL_EFFECT_TYPE_GRASS_GREEN,
78 CAM_GENERAL_EFFECT_TYPE_SKIN_WHITEN,
82 static const gint gst_v4l2camsrc_wb_map[] = {
84 CAM_AWB_MODE_DAYLIGHT,
87 CAM_AWB_MODE_TUNGSTEN,
88 CAM_AWB_MODE_FLUORESCENT,
93 static gint find_item (const gint table[], const gint item);
94 /* Define this to use memory locking for video buffers */
95 /* #define USE_MLOCK */
98 #define GST_V4L2CAMSRC_SET_ACTIVE(element) (element)->buffer = GINT_TO_POINTER (-1)
99 #define GST_V4L2CAMSRC_SET_INACTIVE(element) (element)->buffer = NULL
101 /* On some systems MAP_FAILED seems to be missing */
103 #define MAP_FAILED ((caddr_t) -1)
106 #define RESIZER_MAX_DOWNSCALE_FACTOR 4
107 #define V4L2CAMSRC_POLL_TIMEOUT (20 * GST_SECOND)
108 #define V4L2CAMSRC_SECOND_POLL_TIMEOUT (1 * GST_SECOND)
110 #define GST_TYPE_V4L2CAMSRC_BUFFER (gst_v4l2camsrc_buffer_get_type())
111 #define GST_IS_V4L2CAMSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2CAMSRC_BUFFER))
112 #define GST_V4L2CAMSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2CAMSRC_BUFFER, GstV4l2Buffer))
114 /* Local functions */
116 gst_v4l2camsrc_get_nearest_size (GstMFLDV4l2CamSrc * v4l2camsrc,
117 guint32 pixelformat, gint * width, gint * height);
118 static void gst_v4l2camsrc_buffer_pool_destroy (GstMFLDV4l2CamSrcBufferPool *
119 pool, GstMFLDV4l2CamSrc * v4l2camsrc);
120 static gboolean gst_v4l2camsrc_update_cropping (GstMFLDV4l2CamSrc * v4l2camsrc,
121 gint width, gint height, gfloat zoom);
123 gst_v4l2camsrc_check_focus_status (GstMFLDV4l2CamSrc * v4l2camsrc,
124 GstCameraFocusStatus *fs, gboolean detailed);
126 static gboolean gst_v4l2camsrc_libmfldcam_init (GstMFLDV4l2CamSrc * v4l2camsrc);
127 static gboolean gst_v4l2camsrc_libmfldcam_deinit (GstMFLDV4l2CamSrc *
134 static GstBufferClass *v4l2buffer_parent_class = NULL;
137 gst_v4l2camsrc_buffer_finalize (GstV4l2Buffer * buffer)
139 GstMFLDV4l2CamSrcBufferPool *pool;
140 gboolean resuscitated = FALSE;
141 struct v4l2_buffer *vbuffer;
145 vbuffer = (struct v4l2_buffer *) buffer->vbuffer;
146 index = vbuffer->index;
148 GST_LOG ("finalizing buffer %p %d", buffer, index);
150 g_mutex_lock (pool->lock);
151 if (GST_BUFFER_SIZE (buffer) != 0)
152 /* BUFFER_SIZE is only set if the frame was dequeued */
153 pool->num_live_buffers--;
156 if (pool->is_vaapi_sharing && buffer->gbuffer)
157 GST_BUFFER_DATA(buffer) = GST_BUFFER_DATA(buffer->gbuffer);
158 if (ioctl (pool->video_fd, VIDIOC_QBUF, vbuffer) < 0) {
159 GST_WARNING ("could not requeue buffer %p %d", buffer, index);
161 /* FIXME: check that the caps didn't change */
162 GST_LOG ("reviving buffer %p, %d", buffer, index);
163 gst_buffer_ref (GST_BUFFER (buffer));
164 GST_BUFFER_SIZE (buffer) = 0;
165 pool->buffers[index] = buffer;
166 pool->queued[index] = 1;
167 g_cond_signal (pool->data_cond);
171 GST_LOG ("the pool is shutting down");
173 g_mutex_unlock (pool->lock);
176 GST_LOG ("buffer %p not recovered, unmapping", buffer);
177 if (buffer->use_mmap)
178 munmap ((void *) GST_BUFFER_DATA (buffer), vbuffer->length);
179 gst_mini_object_unref (GST_MINI_OBJECT (pool));
181 if (!buffer->use_mmap) {
182 if (buffer->gbuffer) {
183 /* It was allocated with gst_pad_alloc_buffer */
184 /* FIXME temporal fix for double free error */
185 if (pool->is_vaapi_sharing)
186 gst_buffer_unref (buffer->gbuffer);
187 buffer->gbuffer = NULL;
189 /* It was allocated with posix_memalign */
190 free (GST_BUFFER_DATA (buffer));
194 GST_BUFFER_DATA (buffer) = NULL;
196 g_free (buffer->vbuffer);
198 GST_LOG ("free v4l2buffer");
199 GST_MINI_OBJECT_CLASS (v4l2buffer_parent_class)->finalize (GST_MINI_OBJECT
205 gst_v4l2camsrc_buffer_class_init (gpointer g_class, gpointer class_data)
207 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
209 v4l2buffer_parent_class = g_type_class_peek_parent (g_class);
211 mini_object_class->finalize =
212 (GstMiniObjectFinalizeFunction) gst_v4l2camsrc_buffer_finalize;
216 gst_v4l2camsrc_buffer_get_type (void)
218 static GType _gst_v4l2camsrc_buffer_type;
220 if (G_UNLIKELY (_gst_v4l2camsrc_buffer_type == 0)) {
221 static const GTypeInfo v4l2camsrc_buffer_info = {
222 sizeof (GstBufferClass),
225 gst_v4l2camsrc_buffer_class_init,
228 sizeof (GstV4l2Buffer),
233 _gst_v4l2camsrc_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
234 "GstCameraBuffer", &v4l2camsrc_buffer_info, 0);
236 return _gst_v4l2camsrc_buffer_type;
239 static GstV4l2Buffer *
240 gst_v4l2camsrc_buffer_new (GstMFLDV4l2CamSrcBufferPool * pool,
241 GstMFLDV4l2CamSrc *v4l2camsrc, guint index, GstCaps * caps,
242 gboolean use_mmap, gboolean is_second, guint frame_byte_size,
245 GstV4l2Buffer *ret = NULL;
246 GstFlowReturn flow_ret;
247 GstBuffer *buf_cap_signal2 = NULL; /*output main buffer for capture signal*/
248 struct v4l2_buffer *vbuffer;
250 ret = (GstV4l2Buffer *) gst_mini_object_new (GST_TYPE_V4L2CAMSRC_BUFFER);
251 ret->use_mmap = use_mmap;
252 vbuffer = ret->vbuffer = g_new0 (struct v4l2_buffer, 1);
253 GST_LOG ("creating buffer %u, %p in pool %p", index, ret, pool);
255 (GstMFLDV4l2CamSrcBufferPool *)
256 gst_mini_object_ref (GST_MINI_OBJECT (pool));
258 vbuffer->index = index;
259 vbuffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
262 vbuffer->memory = V4L2_MEMORY_MMAP;
264 vbuffer->memory = V4L2_MEMORY_USERPTR;
266 vbuffer->length = frame_byte_size;
269 if (ioctl (pool->video_fd, VIDIOC_QUERYBUF, vbuffer) < 0)
270 goto querybuf_failed;
274 data = (guint8 *) mmap (0, vbuffer->length,
275 PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd, vbuffer->m.offset);
276 if (data == MAP_FAILED)
278 GST_BUFFER_DATA (ret) = (guint8 *) data;
281 if (!is_second && v4l2camsrc->capture_mode == GST_CAMERA_SRC_CAPTURE_MODE_STILL) {
284 /* alloc buffer for capture callback */
285 buf_cap_signal2 = gst_buffer_new ();
287 GST_BUFFER_DATA(buf_cap_signal2) = NULL;
288 GST_BUFFER_SIZE(buf_cap_signal2) = 0;
289 GST_BUFFER_CAPS(buf_cap_signal2) = gst_caps_new_simple("video/x-raw-yuv",
290 "format", GST_TYPE_FOURCC, v4l2camsrc->capture_fourcc,
291 "width", G_TYPE_INT, v4l2camsrc->capture_w,
292 "height", G_TYPE_INT,v4l2camsrc->capture_h,
295 GST_LOG_OBJECT (v4l2camsrc, "CALL: usrptr callback");
296 g_signal_emit( G_OBJECT (v4l2camsrc),
297 gst_camerasrc_signals[CAMERA_IN_SIGNAL_STILL_USRPTR_BUFFER],
301 if (GST_BUFFER_DATA(buf_cap_signal2) == NULL)
302 goto usrptr_alloc_failed;
304 GST_LOG_OBJECT (v4l2camsrc, "RETURN: usrptr callback: buf=%p, size=%d",
305 GST_BUFFER_DATA(buf_cap_signal2), GST_BUFFER_SIZE(buf_cap_signal2));
306 GST_BUFFER_DATA (ret) = GST_BUFFER_DATA(buf_cap_signal2);
307 gst_buffer_unref(buf_cap_signal2);
310 if (gst_pad_is_linked (pad)) {
311 GST_LOG ("using pad_alloc, size=%d", frame_byte_size);
312 GST_LOG ("ALLOC CAPS: %" GST_PTR_FORMAT, caps);
315 gst_pad_alloc_buffer_and_set_caps (pad, 0LL,
316 frame_byte_size, caps, &ret->gbuffer);
317 if (flow_ret != GST_FLOW_OK)
318 goto pad_alloc_failed;
319 GST_BUFFER_DATA (ret) = ret->gbuffer->data;
323 GST_LOG ("using posix_memalign");
324 if (posix_memalign (&data, getpagesize (), vbuffer->length) != 0) {
325 goto memalign_failed;
327 GST_BUFFER_DATA (ret) = (guint8 *) data;
332 GST_BUFFER_SIZE (ret) = frame_byte_size;
333 GST_BUFFER_FLAG_SET (ret, GST_BUFFER_FLAG_READONLY);
334 gst_buffer_set_caps (GST_BUFFER (ret), caps);
337 GST_DEBUG ("mlocking buffer data");
338 if (mlock ((void *) GST_BUFFER_DATA (ret), frame_byte_size) == -1)
342 /* mlocking succeeded, now we can set the pointer to vbuffer. The existence
343 * of this pointer will be used later to determine if the munlock() is
346 vbuffer->m.userptr = (unsigned int) GST_BUFFER_DATA (ret);
350 GST_LOG (" index: %u", vbuffer->index);
351 GST_LOG (" type: %d", vbuffer->type);
352 GST_LOG (" bytesused: %u", vbuffer->bytesused);
353 GST_LOG (" flags: %08x", vbuffer->flags);
354 GST_LOG (" field: %d", vbuffer->field);
355 GST_LOG (" memory: %d", vbuffer->memory);
356 if (vbuffer->memory == V4L2_MEMORY_MMAP)
357 GST_LOG (" MMAP offset: %p", vbuffer->m.offset);
358 else if (vbuffer->memory == V4L2_MEMORY_USERPTR)
359 GST_LOG (" user address: %p", vbuffer->m.userptr);
360 GST_LOG (" length: %u", vbuffer->length);
361 GST_LOG (" input: %u", vbuffer->input);
370 GST_WARNING ("Failed to mlock memory: %s", g_strerror (errno));
371 gst_buffer_unref (GST_BUFFER (ret));
378 gint errnosave = errno;
380 GST_WARNING ("Failed QUERYBUF: %s", g_strerror (errnosave));
381 gst_buffer_unref (GST_BUFFER (ret));
388 GST_WARNING ("Failed to posix_memalign a buffer");
394 GST_WARNING ("Failed to pad_alloc_buffer: %s",
395 gst_flow_get_name (flow_ret));
401 GST_WARNING ("Failed to alloc usrptr buffer");
407 gint errnosave = errno;
408 GST_WARNING ("Failed to mmap: %s", g_strerror (errnosave));
409 gst_buffer_unref (GST_BUFFER (ret));
417 #define GST_TYPE_V4L2CAMSRC_BUFFER_POOL (gst_v4l2camsrc_buffer_pool_get_type())
418 #define GST_IS_V4L2CAMSRC_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2CAMSRC_BUFFER_POOL))
419 #define GST_V4L2CAMSRC_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2CAMSRC_BUFFER_POOL, GstMFLDV4l2CamSrcBufferPool))
421 static GstMiniObjectClass *buffer_pool_parent_class = NULL;
424 gst_v4l2camsrc_buffer_pool_finalize (GstMFLDV4l2CamSrcBufferPool * pool)
426 g_mutex_free (pool->lock);
429 if (pool->video_fd >= 0)
430 close (pool->video_fd);
433 g_free (pool->buffers);
434 pool->buffers = NULL;
438 g_free (pool->queued);
442 g_cond_free (pool->data_cond);
443 pool->data_cond = NULL;
445 GST_MINI_OBJECT_CLASS (buffer_pool_parent_class)->finalize (GST_MINI_OBJECT
452 gst_v4l2camsrc_buffer_pool_init (GstMFLDV4l2CamSrcBufferPool * pool,
455 pool->lock = g_mutex_new ();
456 pool->running = FALSE;
457 pool->num_live_buffers = 0;
458 pool->data_cond = g_cond_new ();
459 pool->is_vaapi_sharing = FALSE;
460 pool->frame_byte_size = 0;
466 gst_v4l2camsrc_buffer_pool_class_init (gpointer g_class, gpointer class_data)
468 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
470 buffer_pool_parent_class = g_type_class_peek_parent (g_class);
472 mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
473 gst_v4l2camsrc_buffer_pool_finalize;
479 gst_v4l2camsrc_buffer_pool_get_type (void)
481 static GType _gst_v4l2camsrc_buffer_pool_type;
483 if (G_UNLIKELY (_gst_v4l2camsrc_buffer_pool_type == 0)) {
484 static const GTypeInfo v4l2camsrc_buffer_pool_info = {
485 sizeof (GstBufferClass),
488 gst_v4l2camsrc_buffer_pool_class_init,
491 sizeof (GstMFLDV4l2CamSrcBufferPool),
493 (GInstanceInitFunc) gst_v4l2camsrc_buffer_pool_init,
496 _gst_v4l2camsrc_buffer_pool_type =
497 g_type_register_static (GST_TYPE_MINI_OBJECT,
498 "GstMFLDV4l2CamSrcBufferPool", &v4l2camsrc_buffer_pool_info, 0);
500 return _gst_v4l2camsrc_buffer_pool_type;
505 static GstMFLDV4l2CamSrcBufferPool *
506 gst_v4l2camsrc_buffer_pool_new (GstMFLDV4l2CamSrc *v4l2camsrc, gint fd,
507 guint buf_count, GstCaps * caps,
508 gboolean use_mmap, gboolean is_second,
509 guint frame_byte_size, GstPad *pad)
511 GstMFLDV4l2CamSrcBufferPool *pool;
514 pool = (GstMFLDV4l2CamSrcBufferPool *)
515 gst_mini_object_new (GST_TYPE_V4L2CAMSRC_BUFFER_POOL);
517 pool->video_fd = dup (fd);
518 if (pool->video_fd < 0)
521 GstStructure *structure = gst_caps_get_structure (caps, 0);
522 if (structure && gst_structure_has_name(structure, "video/x-vaapi-sharing"))
523 pool->is_vaapi_sharing = TRUE;
525 pool->buffer_count = buf_count;
526 pool->buffers = g_new0 (GstV4l2Buffer *, pool->buffer_count);
527 pool->queued = g_new0 (guint, pool->buffer_count);
528 pool->frame_byte_size = frame_byte_size;
530 for (n = 0; n < pool->buffer_count; n++) {
531 pool->buffers[n] = gst_v4l2camsrc_buffer_new (
532 pool, v4l2camsrc, n, caps,
533 use_mmap, is_second, frame_byte_size, pad);
534 GST_LOG ("buffer ref is %d", GST_MINI_OBJECT_REFCOUNT (pool->buffers[n]));
535 if (!pool->buffers[n])
536 goto buffer_new_failed;
544 gint errnosave = errno;
546 gst_v4l2camsrc_buffer_pool_destroy (pool, v4l2camsrc);
554 gint errnosave = errno;
556 GST_LOG ("creating a new buffer failed");
557 gst_mini_object_unref (GST_MINI_OBJECT (pool));
568 gst_v4l2camsrc_buffer_pool_activate (GstMFLDV4l2CamSrcBufferPool * pool,
569 GstMFLDV4l2CamSrc * v4l2camsrc)
573 g_mutex_lock (pool->lock);
575 for (n = 0; n < pool->buffer_count; n++) {
577 struct v4l2_buffer *buf;
579 buf = (struct v4l2_buffer *) pool->buffers[n]->vbuffer;
581 GST_LOG ("enqueue pool buffer %d", n);
583 if (ioctl (pool->video_fd, VIDIOC_QBUF, buf) < 0)
588 pool->running = TRUE;
590 g_mutex_unlock (pool->lock);
597 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
598 ("Could not enqueue buffers in device '%s'.",
599 v4l2camsrc->videodev),
600 ("enqueing buffer %d/%d failed: %s",
601 n, pool->buffer_count, g_strerror (errno)));
602 g_mutex_unlock (pool->lock);
607 /* requeue buffers that are writable again */
608 /* FIXME: This isn't needed anymore. Buffers are re-queued automatically
609 * when they are finalized, so there is no need to wait for them separately */
611 gst_v4l2_buffer_pool_update (GstMFLDV4l2CamSrcBufferPool * pool,
612 GstMFLDV4l2CamSrc * v4l2camsrc, guint num_buffers)
617 g_mutex_lock (pool->lock);
619 for (n = 0; n < pool->buffer_count; n++) {
620 if (!pool->queued[n]) {
621 GST_LOG ("buffer %d is dequeued", n);
626 /* if all the buffers are dequeued, wait */
627 if (ref == num_buffers) {
628 GST_LOG ("no free buffers available");
629 g_cond_wait (pool->data_cond, pool->lock);
632 g_mutex_unlock (pool->lock);
634 return (ref != num_buffers) ? TRUE : FALSE;
640 gst_v4l2camsrc_buffer_pool_destroy (GstMFLDV4l2CamSrcBufferPool * pool,
641 GstMFLDV4l2CamSrc * v4l2camsrc)
645 g_mutex_lock (pool->lock);
646 pool->running = FALSE;
647 g_mutex_unlock (pool->lock);
649 GST_DEBUG ("destroy pool");
651 /* after this point, no more buffers will be queued or dequeued; no buffer
652 * from pool->buffers that is NULL will be set to a buffer, and no buffer that
653 * is not NULL will be pushed out. */
655 /* miniobjects have no dispose, so they can't break ref-cycles, as buffers ref
656 * the pool, we need to unref the buffer to properly finalize te pool */
657 for (n = 0; n < pool->buffer_count; n++) {
660 g_mutex_lock (pool->lock);
661 buf = GST_BUFFER (pool->buffers[n]);
662 g_mutex_unlock (pool->lock);
666 if (pool->buffers[n].m.userptr) {
667 GST_DEBUG ("munlocking buffer data");
668 munlock ((void *) pool->buffers[n].m.userptr,
669 pool->frame_byte_size);
672 /* we own the ref if the buffer is in pool->buffers; drop it. */
673 gst_buffer_unref (buf);
676 pool->is_vaapi_sharing = FALSE;
677 gst_mini_object_unref (GST_MINI_OBJECT (pool));
680 /******************************************************
681 * gst_v4l2camsrc_get_capture_capabilities():
682 * get the device's capturing capabilities
683 * return value: TRUE on success, FALSE on error
684 ******************************************************/
686 gst_v4l2camsrc_get_capture_capabilities (GstMFLDV4l2CamSrc * v4l2camsrc)
688 GST_DEBUG_OBJECT (v4l2camsrc, "getting capabilities");
690 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
693 if (ioctl (v4l2camsrc->video_fd, VIDIOC_QUERYCAP, &v4l2camsrc->vcap) < 0)
696 GST_LOG_OBJECT (v4l2camsrc, "driver: '%s'", v4l2camsrc->vcap.driver);
697 GST_LOG_OBJECT (v4l2camsrc, "card: '%s'", v4l2camsrc->vcap.card);
698 GST_LOG_OBJECT (v4l2camsrc, "bus_info: '%s'", v4l2camsrc->vcap.bus_info);
699 GST_LOG_OBJECT (v4l2camsrc, "version: %08x", v4l2camsrc->vcap.version);
700 GST_LOG_OBJECT (v4l2camsrc, "capabilites: %08x",
701 v4l2camsrc->vcap.capabilities);
708 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
709 ("Error getting capabilities for device '%s': "
710 "It isn't a v4l2 driver. Check if it is a v4l1 driver.",
711 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
717 /******************************************************
718 * gst_v4l2camsrc_set_input_sensor():
719 * set which sensor is the input of ISP
720 * return value: TRUE on success, FALSE on error
721 ******************************************************/
723 gst_v4l2camsrc_set_input_sensor (GstMFLDV4l2CamSrc * v4l2camsrc)
725 V4L2CameraInputSensor select_sensor;
727 GST_DEBUG_OBJECT (v4l2camsrc, "setting input sensor");
729 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
732 if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_PRIMARY)
733 select_sensor = V2L2_CAMERA_INPUT_SENSOR_PRIMARY;
735 select_sensor =V2L2_CAMERA_INPUT_SENSOR_SECONDARY;
737 if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_INPUT,
741 GST_LOG_OBJECT (v4l2camsrc, "set input sensor to: %d",
749 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
750 ("Error setting input for device '%s': ",
751 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
757 get_supported_mmfw_control (GstMFLDV4l2CamSrc * v4l2camsrc, struct v4l2_queryctrl *control)
760 GST_DEBUG_OBJECT (v4l2camsrc, "set private control (%x)", control->id);
762 for (i = 0; i < N_MMFW_CONTROLS; i++) {
763 if (mmfw_wb_controls[i].id == control->id) {
764 *control = mmfw_wb_controls[i];
772 /******************************************************
773 * gst_v4l2camsrc_fill_lists():
774 * fill the lists of enumerations
775 * return value: TRUE on success, FALSE on error
776 ******************************************************/
778 gst_v4l2camsrc_fill_lists (GstMFLDV4l2CamSrc * v4l2camsrc)
782 GST_DEBUG_OBJECT (v4l2camsrc, "getting enumerations");
783 GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
785 GST_DEBUG_OBJECT (v4l2camsrc, " controls+menus");
786 /* and lastly, controls+menus (if appropriate) */
787 for (n = V4L2_CID_BASE;; n++) {
788 struct v4l2_queryctrl control = { 0, };
789 GstCameraSrcColorBalanceChannel *v4l2channel;
791 GstColorBalanceChannel *channel;
793 /* when we reached the last official CID, continue with private CIDs */
794 if (n == V4L2_CID_LASTP1) {
795 GST_DEBUG_OBJECT (v4l2camsrc, "checking private CIDs");
796 n = V4L2_CID_PRIVATE_BASE;
797 /* FIXME: We are still not handling private controls. We need a
798 new GstInterface to export those controls */
800 GST_DEBUG_OBJECT (v4l2camsrc, "private ID");
805 if( n > SOURCE_PRIV_BASE) {
806 if( n >= MM_CAM_SOURCE_PRIV_LAST)
809 get_supported_mmfw_control(v4l2camsrc, &control);
811 else if (ioctl (v4l2camsrc->video_fd, VIDIOC_QUERYCTRL, &control) < 0) {
812 if (errno == EINVAL) {
813 if (n < V4L2_CID_PRIVATE_BASE)
814 /* continue so that we also check private controls */
819 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
820 ("Failed getting controls attributes on device '%s.'",
821 v4l2camsrc->videodev),
822 ("Failed querying control %d on device '%s'. (%d - %s)",
823 n, v4l2camsrc->videodev, errno, strerror (errno)));
827 if (control.flags & V4L2_CTRL_FLAG_DISABLED)
831 case V4L2_CID_BRIGHTNESS:
832 case V4L2_CID_CONTRAST:
833 case V4L2_CID_SATURATION:
835 case V4L2_CID_BLACK_LEVEL:
836 case V4L2_CID_AUTO_WHITE_BALANCE:
837 case V4L2_CID_DO_WHITE_BALANCE:
838 case V4L2_CID_RED_BALANCE:
839 case V4L2_CID_BLUE_BALANCE:
841 case V4L2_CID_EXPOSURE:
842 case V4L2_CID_AUTOGAIN:
844 case V4L2_CID_COLORFX:
845 case MM_CAM_FILTER_WB_SOURCE_PRIV:
846 case MM_CAM_FILTER_COLOR_TONE_SOURCE_PRIV:
847 case MM_CAM_FILTER_BRIGHTNESS_SOURCE_PRIV:
848 /* we only handle these for now (why?) */
852 case V4L2_CID_HCENTER:
853 case V4L2_CID_VCENTER:
854 #ifdef V4L2_CID_PAN_RESET
855 case V4L2_CID_PAN_RESET:
857 #ifdef V4L2_CID_TILT_RESET
858 case V4L2_CID_TILT_RESET:
860 /* not handled here, handled by VideoOrientation interface */
863 case V4L2_CID_AUDIO_VOLUME:
864 case V4L2_CID_AUDIO_BALANCE:
865 case V4L2_CID_AUDIO_BASS:
866 case V4L2_CID_AUDIO_TREBLE:
867 case V4L2_CID_AUDIO_MUTE:
868 case V4L2_CID_AUDIO_LOUDNESS:
869 /* FIXME: We should implement GstMixer interface */
872 GST_DEBUG_OBJECT (v4l2camsrc,
873 "ControlID %s (%x) unhandled, FIXME", control.name, n);
880 GST_DEBUG_OBJECT (v4l2camsrc, "Adding ControlID %s (%x)", control.name, n);
882 g_object_new (GST_TYPE_CAMERA_SRC_COLOR_BALANCE_CHANNEL, NULL);
883 channel = GST_COLOR_BALANCE_CHANNEL (v4l2channel);
884 channel->label = g_strdup ((const gchar *) control.name);
888 switch (control.type) {
889 case V4L2_CTRL_TYPE_INTEGER:
890 channel->min_value = control.minimum;
891 channel->max_value = control.maximum;
893 case V4L2_CTRL_TYPE_BOOLEAN:
894 channel->min_value = FALSE;
895 channel->max_value = TRUE;
898 /* FIXME we should find out how to handle V4L2_CTRL_TYPE_BUTTON.
899 BUTTON controls like V4L2_CID_DO_WHITE_BALANCE can just be set (1) or
900 unset (0), but can't be queried */
901 GST_DEBUG_OBJECT (v4l2camsrc,
902 "Control with non supported type %s (%x), type=%d",
903 control.name, n, control.type);
904 channel->min_value = channel->max_value = 0;
908 gst_camerasrc_add_color_channel (GST_CAMERA_SRC (v4l2camsrc), channel);
911 GST_DEBUG_OBJECT (v4l2camsrc, "done");
915 /******************************************************
916 * gst_v4l2camsrc_open():
917 * open the video device (v4l2camsrc->videodev)
918 * return value: TRUE on success, FALSE on error
919 ******************************************************/
921 gst_v4l2camsrc_open (GstCameraSrc * camsrc)
924 GstPollFD pollfd = GST_POLL_FD_INIT;
926 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
928 GST_DEBUG_OBJECT (v4l2camsrc, "Trying to open device %s",
929 v4l2camsrc->videodev);
931 GST_V4L2CAMSRC_CHECK_NOT_OPEN (v4l2camsrc);
932 GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
934 /* be sure we have a device */
935 if (!v4l2camsrc->videodev)
936 v4l2camsrc->videodev = g_strdup ("/dev/video");
938 /* check if it is a device */
939 if (stat (v4l2camsrc->videodev, &st) == -1)
942 if (!S_ISCHR (st.st_mode))
945 /* open the device */
946 v4l2camsrc->video_fd =
947 open (v4l2camsrc->videodev, O_RDWR /* | O_NONBLOCK */ );
949 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
952 /* get capabilities, error will be posted */
953 if (!gst_v4l2camsrc_get_capture_capabilities (v4l2camsrc))
956 /* get capabilities, error will be posted */
957 if (!gst_v4l2camsrc_set_input_sensor (v4l2camsrc))
960 /* do we need to be a capture device? */
961 if (GST_IS_V4L2CAMSRC (v4l2camsrc) &&
962 !(v4l2camsrc->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
965 /* Before iterating enumerations, clear the parent's color channel list */
966 gst_camerasrc_clear_color_channels (camsrc);
968 /* create enumerations, posts errors. */
969 if (!gst_v4l2camsrc_fill_lists (v4l2camsrc))
972 GST_INFO_OBJECT (v4l2camsrc,
973 "Opened device '%s' (%s) successfully",
974 v4l2camsrc->vcap.card, v4l2camsrc->videodev);
976 pollfd.fd = v4l2camsrc->video_fd;
977 gst_poll_add_fd (v4l2camsrc->poll, &pollfd);
978 gst_poll_fd_ctl_read (v4l2camsrc->poll, &pollfd, TRUE);
980 gst_v4l2camsrc_libmfldcam_init (v4l2camsrc);
987 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
988 ("Cannot identify device '%s'.", v4l2camsrc->videodev),
994 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
995 ("This isn't a device '%s'.", v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1000 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, OPEN_READ_WRITE,
1001 ("Could not open device '%s' for reading and writing.",
1002 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1007 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
1008 ("Device '%s' is not a capture device.",
1009 v4l2camsrc->videodev),
1010 ("Capabilities: 0x%x", v4l2camsrc->vcap.capabilities));
1015 if (GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc)) {
1017 close (v4l2camsrc->video_fd);
1018 v4l2camsrc->video_fd = -1;
1025 /******************************************************
1026 * gst_v4l2camsrc_close():
1027 * close the video device (v4l2camsrc->video_fd)
1028 * return value: TRUE on success, FALSE on error
1029 ******************************************************/
1031 gst_v4l2camsrc_close (GstCameraSrc * camsrc)
1033 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1035 GstPollFD pollfd = GST_POLL_FD_INIT;
1037 GST_DEBUG_OBJECT (v4l2camsrc, "Trying to close %s", v4l2camsrc->videodev);
1039 GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
1040 GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
1043 gst_v4l2camsrc_libmfldcam_deinit (v4l2camsrc);
1045 close (v4l2camsrc->video_fd);
1046 pollfd.fd = v4l2camsrc->video_fd;
1047 gst_poll_remove_fd (v4l2camsrc->poll, &pollfd);
1048 v4l2camsrc->video_fd = -1;
1053 /******************************************************
1054 * gst_v4l2camsrc_get_attribute():
1055 * try to get the value of one specific attribute
1056 * return value: TRUE on success, FALSE on error
1057 ******************************************************/
1059 gst_v4l2camsrc_get_attribute (GstCameraSrc * camsrc,
1060 int attribute_num, int *value)
1062 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1064 struct v4l2_control control;
1068 GST_DEBUG_OBJECT (v4l2camsrc, "getting value of attribute %d", attribute_num);
1070 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
1073 control.id = attribute_num;
1075 if (control.id > SOURCE_PRIV_BASE) {
1076 switch (control.id) {
1077 case MM_CAM_FILTER_WB_SOURCE_PRIV:
1078 err = cam_feature_get (v4l2camsrc->video_fd, CAM_AWB_MODE, &tmp_value);
1079 *value = find_item (gst_v4l2camsrc_wb_map, tmp_value);
1081 case MM_CAM_FILTER_COLOR_TONE_SOURCE_PRIV:
1082 err = cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE, &tmp_value);
1083 *value = find_item (gst_v4l2camsrc_effect_map, tmp_value);
1085 case MM_CAM_FILTER_BRIGHTNESS_SOURCE_PRIV:
1086 err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION, &tmp_value);
1095 if (ioctl (v4l2camsrc->video_fd, VIDIOC_G_CTRL, &control) < 0)
1097 *value = control.value;
1104 struct v4l2_ext_controls controls;
1105 struct v4l2_ext_control control;
1107 controls.ctrl_class = V4L2_CTRL_CLASS_USER;
1109 controls.controls = &control;
1111 control.id = attribute_num;
1113 if (ioctl (v4l2camsrc->video_fd, VIDIOC_G_EXT_CTRLS, &controls) < 0)
1116 *value = control.value;
1125 GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1126 ("Failed to get value for control %d on device '%s'.",
1127 attribute_num, v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1132 /******************************************************
1133 * gst_v4l2camsrc_set_attribute():
1134 * try to set the value of one specific attribute
1135 * return value: TRUE on success, FALSE on error
1136 ******************************************************/
1138 gst_v4l2camsrc_set_attribute (GstCameraSrc * camsrc,
1139 int attribute_num, const int value)
1141 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1142 struct v4l2_control control;
1144 GST_DEBUG_OBJECT (v4l2camsrc, "setting value of attribute %d to %d",
1145 attribute_num, value);
1147 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
1150 control.id = attribute_num;
1151 control.value = value;
1152 if (control.id > SOURCE_PRIV_BASE) {
1153 switch (control.id) {
1154 case MM_CAM_FILTER_WB_SOURCE_PRIV:
1155 cam_feature_set (v4l2camsrc->video_fd, CAM_AWB_MODE, gst_v4l2camsrc_wb_map[value]);
1157 case MM_CAM_FILTER_COLOR_TONE_SOURCE_PRIV:
1158 cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE, gst_v4l2camsrc_effect_map[value]);
1160 case MM_CAM_FILTER_BRIGHTNESS_SOURCE_PRIV:
1161 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION, value);
1168 if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_CTRL, &control) < 0)
1175 struct v4l2_ext_controls controls;
1176 struct v4l2_ext_control control;
1178 controls.ctrl_class = V4L2_CTRL_CLASS_USER;
1180 controls.controls = &control;
1182 control.id = attribute_num;
1183 control.value = value;
1185 if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_EXT_CTRLS, &controls) < 0)
1194 GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1195 ("Failed to set value %d for control %d on device '%s'.",
1196 value, attribute_num, v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1202 /* complete made up ranking, the values themselves are meaningless */
1203 #define YUV_BASE_RANK 1000
1204 #define JPEG_BASE_RANK 500
1205 #define DV_BASE_RANK 200
1206 #define RGB_BASE_RANK 100
1207 #define YUV_ODD_BASE_RANK 50
1208 #define RGB_ODD_BASE_RANK 25
1209 #define BAYER_BASE_RANK 15
1210 #define S910_BASE_RANK 10
1211 #define GREY_BASE_RANK 5
1212 #define PWC_BASE_RANK 1
1214 /* This flag is already used by libv4l2 although
1215 * it was added to the Linux kernel in 2.6.32
1217 #ifndef V4L2_FMT_FLAG_EMULATED
1218 #define V4L2_FMT_FLAG_EMULATED 0x0002
1222 gst_v4l2camsrc_format_get_rank (const struct v4l2_fmtdesc *fmt)
1224 guint32 fourcc = fmt->pixelformat;
1225 gboolean emulated = ((fmt->flags & V4L2_FMT_FLAG_EMULATED) != 0);
1229 case V4L2_PIX_FMT_MJPEG:
1230 rank = JPEG_BASE_RANK;
1232 case V4L2_PIX_FMT_JPEG:
1233 rank = JPEG_BASE_RANK + 1;
1235 case V4L2_PIX_FMT_MPEG: /* MPEG */
1236 rank = JPEG_BASE_RANK + 2;
1239 case V4L2_PIX_FMT_RGB332:
1240 case V4L2_PIX_FMT_RGB555:
1241 case V4L2_PIX_FMT_RGB555X:
1242 case V4L2_PIX_FMT_RGB565:
1243 case V4L2_PIX_FMT_RGB565X:
1244 rank = RGB_ODD_BASE_RANK;
1247 case V4L2_PIX_FMT_RGB24:
1248 case V4L2_PIX_FMT_BGR24:
1249 rank = RGB_BASE_RANK - 1;
1252 case V4L2_PIX_FMT_RGB32:
1253 case V4L2_PIX_FMT_BGR32:
1254 rank = RGB_BASE_RANK;
1257 case V4L2_PIX_FMT_GREY: /* 8 Greyscale */
1258 rank = GREY_BASE_RANK;
1261 case V4L2_PIX_FMT_NV12: /* 12 Y/CbCr 4:2:0 */
1262 case V4L2_PIX_FMT_NV21: /* 12 Y/CrCb 4:2:0 */
1263 case V4L2_PIX_FMT_YYUV: /* 16 YUV 4:2:2 */
1264 case V4L2_PIX_FMT_HI240: /* 8 8-bit color */
1265 case V4L2_PIX_FMT_NV16: /* 16 bit YUV 422, Y, UV plane */
1266 rank = YUV_ODD_BASE_RANK;
1268 case V4L2_PIX_FMT_YUV444: /* YUV 444, 24 bits per pixel */
1269 rank = YUV_BASE_RANK + 0;
1271 case V4L2_PIX_FMT_YVU410: /* YVU9, 9 bits per pixel */
1272 rank = YUV_BASE_RANK + 3;
1274 case V4L2_PIX_FMT_YUV410: /* YUV9, 9 bits per pixel */
1275 rank = YUV_BASE_RANK + 2;
1277 case V4L2_PIX_FMT_YUV420: /* I420, 12 bits per pixel */
1278 rank = YUV_BASE_RANK + 7;
1280 case V4L2_PIX_FMT_YUYV: /* YUY2, 16 bits per pixel */
1281 rank = YUV_BASE_RANK + 10;
1283 case V4L2_PIX_FMT_YVU420: /* YV12, 12 bits per pixel */
1284 rank = YUV_BASE_RANK + 6;
1286 case V4L2_PIX_FMT_UYVY: /* UYVY, 16 bits per pixel */
1287 rank = YUV_BASE_RANK + 9;
1289 case V4L2_PIX_FMT_Y41P: /* Y41P, 12 bits per pixel */
1290 rank = YUV_BASE_RANK + 5;
1292 case V4L2_PIX_FMT_YUV411P: /* Y41B, 12 bits per pixel */
1293 rank = YUV_BASE_RANK + 4;
1295 case V4L2_PIX_FMT_YUV422P: /* Y42B, 16 bits per pixel */
1296 rank = YUV_BASE_RANK + 8;
1299 case V4L2_PIX_FMT_DV:
1300 rank = DV_BASE_RANK;
1303 case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */
1307 case V4L2_PIX_FMT_SBGGR8:
1308 case V4L2_PIX_FMT_SRGGB8:
1309 case V4L2_PIX_FMT_SGBRG8:
1310 case V4L2_PIX_FMT_SGRBG10:
1311 case V4L2_PIX_FMT_SRGGB10:
1312 case V4L2_PIX_FMT_SGBRG10:
1313 rank = BAYER_BASE_RANK;
1316 #ifdef V4L2_PIX_FMT_SN9C10X
1317 case V4L2_PIX_FMT_SN9C10X:
1318 rank = S910_BASE_RANK;
1322 #ifdef V4L2_PIX_FMT_PWC1
1323 case V4L2_PIX_FMT_PWC1:
1324 rank = PWC_BASE_RANK;
1327 #ifdef V4L2_PIX_FMT_PWC2
1328 case V4L2_PIX_FMT_PWC2:
1329 rank = PWC_BASE_RANK;
1334 GST_LOG("Don't know how to rank pixelformat %" GST_FOURCC_FORMAT,
1335 GST_FOURCC_ARGS(fourcc));
1340 /* All ranks are below 1<<15 so a shift by 15
1341 * will a) make all non-emulated formats larger
1342 * than emulated and b) will not overflow
1351 gst_v4l2camsrc_format_cmp_func (gconstpointer a, gconstpointer b)
1353 const struct v4l2_fmtdesc *fa = a;
1354 const struct v4l2_fmtdesc *fb = b;
1356 if (fa->pixelformat == fb->pixelformat)
1359 return gst_v4l2camsrc_format_get_rank (fb) -
1360 gst_v4l2camsrc_format_get_rank (fa);
1363 static gboolean is_supported_pixelformat(guint32 fourcc)
1365 if(fourcc == V4L2_PIX_FMT_NV12
1366 || fourcc == V4L2_PIX_FMT_YUV420
1367 || fourcc == V4L2_PIX_FMT_SGRBG10)
1372 /******************************************************
1373 * gst_v4l2camsrc_fill_format_list():
1374 * create list of supported capture formats
1375 * return value: TRUE on success, FALSE on error
1376 ******************************************************/
1378 gst_v4l2camsrc_fill_format_list (GstMFLDV4l2CamSrc * v4l2camsrc)
1381 struct v4l2_fmtdesc *format;
1383 GST_DEBUG_OBJECT (v4l2camsrc, "getting src format enumerations");
1385 /* format enumeration */
1387 format = g_new0 (struct v4l2_fmtdesc, 1);
1390 format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1392 if (ioctl (v4l2camsrc->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
1393 if (errno == EINVAL) {
1395 break; /* end of enumeration */
1400 if(!is_supported_pixelformat(format->pixelformat)) {
1401 GST_LOG_OBJECT(v4l2camsrc, " (skipping format %" GST_FOURCC_FORMAT ")",GST_FOURCC_ARGS (format->pixelformat));
1405 GST_LOG_OBJECT (v4l2camsrc, "index: %u", format->index);
1406 GST_LOG_OBJECT (v4l2camsrc, "type: %d", format->type);
1407 GST_LOG_OBJECT (v4l2camsrc, "flags: %08x", format->flags);
1408 GST_LOG_OBJECT (v4l2camsrc, "description: '%s'", format->description);
1409 GST_LOG_OBJECT (v4l2camsrc, "pixelformat: %" GST_FOURCC_FORMAT,
1410 GST_FOURCC_ARGS (format->pixelformat));
1412 /* sort formats according to our preference; we do this, because caps
1413 * are probed in the order the formats are in the list, and the order of
1414 * formats in the final probed caps matters for things like fixation */
1415 v4l2camsrc->formats = g_slist_insert_sorted (v4l2camsrc->formats, format,
1416 (GCompareFunc) gst_v4l2camsrc_format_cmp_func);
1419 GST_DEBUG_OBJECT (v4l2camsrc, "got %d format(s)", n);
1426 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1427 ("Failed to enumerate possible video formats device '%s' can work with",
1428 v4l2camsrc->videodev),
1429 ("Failed to get number %d in pixelformat enumeration for %s. (%d - %s)",
1430 n, v4l2camsrc->videodev, errno, g_strerror (errno)));
1436 /******************************************************
1437 * gst_v4l2camsrc_clear_format_list():
1438 * free list of supported capture formats
1439 * return value: TRUE on success, FALSE on error
1440 ******************************************************/
1442 gst_v4l2camsrc_clear_format_list (GstMFLDV4l2CamSrc * v4l2camsrc)
1444 g_slist_foreach (v4l2camsrc->formats, (GFunc) g_free, NULL);
1445 g_slist_free (v4l2camsrc->formats);
1446 v4l2camsrc->formats = NULL;
1451 /* The frame interval enumeration code first appeared in Linux 2.6.19. */
1452 #ifdef VIDIOC_ENUM_FRAMEINTERVALS
1453 static GstStructure *
1454 gst_v4l2camsrc_probe_caps_for_format_and_size (GstMFLDV4l2CamSrc * v4l2camsrc,
1455 guint32 pixelformat,
1456 guint32 width, guint32 height, const GstStructure * template)
1458 gint fd = v4l2camsrc->video_fd;
1459 struct v4l2_frmivalenum ival;
1462 GValue rates = { 0, };
1464 memset (&ival, 0, sizeof (struct v4l2_frmivalenum));
1466 ival.pixel_format = pixelformat;
1468 ival.height = height;
1470 GST_LOG_OBJECT (v4l2camsrc, "get frame interval for %ux%u, %"
1471 GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat));
1473 /* keep in mind that v4l2 gives us frame intervals (durations); we invert the
1474 * fraction to get framerate */
1475 if (ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0)
1476 goto enum_frameintervals_failed;
1478 if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
1479 GValue rate = { 0, };
1481 g_value_init (&rates, GST_TYPE_LIST);
1482 g_value_init (&rate, GST_TYPE_FRACTION);
1485 num = ival.discrete.numerator;
1486 denom = ival.discrete.denominator;
1488 if (num > G_MAXINT || denom > G_MAXINT) {
1489 /* let us hope we don't get here... */
1494 GST_LOG_OBJECT (v4l2camsrc, "adding discrete framerate: %d/%d",
1497 /* swap to get the framerate */
1498 gst_value_set_fraction (&rate, denom, num);
1499 gst_value_list_append_value (&rates, &rate);
1502 } while (ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
1504 /* FIXME MASSIVE UGLY HACK: Pretend to support 30/1 fps always */
1505 gst_value_set_fraction(&rate, 30, 1);
1506 gst_value_list_append_value(&rates, &rate);
1508 } else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
1509 GValue min = { 0, };
1510 GValue step = { 0, };
1511 GValue max = { 0, };
1512 gboolean added = FALSE;
1513 guint32 minnum, mindenom;
1514 guint32 maxnum, maxdenom;
1516 g_value_init (&rates, GST_TYPE_LIST);
1518 g_value_init (&min, GST_TYPE_FRACTION);
1519 g_value_init (&step, GST_TYPE_FRACTION);
1520 g_value_init (&max, GST_TYPE_FRACTION);
1523 minnum = ival.stepwise.min.numerator;
1524 mindenom = ival.stepwise.min.denominator;
1525 if (minnum > G_MAXINT || mindenom > G_MAXINT) {
1529 GST_LOG_OBJECT (v4l2camsrc, "stepwise min frame interval: %d/%d", minnum,
1531 gst_value_set_fraction (&min, minnum, mindenom);
1534 maxnum = ival.stepwise.max.numerator;
1535 maxdenom = ival.stepwise.max.denominator;
1536 if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
1541 GST_LOG_OBJECT (v4l2camsrc, "stepwise max frame interval: %d/%d", maxnum,
1543 gst_value_set_fraction (&max, maxnum, maxdenom);
1546 num = ival.stepwise.step.numerator;
1547 denom = ival.stepwise.step.denominator;
1548 if (num > G_MAXINT || denom > G_MAXINT) {
1553 if (num == 0 || denom == 0) {
1554 /* in this case we have a wrong fraction or no step, set the step to max
1555 * so that we only add the min value in the loop below */
1560 /* since we only have gst_value_fraction_subtract and not add, negate the
1562 GST_LOG_OBJECT (v4l2camsrc, "stepwise step frame interval: %d/%d",
1565 gst_value_set_fraction (&step, -num, denom);
1567 while (gst_value_compare (&min, &max) <= 0) {
1568 GValue rate = { 0, };
1570 num = gst_value_get_fraction_numerator (&min);
1571 denom = gst_value_get_fraction_denominator (&min);
1572 GST_LOG_OBJECT (v4l2camsrc, "adding stepwise framerate: %d/%d",
1575 /* invert to get the framerate */
1576 g_value_init (&rate, GST_TYPE_FRACTION);
1577 gst_value_set_fraction (&rate, denom, num);
1578 gst_value_list_append_value (&rates, &rate);
1581 /* we're actually adding because step was negated above. This is because
1582 * there is no _add function... */
1583 if (!gst_value_fraction_subtract (&min, &min, &step)) {
1584 GST_WARNING_OBJECT (v4l2camsrc, "could not step fraction!");
1589 /* no range was added, leave the default range from the template */
1590 GST_WARNING_OBJECT (v4l2camsrc, "no range added, leaving default");
1591 g_value_unset (&rates);
1593 } else if (ival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
1594 guint32 maxnum, maxdenom;
1596 g_value_init (&rates, GST_TYPE_FRACTION_RANGE);
1598 num = ival.stepwise.min.numerator;
1599 denom = ival.stepwise.min.denominator;
1600 if (num > G_MAXINT || denom > G_MAXINT) {
1605 maxnum = ival.stepwise.max.numerator;
1606 maxdenom = ival.stepwise.max.denominator;
1607 if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
1612 GST_LOG_OBJECT (v4l2camsrc, "continuous frame interval %d/%d to %d/%d",
1613 maxdenom, maxnum, denom, num);
1615 gst_value_set_fraction_range_full (&rates, maxdenom, maxnum, denom, num);
1621 s = gst_structure_copy (template);
1622 /* https://projects.maemo.org/bugzilla/show_bug.cgi?id=105590 */
1623 gst_structure_set (s,
1624 "width", G_TYPE_INT, (gint) width,
1625 "height", G_TYPE_INT, (gint) height, NULL);
1627 if (G_IS_VALUE (&rates)) {
1628 /* only change the framerate on the template when we have a valid probed new
1630 gst_structure_set_value (s, "framerate", &rates);
1631 g_value_unset (&rates);
1636 enum_frameintervals_failed:
1638 GST_DEBUG_OBJECT (v4l2camsrc,
1639 "Unable to enumerate intervals for %" GST_FOURCC_FORMAT "@%ux%u",
1640 GST_FOURCC_ARGS (pixelformat), width, height);
1645 /* I don't see how this is actually an error, we ignore the format then */
1646 GST_WARNING_OBJECT (v4l2camsrc,
1647 "Unknown frame interval type at %" GST_FOURCC_FORMAT "@%ux%u: %u",
1648 GST_FOURCC_ARGS (pixelformat), width, height, ival.type);
1652 #endif /* defined VIDIOC_ENUM_FRAMEINTERVALS */
1658 compare_resolutions (gconstpointer a, gconstpointer b)
1660 GstStructure *as = (GstStructure *) a;
1661 GstStructure *bs = (GstStructure *) b;
1662 gint aw, bw, ah, bh;
1664 gst_structure_get_int (as, "width", &aw);
1665 gst_structure_get_int (bs, "width", &bw);
1666 gst_structure_get_int (as, "height", &ah);
1667 gst_structure_get_int (bs, "height", &bh);
1669 /* FIXME: What is the best way to compare resolutions if their aspect
1670 * ratio isn't the same? */
1671 return ((aw - bw) + (ah - bh));
1678 fractions_are_equal (gint num1, gint den1, gint num2, gint den2)
1680 GValue fraction1 = { 0, }, fraction2 = {
1683 g_value_init (&fraction1, GST_TYPE_FRACTION);
1684 g_value_init (&fraction2, GST_TYPE_FRACTION);
1685 gst_value_set_fraction (&fraction1, num1, den1);
1686 gst_value_set_fraction (&fraction2, num2, den2);
1687 /* we know we don't have to unset the values in this case */
1688 return (gst_value_compare (&fraction1, &fraction2) == GST_VALUE_EQUAL);
1692 gst_v4l2camsrc_get_frame_size (guint32 fourcc, guint * w, guint * h)
1697 case V4L2_PIX_FMT_YUV420:
1698 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1699 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1701 case V4L2_PIX_FMT_YUYV:
1702 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1704 case V4L2_PIX_FMT_Y41P:
1705 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1707 case V4L2_PIX_FMT_UYVY:
1708 outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1710 case V4L2_PIX_FMT_YVU420:
1711 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1712 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1714 case V4L2_PIX_FMT_YUV411P:
1715 outsize = GST_ROUND_UP_4 (*w) * *h;
1716 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
1718 case V4L2_PIX_FMT_YUV422P:
1719 outsize = GST_ROUND_UP_4 (*w) * *h;
1720 outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
1722 case V4L2_PIX_FMT_NV12:
1723 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1724 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1726 case V4L2_PIX_FMT_NV21:
1727 outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1728 outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1738 gst_v4l2camsrc_configure_device (GstMFLDV4l2CamSrc * v4l2camsrc,
1739 guint32 * pixelformat, guint * width, guint * height,
1740 guint * fps_n, guint * fps_d)
1742 gint fd = v4l2camsrc->video_fd;
1743 struct v4l2_format format;
1744 struct v4l2_streamparm stream;
1745 gboolean ret = TRUE;
1747 GST_DEBUG_OBJECT (v4l2camsrc, "Configuring device to %dx%d, format "
1748 "%" GST_FOURCC_FORMAT, *width, *height, GST_FOURCC_ARGS (*pixelformat));
1750 GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
1752 memset (&format, 0x00, sizeof (struct v4l2_format));
1753 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1755 if (ioctl (fd, VIDIOC_G_FMT, &format) < 0)
1756 goto get_fmt_failed;
1758 if (v4l2camsrc->dump_raw)
1759 format.type = V4L2_BUF_TYPE_PRIVATE;
1761 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1762 format.fmt.pix.width = *width;
1763 format.fmt.pix.height = *height;
1764 format.fmt.pix.pixelformat = *pixelformat;
1765 /* request whole frames; change when gstreamer supports interlaced video
1766 * (INTERLACED mode returns frames where the fields have already been
1767 * combined, there are other modes for requesting fields individually) */
1768 format.fmt.pix.field = V4L2_FIELD_INTERLACED;
1770 if (ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
1771 if (errno != EINVAL)
1772 goto set_fmt_failed;
1774 /* try again with progressive video */
1775 format.fmt.pix.width = *width;
1776 format.fmt.pix.height = *height;
1777 format.fmt.pix.pixelformat = *pixelformat;
1778 format.fmt.pix.field = V4L2_FIELD_NONE;
1779 if (ioctl (fd, VIDIOC_S_FMT, &format) < 0)
1780 goto set_fmt_failed;
1783 if (v4l2camsrc->dump_raw)
1784 v4l2camsrc->raw_output_size = format.fmt.pix.priv;
1786 if (format.fmt.pix.width != *width || format.fmt.pix.height != *height)
1787 goto invalid_dimensions;
1789 if (format.fmt.pix.pixelformat != *pixelformat)
1790 goto invalid_pixelformat;
1792 memset (&stream, 0x00, sizeof (struct v4l2_streamparm));
1793 stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1794 if (ioctl (fd, VIDIOC_G_PARM, &stream) < 0) {
1795 GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1796 ("Could not get parameters on device '%s'",
1797 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1801 if (fps_n == NULL || fps_d == NULL) {
1802 GST_LOG_OBJECT (v4l2camsrc, "Framerate will not be set");
1806 GST_LOG_OBJECT (v4l2camsrc, "Desired framerate: %u/%u", *fps_n, *fps_d);
1808 /* Note: V4L2 provides the frame interval, we have the frame rate */
1809 if (stream.parm.capture.timeperframe.denominator &&
1810 fractions_are_equal (stream.parm.capture.timeperframe.numerator,
1811 stream.parm.capture.timeperframe.denominator, *fps_d, *fps_n)) {
1812 GST_LOG_OBJECT (v4l2camsrc, "Desired framerate already set, nothing to do");
1816 /* We want to change the frame rate, so check whether we can. Some cheap USB
1817 * cameras don't have the capability */
1818 if ((stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
1819 GST_DEBUG_OBJECT (v4l2camsrc, "Not setting framerate (not supported)");
1823 GST_LOG_OBJECT (v4l2camsrc, "Setting framerate to %u/%u", *fps_n, *fps_d);
1825 /* Note: V4L2 wants the frame interval, we have the frame rate */
1826 stream.parm.capture.timeperframe.numerator = *fps_d;
1827 stream.parm.capture.timeperframe.denominator = *fps_n;
1829 /* some cheap USB cam's won't accept any change */
1830 if (ioctl (fd, VIDIOC_S_PARM, &stream) < 0) {
1831 GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1832 ("Video input device did not accept new frame rate setting."),
1837 GST_INFO_OBJECT (v4l2camsrc, "Set frame interval to %u/%u",
1838 stream.parm.capture.timeperframe.numerator,
1839 stream.parm.capture.timeperframe.denominator);
1841 cam_set_frame_rate( ((gfloat)stream.parm.capture.timeperframe.denominator / stream.parm.capture.timeperframe.numerator));
1844 v4l2camsrc->max_zoom_factor = 10.0;
1845 v4l2camsrc->frame_byte_size = gst_v4l2camsrc_get_frame_size (*pixelformat,
1847 /* v4l2camsrc->frame_byte_size = GST_ROUND_UP_2 (*width) * 2 * (*height); */
1849 if (v4l2camsrc->bayer_downscaling) {
1850 struct v4l2_crop crop;
1851 memset (&v4l2camsrc->vcrop, 0, sizeof (struct v4l2_cropcap));
1852 v4l2camsrc->vcrop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1853 if (ioctl (v4l2camsrc->video_fd, VIDIOC_CROPCAP, &v4l2camsrc->vcrop) < 0) {
1854 GST_DEBUG_OBJECT (v4l2camsrc, "Failed to query crop cap");
1858 crop.c = v4l2camsrc->vcrop.defrect; /* reset to default */
1859 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1860 if (-1 == ioctl (fd, VIDIOC_S_CROP, &crop)) {
1863 GST_DEBUG_OBJECT (v4l2camsrc, "Crop not support\n");
1866 GST_DEBUG_OBJECT (v4l2camsrc, "Crop failed\n");
1875 v4l2camsrc->crop_supported = TRUE;
1877 GST_DEBUG_OBJECT (v4l2camsrc, "got cropping bounds: x:%d, y:%d, w:%d, h:%d",
1878 v4l2camsrc->vcrop.bounds.left,
1879 v4l2camsrc->vcrop.bounds.top,
1880 v4l2camsrc->vcrop.bounds.width, v4l2camsrc->vcrop.bounds.height);
1882 GST_DEBUG_OBJECT (v4l2camsrc, "cropping defrect: x:%d, y:%d, w:%d, h:%d",
1883 v4l2camsrc->vcrop.defrect.left,
1884 v4l2camsrc->vcrop.defrect.top,
1885 v4l2camsrc->vcrop.defrect.width, v4l2camsrc->vcrop.defrect.height);
1887 gst_v4l2camsrc_update_cropping (v4l2camsrc, *width, *height, 1.0);
1891 cam_set_capture_fmt (v4l2camsrc->video_fd, *width, *height, *pixelformat);
1898 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1899 ("Device '%s' does not support video capture",
1900 v4l2camsrc->videodev),
1901 ("Call to G_FMT failed: (%s)", g_strerror (errno)));
1906 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1907 ("Device '%s' cannot capture at %dx%d",
1908 v4l2camsrc->videodev, *width, *height),
1909 ("Call to S_FMT failed for %" GST_FOURCC_FORMAT " @ %dx%d: %s",
1910 GST_FOURCC_ARGS (*pixelformat), *width, *height,
1911 g_strerror (errno)));
1916 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1917 ("Device '%s' cannot capture at %dx%d",
1918 v4l2camsrc->videodev, *width, *height),
1919 ("Tried to capture at %dx%d, but device returned size %dx%d",
1920 *width, *height, format.fmt.pix.width, format.fmt.pix.height));
1923 invalid_pixelformat:
1925 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1926 ("Device '%s' cannot capture in the specified format",
1927 v4l2camsrc->videodev),
1928 ("Tried to capture in %" GST_FOURCC_FORMAT
1929 ", but device returned format" " %" GST_FOURCC_FORMAT,
1930 GST_FOURCC_ARGS (*pixelformat),
1931 GST_FOURCC_ARGS (format.fmt.pix.pixelformat)));
1936 static gboolean resolution_is_supported(int w, int h)
1938 return (w % 4) == 0 && (h % 4) == 0;
1941 #define probe_and_add_for_w_h(w, h) \
1943 GST_LOG(" w=%lu h=%lu",w,h); \
1944 tmp = gst_v4l2camsrc_probe_caps_for_format_and_size(v4l2camsrc, \
1945 pixelformat, w, h, template); \
1947 res = g_list_prepend(res, tmp); \
1951 static GList *build_caps_list(GstMFLDV4l2CamSrc * v4l2camsrc,
1952 guint32 pixelformat, const GstStructure * template,
1953 struct v4l2_frmsizeenum *size)
1955 GstStructure *tmp = NULL;
1957 long wl,wh,hl,hh,ws,hs;
1959 wl = size->stepwise.min_width; wh = size->stepwise.max_width; ws = size->stepwise.step_width;
1960 hl = size->stepwise.min_height; hh = size->stepwise.max_height; hs = size->stepwise.step_height;
1962 probe_and_add_for_w_h(wl, hl);
1963 probe_and_add_for_w_h(wh, hh);
1965 tmp = gst_structure_copy(template);
1966 gst_structure_set (tmp,
1967 "width", GST_TYPE_INT_RANGE, wl, wh,
1968 "height", GST_TYPE_INT_RANGE, hl, hh,
1970 res = g_list_prepend(res, tmp);
1977 * gst_v4l2camsrc_probe_caps_for_format:
1978 * @v4l2camsrc: #GstMFLDV4l2CamSrc object
1979 * @pixelformat: pixel format fourcc
1980 * @template: GstStructure template to be used for generating the caps
1982 * Creates GstCaps object which describes the supported caps of the device.
1984 * Returns: GStCaps containing supported video resolutions.
1987 gst_v4l2camsrc_probe_caps_for_format (GstMFLDV4l2CamSrc * v4l2camsrc,
1988 guint32 pixelformat, const GstStructure * template)
1990 GstCaps *ret = gst_caps_new_empty ();
1991 gint min_w, max_w, min_h, max_h;
1994 #ifdef VIDIOC_ENUM_FRAMESIZES
1996 gint fd = v4l2camsrc->video_fd;
1997 struct v4l2_frmsizeenum size;
1998 GList *results = NULL;
2001 memset (&size, 0, sizeof (struct v4l2_frmsizeenum));
2003 size.pixel_format = pixelformat;
2005 if (ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0)
2006 goto enum_framesizes_failed;
2008 if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
2010 w = MIN (size.discrete.width, G_MAXINT);
2011 h = MIN (size.discrete.height, G_MAXINT);
2013 if(resolution_is_supported(w, h)) {
2014 tmp = gst_v4l2camsrc_probe_caps_for_format_and_size (v4l2camsrc,
2015 pixelformat, w, h, template);
2018 results = g_list_prepend (results, tmp);
2022 } while (ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
2023 } else if(size.type == V4L2_FRMSIZE_TYPE_STEPWISE
2024 || size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
2025 results = build_caps_list(v4l2camsrc, pixelformat, template, &size);
2030 /* Sort the resolutions from smallest to largest */
2031 results = g_list_sort (results, compare_resolutions);
2033 while (results != NULL) {
2034 tmp = GST_STRUCTURE (results->data);
2036 gst_caps_merge_structure (ret, tmp);
2038 results = g_list_delete_link (results, results);
2041 if (gst_caps_is_empty (ret))
2042 goto enum_framesizes_no_results;
2047 enum_framesizes_failed:
2049 /* I don't see how this is actually an error */
2050 GST_DEBUG_OBJECT (v4l2camsrc,
2051 "Failed to enumerate frame sizes for pixelformat %" GST_FOURCC_FORMAT
2052 " (%s)", GST_FOURCC_ARGS (pixelformat), g_strerror (errno));
2053 goto default_frame_sizes;
2055 enum_framesizes_no_results:
2057 /* it's possible that VIDIOC_ENUM_FRAMESIZES is defined but the driver in
2058 * question doesn't actually support it yet */
2059 GST_DEBUG_OBJECT (v4l2camsrc, "No results for pixelformat %"
2060 GST_FOURCC_FORMAT " enumerating frame sizes, trying fallback",
2061 GST_FOURCC_ARGS (pixelformat));
2062 goto default_frame_sizes;
2066 GST_WARNING_OBJECT (v4l2camsrc,
2067 "Unknown frame sizeenum type for pixelformat %" GST_FOURCC_FORMAT
2068 ": %u", GST_FOURCC_ARGS (pixelformat), size.type);
2069 goto default_frame_sizes;
2072 #endif /* defined VIDIOC_ENUM_FRAMESIZES */
2074 default_frame_sizes:
2077 max_w = max_h = GST_CAMERA_SRC_MAX_SIZE;
2078 if (!gst_v4l2camsrc_get_nearest_size (v4l2camsrc, pixelformat,
2080 GST_WARNING_OBJECT (v4l2camsrc,
2081 "Could not probe minimum capture size for pixelformat %"
2082 GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2084 if (!gst_v4l2camsrc_get_nearest_size (v4l2camsrc, pixelformat,
2086 GST_WARNING_OBJECT (v4l2camsrc,
2087 "Could not probe maximum capture size for pixelformat %"
2088 GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2091 tmp = gst_structure_copy (template);
2092 gst_structure_set (tmp,
2093 "width", GST_TYPE_INT_RANGE, min_w, max_w,
2094 "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL);
2095 gst_caps_append_structure (ret, tmp);
2100 static void draw_corner_markers_nv12(unsigned char *buf, unsigned w, unsigned h)
2103 #define put_dot(x,y) buf[(x)+w*(y)] = (((x+y)&0x01)?0x00:0xff)
2105 for(j = 0; j < 4; ++j)
2106 for(i = 0; i < 8; ++i) {
2107 put_dot(i, j); put_dot(w-1-i, j);
2108 put_dot(j, i); put_dot(j, h-1-i);
2109 put_dot(i, h-1-j); put_dot(w-1-i, h-1-j);
2110 put_dot(w-1-j, i); put_dot(w-1-j, h-1-i);
2115 /* Crop to upper left corner of NV12 frame. */
2116 static gboolean crop_buffer_inplace_nv12(unsigned char *buf, unsigned in_w, unsigned in_h,
2117 unsigned out_w, unsigned out_h)
2120 unsigned char *in, *out;
2122 if(in_w < out_w || in_h < out_h
2123 || in_w % 4 || out_w % 4
2124 || in_h % 4 || out_h % 4)
2127 in = buf; out = buf;
2128 for(rows = 0; rows < out_h; ++rows) {
2129 memmove(out, in, out_w);
2133 in = buf + in_w * in_h;
2134 for(rows = 0; rows < out_h / 2; ++rows) {
2135 memmove(out, in, out_w);
2144 * gst_v4l2camsrc_libmfld_grab_hq_frame:
2145 * @v4l2camsrc: #GstMFLDV4l2CamSrc object
2146 * @buf: Pointer to v4l2_buffer where to place the image frame
2148 * Grab a High-Quality image by using libmfldcam.
2150 * Returns: TRUE if capture succeeds, FALSE otherwise
2153 gst_v4l2camsrc_libmfld_grab_hq_frame (GstMFLDV4l2CamSrc * v4l2camsrc,
2154 struct v4l2_buffer * buffer)
2158 struct cam_capture_settings st;
2160 st.mmap = v4l2camsrc->use_mmap;
2161 st.ae_awb_af = v4l2camsrc->ae_awb_af_enabled;
2162 st.dump_raw = v4l2camsrc->dump_raw;
2163 st.raw_output_size = v4l2camsrc->raw_output_size;
2164 st.dump_image = v4l2camsrc->dump_image;
2166 err = cam_capture_frames (v4l2camsrc->video_fd, buffer, &st);
2167 if (v4l2camsrc->ae_awb_af_enabled)
2168 mfldcam_3a_start ();
2169 ret = (err == CAM_ERR_NONE);
2174 /******************************************************
2175 * gst_v4l2camsrc_grab_frame ():
2176 * grab a frame for capturing
2177 * return value: GST_FLOW_OK, GST_FLOW_WRONG_STATE or GST_FLOW_ERROR
2178 ******************************************************/
2180 gst_v4l2camsrc_grab_frame (GstCameraSrc * camsrc, GstBuffer ** buf,
2181 GstCameraCapturePhase phase)
2183 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2185 #define NUM_TRIALS 5000
2186 struct v4l2_buffer buffer;
2187 gint32 trials = NUM_TRIALS;
2188 GstBuffer *pool_buffer;
2189 gboolean need_copy = v4l2camsrc->use_copy;
2190 gboolean variable_frame_size = FALSE; /* FIXME if we ever support JPEG etc */
2195 /* wait if all buffers are DQBuf */
2196 g_mutex_lock (v4l2camsrc->device_mutex);
2197 gst_v4l2_buffer_pool_update (v4l2camsrc->pool, v4l2camsrc, v4l2camsrc->num_buffers);
2198 g_mutex_unlock (v4l2camsrc->device_mutex);
2200 memset (&buffer, 0x00, sizeof (buffer));
2201 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2203 if (v4l2camsrc->use_mmap)
2204 buffer.memory = V4L2_MEMORY_MMAP;
2206 buffer.memory = V4L2_MEMORY_USERPTR;
2208 if (phase == GST_CAMERA_CAPTURE) {
2209 gst_camerasrc_send_capture_start_message (camsrc);
2213 ret = gst_poll_wait (v4l2camsrc->poll, V4L2CAMSRC_POLL_TIMEOUT);
2214 if (G_UNLIKELY (ret < 0)) {
2217 if (errno != EAGAIN && errno != EINTR)
2221 if (G_UNLIKELY (ret == 0)) {
2224 g_mutex_lock (v4l2camsrc->device_mutex);
2225 ret = gst_v4l2camsrc_libmfld_grab_hq_frame (v4l2camsrc, &buffer);
2226 g_mutex_unlock (v4l2camsrc->device_mutex);
2231 GST_WARNING_OBJECT (v4l2camsrc,
2232 "problem grabbing frame %d (ix=%d), trials=%d, pool-ct=%d, buf.flags=%d",
2233 buffer.sequence, buffer.index, trials,
2234 GST_MINI_OBJECT_REFCOUNT (v4l2camsrc->pool), buffer.flags);
2236 /* if the sync() got interrupted, we can retry */
2239 GST_WARNING_OBJECT (v4l2camsrc,
2240 "Non-blocking I/O has been selected using O_NONBLOCK and"
2241 " no buffer was in the outgoing queue. device %s",
2242 v4l2camsrc->videodev);
2249 GST_INFO_OBJECT (v4l2camsrc,
2250 "VIDIOC_DQBUF failed due to an internal error."
2251 " Can also indicate temporary problems like signal loss."
2252 " Note the driver might dequeue an (empty) buffer despite"
2253 " returning an error, or even stop capturing."
2254 " device %s", v4l2camsrc->videodev);
2255 /* have we de-queued a buffer ? */
2256 if (!(buffer.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
2258 if ((buffer.index >= 0) && (buffer.index < v4l2camsrc->breq.count)) {
2259 GST_DEBUG_OBJECT (v4l2camsrc, "reenqueing buffer (ix=%ld)", buffer.index);
2260 gst_v4l2camsrc_queue_frame (v4l2camsrc, buffer.index);
2264 GST_DEBUG_OBJECT (v4l2camsrc, "reenqueing buffer");
2265 /* FIXME: this is not a good idea, as drivers usualy return the buffer
2266 * with index-number set to 0, thus the re-enque will fail unless it
2267 * was incidentialy 0.
2268 * We could try to re-enque all buffers without handling the ioctl
2272 if (ioctl (v4l2camsrc->video_fd, VIDIOC_QBUF, &buffer) < 0) {
2280 GST_WARNING_OBJECT (v4l2camsrc,
2281 "could not sync on a buffer on device %s", v4l2camsrc->videodev);
2284 GST_WARNING_OBJECT (v4l2camsrc,
2285 "Grabbing frame got interrupted on %s. No expected reason.",
2286 v4l2camsrc->videodev);
2290 /* check nr. of attempts to capture */
2291 if (--trials == -1) {
2292 goto too_many_trials;
2294 memset (&buffer, 0x00, sizeof (buffer));
2295 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2296 if (v4l2camsrc->use_mmap)
2297 buffer.memory = V4L2_MEMORY_MMAP;
2299 buffer.memory = V4L2_MEMORY_USERPTR;
2303 if (phase == GST_CAMERA_CAPTURE) {
2304 gst_camerasrc_send_capture_stop_message (camsrc);
2306 /* Send the CAF status message */
2307 GstCameraFocusStatus focus_status;
2309 lret = gst_v4l2camsrc_check_focus_status(v4l2camsrc, &focus_status, FALSE);
2311 GST_LOG_OBJECT (v4l2camsrc, "CAF status: %d", focus_status.status);
2312 if (focus_status.status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS )
2313 gst_camerasrc_send_af_status(GST_CAMERA_SRC (v4l2camsrc) ,CAMERASRC_AUTO_FOCUS_RESULT_FOCUSED);
2314 else if (focus_status.status == GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL )
2315 gst_camerasrc_send_af_status(GST_CAMERA_SRC (v4l2camsrc) ,CAMERASRC_AUTO_FOCUS_RESULT_FAILED);
2317 GST_WARNING_OBJECT (v4l2camsrc, "CAF status erronous: %d send as failed", focus_status.status);
2318 gst_camerasrc_send_af_status(GST_CAMERA_SRC (v4l2camsrc) ,CAMERASRC_AUTO_FOCUS_RESULT_FAILED);
2324 g_mutex_lock (v4l2camsrc->pool->lock);
2326 index = buffer.index;
2328 /* get our GstBuffer with that index from the pool, if the buffer is
2329 * in use (NULL) we have a serious problem (should only be possible in mmap
2331 pool_buffer = GST_BUFFER (v4l2camsrc->pool->buffers[index]);
2333 if (G_UNLIKELY (pool_buffer == NULL))
2336 GST_LOG_OBJECT (v4l2camsrc, "grabbed buffer %p at index %d (refct = %d)",
2337 pool_buffer, index, GST_MINI_OBJECT_REFCOUNT (pool_buffer));
2339 /* ref the buffer and requeue, when if becomes writable again */
2340 v4l2camsrc->pool->buffers[index] = NULL;
2341 v4l2camsrc->pool->num_live_buffers++;
2342 v4l2camsrc->pool->queued[index] = 0;
2344 /* SW workaround for ISP padding. */
2346 if(v4l2camsrc->expected_capture_w < 320 && (v4l2camsrc->expected_capture_w % 32 != 0)
2347 && v4l2camsrc->expected_capture_fourcc == V4L2_PIX_FMT_NV12
2348 && !v4l2camsrc->disable_low_res_crop) {
2350 real_w = (v4l2camsrc->expected_capture_w & ~31) + 32;
2352 GST_LOG_OBJECT(v4l2camsrc, "Downscaling padded buffer with cropping (%u,%u) -> (%u,%u)",
2353 real_w, v4l2camsrc->expected_capture_h, v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h);
2355 if(!crop_buffer_inplace_nv12(GST_BUFFER_DATA(pool_buffer),
2356 real_w, v4l2camsrc->expected_capture_h,
2357 v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h)) {
2358 GST_ERROR_OBJECT(v4l2camsrc,"Software crop failed");
2362 if(v4l2camsrc->draw_corner_markers)
2363 draw_corner_markers_nv12(GST_BUFFER_DATA(pool_buffer),
2364 v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h);
2366 g_mutex_unlock (v4l2camsrc->pool->lock);
2368 /* this can change at every frame, esp. with jpeg */
2369 if(variable_frame_size)
2370 GST_BUFFER_SIZE (pool_buffer) = buffer.bytesused;
2372 GST_BUFFER_SIZE (pool_buffer) = v4l2camsrc->frame_byte_size;
2374 GST_BUFFER_OFFSET (pool_buffer) = v4l2camsrc->offset++;
2375 GST_BUFFER_OFFSET_END (pool_buffer) = v4l2camsrc->offset;
2377 /* timestamps, LOCK to get clock and base time. */
2380 GstClockTime timestamp;
2382 GST_OBJECT_LOCK (v4l2camsrc);
2383 if ((clock = GST_ELEMENT_CLOCK (v4l2camsrc))) {
2384 /* we have a clock, get base time and ref clock */
2385 timestamp = GST_ELEMENT (v4l2camsrc)->base_time;
2386 gst_object_ref (clock);
2388 /* no clock, can't set timestamps */
2389 timestamp = GST_CLOCK_TIME_NONE;
2391 GST_OBJECT_UNLOCK (v4l2camsrc);
2394 GstClockTime latency;
2396 /* the time now is the time of the clock minus the base time */
2397 timestamp = gst_clock_get_time (clock) - timestamp;
2398 gst_object_unref (clock);
2401 gst_util_uint64_scale_int (GST_SECOND, camsrc->fps_d, camsrc->fps_n);
2403 if (timestamp > latency)
2404 timestamp -= latency;
2407 GST_BUFFER_DURATION (pool_buffer) = latency;
2409 /* activate settings for next frame (Code from v4l2src) */
2410 if (GST_CLOCK_TIME_IS_VALID (camsrc->duration)) {
2411 v4l2camsrc->ctrl_time += camsrc->duration;
2413 v4l2camsrc->ctrl_time = timestamp;
2415 gst_object_sync_values (G_OBJECT (camsrc), v4l2camsrc->ctrl_time);
2417 /* FIXME: use the timestamp from the buffer itself! */
2418 GST_BUFFER_TIMESTAMP (pool_buffer) = timestamp;
2421 if (G_UNLIKELY (need_copy)) {
2422 GST_DEBUG_OBJECT (v4l2camsrc, "copying buffer");
2423 *buf = gst_buffer_copy (pool_buffer);
2424 GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY);
2425 /* this will requeue */
2426 gst_buffer_unref (pool_buffer);
2428 if (v4l2camsrc->pool->is_vaapi_sharing)
2429 GST_BUFFER_DATA(pool_buffer) = (GST_V4L2CAMSRC_BUFFER(pool_buffer))->gbuffer;
2433 GST_LOG_OBJECT (v4l2camsrc,
2434 "grabbed frame %d (ix=%d), flags %08x, pool-ct=%d", buffer.sequence,
2435 buffer.index, buffer.flags, v4l2camsrc->pool->num_live_buffers);
2442 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ, (NULL),
2443 ("select error %d: %s (%d)", ret, g_strerror (errno), errno));
2444 return GST_FLOW_ERROR;
2448 GST_DEBUG ("stop called");
2449 return GST_FLOW_WRONG_STATE;
2453 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2454 ("Failed trying to get video frames from device '%s'.",
2455 v4l2camsrc->videodev),
2456 ("The buffer type is not supported, or the index is out of bounds,"
2457 " or no buffers have been allocated yet, or the userptr"
2458 " or length are invalid. device %s", v4l2camsrc->videodev));
2459 return GST_FLOW_ERROR;
2463 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2464 ("Failed trying to get video frames from device '%s'. Not enough memory.",
2465 v4l2camsrc->videodev), ("insufficient memory to enqueue a user "
2466 "pointer buffer. device %s.", v4l2camsrc->videodev));
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 ("Failed after %d tries. device %s. system error: %s",
2475 NUM_TRIALS, v4l2camsrc->videodev, g_strerror (errno)));
2476 return GST_FLOW_ERROR;
2480 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2481 ("Failed trying to get video frames from device '%s'.",
2482 v4l2camsrc->videodev),
2483 ("No free buffers found in the pool at index %d.", index));
2484 g_mutex_unlock (v4l2camsrc->pool->lock);
2485 return GST_FLOW_ERROR;
2490 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, WRITE,
2491 ("Could not exchange data with device '%s'.",
2492 v4l2camsrc->videodev),
2493 ("Error queueing buffer on device %s. system error: %s",
2494 v4l2camsrc->videodev, g_strerror (errno)));
2495 return GST_FLOW_ERROR;
2500 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2501 ("Timeout when trying to get video frames from device '%s'.",
2502 v4l2camsrc->videodev), NULL);
2503 return GST_FLOW_ERROR;
2508 /******************************************************
2509 * gst_v4l2camsrc_set_capture():
2510 * set capture parameters for certain operation mode
2511 * return value: TRUE on success, FALSE on error
2512 ******************************************************/
2514 gst_v4l2camsrc_set_capture (GstCameraSrc * camsrc, GstOperationMode mode,
2515 gboolean try_only, guint32 * pixelformat, guint * width, guint * height,
2516 guint * fps_n, guint * fps_d)
2518 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2519 cam_err_t err = CAM_ERR_NONE;
2520 gboolean ret = TRUE;
2522 GST_DEBUG_OBJECT (v4l2camsrc, "mode = %d, try_only = %d", mode, try_only);
2524 v4l2camsrc->expected_capture_w = *width;
2525 v4l2camsrc->expected_capture_h = *height;
2526 v4l2camsrc->expected_capture_fourcc = *pixelformat;
2528 if (mode == GST_PHOTOGRAPHY_OPERATION_MODE_PREVIEW) {
2530 } else if (mode == GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE) {
2531 GST_DEBUG_OBJECT (v4l2camsrc, "Image capture: %dx%d, format "
2532 "%" GST_FOURCC_FORMAT, *width, *height, GST_FOURCC_ARGS (*pixelformat));
2535 /* Round width & height down to be dividable by 4 */
2536 *width = (*width) & ~3;
2537 *height = (*height) & ~3;
2540 ret = gst_v4l2camsrc_configure_device (v4l2camsrc, pixelformat,
2541 width, height, fps_n, fps_d);
2543 v4l2camsrc->tmp_num_buffers = v4l2camsrc->num_buffers;
2544 v4l2camsrc->num_buffers = 1;
2546 v4l2camsrc->capture_w = *width;
2547 v4l2camsrc->capture_h = *height;
2548 if (fps_n && fps_d) {
2549 v4l2camsrc->capture_fps_n = *fps_n;
2550 v4l2camsrc->capture_fps_d = *fps_d;
2552 v4l2camsrc->capture_fourcc = *pixelformat;
2555 /* VIEWFINDER mode */
2556 /* FIXME: handle try_only mode */
2558 v4l2camsrc->num_buffers = v4l2camsrc->tmp_num_buffers;
2560 ret = gst_v4l2camsrc_configure_device (v4l2camsrc, pixelformat,
2561 width, height, fps_n, fps_d);
2563 v4l2camsrc->vf_w = *width;
2564 v4l2camsrc->vf_h = *height;
2565 v4l2camsrc->vf_fourcc = *pixelformat;
2566 if (fps_n && fps_d) {
2567 v4l2camsrc->vf_fps_n = *fps_n;
2568 v4l2camsrc->vf_fps_d = *fps_d;
2571 if (err != CAM_ERR_NONE)
2577 /******************************************************
2578 * gst_v4l2camsrc_capture_start():
2579 * Start capturing frames from the device
2580 * return value: TRUE on success, FALSE on error
2581 ******************************************************/
2583 gst_v4l2camsrc_capture_start (GstCameraSrc * camsrc, GstCaps * caps)
2585 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2587 gint fd = v4l2camsrc->video_fd;
2588 struct v4l2_requestbuffers breq;
2589 gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2590 cam_capture_mode_t cam_mode;
2593 v4l2camsrc->offset = 0;
2595 /* activate settings for first frame */
2596 v4l2camsrc->ctrl_time = 0;
2597 gst_object_sync_values (G_OBJECT (camsrc), v4l2camsrc->ctrl_time);
2599 memset (&breq, 0, sizeof (struct v4l2_requestbuffers));
2601 GST_DEBUG_OBJECT (v4l2camsrc, "initializing the capture system");
2603 GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
2604 GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
2606 if (!(v4l2camsrc->vcap.capabilities & V4L2_CAP_STREAMING))
2607 goto no_capture_method;
2609 GST_DEBUG_OBJECT (v4l2camsrc, "STREAMING, requesting %d CAPTURE buffers",
2610 v4l2camsrc->num_buffers);
2612 err = cam_driver_set_mipi_interrupt(fd,1);
2613 if (err != CAM_ERR_NONE)
2614 GST_DEBUG_OBJECT (v4l2camsrc, "MIPI interrupt enable FAILED !");
2616 breq.count = v4l2camsrc->num_buffers;
2617 breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2619 if(v4l2camsrc->use_mmap && GST_CAPS_IS_SIMPLE(caps)) {
2620 GstStructure *st = gst_caps_get_structure(caps, 0);
2621 if(g_str_has_prefix(gst_structure_get_name(st), "video/x-vaapi-sharing")) {
2622 v4l2camsrc->use_mmap = FALSE;
2623 GST_WARNING_OBJECT(v4l2camsrc, "mmap is not supported with VA shared buffer, turning off");
2627 if (v4l2camsrc->use_mmap)
2628 breq.memory = V4L2_MEMORY_MMAP;
2630 breq.memory = V4L2_MEMORY_USERPTR;
2632 if (ioctl (fd, VIDIOC_REQBUFS, &breq) < 0)
2633 goto reqbufs_failed;
2635 GST_LOG_OBJECT (v4l2camsrc, " count: %u", breq.count);
2636 GST_LOG_OBJECT (v4l2camsrc, " type: %d", breq.type);
2637 GST_LOG_OBJECT (v4l2camsrc, " memory: %d", breq.memory);
2639 if (breq.count < GST_V4L2CAMSRC_MIN_BUFFERS)
2642 if (v4l2camsrc->num_buffers != breq.count) {
2643 GST_WARNING_OBJECT (v4l2camsrc, "using %u buffers instead", breq.count);
2644 v4l2camsrc->num_buffers = breq.count;
2645 g_object_notify (G_OBJECT (v4l2camsrc), "queue-size");
2648 /* Map the buffers */
2649 GST_LOG_OBJECT (v4l2camsrc, "initiating buffer pool");
2651 if (!(v4l2camsrc->pool =
2652 gst_v4l2camsrc_buffer_pool_new (v4l2camsrc, fd,
2653 v4l2camsrc->num_buffers, caps,
2654 v4l2camsrc->use_mmap, FALSE,
2655 v4l2camsrc->frame_byte_size, GST_BASE_SRC_PAD(v4l2camsrc))))
2656 goto buffer_pool_new_failed;
2658 GST_INFO_OBJECT (v4l2camsrc, "capturing buffers");
2660 GST_V4L2CAMSRC_SET_ACTIVE (v4l2camsrc);
2662 GST_DEBUG_OBJECT (v4l2camsrc, "starting the capturing");
2663 GST_V4L2CAMSRC_CHECK_ACTIVE (v4l2camsrc);
2665 if (!gst_v4l2camsrc_buffer_pool_activate (v4l2camsrc->pool, v4l2camsrc))
2666 goto pool_activate_failed;
2668 if (ioctl (fd, VIDIOC_STREAMON, &type) < 0)
2669 goto streamon_failed;
2671 v4l2camsrc->is_active = TRUE;
2672 GST_DEBUG_OBJECT (v4l2camsrc, "STREAMON called");
2674 /* Update the focus only when the Sensor is stream on */
2675 if (v4l2camsrc->focus_updated) {
2676 cam_driver_set_focus_posi(v4l2camsrc->video_fd, v4l2camsrc->focus_posi);
2677 v4l2camsrc->focus_updated = FALSE;
2680 if (v4l2camsrc->zoom_updated) {
2681 gst_v4l2camsrc_libmfldcam_set_zoom(v4l2camsrc, v4l2camsrc->zoom_factor);
2682 v4l2camsrc->zoom_updated = FALSE;
2685 cam_mode = find_item (gst_v4l2camsrc_capture_map,v4l2camsrc->capture_mode);
2686 cam_set_capture_mode (v4l2camsrc->video_fd, cam_mode);
2693 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2694 ("Could not get buffers from device '%s'.",
2695 v4l2camsrc->videodev),
2696 ("error requesting %d buffers: %s",
2697 v4l2camsrc->num_buffers, g_strerror (errno)));
2698 cam_driver_set_mipi_interrupt(fd, 0);
2703 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2704 ("Could not get enough buffers from device '%s'.",
2705 v4l2camsrc->videodev),
2706 ("we received %d from device '%s', we want at least %d",
2707 breq.count, v4l2camsrc->videodev, GST_V4L2CAMSRC_MIN_BUFFERS));
2708 cam_driver_set_mipi_interrupt(fd, 0);
2711 buffer_pool_new_failed:
2713 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2714 ("Could not map buffers from device '%s'",
2715 v4l2camsrc->videodev),
2716 ("Failed to create buffer pool: %s", g_strerror (errno)));
2717 cam_driver_set_mipi_interrupt(fd, 0);
2722 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2723 ("The driver of device '%s' does not support streaming. ",
2724 v4l2camsrc->videodev), (NULL));
2725 cam_driver_set_mipi_interrupt(fd, 0);
2728 pool_activate_failed:
2730 /* already errored */
2731 cam_driver_set_mipi_interrupt(fd, 0);
2736 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, OPEN_READ,
2737 ("Error starting streaming capture from device '%s'.",
2738 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
2739 cam_driver_set_mipi_interrupt(fd, 0);
2744 /******************************************************
2745 * gst_v4l2camsrc_capture_stop():
2746 * stop streaming capture
2747 * return value: TRUE on success, FALSE on error
2748 ******************************************************/
2750 gst_v4l2camsrc_capture_stop (GstCameraSrc * camsrc)
2752 GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2753 struct v4l2_requestbuffers breq;
2754 gint fd = v4l2camsrc->video_fd;
2757 gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2759 memset(&breq, 0, sizeof(struct v4l2_requestbuffers));
2761 GST_DEBUG_OBJECT (v4l2camsrc, "stopping capturing");
2763 if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc)) {
2766 if (!GST_V4L2CAMSRC_IS_ACTIVE (v4l2camsrc)) {
2770 err = cam_driver_set_mipi_interrupt(fd,0);
2771 if (err != CAM_ERR_NONE)
2772 GST_DEBUG_OBJECT (v4l2camsrc, "MIPI interrupt disable FAILED !");
2774 /* we actually need to sync on all queued buffers but not
2775 * on the non-queued ones */
2776 if (ioctl (v4l2camsrc->video_fd, VIDIOC_STREAMOFF, &type) < 0)
2777 goto streamoff_failed;
2779 GST_DEBUG_OBJECT (v4l2camsrc, "STREAMOFF called");
2782 breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2783 if(v4l2camsrc->use_mmap)
2784 breq.memory = V4L2_MEMORY_MMAP;
2786 breq.memory = V4L2_MEMORY_USERPTR;
2788 GST_DEBUG_OBJECT (v4l2camsrc, "REQUEST 0 to finalize buffer");
2790 if(ioctl(v4l2camsrc->video_fd, VIDIOC_REQBUFS, &breq) < 0)
2791 GST_DEBUG_OBJECT (v4l2camsrc, "Failed to REQUEST 0 to finalize buffer");
2794 if (v4l2camsrc->pool) {
2795 gst_v4l2camsrc_buffer_pool_destroy (v4l2camsrc->pool, v4l2camsrc);
2796 v4l2camsrc->pool = NULL;
2799 GST_V4L2CAMSRC_SET_INACTIVE (v4l2camsrc);
2800 v4l2camsrc->is_active = FALSE;
2808 GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, CLOSE,
2809 ("Error stopping streaming capture from device '%s'.",
2810 v4l2camsrc->videodev), GST_ERROR_SYSTEM);
2818 gst_v4l2camsrc_get_nearest_size (GstMFLDV4l2CamSrc * v4l2camsrc,
2819 guint32 pixelformat, gint * width, gint * height)
2821 struct v4l2_format fmt;
2825 g_return_val_if_fail (width != NULL, FALSE);
2826 g_return_val_if_fail (height != NULL, FALSE);
2828 GST_LOG_OBJECT (v4l2camsrc,
2829 "getting nearest size to %dx%d with format %" GST_FOURCC_FORMAT,
2830 *width, *height, GST_FOURCC_ARGS (pixelformat));
2832 fd = v4l2camsrc->video_fd;
2834 /* get size delimiters */
2835 memset (&fmt, 0, sizeof (fmt));
2836 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2837 fmt.fmt.pix.width = *width;
2838 fmt.fmt.pix.height = *height;
2839 fmt.fmt.pix.pixelformat = pixelformat;
2840 fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
2842 /* FIXME: Disable TRY_FMT check, driver is not returning anything useful yet */
2844 r = ioctl (fd, VIDIOC_TRY_FMT, &fmt);
2845 if (r < 0 && errno == EINVAL) {
2846 /* try again with progressive video */
2847 fmt.fmt.pix.width = *width;
2848 fmt.fmt.pix.height = *height;
2849 fmt.fmt.pix.pixelformat = pixelformat;
2850 fmt.fmt.pix.field = V4L2_FIELD_NONE;
2851 r = ioctl (fd, VIDIOC_TRY_FMT, &fmt);
2855 /* The driver might not implement TRY_FMT, in which case we will try
2857 if (errno != ENOTTY)
2861 /* Only try S_FMT if we're not actively capturing yet, which we shouldn't
2862 be, because we're still probing */
2863 if (GST_V4L2CAMSRC_IS_ACTIVE (v4l2camsrc))
2867 GST_LOG_OBJECT (v4l2camsrc,
2868 "Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
2871 fmt.fmt.pix.width = *width;
2872 fmt.fmt.pix.height = *height;
2874 r = ioctl (fd, VIDIOC_S_FMT, &fmt);
2875 if (r < 0 && errno == EINVAL) {
2876 /* try again with progressive video */
2877 fmt.fmt.pix.width = *width;
2878 fmt.fmt.pix.height = *height;
2879 fmt.fmt.pix.pixelformat = pixelformat;
2880 fmt.fmt.pix.field = V4L2_FIELD_NONE;
2881 r = ioctl (fd, VIDIOC_S_FMT, &fmt);
2890 GST_LOG_OBJECT (v4l2camsrc,
2891 "got nearest size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
2893 *width = fmt.fmt.pix.width;
2894 *height = fmt.fmt.pix.height;
2900 /******************************************************
2901 * gst_v4l2camsrc_set_crop():
2902 * set cropping bounds
2903 * return value: TRUE on success, FALSE on error
2904 ******************************************************/
2906 gst_v4l2camsrc_set_crop (GstMFLDV4l2CamSrc * v4l2camsrc,
2907 gint x, gint y, gint w, gint h)
2909 gboolean ret = FALSE;
2910 struct v4l2_crop scrop;
2911 struct v4l2_crop gcrop;
2912 gint cx, cy, cw, ch;
2915 fd = v4l2camsrc->video_fd;
2916 cx = v4l2camsrc->vcrop.bounds.left;
2917 cy = v4l2camsrc->vcrop.bounds.top;
2918 cw = v4l2camsrc->vcrop.bounds.width;
2919 ch = v4l2camsrc->vcrop.bounds.height;
2921 memset (&scrop, 0, sizeof (scrop));
2922 scrop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2924 /* Make sure that cropping area stays inside the crop boundaries */
2925 scrop.c.left = x > cx ? x : cx;
2926 scrop.c.top = y > cy ? y : cy;
2927 scrop.c.width = (scrop.c.left + w) < (cx + cw) ? w : cx + cw - scrop.c.left;
2928 scrop.c.height = (scrop.c.top + h) < (cy + ch) ? h : cy + ch - scrop.c.top;
2930 GST_DEBUG_OBJECT (v4l2camsrc,
2931 "Crop request: left = %d, top = %d, w = %d, h = %d",
2932 scrop.c.left, scrop.c.top, scrop.c.width, scrop.c.height);
2934 g_mutex_lock (v4l2camsrc->device_mutex);
2936 if (-1 == ioctl (fd, VIDIOC_S_CROP, &scrop) && errno != EINVAL) {
2940 if (-1 == ioctl (fd, VIDIOC_G_CROP, &gcrop)) {
2944 g_mutex_unlock (v4l2camsrc->device_mutex);
2946 GST_DEBUG_OBJECT (v4l2camsrc,
2947 "Crop selected: left = %d, top = %d, w = %d, h = %d",
2948 gcrop.c.left, gcrop.c.top, gcrop.c.width, gcrop.c.height);
2951 if (gcrop.c.left != scrop.c.left || gcrop.c.top != scrop.c.top ||
2952 gcrop.c.width != scrop.c.width || gcrop.c.height != scrop.c.height) {
2953 goto crop_not_supported;
2965 g_mutex_unlock (v4l2camsrc->device_mutex);
2966 GST_DEBUG_OBJECT (v4l2camsrc, "VIDIOC_S_CROP not supported");
2970 g_mutex_unlock (v4l2camsrc->device_mutex);
2971 GST_DEBUG_OBJECT (v4l2camsrc, "VIDIOC_G_CROP not supported");
2976 g_mutex_unlock (v4l2camsrc->device_mutex);
2977 GST_DEBUG_OBJECT (v4l2camsrc, "Given crop value not accepted");
2983 /******************************************************
2984 * gst_v4l2camsrc_update_cropping():
2985 * update cropping area according to width, height and zoom factors.
2986 * return value: TRUE on success, FALSE on error
2987 ******************************************************/
2989 gst_v4l2camsrc_update_cropping (GstMFLDV4l2CamSrc * v4l2camsrc, gint width,
2990 gint height, gfloat zoom)
2992 gfloat sensor_ar, reso_ar;
2993 gint crop_x, crop_y, crop_w, crop_h;
2995 g_return_val_if_fail (width != 0, FALSE);
2996 g_return_val_if_fail (height != 0, FALSE);
2997 g_return_val_if_fail (zoom != 0, FALSE);
2999 if (zoom < 1.0 || zoom > v4l2camsrc->max_zoom_factor) {
3000 GST_DEBUG_OBJECT (v4l2camsrc, "invalid zoom = %.2f", zoom);
3003 if (!v4l2camsrc->crop_supported) {
3004 GST_DEBUG_OBJECT (v4l2camsrc, "crop not supported");
3008 sensor_ar = v4l2camsrc->vcrop.defrect.width /
3009 v4l2camsrc->vcrop.defrect.height;
3010 reso_ar = width / height;
3012 if (sensor_ar > reso_ar) {
3013 crop_w = (width * v4l2camsrc->vcrop.defrect.height / height) / zoom;
3014 crop_h = MAX (v4l2camsrc->vcrop.defrect.height, height) / zoom;
3016 crop_w = MAX (v4l2camsrc->vcrop.defrect.width, width) / zoom;
3017 crop_h = (height * v4l2camsrc->vcrop.defrect.width / width) / zoom;
3020 crop_x = ABS ((v4l2camsrc->vcrop.defrect.width - crop_w) / 2);
3021 crop_y = ABS ((v4l2camsrc->vcrop.defrect.height - crop_h) / 2);
3023 GST_LOG_OBJECT (v4l2camsrc, "set cropping: x: %d, y: %d, w: %d, h: %d",
3024 crop_x, crop_y, crop_w, crop_h);
3026 return gst_v4l2camsrc_set_crop (v4l2camsrc, crop_x, crop_y, crop_w, crop_h);
3029 /***************************************************************************
3030 * New MFLD Camera Code ****************************************************
3031 * *************************************************************************/
3033 /* These map tables help to adapt the general photography interface to
3034 * different device implementations.
3036 * Table index = Enumeration value from GstPhotography
3037 * Table value = Device/Implementation -specific setting value
3040 static const gint gst_v4l2camsrc_scene_map[] = {
3041 999, /* GST_PHOTOGRAPHY_SCENE_MODE_MANUAL */
3042 CAM_GENERAL_SCENE_MODE_CLOSEUP,
3043 CAM_GENERAL_SCENE_MODE_PORTRAIT,
3044 CAM_GENERAL_SCENE_MODE_LANDSCAPE,
3045 CAM_GENERAL_SCENE_MODE_SPORT,
3046 CAM_GENERAL_SCENE_MODE_NIGHT,
3047 CAM_GENERAL_SCENE_MODE_AUTO,
3051 static const gint gst_v4l2camsrc_flash_map[] = {
3052 CAM_LIGHT_FLASH_MODE_AUTO,
3053 CAM_LIGHT_FLASH_MODE_OFF,
3054 CAM_LIGHT_FLASH_MODE_ON,
3055 CAM_LIGHT_FLASH_MODE_FILL_IN,
3056 CAM_LIGHT_FLASH_MODE_RED_EYE,
3060 static const gint gst_v4l2camsrc_focus_map[] = {
3061 CAM_FOCUS_MODE_AUTO, /* AF_MODE_NONE = 0 */
3062 CAM_FOCUS_MODE_HYPERFOCAL, /* AF_MODE_PAN */
3063 CAM_FOCUS_MODE_TOUCH_AUTO, /* AF_MODE_AUTO */
3064 CAM_FOCUS_MODE_MANUAL, /* AF_MODE_MANUAL */
3065 CAM_FOCUS_MODE_TOUCH_AUTO, /* AF_TOUCH_AUTO */
3066 CAM_FOCUS_MODE_CONTINUOUS /* AF_CONTINUOUS */
3070 static const gint gst_v4l2camsrc_flicker_map[] = {
3071 CAM_GENERAL_FLICKER_REDUCTION_MODE_OFF, /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF = 0 */
3072 CAM_GENERAL_FLICKER_REDUCTION_MODE_50HZ, /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ */
3073 CAM_GENERAL_FLICKER_REDUCTION_MODE_60HZ, /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_60HZ */
3074 CAM_GENERAL_FLICKER_REDUCTION_MODE_AUTO, /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO */
3078 static const gint gst_v4l2camsrc_iso_map[][2] = {
3079 {CAM_EXPOSURE_ISO_VALUE_1600, 1600},
3080 {CAM_EXPOSURE_ISO_VALUE_800, 800},
3081 {CAM_EXPOSURE_ISO_VALUE_400, 400},
3082 {CAM_EXPOSURE_ISO_VALUE_200, 200},
3083 {CAM_EXPOSURE_ISO_VALUE_100, 100},
3084 {CAM_EXPOSURE_ISO_VALUE_AUTO, 0}
3087 static const gint gst_v4l2camsrc_focus_status_map[][2] =
3089 { GST_PHOTOGRAPHY_FOCUS_STATUS_NONE, CAM_FOCUS_STATUS_IDLE },
3090 { GST_PHOTOGRAPHY_FOCUS_STATUS_RUNNING, CAM_FOCUS_STATUS_RUNNING },
3091 { GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS, CAM_FOCUS_STATUS_SUCCESS },
3092 { GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL, CAM_FOCUS_STATUS_FAIL },
3096 static const gchar *cameralib_error_map[] = {
3103 "CAM_ERR_DEPRECATED",
3104 "CAM_ERR_INVALID_STATE",
3113 static cam_exposure_iso_value_t
3114 gst_v4l2camsrc_libmfld_map_iso (guint iso)
3118 while (gst_v4l2camsrc_iso_map[i][1] != 0) {
3119 if (iso >= gst_v4l2camsrc_iso_map[i][1]) {
3125 return gst_v4l2camsrc_iso_map[i][1];
3133 gst_v4l2camsrc_libmfld_reverse_map_iso (cam_exposure_iso_value_t iso)
3137 while (gst_v4l2camsrc_iso_map[i][1] != 0) {
3138 if (iso == gst_v4l2camsrc_iso_map[i][0]) {
3144 return gst_v4l2camsrc_iso_map[i][1];
3147 static const gint gst_v4l2camsrc_shakerisk_map[] = {
3148 GST_PHOTOGRAPHY_SHAKE_RISK_LOW, /* CAM_EXPOSURE_SHAKE_RISK_LOW = 0 */
3149 GST_PHOTOGRAPHY_SHAKE_RISK_MEDIUM, /* CAM_EXPOSURE_SHAKE_RISK_MEDIUM */
3150 GST_PHOTOGRAPHY_SHAKE_RISK_HIGH, /* CAM_EXPOSURE_SHAKE_RISK_HIGH */
3154 * Return index of the item in the table.
3157 find_item (const gint table[], const gint item)
3161 while (table[i] != -1) {
3162 if (table[i] == item)
3170 gst_v4l2camsrc_read_settings (GstCameraSrc * camsrc,
3171 GstPhotoSettings * photoconf)
3173 GstMFLDV4l2CamSrc *v4l2camsrc;
3174 gint32 wbmode, effect, scene, flash, focus;
3176 gint32 ev, iso, aperture, exposure, noise_reduction;
3179 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3181 g_mutex_lock (v4l2camsrc->device_mutex);
3183 if (!v4l2camsrc->initialized) {
3184 GST_DEBUG ("Device not initialized");
3185 g_mutex_unlock (v4l2camsrc->device_mutex);
3189 GST_DEBUG ("Retrieving settings from camera");
3191 err = cam_feature_get (v4l2camsrc->video_fd, CAM_AWB_MODE, &wbmode);
3192 if (err != CAM_ERR_NONE) {
3193 GST_DEBUG ("CAM_AWB_MODE query failed: %s", cameralib_error_map[err]);
3198 cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE, &effect);
3199 if (err != CAM_ERR_NONE) {
3200 GST_DEBUG ("CAM_GENERAL_EFFECT_TYPE query failed: %s",
3201 cameralib_error_map[err]);
3205 err = cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_SCENE_MODE, &scene);
3206 if (err != CAM_ERR_NONE) {
3207 GST_DEBUG ("CAM_GENERAL_SCENE_MODE query failed: %s",
3208 cameralib_error_map[err]);
3212 err = cam_feature_get (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE, &flash);
3213 if (err != CAM_ERR_NONE) {
3214 GST_DEBUG ("CAM_LIGHT_FLASH_MODE query failed: %s",
3215 cameralib_error_map[err]);
3219 err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION, &ev);
3220 if (err != CAM_ERR_NONE) {
3221 GST_DEBUG ("CAM_EXPOSURE_COMPENSATION query failed: %s",
3222 cameralib_error_map[err]);
3225 err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE, &iso);
3226 if (err != CAM_ERR_NONE) {
3227 GST_DEBUG ("CAM_EXPOSURE_ISO_VALUE query failed: %s",
3228 cameralib_error_map[err]);
3232 err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_APERTURE,
3234 if (err != CAM_ERR_NONE) {
3235 GST_DEBUG ("CAM_EXPOSURE_MANUAL_APERTURE query failed: %s",
3236 cameralib_error_map[err]);
3241 cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_TIME,
3243 if (err != CAM_ERR_NONE) {
3244 GST_DEBUG ("CAM_EXPOSURE_MANUAL_TIME query failed: %s",
3245 cameralib_error_map[err]);
3250 cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_FLICKER_REDUCTION_MODE,
3252 if (err != CAM_ERR_NONE) {
3253 GST_DEBUG ("CAM_GENERAL_FLICKER_REDUCTION_MODE query failed: %s",
3254 cameralib_error_map[err]);
3259 cam_feature_get (v4l2camsrc->video_fd, CAM_NOISE_REDUCTION_MODE,
3261 if (err != CAM_ERR_NONE) {
3262 GST_DEBUG ("CAM_NOISE_REDUCTION query failed: %s",
3263 cameralib_error_map[err]);
3267 photoconf->wb_mode = find_item (gst_v4l2camsrc_wb_map, wbmode);
3268 photoconf->tone_mode = find_item (gst_v4l2camsrc_effect_map, effect);
3269 photoconf->scene_mode = find_item (gst_v4l2camsrc_scene_map, scene);
3270 photoconf->flash_mode = find_item (gst_v4l2camsrc_flash_map, flash);
3271 photoconf->flicker_mode = find_item (gst_v4l2camsrc_flicker_map, flicker);
3273 photoconf->ev_compensation = (gfloat) ev;
3274 photoconf->iso_speed = gst_v4l2camsrc_libmfld_map_iso (iso);
3275 photoconf->aperture = aperture;
3276 photoconf->exposure = exposure;
3277 photoconf->noise_reduction = noise_reduction;
3279 GST_DEBUG ("Scene mode ext: %d, lib: %d", photoconf->scene_mode, scene);
3280 GST_DEBUG ("Focus mode ext: %d, lib: %d", photoconf->focus_mode, focus);
3281 GST_DEBUG ("Flash mode ext: %d, lib: %d", photoconf->flash_mode, flash);
3282 GST_DEBUG ("ISO: %d, EV_comp: %f (%d)", iso, photoconf->ev_compensation, ev);
3284 g_mutex_unlock (v4l2camsrc->device_mutex);
3291 g_mutex_unlock (v4l2camsrc->device_mutex);
3296 gst_v4l2camsrc_read_exif (GstCameraSrc * camsrc,
3297 GstCameraControlExifInfo *exif_info)
3299 GstMFLDV4l2CamSrc *v4l2camsrc;
3302 struct atomisp_makernote_info maker_note;
3305 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3308 if (!v4l2camsrc->initialized) {
3309 GST_DEBUG ("Device not initialized");
3312 buf = (unsigned char *)&maker_note;
3314 GST_DEBUG ("Retrieving makernote from atomisp");
3315 err = cam_get_makernote (v4l2camsrc->video_fd, buf, 0);
3321 exif_info->focal_len_numerator = maker_note.focal_length >> 16;
3322 exif_info->focal_len_denominator = maker_note.focal_length & 0xFFFF;
3323 /* Aperture value (f_num) */
3324 exif_info->aperture_f_num_numerator = maker_note.f_number_curr >> 16;
3325 exif_info->aperture_f_num_denominator = maker_note.f_number_curr & 0xFFFF;
3326 /* isp major, minor,patch level */
3327 exif_info->software_used = v4l2camsrc->vcap.version;
3328 exif_info->colorspace = 65535; /* Uncalibrated (=65535) */
3329 exif_info->metering_mode = 1; /* Average */
3330 cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE, &exif_info->iso);
3332 //* TODO complete exif info */
3333 exif_info->exposure_time_denominator = 0;
3334 exif_info->exposure_time_numerator = 0;
3335 cam_feature_get(v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_TIME, &exposure);
3336 exif_info->exposure_time_denominator = exposure & 0xFFFF;
3337 exif_info->exposure_time_numerator = exposure >>16;
3340 exif_info->shutter_speed_numerator = 0;
3341 exif_info->shutter_speed_denominator = 0;
3342 exif_info->brigtness_numerator = 0;
3343 exif_info->brightness_denominator = 0;
3344 exif_info->flash = cam_is_flash_used();
3345 GST_DEBUG ("Focal lenght numerator : %d", exif_info->focal_len_numerator);
3346 GST_DEBUG ("Focal lenght denominator : %d", exif_info->focal_len_denominator);
3347 GST_DEBUG ("F num numerator : %d", exif_info->aperture_f_num_numerator);
3348 GST_DEBUG ("F num denominator : %d", exif_info->aperture_f_num_denominator);
3349 GST_DEBUG ("Exposure numerator : %d", exif_info->exposure_time_numerator);
3350 GST_DEBUG ("Exposure denominator : %d", exif_info->exposure_time_denominator);
3352 GST_DEBUG ("flash used : %d", exif_info->flash);
3359 g_mutex_unlock (v4l2camsrc->device_mutex);
3365 gst_v4l2camsrc_set_flash_mode (GstCameraSrc * camsrc,
3368 GstMFLDV4l2CamSrc *v4l2camsrc;
3373 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3375 g_mutex_lock (v4l2camsrc->device_mutex);
3377 if (!v4l2camsrc->initialized) {
3378 GST_DEBUG ("Device not initialized");
3379 g_mutex_unlock (v4l2camsrc->device_mutex);
3384 case GST_CAMERA_STROBE_CAP_NONE:
3385 case GST_CAMERA_STROBE_CAP_OFF:
3386 flash = CAM_LIGHT_FLASH_MODE_OFF;
3388 case GST_CAMERA_STROBE_CAP_ON:
3389 flash = CAM_LIGHT_FLASH_MODE_ON;
3391 case GST_CAMERA_STROBE_CAP_AUTO:
3392 flash = CAM_LIGHT_FLASH_MODE_AUTO;
3394 case GST_CAMERA_STROBE_CAP_REDEYE:
3395 flash = CAM_LIGHT_FLASH_MODE_RED_EYE;
3398 flash = CAM_LIGHT_FLASH_MODE_OFF;
3402 GST_DEBUG_OBJECT (v4l2camsrc, "Set flash mode: %d",flash);
3403 err= cam_feature_set (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE,
3409 g_mutex_unlock (v4l2camsrc->device_mutex);
3416 g_mutex_unlock (v4l2camsrc->device_mutex);
3422 gst_v4l2camsrc_set_focus_state(GstCameraSrc *camsrc,
3423 gint mode, gint range)
3425 cam_err_t err = CAM_ERR_NONE;
3426 GST_DEBUG ("update focus mode and range");
3428 err = cam_set_focus_mode(gst_v4l2camsrc_focus_map[mode], range);
3429 return(err == CAM_ERR_NONE);
3434 gst_v4l2camsrc_write_settings (GstCameraSrc * camsrc,
3435 GstPhotoSettings * photoconf, gboolean scene_override)
3437 GstMFLDV4l2CamSrc *v4l2camsrc;
3438 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3439 GST_DEBUG ("Write settings to libmfldcamd");
3441 g_mutex_lock (v4l2camsrc->device_mutex);
3443 if (!v4l2camsrc->initialized) {
3444 g_mutex_unlock (v4l2camsrc->device_mutex);
3445 GST_DEBUG ("Device not initialized");
3449 if (scene_override &&
3450 photoconf->scene_mode != GST_PHOTOGRAPHY_SCENE_MODE_MANUAL) {
3451 /* If scene override flag is set, we just leave the new settings in use */
3452 GST_DEBUG ("SCENE OVERRIDE, ext=%d", photoconf->scene_mode);
3453 cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_SCENE_MODE,
3454 gst_v4l2camsrc_scene_map[photoconf->scene_mode]);
3456 GST_DEBUG ("Normal settings");
3457 cam_feature_set (v4l2camsrc->video_fd, CAM_AWB_MODE,
3458 gst_v4l2camsrc_wb_map[photoconf->wb_mode]);
3460 cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE,
3461 gst_v4l2camsrc_effect_map[photoconf->tone_mode]);
3463 cam_feature_set (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE,
3464 gst_v4l2camsrc_flash_map[photoconf->flash_mode]);
3466 /* These will set exposure mode to MANUAL, is value is != 0 */
3467 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_TIME,
3468 photoconf->exposure);
3469 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_APERTURE,
3470 photoconf->aperture);
3472 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION,
3473 (gint) (photoconf->ev_compensation));
3475 cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE,
3476 gst_v4l2camsrc_libmfld_reverse_map_iso (photoconf->iso_speed));
3478 cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_FLICKER_REDUCTION_MODE,
3479 gst_v4l2camsrc_flicker_map[photoconf->flicker_mode]);
3481 cam_feature_set (v4l2camsrc->video_fd, CAM_NOISE_REDUCTION_MODE,
3482 photoconf->noise_reduction);
3484 g_mutex_unlock (v4l2camsrc->device_mutex);
3490 gst_v4l2camsrc_set_AeAafwindow (GstCameraSrc * camsrc, GstCameraSrc3a_window window)
3492 GstMFLDV4l2CamSrc *v4l2camsrc;
3493 gboolean ret = TRUE;
3495 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3497 GST_DEBUG_OBJECT(v4l2camsrc,"ae-af-window-setting: x_left:%d, x_right:%d,"
3498 "y_bottom:%d, y_top:%d, weight:%d.\n",
3499 window.x_left,window.x_right,
3500 window.y_bottom, window.y_top,
3503 v4l2camsrc->af_window = v4l2camsrc->ae_window = *(GstCameraWindow*)&window;
3505 if (v4l2camsrc->is_active) {
3506 g_mutex_lock (v4l2camsrc->device_mutex);
3507 cam_set_af_ae_window((advci_window *) (&v4l2camsrc->af_window));
3508 g_mutex_unlock (v4l2camsrc->device_mutex);
3515 gst_v4l2camsrc_set_autofocus (GstCameraSrc * camsrc, gboolean on)
3517 GstMFLDV4l2CamSrc *v4l2camsrc;
3518 gboolean ret = FALSE;
3519 cam_err_t err = CAM_ERR_NONE;
3521 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3522 g_mutex_lock (v4l2camsrc->device_mutex);
3523 err= cam_set_autofocus(on);
3524 ret = (err == CAM_ERR_NONE);
3525 g_mutex_unlock (v4l2camsrc->device_mutex);
3527 GST_DEBUG ("setting autofocus: %s", ret ? "ok" : "failed");
3534 gst_v4l2camsrc_get_capabilities (GstCameraSrc * camsrc)
3538 pcaps = GST_PHOTOGRAPHY_CAPS_ZOOM | GST_PHOTOGRAPHY_CAPS_EV_COMP |
3539 GST_PHOTOGRAPHY_CAPS_WB_MODE | GST_PHOTOGRAPHY_CAPS_TONE |
3540 GST_PHOTOGRAPHY_CAPS_SCENE | GST_PHOTOGRAPHY_CAPS_FLASH |
3541 GST_PHOTOGRAPHY_CAPS_FOCUS | GST_PHOTOGRAPHY_CAPS_APERTURE |
3542 GST_PHOTOGRAPHY_CAPS_EXPOSURE | GST_PHOTOGRAPHY_CAPS_SHAKE |
3543 GST_PHOTOGRAPHY_CAPS_ISO_SPEED;
3552 gst_v4l2camsrc_check_focus_status (GstMFLDV4l2CamSrc * v4l2camsrc,
3553 GstCameraFocusStatus *fs, gboolean detailed)
3555 gboolean ret = FALSE;
3556 cam_focus_status_t status;
3559 GST_DEBUG_OBJECT (v4l2camsrc, "Retrieving focus status");
3561 update = cam_checkfocus_status (&status, (v4l2camsrc->debug_flags & GST_CAMERASRC_DEBUG_FLAGS_AUTO_FOCUS));
3563 if (update == TRUE) {
3564 fs->status = cam_find_item_new (gst_v4l2camsrc_focus_status_map, status, TRUE);
3567 GST_DEBUG_OBJECT (v4l2camsrc, "Focus status: %d", fs->status);
3573 gst_v4l2camsrc_set_capture_mode (GstCameraSrc * camsrc,
3574 GstCameraSrcCaptureMode mode)
3576 GstMFLDV4l2CamSrc *v4l2camsrc;
3577 gboolean ret = FALSE;
3578 int err; //cam_err_t err;
3579 cam_capture_mode_t cam_mode;
3580 static const gchar *cmodes[] = { "VIEWFINDER", "STILL", "VIDEO" };
3581 struct v4l2_streamparm parm;
3585 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3587 fd = v4l2camsrc->video_fd;
3589 cam_mode = find_item (gst_v4l2camsrc_capture_map, mode);
3591 g_mutex_lock (v4l2camsrc->device_mutex);
3593 if (v4l2camsrc->initialized) {
3594 v4l2camsrc->capture_mode = mode;
3595 GST_DEBUG ("Setting isp capture mode: %s", cmodes[mode]);
3596 memset (&parm, 0x00, sizeof (struct v4l2_streamparm));
3598 parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3599 err = ioctl(fd, VIDIOC_G_PARM, &parm);
3601 GST_DEBUG("Unable to get frame rate: %s (%d).\n",
3602 strerror(errno), errno);
3605 GST_DEBUG("Current frame rate: %u/%u\n",
3606 parm.parm.capture.timeperframe.numerator,
3607 parm.parm.capture.timeperframe.denominator);
3609 GST_DEBUG("Current run mode: %04x\n", parm.parm.capture.capturemode);
3612 case GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER:
3613 binary = CI_MODE_PREVIEW;
3615 case GST_CAMERA_SRC_CAPTURE_MODE_STILL:
3616 binary = CI_MODE_STILL_CAPTURE;
3618 case GST_CAMERA_SRC_CAPTURE_MODE_VIDEO:
3619 binary = CI_MODE_VIDEO;
3622 binary = CI_MODE_PREVIEW;
3625 parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3626 parm.parm.capture.capturemode = binary;
3628 GST_DEBUG("New run mode: %04x\n", parm.parm.capture.capturemode);
3630 if (ioctl (fd, VIDIOC_S_PARM, &parm) < 0) {
3631 GST_DEBUG("Switch Mode failed !\n");
3635 GST_DEBUG_OBJECT (v4l2camsrc, "Setting capture mode done: %s",
3636 ret ? "OK" : "FAIL");
3639 GST_DEBUG_OBJECT (v4l2camsrc, "Device not initialized");
3643 g_mutex_unlock (v4l2camsrc->device_mutex);
3648 gboolean gst_v4l2camsrc_set_strobe_state (GstCameraSrc * camsrc,
3652 GstMFLDV4l2CamSrc *v4l2camsrc;
3654 cam_err_t err = CAM_ERR_NONE;
3656 v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3657 fd = v4l2camsrc->video_fd;
3659 err = cam_set_flash (fd, state);
3660 return(err == CAM_ERR_NONE);
3663 gst_libmfldcam_capture_correction_update (GstMFLDV4l2CamSrc * v4l2camsrc)
3665 int fd = v4l2camsrc->video_fd;
3668 if (!v4l2camsrc->cc_updated)
3671 if (v4l2camsrc->gdc_enabled)
3672 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_GDC, TRUE);
3674 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_GDC, FALSE);
3679 if (v4l2camsrc->cac_enabled)
3680 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_CAC, TRUE);
3682 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_CAC, FALSE);
3687 if (v4l2camsrc->dvs_enabled)
3688 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_DVS, TRUE);
3690 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_DVS, FALSE);
3695 if (v4l2camsrc->ee_enabled)
3696 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_EE, TRUE);
3698 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_EE, FALSE);
3703 if (v4l2camsrc->sc_enabled)
3704 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_SC, TRUE);
3706 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_SC, FALSE);
3711 if (v4l2camsrc->blc_enabled)
3712 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BLC, TRUE);
3714 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BLC, FALSE);
3716 if (v4l2camsrc->bpd_enabled)
3717 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BPD, TRUE);
3719 ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BPD, FALSE);
3724 v4l2camsrc->cc_updated = FALSE;
3733 GST_WARNING_OBJECT (v4l2camsrc, "Set capture correction failed \n");
3739 * gst_v4l2camsrc_libmfldcam_set_zoom:
3740 * @v4l2camsrc: #GstMFLDV4l2CamSrc object.
3741 * @zoom: Desired zoom factor.
3743 * Set the zoom factor for captured image.
3745 * Returns: TRUE on success.
3748 gst_v4l2camsrc_libmfldcam_set_zoom (GstMFLDV4l2CamSrc * v4l2camsrc, gfloat zoom)
3750 cam_err_t err = CAM_ERR_NONE;
3753 GST_DEBUG_OBJECT (v4l2camsrc, "ZOOM: %f", zoom);
3755 err = cam_set_zoom (v4l2camsrc->video_fd, zoom);
3756 /* ret = err == CAM_ERR_NONE; */
3759 GST_DEBUG_OBJECT (v4l2camsrc, "Setting zoom: %s", ret ? "SUCCESS" : "FAIL");
3765 gst_v4l2camsrc_libmfldcam_get_makernote (GstMFLDV4l2CamSrc * v4l2camsrc, unsigned char *buf, unsigned size)
3767 cam_err_t err = CAM_ERR_NONE;
3769 GST_DEBUG_OBJECT (v4l2camsrc, "%s, !!!!!!line:%d\n", __func__, __LINE__);
3771 err = cam_get_makernote (v4l2camsrc->video_fd, buf, size);
3776 gst_v4l2camsrc_libmfldcam_get_focus_posi(GstMFLDV4l2CamSrc * v4l2camsrc, unsigned *posi)
3778 cam_err_t err = CAM_ERR_NONE;
3779 err = cam_get_focus_posi(v4l2camsrc->video_fd, posi);
3780 if(err != CAM_ERR_NONE)
3787 * @v4l2camsrc: #GstMFLDV4l2CamSrc object
3789 * configure driver default settings and set the opened ISP fd to libmfldcam
3792 gst_v4l2camsrc_libmfldcam_init (GstMFLDV4l2CamSrc * v4l2camsrc)
3795 struct v4l2_input input;
3799 memset(&input, 0, sizeof(input));
3800 if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_PRIMARY)
3801 input.index = V2L2_CAMERA_INPUT_SENSOR_PRIMARY;
3803 input.index = V2L2_CAMERA_INPUT_SENSOR_SECONDARY;
3805 ret = ioctl(v4l2camsrc->video_fd, VIDIOC_ENUMINPUT, &input);
3809 name = (char*)input.name;
3810 space = strchr(name, ' ');
3812 name[space - name] = '\0';
3814 GST_DEBUG_OBJECT (v4l2camsrc, "sensor name %s", name);
3816 err = cam_driver_init (v4l2camsrc->video_fd, name);
3818 if (err != CAM_ERR_NONE) {
3819 GST_WARNING ("libmfldcam initialization failed");
3822 if (v4l2camsrc->cc_updated)
3823 gst_libmfldcam_capture_correction_update (v4l2camsrc);
3825 if (v4l2camsrc->gamma_updated) {
3826 cam_set_tone_control (v4l2camsrc->video_fd, CAM_GAMMA_VALUE,
3828 cam_set_tone_control (v4l2camsrc->video_fd, CAM_BRIGHTNESS_VALUE,
3830 cam_set_tone_control (v4l2camsrc->video_fd, CAM_CONTRAST_VALUE,
3832 v4l2camsrc->gamma_updated = FALSE;
3835 /* Set the default settings here */
3837 GST_DEBUG_OBJECT (v4l2camsrc, "Configure default settings %s",
3838 v4l2camsrc->videodev);
3840 gst_v4l2camsrc_set_attribute (GST_CAMERA_SRC (v4l2camsrc),V4L2_CID_VFLIP,v4l2camsrc->vflip);
3841 if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_SECONDARY) {
3842 gst_v4l2camsrc_set_attribute (GST_CAMERA_SRC (v4l2camsrc),V4L2_CID_HFLIP,v4l2camsrc->hflip);
3843 gst_v4l2camsrc_set_attribute (GST_CAMERA_SRC (v4l2camsrc),V4L2_CID_POWER_LINE_FREQUENCY,CAM_GENERAL_FLICKER_REDUCTION_MODE_50HZ);
3846 v4l2camsrc->initialized = TRUE;
3847 v4l2camsrc->is_open = TRUE;
3852 gst_v4l2camsrc_libmfldcam_deinit (GstMFLDV4l2CamSrc * v4l2camsrc)
3854 //FIXME : determin whether is it initialized
3856 err = cam_driver_deinit (v4l2camsrc->video_fd);
3857 if (err != CAM_ERR_NONE) {
3858 GST_WARNING ("libmfldcam initialization failed");
3862 v4l2camsrc->is_open = FALSE;
3867 gst_v4l2camsrc_open_second(GstCameraSrc *base)
3870 GstPollFD pollfd = GST_POLL_FD_INIT;
3871 const gchar *video_name = GST_V4L2CAMSRC_SECOND_VIDEO_DEFAULT_NAME;
3872 GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
3874 GST_DEBUG_OBJECT (src, "Trying to open %s", video_name);
3876 if (GST_V4L2CAMSRC_IS_SECOND_OPEN(src)) {
3877 GST_WARNING("second video already opened");
3881 /* check if it is a device */
3882 if (stat (video_name, &st) == -1)
3885 if (!S_ISCHR (st.st_mode))
3888 /* open the device */
3889 src->second_video_fd =
3890 open (video_name, O_RDWR /* | O_NONBLOCK */ );
3892 if (!GST_V4L2CAMSRC_IS_SECOND_OPEN (src))
3895 pollfd.fd = src->second_video_fd;
3896 gst_poll_add_fd (src->second_poll, &pollfd);
3897 gst_poll_fd_ctl_read (src->second_poll, &pollfd, TRUE);
3901 GST_WARNING("open second video %s failed", video_name);
3907 gst_v4l2camsrc_close_second(GstCameraSrc *base)
3909 GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
3910 const gchar *video_name = GST_V4L2CAMSRC_SECOND_VIDEO_DEFAULT_NAME;
3912 GstPollFD pollfd = GST_POLL_FD_INIT;
3914 GST_DEBUG_OBJECT (src, "Trying to close %s", video_name);
3916 if (!GST_V4L2CAMSRC_IS_SECOND_OPEN(src)) {
3920 close (src->second_video_fd);
3921 pollfd.fd = src->second_video_fd;
3922 gst_poll_remove_fd (src->second_poll, &pollfd);
3923 src->second_video_fd = -1;
3929 gst_v4l2camsrc_set_second_capture_mode(GstCameraSrc *base)
3931 GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
3932 struct v4l2_streamparm parm;
3933 guint fd = src->second_video_fd;
3936 memset(&parm, 0, sizeof(parm));
3937 parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3939 g_mutex_lock (src->device_mutex);
3940 if ((ret = ioctl(fd, VIDIOC_G_PARM, &parm)) < 0) {
3941 GST_DEBUG_OBJECT(src, "Unable to get second video param: %s (%d).",
3942 strerror(errno), errno);
3945 parm.parm.capture.capturemode = CI_MODE_VIDEO;
3947 if ((ret = ioctl (fd, VIDIOC_S_PARM, &parm)) < 0) {
3948 GST_DEBUG_OBJECT(src, "Unable to set second video param: %s (%d).",
3949 strerror(errno), errno);
3953 g_mutex_unlock (src->device_mutex);
3958 gst_v4l2camsrc_set_second_capture(
3960 guint32 *pixelformat,
3961 guint *width, guint32 *height,
3962 guint *fps_n, guint *fps_d
3965 GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
3966 gint fd = src->second_video_fd;
3967 struct v4l2_format format;
3968 struct v4l2_streamparm stream;
3970 GST_DEBUG_OBJECT(src, "try set second capture");
3972 memset (&format, 0, sizeof (struct v4l2_format));
3973 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3975 if (ioctl (fd, VIDIOC_G_FMT, &format) < 0)
3978 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3979 format.fmt.pix.width = *width;
3980 format.fmt.pix.height = *height;
3981 format.fmt.pix.pixelformat = *pixelformat;
3982 format.fmt.pix.field = V4L2_FIELD_ANY;
3984 if (ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
3985 if (errno != EINVAL)
3988 /* try again with progressive video */
3989 format.fmt.pix.width = *width;
3990 format.fmt.pix.height = *height;
3991 format.fmt.pix.pixelformat = *pixelformat;
3992 format.fmt.pix.field = V4L2_FIELD_NONE;
3993 if (ioctl (fd, VIDIOC_S_FMT, &format) < 0)
3997 if (format.fmt.pix.width != *width || format.fmt.pix.height != *height
3998 || format.fmt.pix.pixelformat != *pixelformat)
4001 memset (&stream, 0x00, sizeof (struct v4l2_streamparm));
4002 stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
4003 if (ioctl (fd, VIDIOC_G_PARM, &stream) < 0) {
4004 GST_DEBUG_OBJECT(src,"second video get param failed");
4008 if (fps_n == NULL || fps_d == NULL) {
4012 /* Note: V4L2 provides the frame interval, we have the frame rate */
4013 if (stream.parm.capture.timeperframe.denominator &&
4014 fractions_are_equal (stream.parm.capture.timeperframe.numerator,
4015 stream.parm.capture.timeperframe.denominator, *fps_d, *fps_n)) {
4019 /* We want to change the frame rate, so check whether we can. Some cheap USB
4020 * cameras don't have the capability */
4021 if ((stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
4022 GST_DEBUG_OBJECT (src, "Not setting framerate (second video not supported)");
4026 stream.parm.capture.timeperframe.numerator = *fps_d;
4027 stream.parm.capture.timeperframe.denominator = *fps_n;
4029 /* some cheap USB cam's won't accept any change */
4030 if (ioctl (fd, VIDIOC_S_PARM, &stream) < 0) {
4031 GST_WARNING_OBJECT (src,
4032 "Second video input device did not accept new frame rate setting");
4037 src->second_frame_byte_size = gst_v4l2camsrc_get_frame_size (*pixelformat,
4042 GST_ERROR_OBJECT (src,
4043 "tried to set format:%" GST_FOURCC_FORMAT " size: %dx%d, "
4044 "but failed and device returned format:%" GST_FOURCC_FORMAT "size: %dx%d",
4045 GST_FOURCC_ARGS (*pixelformat), *width, *height,
4046 GST_FOURCC_ARGS (format.fmt.pix.pixelformat),
4047 format.fmt.pix.width,
4048 format.fmt.pix.height);
4051 GST_WARNING_OBJECT(src, "set second capture failed");
4056 gst_v4l2camsrc_start_second(GstCameraSrc *base, GstCaps *caps)
4058 GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
4059 gint fd = src->second_video_fd;
4060 struct v4l2_requestbuffers breq;
4061 gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
4063 memset (&breq, 0, sizeof (breq));
4064 breq.count = src->second_num_buffers;
4065 breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
4066 //if (src->use_mmap)
4067 // breq.memory = V4L2_MEMORY_MMAP;
4069 breq.memory = V4L2_MEMORY_USERPTR;
4071 if (ioctl (fd, VIDIOC_REQBUFS, &breq) < 0)
4074 GST_DEBUG_OBJECT(src,
4075 "Second video request buffer, count:%d, type:%d, memory:%d",
4076 breq.count, breq.type, breq.memory);
4078 if (breq.count < GST_V4L2CAMSRC_MIN_BUFFERS)
4081 if (src->second_num_buffers != breq.count) {
4082 GST_WARNING_OBJECT (src, "second video using %u buffers instead", breq.count);
4083 src->second_num_buffers = breq.count;
4086 /*init second pool*/
4087 if (!(src->second_pool =
4088 gst_v4l2camsrc_buffer_pool_new (src, fd,
4089 src->second_num_buffers, caps,
4091 src->second_frame_byte_size, GST_CAMERA_SRC_SECOND_PAD(src))))
4094 GST_DEBUG_OBJECT (src, "second video capturing buffers");
4096 if (!gst_v4l2camsrc_buffer_pool_activate (src->second_pool, src))
4099 if (ioctl (fd, VIDIOC_STREAMON, &type) < 0)
4102 GST_DEBUG_OBJECT (src, "second video STREAMON called");
4106 GST_ERROR_OBJECT(src, "second video start failed.");
4111 gst_v4l2camsrc_create_second_buffer(GstCameraSrc *base, GstBuffer **buf)
4113 GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
4114 gint fd = src->second_video_fd;
4115 struct v4l2_buffer v4l2_buffer;
4116 GstV4l2Buffer *pool_buf;
4121 gst_v4l2_buffer_pool_update (src->second_pool, src, src->second_num_buffers);
4124 ret = gst_poll_wait (src->second_poll, V4L2CAMSRC_SECOND_POLL_TIMEOUT);
4125 if (G_UNLIKELY (ret < 0)) {
4128 if (errno != EAGAIN && errno != EINTR)
4132 if (G_UNLIKELY (ret == 0)) {
4135 //g_mutex_lock (src->device_mutex);
4136 memset(&v4l2_buffer, 0, sizeof(v4l2_buffer));
4137 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
4138 v4l2_buffer.memory = V4L2_MEMORY_USERPTR;
4139 ret = ioctl(fd, VIDIOC_DQBUF, &v4l2_buffer);
4140 //g_mutex_unlock (src->device_mutex);
4145 GST_WARNING_OBJECT (src,
4146 "problem grabbing frame %d (ix=%d), trials=%d, pool-ct=%d, buf.flags=%d",
4147 v4l2_buffer.sequence, v4l2_buffer.index, retry,
4148 GST_MINI_OBJECT_REFCOUNT (src->pool), v4l2_buffer.flags);
4150 /* if the sync() got interrupted, we can retry */
4153 GST_WARNING_OBJECT (src,
4154 "Non-blocking I/O has been selected using O_NONBLOCK and"
4155 " no buffer was in the outgoing queue. device /dev/video1");
4162 GST_INFO_OBJECT (src,
4163 "VIDIOC_DQBUF failed due to an internal error."
4164 " Can also indicate temporary problems like signal loss."
4165 " Note the driver might dequeue an (empty) buffer despite"
4166 " returning an error, or even stop capturing."
4167 " device /dev/video1");
4168 /* have we de-queued a buffer ? */
4171 GST_WARNING_OBJECT (src,
4172 "could not sync on a buffer on device /dev/video1");
4175 GST_WARNING_OBJECT (src,
4176 "Grabbing frame got interrupted on /dev/video1. No expected reason.");
4184 index = v4l2_buffer.index;
4186 g_mutex_lock (src->second_pool->lock);
4188 pool_buf = src->second_pool->buffers[index];
4190 if (G_UNLIKELY (pool_buf == NULL))
4193 //GST_LOG_OBJECT (src, "grabbed buffer %p at index %d (refct = %d)",
4194 // pool_buffer, index, GST_MINI_OBJECT_REFCOUNT (pool_buffer));
4196 /* ref the buffer and requeue, when if becomes writable again */
4197 src->second_pool->buffers[index] = NULL;
4198 src->second_pool->num_live_buffers++;
4199 src->second_pool->queued[index] = 0;
4201 g_mutex_unlock (src->second_pool->lock);
4203 GST_BUFFER_SIZE (pool_buf) = src->second_frame_byte_size;
4205 if (src->second_pool->is_vaapi_sharing)
4206 GST_BUFFER_DATA(pool_buf) = (void*)((GST_V4L2CAMSRC_BUFFER(pool_buf))->gbuffer);
4207 *buf = GST_BUFFER_CAST(pool_buf);
4212 return GST_FLOW_WRONG_STATE;
4215 return GST_FLOW_ERROR;
4219 gst_v4l2camsrc_stop_second_wait(GstCameraSrc *base)
4221 GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
4222 gst_poll_set_flushing (src->second_poll, TRUE);