Add support for auto focus range.
[adaptation/intel_mfld/gst-plugins-atomisp.git] / gst / mfldv4l2cam / v4l2camsrc_calls.c
1 /* GStreamer
2  *
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
7  *
8  * v4l2camsrc.c - system calls
9  *
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.
14  *
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.
19  *
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.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 #include <stdlib.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <sys/ioctl.h>
34 #include <sys/mman.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <sys/time.h>
38 #include <unistd.h>
39 #ifdef __sun
40 /* Needed on older Solaris Nevada builds (72 at least) */
41 #include <stropts.h>
42 #include <sys/ioccom.h>
43 #endif
44
45 #include <gst/camera/gstmfldcameracolorbalance.h>
46 #include <gst/controller/gstcontroller.h>
47
48 #include "v4l2camsrc_calls.h"
49 #include <atomisp_v4l2.h>
50 #include <atomisp.h>
51 #include <mfld_cam.h>
52 GST_DEBUG_CATEGORY_EXTERN (gst_v4l2camsrc_debug);
53 #define GST_CAT_DEFAULT gst_v4l2camsrc_debug
54
55 #define GST_V4L2CAMSRC_SECOND_VIDEO_DEFAULT_NAME "/dev/video1"
56
57 extern guint gst_camerasrc_signals[CAMERA_IN_LAST_SIGNAL];
58
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,
63   -1
64 };
65
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,
79   -1
80 };
81
82 static const gint gst_v4l2camsrc_wb_map[] = {
83   CAM_AWB_MODE_AUTO,
84   CAM_AWB_MODE_DAYLIGHT,
85   CAM_AWB_MODE_SUNSET,
86   CAM_AWB_MODE_CLOUDY,
87   CAM_AWB_MODE_TUNGSTEN,
88   CAM_AWB_MODE_FLUORESCENT,
89   -1
90 };
91
92
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 */
96
97 /* lalala... */
98 #define GST_V4L2CAMSRC_SET_ACTIVE(element) (element)->buffer = GINT_TO_POINTER (-1)
99 #define GST_V4L2CAMSRC_SET_INACTIVE(element) (element)->buffer = NULL
100
101 /* On some systems MAP_FAILED seems to be missing */
102 #ifndef MAP_FAILED
103 #define MAP_FAILED ((caddr_t) -1)
104 #endif
105
106 #define RESIZER_MAX_DOWNSCALE_FACTOR 4
107 #define V4L2CAMSRC_POLL_TIMEOUT (20 * GST_SECOND)
108 #define V4L2CAMSRC_SECOND_POLL_TIMEOUT (1 * GST_SECOND)
109
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))
113
114 /* Local functions */
115 static gboolean
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);
122 static gboolean
123 gst_v4l2camsrc_check_focus_status (GstMFLDV4l2CamSrc * v4l2camsrc,
124                                    GstCameraFocusStatus *fs, gboolean detailed);
125
126 static gboolean gst_v4l2camsrc_libmfldcam_init (GstMFLDV4l2CamSrc * v4l2camsrc);
127 static gboolean gst_v4l2camsrc_libmfldcam_deinit (GstMFLDV4l2CamSrc *
128     v4l2camsrc);
129
130 /*
131  * GstCameraBuffer:
132  */
133
134 static GstBufferClass *v4l2buffer_parent_class = NULL;
135
136 static void
137 gst_v4l2camsrc_buffer_finalize (GstV4l2Buffer * buffer)
138 {
139   GstMFLDV4l2CamSrcBufferPool *pool;
140   gboolean resuscitated = FALSE;
141   struct v4l2_buffer *vbuffer;
142   gint index;
143
144   pool = buffer->pool;
145   vbuffer = (struct v4l2_buffer *) buffer->vbuffer;
146   index = vbuffer->index;
147
148   GST_LOG ("finalizing buffer %p %d", buffer, index);
149
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--;
154
155   if (pool->running) {
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);
160     } else {
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);
168       resuscitated = TRUE;
169     }
170   } else {
171     GST_LOG ("the pool is shutting down");
172   }
173   g_mutex_unlock (pool->lock);
174
175   if (!resuscitated) {
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));
180
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;
188       } else {
189         /* It was allocated with posix_memalign */
190         free (GST_BUFFER_DATA (buffer));
191       }
192     }
193
194     GST_BUFFER_DATA (buffer) = NULL;
195
196     g_free (buffer->vbuffer);
197
198     GST_LOG ("free v4l2buffer");
199     GST_MINI_OBJECT_CLASS (v4l2buffer_parent_class)->finalize (GST_MINI_OBJECT
200         (buffer));
201   }
202 }
203
204 static void
205 gst_v4l2camsrc_buffer_class_init (gpointer g_class, gpointer class_data)
206 {
207   GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
208
209   v4l2buffer_parent_class = g_type_class_peek_parent (g_class);
210
211   mini_object_class->finalize =
212       (GstMiniObjectFinalizeFunction) gst_v4l2camsrc_buffer_finalize;
213 }
214
215 static GType
216 gst_v4l2camsrc_buffer_get_type (void)
217 {
218   static GType _gst_v4l2camsrc_buffer_type;
219
220   if (G_UNLIKELY (_gst_v4l2camsrc_buffer_type == 0)) {
221     static const GTypeInfo v4l2camsrc_buffer_info = {
222       sizeof (GstBufferClass),
223       NULL,
224       NULL,
225       gst_v4l2camsrc_buffer_class_init,
226       NULL,
227       NULL,
228       sizeof (GstV4l2Buffer),
229       0,
230       NULL,
231       NULL
232     };
233     _gst_v4l2camsrc_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
234         "GstCameraBuffer", &v4l2camsrc_buffer_info, 0);
235   }
236   return _gst_v4l2camsrc_buffer_type;
237 }
238
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,
243     GstPad *pad)
244 {
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;
249
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);
254   ret->pool =
255       (GstMFLDV4l2CamSrcBufferPool *)
256       gst_mini_object_ref (GST_MINI_OBJECT (pool));
257
258   vbuffer->index = index;
259   vbuffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
260
261   if (use_mmap)
262     vbuffer->memory = V4L2_MEMORY_MMAP;
263   else
264     vbuffer->memory = V4L2_MEMORY_USERPTR;
265
266   vbuffer->length = frame_byte_size;
267   ret->gbuffer = NULL;
268
269   if (ioctl (pool->video_fd, VIDIOC_QUERYBUF, vbuffer) < 0)
270     goto querybuf_failed;
271
272   if (use_mmap) {
273     void *data;
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)
277       goto mmap_failed;
278     GST_BUFFER_DATA (ret) = (guint8 *) data;
279   } else {
280
281     if (!is_second && v4l2camsrc->capture_mode == GST_CAMERA_SRC_CAPTURE_MODE_STILL) {
282
283         /*call signal*/
284         /* alloc buffer for capture callback */
285       buf_cap_signal2 = gst_buffer_new ();
286
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,
293           NULL);
294
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],
298           0,
299           buf_cap_signal2);
300
301       if (GST_BUFFER_DATA(buf_cap_signal2) == NULL)
302         goto usrptr_alloc_failed;
303
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);
308
309     } else {
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);
313
314         flow_ret =
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;
320       } else {
321         void *data;
322
323         GST_LOG ("using posix_memalign");
324         if (posix_memalign (&data, getpagesize (), vbuffer->length) != 0) {
325           goto memalign_failed;
326         }
327         GST_BUFFER_DATA (ret) = (guint8 *) data;
328       }
329     }
330   }
331
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);
335
336 #ifdef USE_MLOCK
337   GST_DEBUG ("mlocking buffer data");
338   if (mlock ((void *) GST_BUFFER_DATA (ret), frame_byte_size) == -1)
339     goto mlock_failed;
340 #endif
341
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
344    * needed */
345   if (!use_mmap)
346     vbuffer->m.userptr = (unsigned int) GST_BUFFER_DATA (ret);
347
348
349 #if 1
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);
362 #endif
363
364   return ret;
365
366   /* ERRORS */
367 #ifdef USE_MLOCK
368 mlock_failed:
369   {
370     GST_WARNING ("Failed to mlock memory: %s", g_strerror (errno));
371     gst_buffer_unref (GST_BUFFER (ret));
372     g_free (vbuffer);
373     return NULL;
374   }
375 #endif
376 querybuf_failed:
377   {
378     gint errnosave = errno;
379
380     GST_WARNING ("Failed QUERYBUF: %s", g_strerror (errnosave));
381     gst_buffer_unref (GST_BUFFER (ret));
382     g_free (vbuffer);
383     errno = errnosave;
384     return NULL;
385   }
386 memalign_failed:
387   {
388     GST_WARNING ("Failed to posix_memalign a buffer");
389     g_free (vbuffer);
390     return NULL;
391   }
392 pad_alloc_failed:
393   {
394     GST_WARNING ("Failed to pad_alloc_buffer: %s",
395         gst_flow_get_name (flow_ret));
396     g_free (vbuffer);
397     return NULL;
398   }
399 usrptr_alloc_failed:
400   {
401     GST_WARNING ("Failed to alloc usrptr buffer");
402     g_free (vbuffer);
403     return NULL;
404   }
405 mmap_failed:
406   {
407     gint errnosave = errno;
408     GST_WARNING ("Failed to mmap: %s", g_strerror (errnosave));
409     gst_buffer_unref (GST_BUFFER (ret));
410     g_free (vbuffer);
411     errno = errnosave;
412     return NULL;
413   }
414 }
415
416
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))
420
421 static GstMiniObjectClass *buffer_pool_parent_class = NULL;
422
423 static void
424 gst_v4l2camsrc_buffer_pool_finalize (GstMFLDV4l2CamSrcBufferPool * pool)
425 {
426   g_mutex_free (pool->lock);
427   pool->lock = NULL;
428
429   if (pool->video_fd >= 0)
430     close (pool->video_fd);
431
432   if (pool->buffers) {
433     g_free (pool->buffers);
434     pool->buffers = NULL;
435   }
436
437   if (pool->queued) {
438     g_free (pool->queued);
439     pool->queued = NULL;
440   }
441
442   g_cond_free (pool->data_cond);
443   pool->data_cond = NULL;
444
445   GST_MINI_OBJECT_CLASS (buffer_pool_parent_class)->finalize (GST_MINI_OBJECT
446       (pool));
447 }
448
449 /*
450  */
451 static void
452 gst_v4l2camsrc_buffer_pool_init (GstMFLDV4l2CamSrcBufferPool * pool,
453     gpointer g_class)
454 {
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;
461 }
462
463 /*
464  */
465 static void
466 gst_v4l2camsrc_buffer_pool_class_init (gpointer g_class, gpointer class_data)
467 {
468   GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
469
470   buffer_pool_parent_class = g_type_class_peek_parent (g_class);
471
472   mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
473       gst_v4l2camsrc_buffer_pool_finalize;
474 }
475
476 /*
477  */
478 static GType
479 gst_v4l2camsrc_buffer_pool_get_type (void)
480 {
481   static GType _gst_v4l2camsrc_buffer_pool_type;
482
483   if (G_UNLIKELY (_gst_v4l2camsrc_buffer_pool_type == 0)) {
484     static const GTypeInfo v4l2camsrc_buffer_pool_info = {
485       sizeof (GstBufferClass),
486       NULL,
487       NULL,
488       gst_v4l2camsrc_buffer_pool_class_init,
489       NULL,
490       NULL,
491       sizeof (GstMFLDV4l2CamSrcBufferPool),
492       0,
493       (GInstanceInitFunc) gst_v4l2camsrc_buffer_pool_init,
494       NULL
495     };
496     _gst_v4l2camsrc_buffer_pool_type =
497         g_type_register_static (GST_TYPE_MINI_OBJECT,
498         "GstMFLDV4l2CamSrcBufferPool", &v4l2camsrc_buffer_pool_info, 0);
499   }
500   return _gst_v4l2camsrc_buffer_pool_type;
501 }
502
503 /*
504  */
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)
510 {
511   GstMFLDV4l2CamSrcBufferPool *pool;
512   gint n;
513
514   pool = (GstMFLDV4l2CamSrcBufferPool *)
515       gst_mini_object_new (GST_TYPE_V4L2CAMSRC_BUFFER_POOL);
516
517   pool->video_fd = dup (fd);
518   if (pool->video_fd < 0)
519     goto dup_failed;
520
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;
524
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;
529
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;
537   }
538
539   return pool;
540
541   /* ERRORS */
542 dup_failed:
543   {
544     gint errnosave = errno;
545
546     gst_v4l2camsrc_buffer_pool_destroy (pool, v4l2camsrc);
547
548     errno = errnosave;
549
550     return NULL;
551   }
552 buffer_new_failed:
553   {
554     gint errnosave = errno;
555
556     GST_LOG ("creating a new buffer failed");
557     gst_mini_object_unref (GST_MINI_OBJECT (pool));
558
559     errno = errnosave;
560
561     return NULL;
562   }
563 }
564
565 /*
566  */
567 static gboolean
568 gst_v4l2camsrc_buffer_pool_activate (GstMFLDV4l2CamSrcBufferPool * pool,
569     GstMFLDV4l2CamSrc * v4l2camsrc)
570 {
571   gint n;
572
573   g_mutex_lock (pool->lock);
574
575   for (n = 0; n < pool->buffer_count; n++) {
576
577     struct v4l2_buffer *buf;
578
579     buf = (struct v4l2_buffer *) pool->buffers[n]->vbuffer;
580
581     GST_LOG ("enqueue pool buffer %d", n);
582
583     if (ioctl (pool->video_fd, VIDIOC_QBUF, buf) < 0)
584       goto queue_failed;
585
586     pool->queued[n] = 1;
587   }
588   pool->running = TRUE;
589
590   g_mutex_unlock (pool->lock);
591
592   return TRUE;
593
594   /* ERRORS */
595 queue_failed:
596   {
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);
603     return FALSE;
604   }
605 }
606
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 */
610 static gboolean
611 gst_v4l2_buffer_pool_update (GstMFLDV4l2CamSrcBufferPool * pool,
612     GstMFLDV4l2CamSrc * v4l2camsrc, guint num_buffers)
613 {
614   gint n;
615   gint ref = 0;
616
617   g_mutex_lock (pool->lock);
618
619   for (n = 0; n < pool->buffer_count; n++) {
620     if (!pool->queued[n]) {
621       GST_LOG ("buffer %d is dequeued", n);
622       ref++;
623     }
624   }
625
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);
630   }
631
632   g_mutex_unlock (pool->lock);
633
634   return (ref != num_buffers) ? TRUE : FALSE;
635 }
636
637 /*
638  */
639 static void
640 gst_v4l2camsrc_buffer_pool_destroy (GstMFLDV4l2CamSrcBufferPool * pool,
641     GstMFLDV4l2CamSrc * v4l2camsrc)
642 {
643   gint n;
644
645   g_mutex_lock (pool->lock);
646   pool->running = FALSE;
647   g_mutex_unlock (pool->lock);
648
649   GST_DEBUG ("destroy pool");
650
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. */
654
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++) {
658     GstBuffer *buf;
659
660     g_mutex_lock (pool->lock);
661     buf = GST_BUFFER (pool->buffers[n]);
662     g_mutex_unlock (pool->lock);
663
664     if (buf) {
665 #ifdef USE_MLOCK
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);
670       }
671 #endif
672       /* we own the ref if the buffer is in pool->buffers; drop it. */
673       gst_buffer_unref (buf);
674     }
675   }
676   pool->is_vaapi_sharing = FALSE;
677   gst_mini_object_unref (GST_MINI_OBJECT (pool));
678 }
679
680 /******************************************************
681  * gst_v4l2camsrc_get_capture_capabilities():
682  *   get the device's capturing capabilities
683  * return value: TRUE on success, FALSE on error
684  ******************************************************/
685 static gboolean
686 gst_v4l2camsrc_get_capture_capabilities (GstMFLDV4l2CamSrc * v4l2camsrc)
687 {
688   GST_DEBUG_OBJECT (v4l2camsrc, "getting capabilities");
689
690   if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
691     return FALSE;
692
693   if (ioctl (v4l2camsrc->video_fd, VIDIOC_QUERYCAP, &v4l2camsrc->vcap) < 0)
694     goto cap_failed;
695
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);
702
703   return TRUE;
704
705   /* ERRORS */
706 cap_failed:
707   {
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);
712     return FALSE;
713   }
714 }
715
716
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  ******************************************************/
722 static gboolean
723 gst_v4l2camsrc_set_input_sensor (GstMFLDV4l2CamSrc * v4l2camsrc)
724 {
725   V4L2CameraInputSensor select_sensor;
726   
727   GST_DEBUG_OBJECT (v4l2camsrc, "setting input sensor");
728
729   if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
730     return FALSE;
731
732   if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_PRIMARY)
733     select_sensor = V2L2_CAMERA_INPUT_SENSOR_PRIMARY;
734   else
735     select_sensor =V2L2_CAMERA_INPUT_SENSOR_SECONDARY;
736
737   if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_INPUT,
738             &select_sensor) < 0)
739     goto s_input_failed;
740
741   GST_LOG_OBJECT (v4l2camsrc, "set input sensor to:      %d",
742           select_sensor);
743
744   return TRUE;
745
746   /* ERRORS */
747 s_input_failed:
748   {
749     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
750         ("Error setting input for device '%s': ",
751             v4l2camsrc->videodev), GST_ERROR_SYSTEM);
752     return FALSE;
753   }
754 }
755
756 static gboolean
757 get_supported_mmfw_control (GstMFLDV4l2CamSrc * v4l2camsrc, struct v4l2_queryctrl *control)
758 {
759   int i;
760   GST_DEBUG_OBJECT (v4l2camsrc, "set  private control (%x)",  control->id);
761
762   for (i = 0; i < N_MMFW_CONTROLS; i++) {
763     if (mmfw_wb_controls[i].id == control->id) {
764       *control =  mmfw_wb_controls[i];
765       return TRUE;
766     }
767   }
768   return FALSE;
769 }
770
771
772 /******************************************************
773  * gst_v4l2camsrc_fill_lists():
774  *   fill the lists of enumerations
775  * return value: TRUE on success, FALSE on error
776  ******************************************************/
777 static gboolean
778 gst_v4l2camsrc_fill_lists (GstMFLDV4l2CamSrc * v4l2camsrc)
779 {
780   gint n;
781
782   GST_DEBUG_OBJECT (v4l2camsrc, "getting enumerations");
783   GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
784
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;
790
791     GstColorBalanceChannel *channel;
792
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 */
799       //break;
800       GST_DEBUG_OBJECT (v4l2camsrc, "private ID");
801     }
802
803     control.id = n;
804
805     if( n  > SOURCE_PRIV_BASE)  {
806        if(  n >= MM_CAM_SOURCE_PRIV_LAST)
807           break;
808        else
809          get_supported_mmfw_control(v4l2camsrc, &control);
810     }
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 */
815           continue;
816         else
817           break;
818       } else {
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)));
824         return FALSE;
825       }
826     }
827     if (control.flags & V4L2_CTRL_FLAG_DISABLED)
828       continue;
829
830     switch (n) {
831       case V4L2_CID_BRIGHTNESS:
832       case V4L2_CID_CONTRAST:
833       case V4L2_CID_SATURATION:
834       case V4L2_CID_HUE:
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:
840       case V4L2_CID_GAMMA:
841       case V4L2_CID_EXPOSURE:
842       case V4L2_CID_AUTOGAIN:
843       case V4L2_CID_GAIN:
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?) */
849         break;
850       case V4L2_CID_HFLIP:
851       case V4L2_CID_VFLIP:
852       case V4L2_CID_HCENTER:
853       case V4L2_CID_VCENTER:
854 #ifdef V4L2_CID_PAN_RESET
855       case V4L2_CID_PAN_RESET:
856 #endif
857 #ifdef V4L2_CID_TILT_RESET
858       case V4L2_CID_TILT_RESET:
859 #endif
860         /* not handled here, handled by VideoOrientation interface */
861         control.id++;
862         break;
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 */
870         /* fall through */
871       default:
872         GST_DEBUG_OBJECT (v4l2camsrc,
873             "ControlID %s (%x) unhandled, FIXME", control.name, n);
874         control.id++;
875         break;
876     }
877     if (n != control.id)
878       continue;
879
880     GST_DEBUG_OBJECT (v4l2camsrc, "Adding ControlID %s (%x)", control.name, n);
881     v4l2channel =
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);
885
886     v4l2channel->id = n;
887
888     switch (control.type) {
889       case V4L2_CTRL_TYPE_INTEGER:
890         channel->min_value = control.minimum;
891         channel->max_value = control.maximum;
892         break;
893       case V4L2_CTRL_TYPE_BOOLEAN:
894         channel->min_value = FALSE;
895         channel->max_value = TRUE;
896         break;
897       default:
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;
905         break;
906     }
907
908     gst_camerasrc_add_color_channel (GST_CAMERA_SRC (v4l2camsrc), channel);
909   }
910
911   GST_DEBUG_OBJECT (v4l2camsrc, "done");
912   return TRUE;
913 }
914
915 /******************************************************
916  * gst_v4l2camsrc_open():
917  *   open the video device (v4l2camsrc->videodev)
918  * return value: TRUE on success, FALSE on error
919  ******************************************************/
920 gboolean
921 gst_v4l2camsrc_open (GstCameraSrc * camsrc)
922 {
923   struct stat st;
924   GstPollFD pollfd = GST_POLL_FD_INIT;
925
926   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
927
928   GST_DEBUG_OBJECT (v4l2camsrc, "Trying to open device %s",
929       v4l2camsrc->videodev);
930
931   GST_V4L2CAMSRC_CHECK_NOT_OPEN (v4l2camsrc);
932   GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
933
934   /* be sure we have a device */
935   if (!v4l2camsrc->videodev)
936     v4l2camsrc->videodev = g_strdup ("/dev/video");
937
938   /* check if it is a device */
939   if (stat (v4l2camsrc->videodev, &st) == -1)
940     goto stat_failed;
941
942   if (!S_ISCHR (st.st_mode))
943     goto no_device;
944
945   /* open the device */
946   v4l2camsrc->video_fd =
947       open (v4l2camsrc->videodev, O_RDWR /* | O_NONBLOCK */ );
948
949   if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
950     goto not_open;
951
952   /* get capabilities, error will be posted */
953   if (!gst_v4l2camsrc_get_capture_capabilities (v4l2camsrc))
954     goto error;
955
956   /* get capabilities, error will be posted */
957   if (!gst_v4l2camsrc_set_input_sensor (v4l2camsrc))
958     goto error;
959
960   /* do we need to be a capture device? */
961   if (GST_IS_V4L2CAMSRC (v4l2camsrc) &&
962       !(v4l2camsrc->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
963     goto not_capture;
964
965   /* Before iterating enumerations, clear the parent's color channel list */
966   gst_camerasrc_clear_color_channels (camsrc);
967
968   /* create enumerations, posts errors. */
969   if (!gst_v4l2camsrc_fill_lists (v4l2camsrc))
970     goto error;
971
972   GST_INFO_OBJECT (v4l2camsrc,
973       "Opened device '%s' (%s) successfully",
974       v4l2camsrc->vcap.card, v4l2camsrc->videodev);
975
976   pollfd.fd = v4l2camsrc->video_fd;
977   gst_poll_add_fd (v4l2camsrc->poll, &pollfd);
978   gst_poll_fd_ctl_read (v4l2camsrc->poll, &pollfd, TRUE);
979
980   gst_v4l2camsrc_libmfldcam_init (v4l2camsrc);
981
982   return TRUE;
983
984   /* ERRORS */
985 stat_failed:
986   {
987     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
988         ("Cannot identify device '%s'.", v4l2camsrc->videodev),
989         GST_ERROR_SYSTEM);
990     goto error;
991   }
992 no_device:
993   {
994     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
995         ("This isn't a device '%s'.", v4l2camsrc->videodev), GST_ERROR_SYSTEM);
996     goto error;
997   }
998 not_open:
999   {
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);
1003     goto error;
1004   }
1005 not_capture:
1006   {
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));
1011     goto error;
1012   }
1013 error:
1014   {
1015     if (GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc)) {
1016       /* close device */
1017       close (v4l2camsrc->video_fd);
1018       v4l2camsrc->video_fd = -1;
1019     }
1020
1021     return FALSE;
1022   }
1023 }
1024
1025 /******************************************************
1026  * gst_v4l2camsrc_close():
1027  *   close the video device (v4l2camsrc->video_fd)
1028  * return value: TRUE on success, FALSE on error
1029  ******************************************************/
1030 gboolean
1031 gst_v4l2camsrc_close (GstCameraSrc * camsrc)
1032 {
1033   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1034
1035   GstPollFD pollfd = GST_POLL_FD_INIT;
1036
1037   GST_DEBUG_OBJECT (v4l2camsrc, "Trying to close %s", v4l2camsrc->videodev);
1038
1039   GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
1040   GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
1041
1042   /* close device */
1043   gst_v4l2camsrc_libmfldcam_deinit (v4l2camsrc);
1044
1045   close (v4l2camsrc->video_fd);
1046   pollfd.fd = v4l2camsrc->video_fd;
1047   gst_poll_remove_fd (v4l2camsrc->poll, &pollfd);
1048   v4l2camsrc->video_fd = -1;
1049
1050   return TRUE;
1051 }
1052
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  ******************************************************/
1058 gboolean
1059 gst_v4l2camsrc_get_attribute (GstCameraSrc * camsrc,
1060     int attribute_num, int *value)
1061 {
1062   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1063
1064   struct v4l2_control control;
1065   cam_err_t err;
1066   int tmp_value;
1067
1068   GST_DEBUG_OBJECT (v4l2camsrc, "getting value of attribute %d", attribute_num);
1069
1070   if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
1071     return FALSE;
1072
1073   control.id = attribute_num;
1074
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);
1080         break;
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);
1084         break;
1085      case MM_CAM_FILTER_BRIGHTNESS_SOURCE_PRIV:
1086           err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION, &tmp_value);
1087           *value = tmp_value;
1088         break;
1089
1090       default:
1091         break;
1092     }
1093   }
1094   else {
1095     if (ioctl (v4l2camsrc->video_fd, VIDIOC_G_CTRL, &control) < 0)
1096       goto ctrl_failed1;
1097     *value = control.value;
1098   }
1099
1100   return TRUE;
1101
1102 ctrl_failed1:
1103   {
1104     struct v4l2_ext_controls controls;
1105     struct v4l2_ext_control control;
1106
1107     controls.ctrl_class = V4L2_CTRL_CLASS_USER;
1108     controls.count = 1;
1109     controls.controls = &control;
1110
1111     control.id = attribute_num;
1112
1113     if (ioctl (v4l2camsrc->video_fd, VIDIOC_G_EXT_CTRLS, &controls) < 0)
1114       goto ctrl_failed2;
1115
1116     *value = control.value;
1117
1118     return TRUE;
1119
1120   }
1121
1122   /* ERRORS */
1123 ctrl_failed2:
1124   {
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);
1128     return FALSE;
1129   }
1130 }
1131
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  ******************************************************/
1137 gboolean
1138 gst_v4l2camsrc_set_attribute (GstCameraSrc * camsrc,
1139     int attribute_num, const int value)
1140 {
1141   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1142   struct v4l2_control control;
1143
1144   GST_DEBUG_OBJECT (v4l2camsrc, "setting value of attribute %d to %d",
1145       attribute_num, value);
1146
1147   if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
1148     return FALSE;
1149
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]);
1156         break;
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]);
1159         break;
1160       case MM_CAM_FILTER_BRIGHTNESS_SOURCE_PRIV:
1161           cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION, value);
1162         break;
1163       default:
1164         break;
1165     }
1166   }
1167   else {
1168     if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_CTRL, &control) < 0)
1169       goto ctrl_failed1;
1170   }
1171   return TRUE;
1172
1173 ctrl_failed1:
1174   {
1175     struct v4l2_ext_controls controls;
1176     struct v4l2_ext_control control;
1177
1178     controls.ctrl_class = V4L2_CTRL_CLASS_USER;
1179     controls.count = 1;
1180     controls.controls = &control;
1181
1182     control.id = attribute_num;
1183     control.value = value;
1184
1185     if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_EXT_CTRLS, &controls) < 0)
1186       goto ctrl_failed2;
1187
1188     return TRUE;
1189   }
1190
1191   /* ERRORS */
1192 ctrl_failed2:
1193   {
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);
1197     return FALSE;
1198   }
1199 }
1200
1201
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
1213
1214 /* This flag is already used by libv4l2 although
1215  * it was added to the Linux kernel in 2.6.32
1216  */
1217 #ifndef V4L2_FMT_FLAG_EMULATED
1218 #define V4L2_FMT_FLAG_EMULATED 0x0002
1219 #endif
1220
1221 static gint
1222 gst_v4l2camsrc_format_get_rank (const struct v4l2_fmtdesc *fmt)
1223 {
1224   guint32 fourcc = fmt->pixelformat;
1225   gboolean emulated = ((fmt->flags & V4L2_FMT_FLAG_EMULATED) != 0);
1226   gint rank = 0;
1227
1228   switch (fourcc) {
1229     case V4L2_PIX_FMT_MJPEG:
1230       rank = JPEG_BASE_RANK;
1231       break;
1232     case V4L2_PIX_FMT_JPEG:
1233       rank = JPEG_BASE_RANK + 1;
1234       break;
1235     case V4L2_PIX_FMT_MPEG:    /* MPEG          */
1236       rank = JPEG_BASE_RANK + 2;
1237       break;
1238
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;
1245       break;
1246
1247     case V4L2_PIX_FMT_RGB24:
1248     case V4L2_PIX_FMT_BGR24:
1249       rank = RGB_BASE_RANK - 1;
1250       break;
1251
1252     case V4L2_PIX_FMT_RGB32:
1253     case V4L2_PIX_FMT_BGR32:
1254       rank = RGB_BASE_RANK;
1255       break;
1256
1257     case V4L2_PIX_FMT_GREY:    /*  8  Greyscale     */
1258       rank = GREY_BASE_RANK;
1259       break;
1260
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;
1267       break;
1268     case V4L2_PIX_FMT_YUV444:  /* YUV 444,  24 bits per pixel */
1269       rank = YUV_BASE_RANK + 0;
1270       break;
1271     case V4L2_PIX_FMT_YVU410:  /* YVU9,  9 bits per pixel */
1272       rank = YUV_BASE_RANK + 3;
1273       break;
1274     case V4L2_PIX_FMT_YUV410:  /* YUV9,  9 bits per pixel */
1275       rank = YUV_BASE_RANK + 2;
1276       break;
1277     case V4L2_PIX_FMT_YUV420:  /* I420, 12 bits per pixel */
1278       rank = YUV_BASE_RANK + 7;
1279       break;
1280     case V4L2_PIX_FMT_YUYV:    /* YUY2, 16 bits per pixel */
1281       rank = YUV_BASE_RANK + 10;
1282       break;
1283     case V4L2_PIX_FMT_YVU420:  /* YV12, 12 bits per pixel */
1284       rank = YUV_BASE_RANK + 6;
1285       break;
1286     case V4L2_PIX_FMT_UYVY:    /* UYVY, 16 bits per pixel */
1287       rank = YUV_BASE_RANK + 9;
1288       break;
1289     case V4L2_PIX_FMT_Y41P:    /* Y41P, 12 bits per pixel */
1290       rank = YUV_BASE_RANK + 5;
1291       break;
1292     case V4L2_PIX_FMT_YUV411P: /* Y41B, 12 bits per pixel */
1293       rank = YUV_BASE_RANK + 4;
1294       break;
1295     case V4L2_PIX_FMT_YUV422P: /* Y42B, 16 bits per pixel */
1296       rank = YUV_BASE_RANK + 8;
1297       break;
1298
1299     case V4L2_PIX_FMT_DV:
1300       rank = DV_BASE_RANK;
1301       break;
1302
1303     case V4L2_PIX_FMT_WNVA:    /* Winnov hw compres */
1304       rank = 0;
1305       break;
1306
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;
1314       break;
1315
1316 #ifdef V4L2_PIX_FMT_SN9C10X
1317     case V4L2_PIX_FMT_SN9C10X:
1318       rank = S910_BASE_RANK;
1319       break;
1320 #endif
1321
1322 #ifdef V4L2_PIX_FMT_PWC1
1323     case V4L2_PIX_FMT_PWC1:
1324       rank = PWC_BASE_RANK;
1325       break;
1326 #endif
1327 #ifdef V4L2_PIX_FMT_PWC2
1328     case V4L2_PIX_FMT_PWC2:
1329       rank = PWC_BASE_RANK;
1330       break;
1331 #endif
1332
1333     default:
1334       GST_LOG("Don't know how to rank pixelformat %" GST_FOURCC_FORMAT,
1335                 GST_FOURCC_ARGS(fourcc));
1336       rank = 0;
1337       break;
1338   }
1339
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
1343    */
1344   if (!emulated)
1345     rank <<= 15;
1346
1347   return rank;
1348 }
1349
1350 static gint
1351 gst_v4l2camsrc_format_cmp_func (gconstpointer a, gconstpointer b)
1352 {
1353   const struct v4l2_fmtdesc *fa = a;
1354   const struct v4l2_fmtdesc *fb = b;
1355
1356   if (fa->pixelformat == fb->pixelformat)
1357     return 0;
1358
1359   return gst_v4l2camsrc_format_get_rank (fb) -
1360       gst_v4l2camsrc_format_get_rank (fa);
1361 }
1362
1363 static gboolean is_supported_pixelformat(guint32 fourcc)
1364 {
1365   if(fourcc == V4L2_PIX_FMT_NV12
1366       || fourcc == V4L2_PIX_FMT_YUV420
1367       || fourcc == V4L2_PIX_FMT_SGRBG10)
1368     return TRUE;
1369   return FALSE;
1370 }
1371
1372 /******************************************************
1373  * gst_v4l2camsrc_fill_format_list():
1374  *   create list of supported capture formats
1375  * return value: TRUE on success, FALSE on error
1376  ******************************************************/
1377 gboolean
1378 gst_v4l2camsrc_fill_format_list (GstMFLDV4l2CamSrc * v4l2camsrc)
1379 {
1380   gint n;
1381   struct v4l2_fmtdesc *format;
1382
1383   GST_DEBUG_OBJECT (v4l2camsrc, "getting src format enumerations");
1384
1385   /* format enumeration */
1386   for (n = 0;; n++) {
1387     format = g_new0 (struct v4l2_fmtdesc, 1);
1388
1389     format->index = n;
1390     format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1391
1392     if (ioctl (v4l2camsrc->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
1393       if (errno == EINVAL) {
1394         g_free (format);
1395         break;                  /* end of enumeration */
1396       } else {
1397         goto failed;
1398       }
1399     }
1400     if(!is_supported_pixelformat(format->pixelformat)) {
1401       GST_LOG_OBJECT(v4l2camsrc, "  (skipping format %" GST_FOURCC_FORMAT ")",GST_FOURCC_ARGS (format->pixelformat));
1402       continue;
1403     }
1404
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));
1411
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);
1417   }
1418
1419   GST_DEBUG_OBJECT (v4l2camsrc, "got %d format(s)", n);
1420
1421   return TRUE;
1422
1423   /* ERRORS */
1424 failed:
1425   {
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)));
1431     g_free (format);
1432     return FALSE;
1433   }
1434 }
1435
1436 /******************************************************
1437  * gst_v4l2camsrc_clear_format_list():
1438  *   free list of supported capture formats
1439  * return value: TRUE on success, FALSE on error
1440  ******************************************************/
1441 gboolean
1442 gst_v4l2camsrc_clear_format_list (GstMFLDV4l2CamSrc * v4l2camsrc)
1443 {
1444   g_slist_foreach (v4l2camsrc->formats, (GFunc) g_free, NULL);
1445   g_slist_free (v4l2camsrc->formats);
1446   v4l2camsrc->formats = NULL;
1447
1448   return TRUE;
1449 }
1450
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)
1457 {
1458   gint fd = v4l2camsrc->video_fd;
1459   struct v4l2_frmivalenum ival;
1460   guint32 num, denom;
1461   GstStructure *s;
1462   GValue rates = { 0, };
1463
1464   memset (&ival, 0, sizeof (struct v4l2_frmivalenum));
1465   ival.index = 0;
1466   ival.pixel_format = pixelformat;
1467   ival.width = width;
1468   ival.height = height;
1469
1470   GST_LOG_OBJECT (v4l2camsrc, "get frame interval for %ux%u, %"
1471       GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat));
1472
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;
1477
1478   if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
1479     GValue rate = { 0, };
1480
1481     g_value_init (&rates, GST_TYPE_LIST);
1482     g_value_init (&rate, GST_TYPE_FRACTION);
1483
1484     do {
1485       num = ival.discrete.numerator;
1486       denom = ival.discrete.denominator;
1487
1488       if (num > G_MAXINT || denom > G_MAXINT) {
1489         /* let us hope we don't get here... */
1490         num >>= 1;
1491         denom >>= 1;
1492       }
1493
1494       GST_LOG_OBJECT (v4l2camsrc, "adding discrete framerate: %d/%d",
1495           denom, num);
1496
1497       /* swap to get the framerate */
1498       gst_value_set_fraction (&rate, denom, num);
1499       gst_value_list_append_value (&rates, &rate);
1500
1501       ival.index++;
1502     } while (ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
1503
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);
1507
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;
1515
1516     g_value_init (&rates, GST_TYPE_LIST);
1517
1518     g_value_init (&min, GST_TYPE_FRACTION);
1519     g_value_init (&step, GST_TYPE_FRACTION);
1520     g_value_init (&max, GST_TYPE_FRACTION);
1521
1522     /* get the min */
1523     minnum = ival.stepwise.min.numerator;
1524     mindenom = ival.stepwise.min.denominator;
1525     if (minnum > G_MAXINT || mindenom > G_MAXINT) {
1526       minnum >>= 1;
1527       mindenom >>= 1;
1528     }
1529     GST_LOG_OBJECT (v4l2camsrc, "stepwise min frame interval: %d/%d", minnum,
1530         mindenom);
1531     gst_value_set_fraction (&min, minnum, mindenom);
1532
1533     /* get the max */
1534     maxnum = ival.stepwise.max.numerator;
1535     maxdenom = ival.stepwise.max.denominator;
1536     if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
1537       maxnum >>= 1;
1538       maxdenom >>= 1;
1539     }
1540
1541     GST_LOG_OBJECT (v4l2camsrc, "stepwise max frame interval: %d/%d", maxnum,
1542         maxdenom);
1543     gst_value_set_fraction (&max, maxnum, maxdenom);
1544
1545     /* get the step */
1546     num = ival.stepwise.step.numerator;
1547     denom = ival.stepwise.step.denominator;
1548     if (num > G_MAXINT || denom > G_MAXINT) {
1549       num >>= 1;
1550       denom >>= 1;
1551     }
1552
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 */
1556       num = maxnum;
1557       denom = maxdenom;
1558     }
1559
1560     /* since we only have gst_value_fraction_subtract and not add, negate the
1561      * numerator */
1562     GST_LOG_OBJECT (v4l2camsrc, "stepwise step frame interval: %d/%d",
1563         num, denom);
1564
1565     gst_value_set_fraction (&step, -num, denom);
1566
1567     while (gst_value_compare (&min, &max) <= 0) {
1568       GValue rate = { 0, };
1569
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",
1573           denom, num);
1574
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);
1579       added = TRUE;
1580
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!");
1585         break;
1586       }
1587     }
1588     if (!added) {
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);
1592     }
1593   } else if (ival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
1594     guint32 maxnum, maxdenom;
1595
1596     g_value_init (&rates, GST_TYPE_FRACTION_RANGE);
1597
1598     num = ival.stepwise.min.numerator;
1599     denom = ival.stepwise.min.denominator;
1600     if (num > G_MAXINT || denom > G_MAXINT) {
1601       num >>= 1;
1602       denom >>= 1;
1603     }
1604
1605     maxnum = ival.stepwise.max.numerator;
1606     maxdenom = ival.stepwise.max.denominator;
1607     if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
1608       maxnum >>= 1;
1609       maxdenom >>= 1;
1610     }
1611
1612     GST_LOG_OBJECT (v4l2camsrc, "continuous frame interval %d/%d to %d/%d",
1613         maxdenom, maxnum, denom, num);
1614
1615     gst_value_set_fraction_range_full (&rates, maxdenom, maxnum, denom, num);
1616   } else {
1617     goto unknown_type;
1618   }
1619
1620 return_data:
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);
1626
1627   if (G_IS_VALUE (&rates)) {
1628     /* only change the framerate on the template when we have a valid probed new
1629      * value */
1630     gst_structure_set_value (s, "framerate", &rates);
1631     g_value_unset (&rates);
1632   }
1633   return s;
1634
1635   /* ERRORS */
1636 enum_frameintervals_failed:
1637   {
1638     GST_DEBUG_OBJECT (v4l2camsrc,
1639         "Unable to enumerate intervals for %" GST_FOURCC_FORMAT "@%ux%u",
1640         GST_FOURCC_ARGS (pixelformat), width, height);
1641     goto return_data;
1642   }
1643 unknown_type:
1644   {
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);
1649     return NULL;
1650   }
1651 }
1652 #endif /* defined VIDIOC_ENUM_FRAMEINTERVALS */
1653
1654
1655 /*
1656  */
1657 static gint
1658 compare_resolutions (gconstpointer a, gconstpointer b)
1659 {
1660   GstStructure *as = (GstStructure *) a;
1661   GstStructure *bs = (GstStructure *) b;
1662   gint aw, bw, ah, bh;
1663
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);
1668
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));
1672 }
1673
1674
1675 /*
1676  */
1677 static gboolean
1678 fractions_are_equal (gint num1, gint den1, gint num2, gint den2)
1679 {
1680   GValue fraction1 = { 0, }, fraction2 = {
1681   0,};
1682
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);
1689 }
1690
1691 static guint
1692 gst_v4l2camsrc_get_frame_size (guint32 fourcc, guint * w, guint * h)
1693 {
1694   guint outsize = 0;
1695
1696   switch (fourcc) {
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));
1700       break;
1701     case V4L2_PIX_FMT_YUYV:
1702       outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1703       break;
1704     case V4L2_PIX_FMT_Y41P:
1705       outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1706       break;
1707     case V4L2_PIX_FMT_UYVY:
1708       outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1709       break;
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));
1713       break;
1714     case V4L2_PIX_FMT_YUV411P:
1715       outsize = GST_ROUND_UP_4 (*w) * *h;
1716       outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
1717       break;
1718     case V4L2_PIX_FMT_YUV422P:
1719       outsize = GST_ROUND_UP_4 (*w) * *h;
1720       outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
1721       break;
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;
1725       break;
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;
1729       break;
1730   }
1731
1732   return outsize;
1733 }
1734
1735 /*
1736  */
1737 static gboolean
1738 gst_v4l2camsrc_configure_device (GstMFLDV4l2CamSrc * v4l2camsrc,
1739     guint32 * pixelformat, guint * width, guint * height,
1740     guint * fps_n, guint * fps_d)
1741 {
1742   gint fd = v4l2camsrc->video_fd;
1743   struct v4l2_format format;
1744   struct v4l2_streamparm stream;
1745   gboolean ret = TRUE;
1746
1747   GST_DEBUG_OBJECT (v4l2camsrc, "Configuring device to %dx%d, format "
1748       "%" GST_FOURCC_FORMAT, *width, *height, GST_FOURCC_ARGS (*pixelformat));
1749
1750   GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
1751
1752   memset (&format, 0x00, sizeof (struct v4l2_format));
1753   format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1754
1755   if (ioctl (fd, VIDIOC_G_FMT, &format) < 0)
1756     goto get_fmt_failed;
1757
1758   if (v4l2camsrc->dump_raw)
1759     format.type = V4L2_BUF_TYPE_PRIVATE;
1760   else
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;
1769
1770   if (ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
1771     if (errno != EINVAL)
1772       goto set_fmt_failed;
1773
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;
1781   }
1782
1783   if (v4l2camsrc->dump_raw)
1784     v4l2camsrc->raw_output_size = format.fmt.pix.priv;
1785
1786   if (format.fmt.pix.width != *width || format.fmt.pix.height != *height)
1787     goto invalid_dimensions;
1788
1789   if (format.fmt.pix.pixelformat != *pixelformat)
1790     goto invalid_pixelformat;
1791
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);
1798     goto done;
1799   }
1800
1801   if (fps_n == NULL || fps_d == NULL) {
1802     GST_LOG_OBJECT (v4l2camsrc, "Framerate will not be set");
1803     goto done;
1804   }
1805
1806   GST_LOG_OBJECT (v4l2camsrc, "Desired framerate: %u/%u", *fps_n, *fps_d);
1807
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");
1813     goto done;
1814   }
1815
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)");
1820     goto done;
1821   }
1822
1823   GST_LOG_OBJECT (v4l2camsrc, "Setting framerate to %u/%u", *fps_n, *fps_d);
1824
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;
1828
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."),
1833         GST_ERROR_SYSTEM);
1834     goto done;
1835   }
1836
1837   GST_INFO_OBJECT (v4l2camsrc, "Set frame interval to %u/%u",
1838       stream.parm.capture.timeperframe.numerator,
1839       stream.parm.capture.timeperframe.denominator);
1840
1841   cam_set_frame_rate( ((gfloat)stream.parm.capture.timeperframe.denominator / stream.parm.capture.timeperframe.numerator));
1842
1843 done:
1844   v4l2camsrc->max_zoom_factor = 10.0;
1845   v4l2camsrc->frame_byte_size = gst_v4l2camsrc_get_frame_size (*pixelformat,
1846       width, height);
1847   /* v4l2camsrc->frame_byte_size = GST_ROUND_UP_2 (*width) * 2 * (*height); */
1848
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");
1855       goto no_crop;
1856     }
1857
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)) {
1861       switch (errno) {
1862         case EINVAL:
1863           GST_DEBUG_OBJECT (v4l2camsrc, "Crop not support\n");
1864           break;
1865         default:
1866           GST_DEBUG_OBJECT (v4l2camsrc, "Crop failed\n");
1867           break;
1868       }
1869     }
1870
1871     goto no_crop;
1872
1873
1874
1875     v4l2camsrc->crop_supported = TRUE;
1876
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);
1881
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);
1886
1887     gst_v4l2camsrc_update_cropping (v4l2camsrc, *width, *height, 1.0);
1888   }
1889
1890 no_crop:
1891   cam_set_capture_fmt (v4l2camsrc->video_fd, *width, *height, *pixelformat);
1892
1893   return ret;
1894
1895   /* ERRORS */
1896 get_fmt_failed:
1897   {
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)));
1902     return FALSE;
1903   }
1904 set_fmt_failed:
1905   {
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)));
1912     return FALSE;
1913   }
1914 invalid_dimensions:
1915   {
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));
1921     return FALSE;
1922   }
1923 invalid_pixelformat:
1924   {
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)));
1932     return FALSE;
1933   }
1934 }
1935
1936 static gboolean resolution_is_supported(int w, int h)
1937 {
1938         return (w % 4) == 0 && (h % 4) == 0;
1939 }
1940
1941 #define probe_and_add_for_w_h(w, h)                                     \
1942         do{                                                             \
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); \
1946                 if(tmp)                                                 \
1947                         res = g_list_prepend(res, tmp);                 \
1948         } while(0)
1949
1950
1951 static GList *build_caps_list(GstMFLDV4l2CamSrc * v4l2camsrc,
1952         guint32 pixelformat, const GstStructure * template,
1953         struct v4l2_frmsizeenum *size)
1954 {
1955         GstStructure *tmp = NULL;
1956         GList *res = NULL;
1957         long wl,wh,hl,hh,ws,hs;
1958
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;
1961
1962         probe_and_add_for_w_h(wl, hl);
1963         probe_and_add_for_w_h(wh, hh);
1964
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,
1969                         NULL);
1970         res = g_list_prepend(res, tmp);
1971
1972         return res;
1973 }
1974
1975
1976 /**
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
1981  *
1982  * Creates GstCaps object which describes the supported caps of the device.
1983  *
1984  * Returns: GStCaps containing supported video resolutions.
1985  */
1986 GstCaps *
1987 gst_v4l2camsrc_probe_caps_for_format (GstMFLDV4l2CamSrc * v4l2camsrc,
1988     guint32 pixelformat, const GstStructure * template)
1989 {
1990   GstCaps *ret = gst_caps_new_empty ();
1991   gint min_w, max_w, min_h, max_h;
1992   GstStructure *tmp;
1993
1994 #ifdef VIDIOC_ENUM_FRAMESIZES
1995   {
1996     gint fd = v4l2camsrc->video_fd;
1997     struct v4l2_frmsizeenum size;
1998     GList *results = NULL;
1999     gint w, h;
2000
2001     memset (&size, 0, sizeof (struct v4l2_frmsizeenum));
2002     size.index = 0;
2003     size.pixel_format = pixelformat;
2004
2005     if (ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0)
2006       goto enum_framesizes_failed;
2007
2008     if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
2009       do {
2010         w = MIN (size.discrete.width, G_MAXINT);
2011         h = MIN (size.discrete.height, G_MAXINT);
2012
2013         if(resolution_is_supported(w, h)) {
2014                 tmp = gst_v4l2camsrc_probe_caps_for_format_and_size (v4l2camsrc,
2015                         pixelformat, w, h, template);
2016
2017                 if (tmp)
2018                         results = g_list_prepend (results, tmp);
2019         }
2020
2021         size.index++;
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);
2026     } else {
2027       goto unknown_type;
2028     }
2029
2030     /* Sort the resolutions from smallest to largest */
2031     results = g_list_sort (results, compare_resolutions);
2032
2033     while (results != NULL) {
2034       tmp = GST_STRUCTURE (results->data);
2035
2036       gst_caps_merge_structure (ret, tmp);
2037
2038       results = g_list_delete_link (results, results);
2039     }
2040
2041     if (gst_caps_is_empty (ret))
2042       goto enum_framesizes_no_results;
2043
2044     return ret;
2045
2046     /* ERRORS */
2047   enum_framesizes_failed:
2048     {
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;
2054     }
2055   enum_framesizes_no_results:
2056     {
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;
2063     }
2064   unknown_type:
2065     {
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;
2070     }
2071   }
2072 #endif /* defined VIDIOC_ENUM_FRAMESIZES */
2073
2074 default_frame_sizes:
2075
2076   min_w = min_h = 1;
2077   max_w = max_h = GST_CAMERA_SRC_MAX_SIZE;
2078   if (!gst_v4l2camsrc_get_nearest_size (v4l2camsrc, pixelformat,
2079           &min_w, &min_h)) {
2080     GST_WARNING_OBJECT (v4l2camsrc,
2081         "Could not probe minimum capture size for pixelformat %"
2082         GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2083   }
2084   if (!gst_v4l2camsrc_get_nearest_size (v4l2camsrc, pixelformat,
2085           &max_w, &max_h)) {
2086     GST_WARNING_OBJECT (v4l2camsrc,
2087         "Could not probe maximum capture size for pixelformat %"
2088         GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2089   }
2090
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);
2096
2097   return ret;
2098 }
2099
2100 static void draw_corner_markers_nv12(unsigned char *buf, unsigned w, unsigned h)
2101 {
2102         int i,j;
2103 #define put_dot(x,y) buf[(x)+w*(y)] = (((x+y)&0x01)?0x00:0xff)
2104
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);
2111                 }
2112 #undef put_dot
2113 }
2114
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)
2118 {
2119         unsigned rows;
2120         unsigned char *in, *out;
2121
2122         if(in_w < out_w || in_h < out_h
2123                 || in_w % 4 || out_w % 4
2124                 || in_h % 4 || out_h % 4)
2125                 return FALSE;
2126
2127         in = buf; out = buf;
2128         for(rows = 0; rows < out_h; ++rows) {
2129                 memmove(out, in, out_w);
2130                 in += in_w;
2131                 out += out_w;
2132         }
2133         in = buf + in_w * in_h;
2134         for(rows = 0; rows < out_h / 2; ++rows) {
2135                 memmove(out, in, out_w);
2136                 in += in_w;
2137                 out += out_w;
2138         }
2139
2140         return TRUE;
2141 }
2142
2143 /**
2144  * gst_v4l2camsrc_libmfld_grab_hq_frame:
2145  * @v4l2camsrc: #GstMFLDV4l2CamSrc object
2146  * @buf: Pointer to v4l2_buffer where to place the image frame
2147  *
2148  * Grab a High-Quality image by using libmfldcam.
2149  *
2150  * Returns: TRUE if capture succeeds, FALSE otherwise
2151  */
2152 gboolean
2153 gst_v4l2camsrc_libmfld_grab_hq_frame (GstMFLDV4l2CamSrc * v4l2camsrc,
2154     struct v4l2_buffer * buffer)
2155 {
2156   cam_err_t err;
2157   gboolean ret;
2158   struct cam_capture_settings st;
2159
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;
2165
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);
2170
2171   return ret;
2172 }
2173
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  ******************************************************/
2179 GstFlowReturn
2180 gst_v4l2camsrc_grab_frame (GstCameraSrc * camsrc, GstBuffer ** buf,
2181     GstCameraCapturePhase phase)
2182 {
2183   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2184
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 */
2191   gint index;
2192   gint ret;
2193   unsigned real_w;
2194
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);
2199
2200   memset (&buffer, 0x00, sizeof (buffer));
2201   buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2202
2203   if (v4l2camsrc->use_mmap)
2204     buffer.memory = V4L2_MEMORY_MMAP;
2205   else
2206     buffer.memory = V4L2_MEMORY_USERPTR;
2207
2208   if (phase == GST_CAMERA_CAPTURE) {
2209     gst_camerasrc_send_capture_start_message (camsrc);
2210   }
2211
2212   for (;;) {
2213     ret = gst_poll_wait (v4l2camsrc->poll, V4L2CAMSRC_POLL_TIMEOUT);
2214     if (G_UNLIKELY (ret < 0)) {
2215       if (errno == EBUSY)
2216         goto stopped;
2217       if (errno != EAGAIN && errno != EINTR)
2218         goto select_error;
2219     }
2220
2221     if (G_UNLIKELY (ret == 0)) {
2222       goto timeout;
2223     }
2224     g_mutex_lock (v4l2camsrc->device_mutex);
2225     ret = gst_v4l2camsrc_libmfld_grab_hq_frame (v4l2camsrc, &buffer);
2226     g_mutex_unlock (v4l2camsrc->device_mutex);
2227
2228     if (ret >= 0)
2229       break;
2230
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);
2235
2236     /* if the sync() got interrupted, we can retry */
2237     switch (errno) {
2238       case EAGAIN:
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);
2243         break;
2244       case EINVAL:
2245         goto einval;
2246       case ENOMEM:
2247         goto enomem;
2248       case EIO:
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))) {
2257           /* this fails
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);
2261              }
2262              else {
2263            */
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
2269            * return.
2270            */
2271           /*
2272              if (ioctl (v4l2camsrc->video_fd, VIDIOC_QBUF, &buffer) < 0) {
2273              goto qbuf_failed;
2274              }
2275            */
2276           /*} */
2277         }
2278         break;
2279       case EINTR:
2280         GST_WARNING_OBJECT (v4l2camsrc,
2281             "could not sync on a buffer on device %s", v4l2camsrc->videodev);
2282         break;
2283       default:
2284         GST_WARNING_OBJECT (v4l2camsrc,
2285             "Grabbing frame got interrupted on %s. No expected reason.",
2286             v4l2camsrc->videodev);
2287         break;
2288     }
2289
2290     /* check nr. of attempts to capture */
2291     if (--trials == -1) {
2292       goto too_many_trials;
2293     } else {
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;
2298       else
2299         buffer.memory = V4L2_MEMORY_USERPTR;
2300     }
2301   }
2302
2303   if (phase == GST_CAMERA_CAPTURE) {
2304     gst_camerasrc_send_capture_stop_message (camsrc);
2305   } else  {
2306     /* Send the CAF status message */
2307     GstCameraFocusStatus focus_status;
2308     gboolean lret;
2309     lret = gst_v4l2camsrc_check_focus_status(v4l2camsrc, &focus_status, FALSE);
2310     if (lret) {
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);
2316       else {
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);
2319       }
2320     }
2321   }
2322
2323
2324   g_mutex_lock (v4l2camsrc->pool->lock);
2325
2326   index = buffer.index;
2327
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
2330    * case). */
2331   pool_buffer = GST_BUFFER (v4l2camsrc->pool->buffers[index]);
2332
2333   if (G_UNLIKELY (pool_buffer == NULL))
2334     goto no_buffer;
2335
2336   GST_LOG_OBJECT (v4l2camsrc, "grabbed buffer %p at index %d (refct = %d)",
2337       pool_buffer, index, GST_MINI_OBJECT_REFCOUNT (pool_buffer));
2338
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;
2343
2344   /* SW workaround for ISP padding. */
2345
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) {
2349
2350     real_w = (v4l2camsrc->expected_capture_w & ~31) + 32;
2351
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);
2354
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");
2359     }
2360   }
2361
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);
2365
2366   g_mutex_unlock (v4l2camsrc->pool->lock);
2367
2368   /* this can change at every frame, esp. with jpeg */
2369   if(variable_frame_size)
2370           GST_BUFFER_SIZE (pool_buffer) = buffer.bytesused;
2371   else
2372           GST_BUFFER_SIZE (pool_buffer) = v4l2camsrc->frame_byte_size;
2373
2374   GST_BUFFER_OFFSET (pool_buffer) = v4l2camsrc->offset++;
2375   GST_BUFFER_OFFSET_END (pool_buffer) = v4l2camsrc->offset;
2376
2377   /* timestamps, LOCK to get clock and base time. */
2378   {
2379     GstClock *clock;
2380     GstClockTime timestamp;
2381
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);
2387     } else {
2388       /* no clock, can't set timestamps */
2389       timestamp = GST_CLOCK_TIME_NONE;
2390     }
2391     GST_OBJECT_UNLOCK (v4l2camsrc);
2392
2393     if (clock) {
2394       GstClockTime latency;
2395
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);
2399
2400       latency =
2401           gst_util_uint64_scale_int (GST_SECOND, camsrc->fps_d, camsrc->fps_n);
2402
2403       if (timestamp > latency)
2404         timestamp -= latency;
2405       else
2406         timestamp = 0;
2407       GST_BUFFER_DURATION (pool_buffer) = latency;
2408     }
2409     /* activate settings for next frame (Code from v4l2src) */
2410     if (GST_CLOCK_TIME_IS_VALID (camsrc->duration)) {
2411       v4l2camsrc->ctrl_time += camsrc->duration;
2412     } else {
2413       v4l2camsrc->ctrl_time = timestamp;
2414     }
2415     gst_object_sync_values (G_OBJECT (camsrc), v4l2camsrc->ctrl_time);
2416
2417     /* FIXME: use the timestamp from the buffer itself! */
2418     GST_BUFFER_TIMESTAMP (pool_buffer) = timestamp;
2419   }
2420
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);
2427   } else {
2428     if (v4l2camsrc->pool->is_vaapi_sharing)
2429         GST_BUFFER_DATA(pool_buffer) = (GST_V4L2CAMSRC_BUFFER(pool_buffer))->gbuffer;
2430     *buf = pool_buffer;
2431   }
2432
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);
2436
2437   return GST_FLOW_OK;
2438
2439   /* ERRORS */
2440 select_error:
2441   {
2442     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ, (NULL),
2443         ("select error %d: %s (%d)", ret, g_strerror (errno), errno));
2444     return GST_FLOW_ERROR;
2445   }
2446 stopped:
2447   {
2448     GST_DEBUG ("stop called");
2449     return GST_FLOW_WRONG_STATE;
2450   }
2451 einval:
2452   {
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;
2460   }
2461 enomem:
2462   {
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;
2468   }
2469 too_many_trials:
2470   {
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;
2477   }
2478 no_buffer:
2479   {
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;
2486   }
2487 /*
2488 qbuf_failed:
2489   {
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;
2496   }
2497 */
2498 timeout:
2499   {
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;
2504   }
2505 }
2506
2507
2508 /******************************************************
2509  * gst_v4l2camsrc_set_capture():
2510  *   set capture parameters for certain operation mode
2511  * return value: TRUE on success, FALSE on error
2512  ******************************************************/
2513 gboolean
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)
2517 {
2518   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2519   cam_err_t err = CAM_ERR_NONE;
2520   gboolean ret = TRUE;
2521
2522   GST_DEBUG_OBJECT (v4l2camsrc, "mode = %d, try_only = %d", mode, try_only);
2523
2524   v4l2camsrc->expected_capture_w = *width;
2525   v4l2camsrc->expected_capture_h = *height;
2526   v4l2camsrc->expected_capture_fourcc = *pixelformat;
2527
2528   if (mode == GST_PHOTOGRAPHY_OPERATION_MODE_PREVIEW) {
2529     return FALSE;
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));
2533
2534     if (try_only) {
2535       /* Round width & height down to be dividable by 4 */
2536       *width = (*width) & ~3;
2537       *height = (*height) & ~3;
2538       ret = TRUE;
2539     } else {
2540       ret = gst_v4l2camsrc_configure_device (v4l2camsrc, pixelformat,
2541           width, height, fps_n, fps_d);
2542
2543       v4l2camsrc->tmp_num_buffers = v4l2camsrc->num_buffers;
2544       v4l2camsrc->num_buffers = 1;
2545
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;
2551       }
2552       v4l2camsrc->capture_fourcc = *pixelformat;
2553     }
2554   } else {
2555     /* VIEWFINDER mode */
2556     /* FIXME: handle try_only mode */
2557
2558     v4l2camsrc->num_buffers = v4l2camsrc->tmp_num_buffers;
2559
2560     ret = gst_v4l2camsrc_configure_device (v4l2camsrc, pixelformat,
2561         width, height, fps_n, fps_d);
2562
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;
2569     }
2570   }
2571   if (err != CAM_ERR_NONE)
2572     ret = FALSE;
2573
2574   return ret;
2575 }
2576
2577 /******************************************************
2578  * gst_v4l2camsrc_capture_start():
2579  *   Start capturing frames from the device
2580  * return value: TRUE on success, FALSE on error
2581  ******************************************************/
2582 gboolean
2583 gst_v4l2camsrc_capture_start (GstCameraSrc * camsrc, GstCaps * caps)
2584 {
2585   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2586
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;
2591   cam_err_t err;
2592
2593   v4l2camsrc->offset = 0;
2594
2595   /* activate settings for first frame */
2596   v4l2camsrc->ctrl_time = 0;
2597   gst_object_sync_values (G_OBJECT (camsrc), v4l2camsrc->ctrl_time);
2598
2599   memset (&breq, 0, sizeof (struct v4l2_requestbuffers));
2600
2601   GST_DEBUG_OBJECT (v4l2camsrc, "initializing the capture system");
2602
2603   GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
2604   GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
2605
2606   if (!(v4l2camsrc->vcap.capabilities & V4L2_CAP_STREAMING))
2607     goto no_capture_method;
2608
2609   GST_DEBUG_OBJECT (v4l2camsrc, "STREAMING, requesting %d CAPTURE buffers",
2610       v4l2camsrc->num_buffers);
2611
2612   err = cam_driver_set_mipi_interrupt(fd,1);
2613   if (err != CAM_ERR_NONE)
2614     GST_DEBUG_OBJECT (v4l2camsrc, "MIPI interrupt enable FAILED !");
2615
2616   breq.count = v4l2camsrc->num_buffers;
2617   breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2618
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");
2624     }
2625   }
2626
2627   if (v4l2camsrc->use_mmap)
2628     breq.memory = V4L2_MEMORY_MMAP;
2629   else
2630     breq.memory = V4L2_MEMORY_USERPTR;
2631
2632   if (ioctl (fd, VIDIOC_REQBUFS, &breq) < 0)
2633     goto reqbufs_failed;
2634
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);
2638
2639   if (breq.count < GST_V4L2CAMSRC_MIN_BUFFERS)
2640     goto no_buffers;
2641
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");
2646   }
2647
2648   /* Map the buffers */
2649   GST_LOG_OBJECT (v4l2camsrc, "initiating buffer pool");
2650
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;
2657
2658   GST_INFO_OBJECT (v4l2camsrc, "capturing buffers");
2659
2660   GST_V4L2CAMSRC_SET_ACTIVE (v4l2camsrc);
2661
2662   GST_DEBUG_OBJECT (v4l2camsrc, "starting the capturing");
2663   GST_V4L2CAMSRC_CHECK_ACTIVE (v4l2camsrc);
2664
2665   if (!gst_v4l2camsrc_buffer_pool_activate (v4l2camsrc->pool, v4l2camsrc))
2666     goto pool_activate_failed;
2667
2668   if (ioctl (fd, VIDIOC_STREAMON, &type) < 0)
2669     goto streamon_failed;
2670
2671   v4l2camsrc->is_active = TRUE;
2672   GST_DEBUG_OBJECT (v4l2camsrc, "STREAMON called");
2673
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;
2678   }
2679
2680   if (v4l2camsrc->zoom_updated) {
2681     gst_v4l2camsrc_libmfldcam_set_zoom(v4l2camsrc, v4l2camsrc->zoom_factor);
2682     v4l2camsrc->zoom_updated = FALSE;
2683   }
2684
2685    cam_mode = find_item (gst_v4l2camsrc_capture_map,v4l2camsrc->capture_mode);
2686    cam_set_capture_mode (v4l2camsrc->video_fd, cam_mode);
2687
2688   return TRUE;
2689
2690   /* ERRORS */
2691 reqbufs_failed:
2692   {
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);
2699     return FALSE;
2700   }
2701 no_buffers:
2702   {
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);
2709     return FALSE;
2710   }
2711 buffer_pool_new_failed:
2712   {
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);
2718     return FALSE;
2719   }
2720 no_capture_method:
2721   {
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);
2726     return FALSE;
2727   }
2728 pool_activate_failed:
2729   {
2730     /* already errored */
2731     cam_driver_set_mipi_interrupt(fd, 0);
2732     return FALSE;
2733   }
2734 streamon_failed:
2735   {
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);
2740     return FALSE;
2741   }
2742 }
2743
2744 /******************************************************
2745  * gst_v4l2camsrc_capture_stop():
2746  *   stop streaming capture
2747  * return value: TRUE on success, FALSE on error
2748  ******************************************************/
2749 gboolean
2750 gst_v4l2camsrc_capture_stop (GstCameraSrc * camsrc)
2751 {
2752   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2753   struct v4l2_requestbuffers breq;
2754   gint fd = v4l2camsrc->video_fd;
2755   cam_err_t err;
2756
2757   gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2758
2759   memset(&breq, 0, sizeof(struct v4l2_requestbuffers));
2760
2761   GST_DEBUG_OBJECT (v4l2camsrc, "stopping capturing");
2762
2763   if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc)) {
2764     return TRUE;
2765   }
2766   if (!GST_V4L2CAMSRC_IS_ACTIVE (v4l2camsrc)) {
2767     return TRUE;
2768   }
2769
2770   err = cam_driver_set_mipi_interrupt(fd,0);
2771   if (err != CAM_ERR_NONE)
2772     GST_DEBUG_OBJECT (v4l2camsrc, "MIPI interrupt disable FAILED !");
2773
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;
2778
2779   GST_DEBUG_OBJECT (v4l2camsrc, "STREAMOFF called");
2780
2781   breq.count = 0;
2782   breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2783   if(v4l2camsrc->use_mmap)
2784           breq.memory = V4L2_MEMORY_MMAP;
2785   else
2786           breq.memory = V4L2_MEMORY_USERPTR;
2787
2788   GST_DEBUG_OBJECT (v4l2camsrc, "REQUEST 0 to finalize buffer");
2789
2790   if(ioctl(v4l2camsrc->video_fd, VIDIOC_REQBUFS, &breq) < 0)
2791     GST_DEBUG_OBJECT (v4l2camsrc, "Failed to REQUEST 0 to finalize buffer");
2792
2793
2794   if (v4l2camsrc->pool) {
2795     gst_v4l2camsrc_buffer_pool_destroy (v4l2camsrc->pool, v4l2camsrc);
2796     v4l2camsrc->pool = NULL;
2797   }
2798
2799   GST_V4L2CAMSRC_SET_INACTIVE (v4l2camsrc);
2800   v4l2camsrc->is_active = FALSE;
2801   mfldcam_3a_stop ();
2802
2803   return TRUE;
2804
2805   /* ERRORS */
2806 streamoff_failed:
2807   {
2808     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, CLOSE,
2809         ("Error stopping streaming capture from device '%s'.",
2810             v4l2camsrc->videodev), GST_ERROR_SYSTEM);
2811     return FALSE;
2812   }
2813 }
2814
2815 /*
2816  */
2817 static gboolean
2818 gst_v4l2camsrc_get_nearest_size (GstMFLDV4l2CamSrc * v4l2camsrc,
2819     guint32 pixelformat, gint * width, gint * height)
2820 {
2821   struct v4l2_format fmt;
2822   int fd;
2823   int r;
2824
2825   g_return_val_if_fail (width != NULL, FALSE);
2826   g_return_val_if_fail (height != NULL, FALSE);
2827
2828   GST_LOG_OBJECT (v4l2camsrc,
2829       "getting nearest size to %dx%d with format %" GST_FOURCC_FORMAT,
2830       *width, *height, GST_FOURCC_ARGS (pixelformat));
2831
2832   fd = v4l2camsrc->video_fd;
2833
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;
2841
2842 /* FIXME: Disable TRY_FMT check, driver is not returning anything useful yet */
2843 #if 0
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);
2852   }
2853
2854   if (r < 0) {
2855     /* The driver might not implement TRY_FMT, in which case we will try
2856        S_FMT to probe */
2857     if (errno != ENOTTY)
2858       return FALSE;
2859 #endif
2860
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))
2864       return FALSE;
2865
2866 #if 0
2867     GST_LOG_OBJECT (v4l2camsrc,
2868         "Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
2869 #endif
2870
2871     fmt.fmt.pix.width = *width;
2872     fmt.fmt.pix.height = *height;
2873
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);
2882     }
2883
2884     if (r < 0)
2885       return FALSE;
2886 #if 0
2887   }
2888 #endif
2889
2890   GST_LOG_OBJECT (v4l2camsrc,
2891       "got nearest size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
2892
2893   *width = fmt.fmt.pix.width;
2894   *height = fmt.fmt.pix.height;
2895
2896   return TRUE;
2897 }
2898
2899
2900 /******************************************************
2901  * gst_v4l2camsrc_set_crop():
2902  *   set cropping bounds
2903  * return value: TRUE on success, FALSE on error
2904  ******************************************************/
2905 static gboolean
2906 gst_v4l2camsrc_set_crop (GstMFLDV4l2CamSrc * v4l2camsrc,
2907     gint x, gint y, gint w, gint h)
2908 {
2909   gboolean ret = FALSE;
2910   struct v4l2_crop scrop;
2911   struct v4l2_crop gcrop;
2912   gint cx, cy, cw, ch;
2913   int fd;
2914
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;
2920
2921   memset (&scrop, 0, sizeof (scrop));
2922   scrop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2923
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;
2929
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);
2933
2934   g_mutex_lock (v4l2camsrc->device_mutex);
2935
2936   if (-1 == ioctl (fd, VIDIOC_S_CROP, &scrop) && errno != EINVAL) {
2937     goto s_crop_failed;
2938   }
2939
2940   if (-1 == ioctl (fd, VIDIOC_G_CROP, &gcrop)) {
2941     goto g_crop_failed;
2942   }
2943
2944   g_mutex_unlock (v4l2camsrc->device_mutex);
2945
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);
2949
2950 #if 0
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;
2954   }
2955 #endif
2956
2957   ret = TRUE;
2958
2959 done:
2960
2961   return ret;
2962
2963 /* ERRORS */
2964 s_crop_failed:
2965   g_mutex_unlock (v4l2camsrc->device_mutex);
2966   GST_DEBUG_OBJECT (v4l2camsrc, "VIDIOC_S_CROP not supported");
2967   goto done;
2968
2969 g_crop_failed:
2970   g_mutex_unlock (v4l2camsrc->device_mutex);
2971   GST_DEBUG_OBJECT (v4l2camsrc, "VIDIOC_G_CROP not supported");
2972   goto done;
2973
2974 #if 0
2975 crop_not_supported:
2976   g_mutex_unlock (v4l2camsrc->device_mutex);
2977   GST_DEBUG_OBJECT (v4l2camsrc, "Given crop value not accepted");
2978   goto done;
2979 #endif
2980 }
2981
2982
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  ******************************************************/
2988 static gboolean
2989 gst_v4l2camsrc_update_cropping (GstMFLDV4l2CamSrc * v4l2camsrc, gint width,
2990     gint height, gfloat zoom)
2991 {
2992   gfloat sensor_ar, reso_ar;
2993   gint crop_x, crop_y, crop_w, crop_h;
2994
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);
2998
2999   if (zoom < 1.0 || zoom > v4l2camsrc->max_zoom_factor) {
3000     GST_DEBUG_OBJECT (v4l2camsrc, "invalid zoom = %.2f", zoom);
3001     return FALSE;
3002   }
3003   if (!v4l2camsrc->crop_supported) {
3004     GST_DEBUG_OBJECT (v4l2camsrc, "crop not supported");
3005     return FALSE;
3006   }
3007
3008   sensor_ar = v4l2camsrc->vcrop.defrect.width /
3009       v4l2camsrc->vcrop.defrect.height;
3010   reso_ar = width / height;
3011
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;
3015   } else {
3016     crop_w = MAX (v4l2camsrc->vcrop.defrect.width, width) / zoom;
3017     crop_h = (height * v4l2camsrc->vcrop.defrect.width / width) / zoom;
3018   }
3019
3020   crop_x = ABS ((v4l2camsrc->vcrop.defrect.width - crop_w) / 2);
3021   crop_y = ABS ((v4l2camsrc->vcrop.defrect.height - crop_h) / 2);
3022
3023   GST_LOG_OBJECT (v4l2camsrc, "set cropping: x: %d, y: %d, w: %d, h: %d",
3024       crop_x, crop_y, crop_w, crop_h);
3025
3026   return gst_v4l2camsrc_set_crop (v4l2camsrc, crop_x, crop_y, crop_w, crop_h);
3027 }
3028
3029 /***************************************************************************
3030  * New MFLD Camera Code ****************************************************
3031  * *************************************************************************/
3032
3033 /* These map tables help to adapt the general photography interface to
3034  * different device implementations.
3035  *
3036  * Table index = Enumeration value from GstPhotography
3037  * Table value = Device/Implementation -specific setting value
3038  */
3039
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,
3048   -1
3049 };
3050
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,
3057   -1
3058 };
3059
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 */
3067   -1
3068 };
3069
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 */
3075   -1
3076 };
3077
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}
3085 };
3086
3087 static const gint gst_v4l2camsrc_focus_status_map[][2] =
3088 {
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 },
3093   { -1, -1 }
3094 };
3095
3096 static const gchar *cameralib_error_map[] = {
3097   "CAM_ERR_NONE",
3098   "CAM_ERR_PARAM",
3099   "CAM_ERR_UNSUPP",
3100   "CAM_ERR_HW",
3101   "CAM_ERR_SYS",
3102   "CAM_ERR_LEXIT",
3103   "CAM_ERR_DEPRECATED",
3104   "CAM_ERR_INVALID_STATE",
3105   "CAM_ERR_INTERNAL",
3106   "CAM_ERR_NOT_OPEN",
3107   "CAM_ERR_3A"
3108 };
3109
3110 /*
3111  *
3112  */
3113 static cam_exposure_iso_value_t
3114 gst_v4l2camsrc_libmfld_map_iso (guint iso)
3115 {
3116   guint i = 0;
3117
3118   while (gst_v4l2camsrc_iso_map[i][1] != 0) {
3119     if (iso >= gst_v4l2camsrc_iso_map[i][1]) {
3120       break;
3121     }
3122     i++;
3123   }
3124
3125   return gst_v4l2camsrc_iso_map[i][1];
3126 }
3127
3128
3129 /*
3130  *
3131  */
3132 static guint
3133 gst_v4l2camsrc_libmfld_reverse_map_iso (cam_exposure_iso_value_t iso)
3134 {
3135   guint i = 0;
3136
3137   while (gst_v4l2camsrc_iso_map[i][1] != 0) {
3138     if (iso == gst_v4l2camsrc_iso_map[i][0]) {
3139       break;
3140     }
3141     i++;
3142   }
3143
3144   return gst_v4l2camsrc_iso_map[i][1];
3145 }
3146
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 */
3151 };
3152
3153 /*
3154  * Return index of the item in the table.
3155  */
3156 static gint
3157 find_item (const gint table[], const gint item)
3158 {
3159   guint i = 0;
3160
3161   while (table[i] != -1) {
3162     if (table[i] == item)
3163       return i;
3164     i++;
3165   }
3166   return 0;
3167 }
3168
3169 gboolean
3170 gst_v4l2camsrc_read_settings (GstCameraSrc * camsrc,
3171     GstPhotoSettings * photoconf)
3172 {
3173   GstMFLDV4l2CamSrc *v4l2camsrc;
3174   gint32 wbmode, effect, scene, flash, focus;
3175   gint32 flicker;
3176   gint32 ev, iso, aperture, exposure, noise_reduction;
3177   cam_err_t err;
3178
3179   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3180
3181   g_mutex_lock (v4l2camsrc->device_mutex);
3182
3183   if (!v4l2camsrc->initialized) {
3184     GST_DEBUG ("Device not initialized");
3185     g_mutex_unlock (v4l2camsrc->device_mutex);
3186     return FALSE;
3187   }
3188
3189   GST_DEBUG ("Retrieving settings from camera");
3190
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]);
3194     goto error;
3195   }
3196
3197   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]);
3202     goto error;
3203   }
3204
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]);
3209     goto error;
3210   }
3211
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]);
3216     goto error;
3217   }
3218
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]);
3223     goto error;
3224   }
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]);
3229     goto error;
3230   }
3231
3232   err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_APERTURE,
3233       &aperture);
3234   if (err != CAM_ERR_NONE) {
3235     GST_DEBUG ("CAM_EXPOSURE_MANUAL_APERTURE query failed: %s",
3236         cameralib_error_map[err]);
3237     goto error;
3238   }
3239
3240   err =
3241       cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_TIME,
3242       &exposure);
3243   if (err != CAM_ERR_NONE) {
3244     GST_DEBUG ("CAM_EXPOSURE_MANUAL_TIME query failed: %s",
3245         cameralib_error_map[err]);
3246     goto error;
3247   }
3248
3249   err =
3250       cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_FLICKER_REDUCTION_MODE,
3251       &flicker);
3252   if (err != CAM_ERR_NONE) {
3253     GST_DEBUG ("CAM_GENERAL_FLICKER_REDUCTION_MODE query failed: %s",
3254         cameralib_error_map[err]);
3255     goto error;
3256   }
3257
3258   err =
3259       cam_feature_get (v4l2camsrc->video_fd, CAM_NOISE_REDUCTION_MODE,
3260       &noise_reduction);
3261   if (err != CAM_ERR_NONE) {
3262     GST_DEBUG ("CAM_NOISE_REDUCTION query failed: %s",
3263         cameralib_error_map[err]);
3264     goto error;
3265   }
3266
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);
3272
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;
3278
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);
3283
3284   g_mutex_unlock (v4l2camsrc->device_mutex);
3285
3286   return TRUE;
3287
3288 /* ERRORS */
3289 error:
3290   {
3291     g_mutex_unlock (v4l2camsrc->device_mutex);
3292     return FALSE;
3293   }
3294 }
3295 gboolean
3296 gst_v4l2camsrc_read_exif (GstCameraSrc * camsrc,
3297     GstCameraControlExifInfo *exif_info)
3298 {
3299   GstMFLDV4l2CamSrc *v4l2camsrc;
3300   cam_err_t err;
3301   int exposure = 0;
3302   struct atomisp_makernote_info maker_note;
3303   unsigned char *buf;
3304
3305   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3306
3307
3308   if (!v4l2camsrc->initialized) {
3309     GST_DEBUG ("Device not initialized");
3310     return FALSE;
3311   }
3312   buf = (unsigned char *)&maker_note;
3313
3314   GST_DEBUG ("Retrieving makernote from atomisp");
3315   err = cam_get_makernote (v4l2camsrc->video_fd, buf, 0);
3316
3317   if(err)
3318      goto error;
3319
3320   /* focal lenght */
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);
3331
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;
3338
3339
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);
3351
3352   GST_DEBUG ("flash used  : %d", exif_info->flash);
3353
3354   return TRUE;
3355
3356 /* ERRORS */
3357 error:
3358   {
3359     g_mutex_unlock (v4l2camsrc->device_mutex);
3360     return FALSE;
3361   }
3362 }
3363
3364 gboolean
3365 gst_v4l2camsrc_set_flash_mode (GstCameraSrc * camsrc,
3366     int value)
3367 {
3368   GstMFLDV4l2CamSrc *v4l2camsrc;
3369   cam_err_t err;
3370   gint32 flash;
3371
3372
3373   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3374
3375   g_mutex_lock (v4l2camsrc->device_mutex);
3376
3377   if (!v4l2camsrc->initialized) {
3378     GST_DEBUG ("Device not initialized");
3379     g_mutex_unlock (v4l2camsrc->device_mutex);
3380     return FALSE;
3381   }
3382
3383   switch (value) {
3384     case GST_CAMERA_STROBE_CAP_NONE:
3385     case GST_CAMERA_STROBE_CAP_OFF:
3386       flash = CAM_LIGHT_FLASH_MODE_OFF;
3387       break;
3388     case GST_CAMERA_STROBE_CAP_ON:
3389       flash = CAM_LIGHT_FLASH_MODE_ON;
3390       break;
3391     case GST_CAMERA_STROBE_CAP_AUTO:
3392       flash = CAM_LIGHT_FLASH_MODE_AUTO;
3393       break;
3394     case GST_CAMERA_STROBE_CAP_REDEYE:
3395       flash = CAM_LIGHT_FLASH_MODE_RED_EYE;
3396       break;
3397     default:
3398       flash = CAM_LIGHT_FLASH_MODE_OFF;
3399       break;
3400    }
3401
3402   GST_DEBUG_OBJECT (v4l2camsrc, "Set flash mode: %d",flash);
3403   err= cam_feature_set (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE,
3404         flash);
3405
3406   if(err)
3407     goto error;
3408
3409   g_mutex_unlock (v4l2camsrc->device_mutex);
3410
3411   return TRUE;
3412
3413 /* ERRORS */
3414 error:
3415   {
3416     g_mutex_unlock (v4l2camsrc->device_mutex);
3417     return FALSE;
3418   }
3419 }
3420
3421 gboolean
3422 gst_v4l2camsrc_set_focus_state(GstCameraSrc *camsrc,
3423      gint mode, gint range)
3424 {
3425   cam_err_t err = CAM_ERR_NONE;
3426   GST_DEBUG ("update focus mode and range");
3427
3428   err = cam_set_focus_mode(gst_v4l2camsrc_focus_map[mode], range);
3429   return(err == CAM_ERR_NONE);
3430 }
3431
3432
3433 gboolean
3434 gst_v4l2camsrc_write_settings (GstCameraSrc * camsrc,
3435     GstPhotoSettings * photoconf, gboolean scene_override)
3436 {
3437   GstMFLDV4l2CamSrc *v4l2camsrc;
3438   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3439   GST_DEBUG ("Write settings to libmfldcamd");
3440
3441   g_mutex_lock (v4l2camsrc->device_mutex);
3442
3443   if (!v4l2camsrc->initialized) {
3444     g_mutex_unlock (v4l2camsrc->device_mutex);
3445     GST_DEBUG ("Device not initialized");
3446     return FALSE;
3447   }
3448
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]);
3455   } else {
3456     GST_DEBUG ("Normal settings");
3457     cam_feature_set (v4l2camsrc->video_fd, CAM_AWB_MODE,
3458         gst_v4l2camsrc_wb_map[photoconf->wb_mode]);
3459
3460     cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE,
3461         gst_v4l2camsrc_effect_map[photoconf->tone_mode]);
3462
3463     cam_feature_set (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE,
3464         gst_v4l2camsrc_flash_map[photoconf->flash_mode]);
3465
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);
3471
3472     cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION,
3473         (gint) (photoconf->ev_compensation));
3474
3475     cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE,
3476                 gst_v4l2camsrc_libmfld_reverse_map_iso (photoconf->iso_speed));
3477
3478     cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_FLICKER_REDUCTION_MODE,
3479         gst_v4l2camsrc_flicker_map[photoconf->flicker_mode]);
3480
3481     cam_feature_set (v4l2camsrc->video_fd, CAM_NOISE_REDUCTION_MODE,
3482         photoconf->noise_reduction);
3483   }
3484   g_mutex_unlock (v4l2camsrc->device_mutex);
3485
3486   return TRUE;
3487 }
3488
3489 gboolean
3490 gst_v4l2camsrc_set_AeAafwindow (GstCameraSrc * camsrc, GstCameraSrc3a_window window)
3491 {
3492   GstMFLDV4l2CamSrc *v4l2camsrc;
3493   gboolean ret = TRUE;
3494
3495   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3496
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,
3501          window.weight);
3502
3503   v4l2camsrc->af_window = v4l2camsrc->ae_window  = *(GstCameraWindow*)&window;
3504
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);
3509   }
3510
3511   return ret;
3512 }
3513
3514 gboolean
3515 gst_v4l2camsrc_set_autofocus (GstCameraSrc * camsrc, gboolean on)
3516 {
3517   GstMFLDV4l2CamSrc *v4l2camsrc;
3518   gboolean ret = FALSE;
3519   cam_err_t err = CAM_ERR_NONE;
3520
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);
3526
3527   GST_DEBUG ("setting autofocus: %s", ret ? "ok" : "failed");
3528   return ret;
3529 }
3530 /*
3531  *
3532  */
3533 GstPhotoCaps
3534 gst_v4l2camsrc_get_capabilities (GstCameraSrc * camsrc)
3535 {
3536   GstPhotoCaps pcaps;
3537
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;
3544
3545   return pcaps;
3546 }
3547
3548 /*
3549  *
3550  */
3551 gboolean
3552 gst_v4l2camsrc_check_focus_status (GstMFLDV4l2CamSrc * v4l2camsrc,
3553                                    GstCameraFocusStatus *fs, gboolean detailed)
3554 {
3555   gboolean ret = FALSE;
3556   cam_focus_status_t status;
3557   gboolean update;
3558
3559   GST_DEBUG_OBJECT (v4l2camsrc, "Retrieving focus status");
3560
3561   update = cam_checkfocus_status (&status, (v4l2camsrc->debug_flags & GST_CAMERASRC_DEBUG_FLAGS_AUTO_FOCUS));
3562
3563   if (update == TRUE) {
3564     fs->status = cam_find_item_new (gst_v4l2camsrc_focus_status_map, status, TRUE);
3565     ret =  TRUE;
3566
3567     GST_DEBUG_OBJECT (v4l2camsrc, "Focus status: %d", fs->status);
3568   }
3569   return ret;
3570 }
3571
3572 gboolean
3573 gst_v4l2camsrc_set_capture_mode (GstCameraSrc * camsrc,
3574     GstCameraSrcCaptureMode mode)
3575 {
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;
3582   int binary;
3583   gint fd;
3584
3585   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3586
3587   fd = v4l2camsrc->video_fd;
3588
3589   cam_mode = find_item (gst_v4l2camsrc_capture_map, mode);
3590
3591   g_mutex_lock (v4l2camsrc->device_mutex);
3592
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));
3597
3598     parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3599     err = ioctl(fd, VIDIOC_G_PARM, &parm);
3600     if (err < 0) {
3601       GST_DEBUG("Unable to get frame rate: %s (%d).\n",
3602       strerror(errno), errno);
3603       goto done;
3604     }
3605     GST_DEBUG("Current frame rate: %u/%u\n",
3606         parm.parm.capture.timeperframe.numerator,
3607         parm.parm.capture.timeperframe.denominator);
3608
3609     GST_DEBUG("Current run mode: %04x\n", parm.parm.capture.capturemode);
3610
3611     switch (mode) {
3612       case GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER:
3613         binary = CI_MODE_PREVIEW;
3614         break;;
3615       case GST_CAMERA_SRC_CAPTURE_MODE_STILL:
3616         binary = CI_MODE_STILL_CAPTURE;
3617         break;
3618       case GST_CAMERA_SRC_CAPTURE_MODE_VIDEO:
3619         binary = CI_MODE_VIDEO;
3620         break;
3621       default:
3622         binary = CI_MODE_PREVIEW;
3623         break;
3624     }
3625     parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3626     parm.parm.capture.capturemode = binary;
3627
3628     GST_DEBUG("New run mode: %04x\n", parm.parm.capture.capturemode);
3629
3630     if (ioctl (fd, VIDIOC_S_PARM, &parm) < 0) {
3631       GST_DEBUG("Switch Mode failed !\n");
3632     }
3633
3634     ret = (err >= 0);
3635     GST_DEBUG_OBJECT (v4l2camsrc, "Setting capture mode done: %s",
3636         ret ? "OK" : "FAIL");
3637   }
3638   else {
3639     GST_DEBUG_OBJECT (v4l2camsrc, "Device not initialized");
3640   }
3641
3642 done:
3643   g_mutex_unlock (v4l2camsrc->device_mutex);
3644
3645   return ret;
3646 }
3647
3648 gboolean gst_v4l2camsrc_set_strobe_state (GstCameraSrc * camsrc,
3649     gboolean state)
3650
3651 {
3652   GstMFLDV4l2CamSrc *v4l2camsrc;
3653   gint fd;
3654   cam_err_t err = CAM_ERR_NONE;
3655
3656   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3657   fd = v4l2camsrc->video_fd;
3658
3659   err  = cam_set_flash (fd, state);
3660   return(err == CAM_ERR_NONE);
3661 }
3662 gboolean
3663 gst_libmfldcam_capture_correction_update (GstMFLDV4l2CamSrc * v4l2camsrc)
3664 {
3665   int fd = v4l2camsrc->video_fd;
3666   gboolean ret;
3667
3668   if (!v4l2camsrc->cc_updated)
3669     return TRUE;
3670
3671   if (v4l2camsrc->gdc_enabled)
3672     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_GDC, TRUE);
3673   else
3674     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_GDC, FALSE);
3675
3676   if (ret)
3677     goto set_cc_failed;
3678
3679   if (v4l2camsrc->cac_enabled)
3680     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_CAC, TRUE);
3681   else
3682     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_CAC, FALSE);
3683
3684   if (ret)
3685     goto set_cc_failed;
3686
3687   if (v4l2camsrc->dvs_enabled)
3688     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_DVS, TRUE);
3689   else
3690     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_DVS, FALSE);
3691
3692   if (ret)
3693     goto set_cc_failed;
3694
3695   if (v4l2camsrc->ee_enabled)
3696     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_EE, TRUE);
3697   else
3698     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_EE, FALSE);
3699
3700   if (ret)
3701     goto set_cc_failed;
3702
3703   if (v4l2camsrc->sc_enabled)
3704     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_SC, TRUE);
3705   else
3706     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_SC, FALSE);
3707
3708   if (ret)
3709     goto set_cc_failed;
3710
3711   if (v4l2camsrc->blc_enabled)
3712     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BLC, TRUE);
3713   else
3714     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BLC, FALSE);
3715
3716   if (v4l2camsrc->bpd_enabled)
3717     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BPD, TRUE);
3718   else
3719     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BPD, FALSE);
3720
3721   if (ret)
3722     goto set_cc_failed;
3723
3724   v4l2camsrc->cc_updated = FALSE;
3725
3726   if (ret)
3727     goto set_cc_failed;
3728
3729
3730   return TRUE;
3731
3732 set_cc_failed:
3733   GST_WARNING_OBJECT (v4l2camsrc, "Set capture correction failed \n");
3734   return FALSE;
3735
3736 }
3737
3738 /**
3739  * gst_v4l2camsrc_libmfldcam_set_zoom:
3740  * @v4l2camsrc: #GstMFLDV4l2CamSrc object.
3741  * @zoom: Desired zoom factor.
3742  *
3743  * Set the zoom factor for captured image.
3744  *
3745  * Returns: TRUE on success.
3746  */
3747 gboolean
3748 gst_v4l2camsrc_libmfldcam_set_zoom (GstMFLDV4l2CamSrc * v4l2camsrc, gfloat zoom)
3749 {
3750   cam_err_t err = CAM_ERR_NONE;
3751   gboolean ret;
3752
3753   GST_DEBUG_OBJECT (v4l2camsrc, "ZOOM: %f", zoom);
3754
3755   err = cam_set_zoom (v4l2camsrc->video_fd, zoom);
3756   /* ret = err == CAM_ERR_NONE; */
3757   ret = TRUE;
3758
3759   GST_DEBUG_OBJECT (v4l2camsrc, "Setting zoom: %s", ret ? "SUCCESS" : "FAIL");
3760
3761   return ret;
3762 }
3763
3764 gboolean
3765 gst_v4l2camsrc_libmfldcam_get_makernote (GstMFLDV4l2CamSrc * v4l2camsrc, unsigned char *buf, unsigned size)
3766 {
3767   cam_err_t err = CAM_ERR_NONE;
3768
3769   GST_DEBUG_OBJECT (v4l2camsrc, "%s, !!!!!!line:%d\n", __func__, __LINE__);
3770
3771   err = cam_get_makernote (v4l2camsrc->video_fd, buf, size);
3772   return err;
3773 }
3774
3775 gboolean
3776 gst_v4l2camsrc_libmfldcam_get_focus_posi(GstMFLDV4l2CamSrc * v4l2camsrc, unsigned *posi)
3777 {
3778   cam_err_t err = CAM_ERR_NONE;
3779   err = cam_get_focus_posi(v4l2camsrc->video_fd, posi);
3780   if(err != CAM_ERR_NONE)
3781     return FALSE;
3782
3783   return TRUE;
3784 }
3785
3786 /**
3787  * @v4l2camsrc: #GstMFLDV4l2CamSrc object
3788  *
3789  * configure driver default settings and set the opened ISP fd to libmfldcam
3790  */
3791 gboolean
3792 gst_v4l2camsrc_libmfldcam_init (GstMFLDV4l2CamSrc * v4l2camsrc)
3793 {
3794   cam_err_t err;
3795   struct v4l2_input input;
3796   int ret;
3797   char *name, *space;
3798
3799   memset(&input, 0, sizeof(input));
3800   if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_PRIMARY)
3801     input.index = V2L2_CAMERA_INPUT_SENSOR_PRIMARY;
3802   else
3803     input.index = V2L2_CAMERA_INPUT_SENSOR_SECONDARY;
3804
3805   ret = ioctl(v4l2camsrc->video_fd, VIDIOC_ENUMINPUT, &input);
3806   if (ret < 0) {
3807     return FALSE;
3808   }
3809   name = (char*)input.name;
3810   space = strchr(name, ' ');
3811   if (space > name) {
3812       name[space - name] = '\0';
3813   }
3814   GST_DEBUG_OBJECT (v4l2camsrc, "sensor name %s", name);
3815
3816   err = cam_driver_init (v4l2camsrc->video_fd, name);
3817
3818   if (err != CAM_ERR_NONE) {
3819     GST_WARNING ("libmfldcam initialization failed");
3820     return FALSE;
3821   }
3822   if (v4l2camsrc->cc_updated)
3823     gst_libmfldcam_capture_correction_update (v4l2camsrc);
3824
3825   if (v4l2camsrc->gamma_updated) {
3826     cam_set_tone_control (v4l2camsrc->video_fd, CAM_GAMMA_VALUE,
3827         &v4l2camsrc->tone);
3828     cam_set_tone_control (v4l2camsrc->video_fd, CAM_BRIGHTNESS_VALUE,
3829         &v4l2camsrc->tone);
3830     cam_set_tone_control (v4l2camsrc->video_fd, CAM_CONTRAST_VALUE,
3831         &v4l2camsrc->tone);
3832     v4l2camsrc->gamma_updated = FALSE;
3833   }
3834
3835   /* Set the default settings here */
3836   //FIXME
3837   GST_DEBUG_OBJECT (v4l2camsrc, "Configure default settings %s",
3838       v4l2camsrc->videodev);
3839
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);
3844   }
3845
3846   v4l2camsrc->initialized = TRUE;
3847   v4l2camsrc->is_open = TRUE;
3848   return TRUE;
3849 }
3850
3851 gboolean
3852 gst_v4l2camsrc_libmfldcam_deinit (GstMFLDV4l2CamSrc * v4l2camsrc)
3853 {
3854   //FIXME : determin whether is it initialized
3855   cam_err_t err;
3856   err = cam_driver_deinit (v4l2camsrc->video_fd);
3857   if (err != CAM_ERR_NONE) {
3858     GST_WARNING ("libmfldcam initialization failed");
3859     return FALSE;
3860   }
3861   //FIXME
3862   v4l2camsrc->is_open = FALSE;
3863   return TRUE;
3864 }
3865
3866 gboolean
3867 gst_v4l2camsrc_open_second(GstCameraSrc *base)
3868 {
3869   struct stat st;
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);
3873
3874   GST_DEBUG_OBJECT (src, "Trying to open %s", video_name);
3875
3876   if (GST_V4L2CAMSRC_IS_SECOND_OPEN(src)) {
3877     GST_WARNING("second video already opened");
3878     return FALSE;
3879   }
3880
3881   /* check if it is a device */
3882   if (stat (video_name, &st) == -1)
3883     goto failed;
3884
3885   if (!S_ISCHR (st.st_mode))
3886     goto failed;
3887
3888   /* open the device */
3889   src->second_video_fd =
3890       open (video_name, O_RDWR /* | O_NONBLOCK */ );
3891
3892   if (!GST_V4L2CAMSRC_IS_SECOND_OPEN (src))
3893     goto failed;
3894
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);
3898   return TRUE;
3899
3900 failed:
3901   GST_WARNING("open second video %s failed", video_name);
3902
3903
3904 }
3905
3906 gboolean
3907 gst_v4l2camsrc_close_second(GstCameraSrc *base)
3908 {
3909   GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
3910   const gchar *video_name = GST_V4L2CAMSRC_SECOND_VIDEO_DEFAULT_NAME;
3911
3912   GstPollFD pollfd = GST_POLL_FD_INIT;
3913
3914   GST_DEBUG_OBJECT (src, "Trying to close %s", video_name);
3915
3916   if (!GST_V4L2CAMSRC_IS_SECOND_OPEN(src)) {
3917     return TRUE;
3918   }
3919
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;
3924
3925   return TRUE;
3926 }
3927
3928 gboolean
3929 gst_v4l2camsrc_set_second_capture_mode(GstCameraSrc *base)
3930 {
3931   GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
3932   struct v4l2_streamparm parm;
3933   guint fd = src->second_video_fd;
3934   int ret = 0;
3935
3936   memset(&parm, 0, sizeof(parm));
3937   parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3938
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);
3943     goto done;
3944   }
3945   parm.parm.capture.capturemode = CI_MODE_VIDEO;
3946
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);
3950   }
3951
3952 done:
3953   g_mutex_unlock (src->device_mutex);
3954   return (ret == 0);
3955 }
3956
3957 gboolean
3958 gst_v4l2camsrc_set_second_capture(
3959     GstCameraSrc *base,
3960     guint32 *pixelformat,
3961     guint *width, guint32 *height,
3962     guint *fps_n, guint *fps_d
3963 )
3964 {
3965   GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
3966   gint fd = src->second_video_fd;
3967   struct v4l2_format format;
3968   struct v4l2_streamparm stream;
3969
3970   GST_DEBUG_OBJECT(src, "try set second capture");
3971
3972   memset (&format, 0, sizeof (struct v4l2_format));
3973   format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3974
3975   if (ioctl (fd, VIDIOC_G_FMT, &format) < 0)
3976     goto failed;
3977
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;
3983
3984   if (ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
3985     if (errno != EINVAL)
3986       goto failed;
3987
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)
3994       goto failed;
3995   }
3996
3997   if (format.fmt.pix.width != *width || format.fmt.pix.height != *height
3998       || format.fmt.pix.pixelformat != *pixelformat)
3999     goto invalid_info;
4000
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");
4005     goto done;
4006   }
4007
4008   if (fps_n == NULL || fps_d == NULL) {
4009     goto done;
4010   }
4011
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)) {
4016     goto done;
4017   }
4018
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)");
4023     goto done;
4024   }
4025
4026   stream.parm.capture.timeperframe.numerator = *fps_d;
4027   stream.parm.capture.timeperframe.denominator = *fps_n;
4028
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");
4033     goto done;
4034   }
4035
4036 done:
4037   src->second_frame_byte_size = gst_v4l2camsrc_get_frame_size (*pixelformat,
4038       width, height);
4039   return TRUE;
4040
4041 invalid_info:
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);
4049
4050 failed:
4051   GST_WARNING_OBJECT(src, "set second capture failed");
4052   return FALSE;
4053 }
4054
4055 gboolean
4056 gst_v4l2camsrc_start_second(GstCameraSrc *base, GstCaps *caps)
4057 {
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;
4062
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;
4068   //else
4069     breq.memory = V4L2_MEMORY_USERPTR;
4070
4071   if (ioctl (fd, VIDIOC_REQBUFS, &breq) < 0)
4072     goto failed;
4073
4074   GST_DEBUG_OBJECT(src,
4075       "Second video request buffer, count:%d, type:%d, memory:%d",
4076       breq.count, breq.type, breq.memory);
4077
4078   if (breq.count < GST_V4L2CAMSRC_MIN_BUFFERS)
4079     goto failed;
4080
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;
4084   }
4085
4086   /*init second pool*/
4087   if (!(src->second_pool =
4088           gst_v4l2camsrc_buffer_pool_new (src, fd,
4089               src->second_num_buffers, caps,
4090               FALSE, TRUE,
4091               src->second_frame_byte_size, GST_CAMERA_SRC_SECOND_PAD(src))))
4092     goto failed;
4093
4094   GST_DEBUG_OBJECT (src, "second video capturing buffers");
4095
4096   if (!gst_v4l2camsrc_buffer_pool_activate (src->second_pool, src))
4097     goto failed;
4098
4099   if (ioctl (fd, VIDIOC_STREAMON, &type) < 0)
4100     goto failed;
4101
4102   GST_DEBUG_OBJECT (src, "second video STREAMON called");
4103   return TRUE;
4104
4105 failed:
4106   GST_ERROR_OBJECT(src, "second video start failed.");
4107   return FALSE;
4108 }
4109
4110 GstFlowReturn
4111 gst_v4l2camsrc_create_second_buffer(GstCameraSrc *base, GstBuffer **buf)
4112 {
4113   GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
4114   gint fd = src->second_video_fd;
4115   struct v4l2_buffer v4l2_buffer;
4116   GstV4l2Buffer *pool_buf;
4117   guint retry = 5;
4118   gint index;
4119   gint ret;
4120
4121   gst_v4l2_buffer_pool_update (src->second_pool, src, src->second_num_buffers);
4122
4123   for (;;) {
4124     ret = gst_poll_wait (src->second_poll, V4L2CAMSRC_SECOND_POLL_TIMEOUT);
4125     if (G_UNLIKELY (ret < 0)) {
4126       if (errno == EBUSY)
4127         goto busy;
4128       if (errno != EAGAIN && errno != EINTR)
4129         goto failed;
4130     }
4131
4132     if (G_UNLIKELY (ret == 0)) {
4133       goto timeout;
4134     }
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);
4141
4142     if (ret >= 0)
4143       break;
4144
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);
4149
4150     /* if the sync() got interrupted, we can retry */
4151     switch (errno) {
4152       case EAGAIN:
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");
4156         break;
4157       case EINVAL:
4158         goto failed;
4159       case ENOMEM:
4160         goto failed;
4161       case EIO:
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 ? */
4169         break;
4170       case EINTR:
4171         GST_WARNING_OBJECT (src,
4172             "could not sync on a buffer on device /dev/video1");
4173         break;
4174       default:
4175         GST_WARNING_OBJECT (src,
4176             "Grabbing frame got interrupted on /dev/video1. No expected reason.");
4177         break;
4178     }
4179
4180     if (++retry > 5)
4181       goto failed;
4182   }
4183
4184   index = v4l2_buffer.index;
4185
4186   g_mutex_lock (src->second_pool->lock);
4187
4188   pool_buf = src->second_pool->buffers[index];
4189
4190   if (G_UNLIKELY (pool_buf == NULL))
4191     goto failed;
4192
4193   //GST_LOG_OBJECT (src, "grabbed buffer %p at index %d (refct = %d)",
4194   //    pool_buffer, index, GST_MINI_OBJECT_REFCOUNT (pool_buffer));
4195
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;
4200
4201   g_mutex_unlock (src->second_pool->lock);
4202
4203   GST_BUFFER_SIZE (pool_buf) = src->second_frame_byte_size;
4204
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);
4208
4209   return GST_FLOW_OK;
4210
4211 busy:
4212   return GST_FLOW_WRONG_STATE;
4213 timeout:
4214 failed:
4215   return GST_FLOW_ERROR;
4216 }
4217
4218 void
4219 gst_v4l2camsrc_stop_second_wait(GstCameraSrc *base)
4220 {
4221   GstMFLDV4l2CamSrc *src = GST_V4L2CAMSRC_CAST (base);
4222   gst_poll_set_flushing (src->second_poll, TRUE);
4223 }