Set 50Hz flicker detection as default for secondary camera.
[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 extern guint gst_camerasrc_signals[CAMERA_IN_LAST_SIGNAL];
56
57 static const gint gst_v4l2camsrc_capture_map[] = {
58   CAM_VIEWFINDER_MODE_VIEWFINDER,
59   CAM_VIEWFINDER_MODE_STILL_CAPTURE,
60   CAM_VIEWFINDER_MODE_VIDEO_RECORD,
61   -1
62 };
63
64 static const gint gst_v4l2camsrc_effect_map[] = {
65   CAM_GENERAL_EFFECT_TYPE_NORMAL,
66   CAM_GENERAL_EFFECT_TYPE_SEPIA,
67   CAM_GENERAL_EFFECT_TYPE_NEGATIVE,
68   CAM_GENERAL_EFFECT_TYPE_GRAYSCALE,
69   CAM_GENERAL_EFFECT_TYPE_NORMAL,
70   CAM_GENERAL_EFFECT_TYPE_VIVID,
71   CAM_GENERAL_EFFECT_TYPE_NORMAL,
72   CAM_GENERAL_EFFECT_TYPE_NORMAL,
73   CAM_GENERAL_EFFECT_TYPE_NORMAL,
74   CAM_GENERAL_EFFECT_TYPE_SKY_BLUE,
75   CAM_GENERAL_EFFECT_TYPE_GRASS_GREEN,
76   CAM_GENERAL_EFFECT_TYPE_SKIN_WHITEN,
77   -1
78 };
79
80 static const gint gst_v4l2camsrc_wb_map[] = {
81   CAM_AWB_MODE_AUTO,
82   CAM_AWB_MODE_DAYLIGHT,
83   CAM_AWB_MODE_SUNSET,
84   CAM_AWB_MODE_CLOUDY,
85   CAM_AWB_MODE_TUNGSTEN,
86   CAM_AWB_MODE_FLUORESCENT,
87   -1
88 };
89
90
91 static gint find_item (const gint table[], const gint item);
92 /* Define this to use memory locking for video buffers */
93 /* #define USE_MLOCK */
94
95 /* lalala... */
96 #define GST_V4L2CAMSRC_SET_ACTIVE(element) (element)->buffer = GINT_TO_POINTER (-1)
97 #define GST_V4L2CAMSRC_SET_INACTIVE(element) (element)->buffer = NULL
98
99 /* On some systems MAP_FAILED seems to be missing */
100 #ifndef MAP_FAILED
101 #define MAP_FAILED ((caddr_t) -1)
102 #endif
103
104 #define RESIZER_MAX_DOWNSCALE_FACTOR 4
105 #define V4L2CAMSRC_POLL_TIMEOUT (20 * GST_SECOND)
106
107 #define GST_TYPE_V4L2CAMSRC_BUFFER (gst_v4l2camsrc_buffer_get_type())
108 #define GST_IS_V4L2CAMSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2CAMSRC_BUFFER))
109 #define GST_V4L2CAMSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2CAMSRC_BUFFER, GstV4l2Buffer))
110
111 /* Local functions */
112 static gboolean
113 gst_v4l2camsrc_get_nearest_size (GstMFLDV4l2CamSrc * v4l2camsrc,
114     guint32 pixelformat, gint * width, gint * height);
115 static void gst_v4l2camsrc_buffer_pool_destroy (GstMFLDV4l2CamSrcBufferPool *
116     pool, GstMFLDV4l2CamSrc * v4l2camsrc);
117 static gboolean gst_v4l2camsrc_update_cropping (GstMFLDV4l2CamSrc * v4l2camsrc,
118     gint width, gint height, gfloat zoom);
119 static gboolean
120 gst_v4l2camsrc_check_focus_status (GstMFLDV4l2CamSrc * v4l2camsrc,
121                                    GstCameraFocusStatus *fs, gboolean detailed);
122
123 static gboolean gst_v4l2camsrc_libmfldcam_init (GstMFLDV4l2CamSrc * v4l2camsrc);
124 static gboolean gst_v4l2camsrc_libmfldcam_deinit (GstMFLDV4l2CamSrc *
125     v4l2camsrc);
126
127 /*
128  * GstCameraBuffer:
129  */
130
131 static GstBufferClass *v4l2buffer_parent_class = NULL;
132
133 static void
134 gst_v4l2camsrc_buffer_finalize (GstV4l2Buffer * buffer)
135 {
136   GstMFLDV4l2CamSrcBufferPool *pool;
137   gboolean resuscitated = FALSE;
138   struct v4l2_buffer *vbuffer;
139   gint index;
140
141   pool = buffer->pool;
142   vbuffer = (struct v4l2_buffer *) buffer->vbuffer;
143   index = vbuffer->index;
144
145   GST_LOG ("finalizing buffer %p %d", buffer, index);
146
147   g_mutex_lock (pool->lock);
148   if (GST_BUFFER_SIZE (buffer) != 0)
149     /* BUFFER_SIZE is only set if the frame was dequeued */
150     pool->num_live_buffers--;
151
152   if (pool->running) {
153     if (pool->is_vaapi_sharing && buffer->gbuffer)
154       GST_BUFFER_DATA(buffer) = GST_BUFFER_DATA(buffer->gbuffer);
155     if (ioctl (pool->video_fd, VIDIOC_QBUF, vbuffer) < 0) {
156       GST_WARNING ("could not requeue buffer %p %d", buffer, index);
157     } else {
158       /* FIXME: check that the caps didn't change */
159       GST_LOG ("reviving buffer %p, %d", buffer, index);
160       gst_buffer_ref (GST_BUFFER (buffer));
161       GST_BUFFER_SIZE (buffer) = 0;
162       pool->buffers[index] = buffer;
163       pool->queued[index] = 1;
164       g_cond_signal (pool->data_cond);
165       resuscitated = TRUE;
166     }
167   } else {
168     GST_LOG ("the pool is shutting down");
169   }
170   g_mutex_unlock (pool->lock);
171
172   if (!resuscitated) {
173     GST_LOG ("buffer %p not recovered, unmapping", buffer);
174     if (buffer->use_mmap)
175       munmap ((void *) GST_BUFFER_DATA (buffer), vbuffer->length);
176     gst_mini_object_unref (GST_MINI_OBJECT (pool));
177
178     if (!buffer->use_mmap) {
179       if (buffer->gbuffer) {
180         /* It was allocated with gst_pad_alloc_buffer */
181         /* FIXME temporal fix for double free error */
182         if (pool->is_vaapi_sharing)
183           gst_buffer_unref (buffer->gbuffer);
184         buffer->gbuffer = NULL;
185       } else {
186         /* It was allocated with posix_memalign */
187         free (GST_BUFFER_DATA (buffer));
188       }
189     }
190
191     GST_BUFFER_DATA (buffer) = NULL;
192
193     g_free (buffer->vbuffer);
194
195     GST_LOG ("free v4l2buffer");
196     GST_MINI_OBJECT_CLASS (v4l2buffer_parent_class)->finalize (GST_MINI_OBJECT
197         (buffer));
198   }
199 }
200
201 static void
202 gst_v4l2camsrc_buffer_class_init (gpointer g_class, gpointer class_data)
203 {
204   GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
205
206   v4l2buffer_parent_class = g_type_class_peek_parent (g_class);
207
208   mini_object_class->finalize =
209       (GstMiniObjectFinalizeFunction) gst_v4l2camsrc_buffer_finalize;
210 }
211
212 static GType
213 gst_v4l2camsrc_buffer_get_type (void)
214 {
215   static GType _gst_v4l2camsrc_buffer_type;
216
217   if (G_UNLIKELY (_gst_v4l2camsrc_buffer_type == 0)) {
218     static const GTypeInfo v4l2camsrc_buffer_info = {
219       sizeof (GstBufferClass),
220       NULL,
221       NULL,
222       gst_v4l2camsrc_buffer_class_init,
223       NULL,
224       NULL,
225       sizeof (GstV4l2Buffer),
226       0,
227       NULL,
228       NULL
229     };
230     _gst_v4l2camsrc_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
231         "GstCameraBuffer", &v4l2camsrc_buffer_info, 0);
232   }
233   return _gst_v4l2camsrc_buffer_type;
234 }
235
236 static GstV4l2Buffer *
237 gst_v4l2camsrc_buffer_new (GstMFLDV4l2CamSrcBufferPool * pool,
238     GstCameraSrc * camsrc, guint index, GstCaps * caps)
239 {
240   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
241   GstV4l2Buffer *ret = NULL;
242   GstFlowReturn flow_ret;
243   GstBuffer *buf_cap_signal2 = NULL;      /*output main buffer for capture signal*/
244   struct v4l2_buffer *vbuffer;
245
246   ret = (GstV4l2Buffer *) gst_mini_object_new (GST_TYPE_V4L2CAMSRC_BUFFER);
247   ret->use_mmap = v4l2camsrc->use_mmap;
248   vbuffer = ret->vbuffer = g_new0 (struct v4l2_buffer, 1);
249   GST_LOG ("creating buffer %u, %p in pool %p", index, ret, pool);
250   ret->pool =
251       (GstMFLDV4l2CamSrcBufferPool *)
252       gst_mini_object_ref (GST_MINI_OBJECT (pool));
253
254   vbuffer->index = index;
255   vbuffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
256
257   if (v4l2camsrc->use_mmap)
258     vbuffer->memory = V4L2_MEMORY_MMAP;
259   else
260     vbuffer->memory = V4L2_MEMORY_USERPTR;
261
262   vbuffer->length = v4l2camsrc->frame_byte_size;
263   ret->gbuffer = NULL;
264
265   if (ioctl (pool->video_fd, VIDIOC_QUERYBUF, vbuffer) < 0)
266     goto querybuf_failed;
267
268   if (v4l2camsrc->use_mmap) {
269     void *data;
270     data = (guint8 *) mmap (0, vbuffer->length,
271         PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd, vbuffer->m.offset);
272     if (data == MAP_FAILED)
273       goto mmap_failed;
274     GST_BUFFER_DATA (ret) = (guint8 *) data;
275   } else {
276
277     if (v4l2camsrc->capture_mode == GST_CAMERA_SRC_CAPTURE_MODE_STILL) {
278
279         /*call signal*/
280         /* alloc buffer for capture callback */
281       buf_cap_signal2 = gst_buffer_new ();
282
283       GST_BUFFER_DATA(buf_cap_signal2) = NULL;
284       GST_BUFFER_SIZE(buf_cap_signal2) = 0;
285       GST_BUFFER_CAPS(buf_cap_signal2) = gst_caps_new_simple("video/x-raw-yuv",
286           "format", GST_TYPE_FOURCC, v4l2camsrc->capture_fourcc,
287           "width", G_TYPE_INT,  v4l2camsrc->capture_w,
288           "height", G_TYPE_INT,v4l2camsrc->capture_h,
289           NULL);
290
291       GST_LOG_OBJECT (camsrc, "CALL: usrptr callback");
292       g_signal_emit( G_OBJECT (camsrc),
293           gst_camerasrc_signals[CAMERA_IN_SIGNAL_STILL_USRPTR_BUFFER],
294           0,
295           buf_cap_signal2);
296
297       if (GST_BUFFER_DATA(buf_cap_signal2) == NULL)
298         goto usrptr_alloc_failed;
299
300       GST_LOG_OBJECT (camsrc, "RETURN: usrptr callback: buf=%p, size=%d",
301           GST_BUFFER_DATA(buf_cap_signal2), GST_BUFFER_SIZE(buf_cap_signal2));
302       GST_BUFFER_DATA (ret) = GST_BUFFER_DATA(buf_cap_signal2);
303       gst_buffer_unref(buf_cap_signal2);
304
305     } else {
306       if (gst_pad_is_linked (GST_BASE_SRC_PAD (v4l2camsrc))) {
307         GST_LOG ("using pad_alloc, size=%d", v4l2camsrc->frame_byte_size);
308         GST_LOG ("ALLOC CAPS: %" GST_PTR_FORMAT, caps);
309
310         flow_ret =
311             gst_pad_alloc_buffer_and_set_caps (GST_BASE_SRC_PAD (v4l2camsrc), 0LL,
312             v4l2camsrc->frame_byte_size, caps, &ret->gbuffer);
313         if (flow_ret != GST_FLOW_OK)
314           goto pad_alloc_failed;
315         GST_BUFFER_DATA (ret) = ret->gbuffer->data;
316       } else {
317         void *data;
318
319         GST_LOG ("using posix_memalign");
320         if (posix_memalign (&data, getpagesize (), vbuffer->length) != 0) {
321           goto memalign_failed;
322         }
323         GST_BUFFER_DATA (ret) = (guint8 *) data;
324       }
325     }
326   }
327
328   GST_BUFFER_SIZE (ret) = v4l2camsrc->frame_byte_size;
329   GST_BUFFER_FLAG_SET (ret, GST_BUFFER_FLAG_READONLY);
330   gst_buffer_set_caps (GST_BUFFER (ret), caps);
331
332 #ifdef USE_MLOCK
333   GST_DEBUG ("mlocking buffer data");
334   if (mlock ((void *) GST_BUFFER_DATA (ret), v4l2camsrc->frame_byte_size) == -1)
335     goto mlock_failed;
336 #endif
337
338   /* mlocking succeeded, now we can set the pointer to vbuffer. The existence
339    * of this pointer will be used later to determine if the munlock() is
340    * needed */
341   if (!v4l2camsrc->use_mmap)
342     vbuffer->m.userptr = (unsigned int) GST_BUFFER_DATA (ret);
343
344
345 #if 1
346   GST_LOG ("  index:     %u", vbuffer->index);
347   GST_LOG ("  type:      %d", vbuffer->type);
348   GST_LOG ("  bytesused: %u", vbuffer->bytesused);
349   GST_LOG ("  flags:     %08x", vbuffer->flags);
350   GST_LOG ("  field:     %d", vbuffer->field);
351   GST_LOG ("  memory:    %d", vbuffer->memory);
352   if (vbuffer->memory == V4L2_MEMORY_MMAP)
353     GST_LOG ("  MMAP offset:  %p", vbuffer->m.offset);
354   else if (vbuffer->memory == V4L2_MEMORY_USERPTR)
355     GST_LOG ("  user address: %p", vbuffer->m.userptr);
356   GST_LOG ("  length:    %u", vbuffer->length);
357   GST_LOG ("  input:     %u", vbuffer->input);
358 #endif
359
360   return ret;
361
362   /* ERRORS */
363 #ifdef USE_MLOCK
364 mlock_failed:
365   {
366     GST_WARNING ("Failed to mlock memory: %s", g_strerror (errno));
367     gst_buffer_unref (GST_BUFFER (ret));
368     g_free (vbuffer);
369     return NULL;
370   }
371 #endif
372 querybuf_failed:
373   {
374     gint errnosave = errno;
375
376     GST_WARNING ("Failed QUERYBUF: %s", g_strerror (errnosave));
377     gst_buffer_unref (GST_BUFFER (ret));
378     g_free (vbuffer);
379     errno = errnosave;
380     return NULL;
381   }
382 memalign_failed:
383   {
384     GST_WARNING ("Failed to posix_memalign a buffer");
385     g_free (vbuffer);
386     return NULL;
387   }
388 pad_alloc_failed:
389   {
390     GST_WARNING ("Failed to pad_alloc_buffer: %s",
391         gst_flow_get_name (flow_ret));
392     g_free (vbuffer);
393     return NULL;
394   }
395 usrptr_alloc_failed:
396   {
397     GST_WARNING ("Failed to alloc usrptr buffer");
398     g_free (vbuffer);
399     return NULL;
400   }
401 mmap_failed:
402   {
403     gint errnosave = errno;
404     GST_WARNING ("Failed to mmap: %s", g_strerror (errnosave));
405     gst_buffer_unref (GST_BUFFER (ret));
406     g_free (vbuffer);
407     errno = errnosave;
408     return NULL;
409   }
410 }
411
412
413 #define GST_TYPE_V4L2CAMSRC_BUFFER_POOL (gst_v4l2camsrc_buffer_pool_get_type())
414 #define GST_IS_V4L2CAMSRC_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2CAMSRC_BUFFER_POOL))
415 #define GST_V4L2CAMSRC_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2CAMSRC_BUFFER_POOL, GstMFLDV4l2CamSrcBufferPool))
416
417 static GstMiniObjectClass *buffer_pool_parent_class = NULL;
418
419 static void
420 gst_v4l2camsrc_buffer_pool_finalize (GstMFLDV4l2CamSrcBufferPool * pool)
421 {
422   g_mutex_free (pool->lock);
423   pool->lock = NULL;
424
425   if (pool->video_fd >= 0)
426     close (pool->video_fd);
427
428   if (pool->buffers) {
429     g_free (pool->buffers);
430     pool->buffers = NULL;
431   }
432
433   if (pool->queued) {
434     g_free (pool->queued);
435     pool->queued = NULL;
436   }
437
438   g_cond_free (pool->data_cond);
439   pool->data_cond = NULL;
440
441   GST_MINI_OBJECT_CLASS (buffer_pool_parent_class)->finalize (GST_MINI_OBJECT
442       (pool));
443 }
444
445 /*
446  */
447 static void
448 gst_v4l2camsrc_buffer_pool_init (GstMFLDV4l2CamSrcBufferPool * pool,
449     gpointer g_class)
450 {
451   pool->lock = g_mutex_new ();
452   pool->running = FALSE;
453   pool->num_live_buffers = 0;
454   pool->data_cond = g_cond_new ();
455   pool->is_vaapi_sharing = FALSE;
456 }
457
458 /*
459  */
460 static void
461 gst_v4l2camsrc_buffer_pool_class_init (gpointer g_class, gpointer class_data)
462 {
463   GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
464
465   buffer_pool_parent_class = g_type_class_peek_parent (g_class);
466
467   mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
468       gst_v4l2camsrc_buffer_pool_finalize;
469 }
470
471 /*
472  */
473 static GType
474 gst_v4l2camsrc_buffer_pool_get_type (void)
475 {
476   static GType _gst_v4l2camsrc_buffer_pool_type;
477
478   if (G_UNLIKELY (_gst_v4l2camsrc_buffer_pool_type == 0)) {
479     static const GTypeInfo v4l2camsrc_buffer_pool_info = {
480       sizeof (GstBufferClass),
481       NULL,
482       NULL,
483       gst_v4l2camsrc_buffer_pool_class_init,
484       NULL,
485       NULL,
486       sizeof (GstMFLDV4l2CamSrcBufferPool),
487       0,
488       (GInstanceInitFunc) gst_v4l2camsrc_buffer_pool_init,
489       NULL
490     };
491     _gst_v4l2camsrc_buffer_pool_type =
492         g_type_register_static (GST_TYPE_MINI_OBJECT,
493         "GstMFLDV4l2CamSrcBufferPool", &v4l2camsrc_buffer_pool_info, 0);
494   }
495   return _gst_v4l2camsrc_buffer_pool_type;
496 }
497
498 /*
499  */
500 static GstMFLDV4l2CamSrcBufferPool *
501 gst_v4l2camsrc_buffer_pool_new (GstCameraSrc * camsrc, gint fd,
502     GstCaps * caps)
503 {
504   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
505   GstMFLDV4l2CamSrcBufferPool *pool;
506   gint n;
507
508   pool = (GstMFLDV4l2CamSrcBufferPool *)
509       gst_mini_object_new (GST_TYPE_V4L2CAMSRC_BUFFER_POOL);
510
511   pool->video_fd = dup (fd);
512   if (pool->video_fd < 0)
513     goto dup_failed;
514
515   GstStructure *structure = gst_caps_get_structure (caps, 0);
516   if (structure && gst_structure_has_name(structure, "video/x-vaapi-sharing"))
517     pool->is_vaapi_sharing = TRUE;
518
519   pool->buffer_count = v4l2camsrc->num_buffers;
520   pool->buffers = g_new0 (GstV4l2Buffer *, pool->buffer_count);
521   pool->queued = g_new0 (guint, pool->buffer_count);
522
523   for (n = 0; n < pool->buffer_count; n++) {
524     pool->buffers[n] = gst_v4l2camsrc_buffer_new (pool, camsrc, n, caps);
525     GST_LOG ("buffer ref is %d", GST_MINI_OBJECT_REFCOUNT (pool->buffers[n]));
526     if (!pool->buffers[n])
527       goto buffer_new_failed;
528   }
529
530   return pool;
531
532   /* ERRORS */
533 dup_failed:
534   {
535     gint errnosave = errno;
536
537     gst_v4l2camsrc_buffer_pool_destroy (pool, v4l2camsrc);
538
539     errno = errnosave;
540
541     return NULL;
542   }
543 buffer_new_failed:
544   {
545     gint errnosave = errno;
546
547     GST_LOG ("creating a new buffer failed");
548     gst_mini_object_unref (GST_MINI_OBJECT (pool));
549
550     errno = errnosave;
551
552     return NULL;
553   }
554 }
555
556 /*
557  */
558 static gboolean
559 gst_v4l2camsrc_buffer_pool_activate (GstMFLDV4l2CamSrcBufferPool * pool,
560     GstMFLDV4l2CamSrc * v4l2camsrc)
561 {
562   gint n;
563
564   g_mutex_lock (pool->lock);
565
566   for (n = 0; n < pool->buffer_count; n++) {
567
568     struct v4l2_buffer *buf;
569
570     buf = (struct v4l2_buffer *) pool->buffers[n]->vbuffer;
571
572     GST_LOG ("enqueue pool buffer %d", n);
573
574     if (ioctl (pool->video_fd, VIDIOC_QBUF, buf) < 0)
575       goto queue_failed;
576
577     pool->queued[n] = 1;
578   }
579   pool->running = TRUE;
580
581   g_mutex_unlock (pool->lock);
582
583   return TRUE;
584
585   /* ERRORS */
586 queue_failed:
587   {
588     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
589         ("Could not enqueue buffers in device '%s'.",
590             v4l2camsrc->videodev),
591         ("enqueing buffer %d/%d failed: %s",
592             n, v4l2camsrc->num_buffers, g_strerror (errno)));
593     g_mutex_unlock (pool->lock);
594     return FALSE;
595   }
596 }
597
598 /* requeue buffers that are writable again */
599 /* FIXME: This isn't needed anymore. Buffers are re-queued automatically
600  * when they are finalized, so there is no need to wait for them separately */
601 static gboolean
602 gst_v4l2_buffer_pool_update (GstMFLDV4l2CamSrcBufferPool * pool,
603     GstMFLDV4l2CamSrc * v4l2camsrc)
604 {
605   gint n;
606   gint ref = 0;
607
608   g_mutex_lock (pool->lock);
609
610   for (n = 0; n < pool->buffer_count; n++) {
611     if (!pool->queued[n]) {
612       GST_LOG ("buffer %d is dequeued", n);
613       ref++;
614     }
615   }
616
617   /* if all the buffers are dequeued, wait */
618   if (ref == v4l2camsrc->num_buffers) {
619     GST_LOG ("no free buffers available");
620     g_cond_wait (pool->data_cond, pool->lock);
621   }
622
623   g_mutex_unlock (pool->lock);
624
625   return (ref != v4l2camsrc->num_buffers) ? TRUE : FALSE;
626 }
627
628 /*
629  */
630 static void
631 gst_v4l2camsrc_buffer_pool_destroy (GstMFLDV4l2CamSrcBufferPool * pool,
632     GstMFLDV4l2CamSrc * v4l2camsrc)
633 {
634   gint n;
635
636   g_mutex_lock (pool->lock);
637   pool->running = FALSE;
638   g_mutex_unlock (pool->lock);
639
640   GST_DEBUG ("destroy pool");
641
642   /* after this point, no more buffers will be queued or dequeued; no buffer
643    * from pool->buffers that is NULL will be set to a buffer, and no buffer that
644    * is not NULL will be pushed out. */
645
646   /* miniobjects have no dispose, so they can't break ref-cycles, as buffers ref
647    * the pool, we need to unref the buffer to properly finalize te pool */
648   for (n = 0; n < pool->buffer_count; n++) {
649     GstBuffer *buf;
650
651     g_mutex_lock (pool->lock);
652     buf = GST_BUFFER (pool->buffers[n]);
653     g_mutex_unlock (pool->lock);
654
655     if (buf) {
656 #ifdef USE_MLOCK
657       if (pool->buffers[n].m.userptr) {
658         GST_DEBUG ("munlocking buffer data");
659         munlock ((void *) pool->buffers[n].m.userptr,
660             v4l2camsrc->frame_byte_size);
661       }
662 #endif
663       /* we own the ref if the buffer is in pool->buffers; drop it. */
664       gst_buffer_unref (buf);
665     }
666   }
667   pool->is_vaapi_sharing = FALSE;
668   gst_mini_object_unref (GST_MINI_OBJECT (pool));
669 }
670
671 /******************************************************
672  * gst_v4l2camsrc_get_capture_capabilities():
673  *   get the device's capturing capabilities
674  * return value: TRUE on success, FALSE on error
675  ******************************************************/
676 static gboolean
677 gst_v4l2camsrc_get_capture_capabilities (GstMFLDV4l2CamSrc * v4l2camsrc)
678 {
679   GST_DEBUG_OBJECT (v4l2camsrc, "getting capabilities");
680
681   if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
682     return FALSE;
683
684   if (ioctl (v4l2camsrc->video_fd, VIDIOC_QUERYCAP, &v4l2camsrc->vcap) < 0)
685     goto cap_failed;
686
687   GST_LOG_OBJECT (v4l2camsrc, "driver:      '%s'", v4l2camsrc->vcap.driver);
688   GST_LOG_OBJECT (v4l2camsrc, "card:        '%s'", v4l2camsrc->vcap.card);
689   GST_LOG_OBJECT (v4l2camsrc, "bus_info:    '%s'", v4l2camsrc->vcap.bus_info);
690   GST_LOG_OBJECT (v4l2camsrc, "version:     %08x", v4l2camsrc->vcap.version);
691   GST_LOG_OBJECT (v4l2camsrc, "capabilites: %08x",
692       v4l2camsrc->vcap.capabilities);
693
694   return TRUE;
695
696   /* ERRORS */
697 cap_failed:
698   {
699     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
700         ("Error getting capabilities for device '%s': "
701             "It isn't a v4l2 driver. Check if it is a v4l1 driver.",
702             v4l2camsrc->videodev), GST_ERROR_SYSTEM);
703     return FALSE;
704   }
705 }
706
707
708 /******************************************************
709  * gst_v4l2camsrc_set_input_sensor():
710  *   set which sensor is the input of ISP
711  * return value: TRUE on success, FALSE on error
712  ******************************************************/
713 static gboolean
714 gst_v4l2camsrc_set_input_sensor (GstMFLDV4l2CamSrc * v4l2camsrc)
715 {
716   V4L2CameraInputSensor select_sensor;
717   
718   GST_DEBUG_OBJECT (v4l2camsrc, "setting input sensor");
719
720   if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
721     return FALSE;
722
723   if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_PRIMARY)
724     select_sensor = V2L2_CAMERA_INPUT_SENSOR_PRIMARY;
725   else
726     select_sensor =V2L2_CAMERA_INPUT_SENSOR_SECONDARY;
727
728   if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_INPUT,
729             &select_sensor) < 0)
730     goto s_input_failed;
731
732   GST_LOG_OBJECT (v4l2camsrc, "set input sensor to:      %d",
733           select_sensor);
734
735   return TRUE;
736
737   /* ERRORS */
738 s_input_failed:
739   {
740     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
741         ("Error setting input for device '%s': ",
742             v4l2camsrc->videodev), GST_ERROR_SYSTEM);
743     return FALSE;
744   }
745 }
746
747 static gboolean
748 get_supported_mmfw_control (GstMFLDV4l2CamSrc * v4l2camsrc, struct v4l2_queryctrl *control)
749 {
750   int i;
751   GST_DEBUG_OBJECT (v4l2camsrc, "set  private control (%x)",  control->id);
752
753   for (i = 0; i < N_MMFW_CONTROLS; i++) {
754     if (mmfw_wb_controls[i].id == control->id) {
755       *control =  mmfw_wb_controls[i];
756       return TRUE;
757     }
758   }
759   return FALSE;
760 }
761
762
763 /******************************************************
764  * gst_v4l2camsrc_fill_lists():
765  *   fill the lists of enumerations
766  * return value: TRUE on success, FALSE on error
767  ******************************************************/
768 static gboolean
769 gst_v4l2camsrc_fill_lists (GstMFLDV4l2CamSrc * v4l2camsrc)
770 {
771   gint n;
772
773   GST_DEBUG_OBJECT (v4l2camsrc, "getting enumerations");
774   GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
775
776   GST_DEBUG_OBJECT (v4l2camsrc, "  controls+menus");
777   /* and lastly, controls+menus (if appropriate) */
778   for (n = V4L2_CID_BASE;; n++) {
779     struct v4l2_queryctrl control = { 0, };
780     GstCameraSrcColorBalanceChannel *v4l2channel;
781
782     GstColorBalanceChannel *channel;
783
784     /* when we reached the last official CID, continue with private CIDs */
785     if (n == V4L2_CID_LASTP1) {
786       GST_DEBUG_OBJECT (v4l2camsrc, "checking private CIDs");
787       n = V4L2_CID_PRIVATE_BASE;
788       /* FIXME: We are still not handling private controls. We need a
789          new GstInterface to export those controls */
790       //break;
791       GST_DEBUG_OBJECT (v4l2camsrc, "private ID");
792     }
793
794     control.id = n;
795
796     if( n  > SOURCE_PRIV_BASE)  {
797        if(  n > MM_CAM_SOURCE_PRIV_LAST)
798           break;
799        else
800          get_supported_mmfw_control(v4l2camsrc, &control);
801     }
802     else if (ioctl (v4l2camsrc->video_fd, VIDIOC_QUERYCTRL, &control) < 0)   {
803       if (errno == EINVAL) {
804         if (n < V4L2_CID_PRIVATE_BASE)
805           /* continue so that we also check private controls */
806           continue;
807         else
808           break;
809       } else {
810         GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
811             ("Failed getting controls attributes on device '%s.'",
812                 v4l2camsrc->videodev),
813             ("Failed querying control %d on device '%s'. (%d - %s)",
814                 n, v4l2camsrc->videodev, errno, strerror (errno)));
815         return FALSE;
816       }
817     }
818     if (control.flags & V4L2_CTRL_FLAG_DISABLED)
819       continue;
820
821     switch (n) {
822       case V4L2_CID_BRIGHTNESS:
823       case V4L2_CID_CONTRAST:
824       case V4L2_CID_SATURATION:
825       case V4L2_CID_HUE:
826       case V4L2_CID_BLACK_LEVEL:
827       case V4L2_CID_AUTO_WHITE_BALANCE:
828       case V4L2_CID_DO_WHITE_BALANCE:
829       case V4L2_CID_RED_BALANCE:
830       case V4L2_CID_BLUE_BALANCE:
831       case V4L2_CID_GAMMA:
832       case V4L2_CID_EXPOSURE:
833       case V4L2_CID_AUTOGAIN:
834       case V4L2_CID_GAIN:
835       case V4L2_CID_COLORFX:
836       case MM_CAM_FILTER_WB_SOURCE_PRIV:
837       case MM_CAM_FILTER_COLOR_TONE_SOURCE_PRIV:
838         /* we only handle these for now (why?) */
839         break;
840       case V4L2_CID_HFLIP:
841       case V4L2_CID_VFLIP:
842       case V4L2_CID_HCENTER:
843       case V4L2_CID_VCENTER:
844 #ifdef V4L2_CID_PAN_RESET
845       case V4L2_CID_PAN_RESET:
846 #endif
847 #ifdef V4L2_CID_TILT_RESET
848       case V4L2_CID_TILT_RESET:
849 #endif
850         /* not handled here, handled by VideoOrientation interface */
851         control.id++;
852         break;
853       case V4L2_CID_AUDIO_VOLUME:
854       case V4L2_CID_AUDIO_BALANCE:
855       case V4L2_CID_AUDIO_BASS:
856       case V4L2_CID_AUDIO_TREBLE:
857       case V4L2_CID_AUDIO_MUTE:
858       case V4L2_CID_AUDIO_LOUDNESS:
859         /* FIXME: We should implement GstMixer interface */
860         /* fall through */
861       default:
862         GST_DEBUG_OBJECT (v4l2camsrc,
863             "ControlID %s (%x) unhandled, FIXME", control.name, n);
864         control.id++;
865         break;
866     }
867     if (n != control.id)
868       continue;
869
870     GST_DEBUG_OBJECT (v4l2camsrc, "Adding ControlID %s (%x)", control.name, n);
871     v4l2channel =
872         g_object_new (GST_TYPE_CAMERA_SRC_COLOR_BALANCE_CHANNEL, NULL);
873     channel = GST_COLOR_BALANCE_CHANNEL (v4l2channel);
874     channel->label = g_strdup ((const gchar *) control.name);
875
876     v4l2channel->id = n;
877
878     switch (control.type) {
879       case V4L2_CTRL_TYPE_INTEGER:
880         channel->min_value = control.minimum;
881         channel->max_value = control.maximum;
882         break;
883       case V4L2_CTRL_TYPE_BOOLEAN:
884         channel->min_value = FALSE;
885         channel->max_value = TRUE;
886         break;
887       default:
888         /* FIXME we should find out how to handle V4L2_CTRL_TYPE_BUTTON.
889            BUTTON controls like V4L2_CID_DO_WHITE_BALANCE can just be set (1) or
890            unset (0), but can't be queried */
891         GST_DEBUG_OBJECT (v4l2camsrc,
892             "Control with non supported type %s (%x), type=%d",
893             control.name, n, control.type);
894         channel->min_value = channel->max_value = 0;
895         break;
896     }
897
898     gst_camerasrc_add_color_channel (GST_CAMERA_SRC (v4l2camsrc), channel);
899   }
900
901   GST_DEBUG_OBJECT (v4l2camsrc, "done");
902   return TRUE;
903 }
904
905 /******************************************************
906  * gst_v4l2camsrc_open():
907  *   open the video device (v4l2camsrc->videodev)
908  * return value: TRUE on success, FALSE on error
909  ******************************************************/
910 gboolean
911 gst_v4l2camsrc_open (GstCameraSrc * camsrc)
912 {
913   struct stat st;
914   GstPollFD pollfd = GST_POLL_FD_INIT;
915
916   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
917
918   GST_DEBUG_OBJECT (v4l2camsrc, "Trying to open device %s",
919       v4l2camsrc->videodev);
920
921   GST_V4L2CAMSRC_CHECK_NOT_OPEN (v4l2camsrc);
922   GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
923
924   /* be sure we have a device */
925   if (!v4l2camsrc->videodev)
926     v4l2camsrc->videodev = g_strdup ("/dev/video");
927
928   /* check if it is a device */
929   if (stat (v4l2camsrc->videodev, &st) == -1)
930     goto stat_failed;
931
932   if (!S_ISCHR (st.st_mode))
933     goto no_device;
934
935   /* open the device */
936   v4l2camsrc->video_fd =
937       open (v4l2camsrc->videodev, O_RDWR /* | O_NONBLOCK */ );
938
939   if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
940     goto not_open;
941
942   /* get capabilities, error will be posted */
943   if (!gst_v4l2camsrc_get_capture_capabilities (v4l2camsrc))
944     goto error;
945
946   /* get capabilities, error will be posted */
947   if (!gst_v4l2camsrc_set_input_sensor (v4l2camsrc))
948     goto error;
949
950   /* do we need to be a capture device? */
951   if (GST_IS_V4L2CAMSRC (v4l2camsrc) &&
952       !(v4l2camsrc->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
953     goto not_capture;
954
955   /* Before iterating enumerations, clear the parent's color channel list */
956   gst_camerasrc_clear_color_channels (camsrc);
957
958   /* create enumerations, posts errors. */
959   if (!gst_v4l2camsrc_fill_lists (v4l2camsrc))
960     goto error;
961
962   GST_INFO_OBJECT (v4l2camsrc,
963       "Opened device '%s' (%s) successfully",
964       v4l2camsrc->vcap.card, v4l2camsrc->videodev);
965
966   pollfd.fd = v4l2camsrc->video_fd;
967   gst_poll_add_fd (v4l2camsrc->poll, &pollfd);
968   gst_poll_fd_ctl_read (v4l2camsrc->poll, &pollfd, TRUE);
969
970   gst_v4l2camsrc_libmfldcam_init (v4l2camsrc);
971
972   return TRUE;
973
974   /* ERRORS */
975 stat_failed:
976   {
977     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
978         ("Cannot identify device '%s'.", v4l2camsrc->videodev),
979         GST_ERROR_SYSTEM);
980     goto error;
981   }
982 no_device:
983   {
984     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
985         ("This isn't a device '%s'.", v4l2camsrc->videodev), GST_ERROR_SYSTEM);
986     goto error;
987   }
988 not_open:
989   {
990     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, OPEN_READ_WRITE,
991         ("Could not open device '%s' for reading and writing.",
992             v4l2camsrc->videodev), GST_ERROR_SYSTEM);
993     goto error;
994   }
995 not_capture:
996   {
997     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, NOT_FOUND,
998         ("Device '%s' is not a capture device.",
999             v4l2camsrc->videodev),
1000         ("Capabilities: 0x%x", v4l2camsrc->vcap.capabilities));
1001     goto error;
1002   }
1003 error:
1004   {
1005     if (GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc)) {
1006       /* close device */
1007       close (v4l2camsrc->video_fd);
1008       v4l2camsrc->video_fd = -1;
1009     }
1010
1011     return FALSE;
1012   }
1013 }
1014
1015 /******************************************************
1016  * gst_v4l2camsrc_close():
1017  *   close the video device (v4l2camsrc->video_fd)
1018  * return value: TRUE on success, FALSE on error
1019  ******************************************************/
1020 gboolean
1021 gst_v4l2camsrc_close (GstCameraSrc * camsrc)
1022 {
1023   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1024
1025   GstPollFD pollfd = GST_POLL_FD_INIT;
1026
1027   GST_DEBUG_OBJECT (v4l2camsrc, "Trying to close %s", v4l2camsrc->videodev);
1028
1029   GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
1030   GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
1031
1032   /* close device */
1033   gst_v4l2camsrc_libmfldcam_deinit (v4l2camsrc);
1034
1035   close (v4l2camsrc->video_fd);
1036   pollfd.fd = v4l2camsrc->video_fd;
1037   gst_poll_remove_fd (v4l2camsrc->poll, &pollfd);
1038   v4l2camsrc->video_fd = -1;
1039
1040   return TRUE;
1041 }
1042
1043 /******************************************************
1044  * gst_v4l2camsrc_get_attribute():
1045  *   try to get the value of one specific attribute
1046  * return value: TRUE on success, FALSE on error
1047  ******************************************************/
1048 gboolean
1049 gst_v4l2camsrc_get_attribute (GstCameraSrc * camsrc,
1050     int attribute_num, int *value)
1051 {
1052   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1053
1054   struct v4l2_control control;
1055   cam_err_t err;
1056   int tmp_value;
1057
1058   GST_DEBUG_OBJECT (v4l2camsrc, "getting value of attribute %d", attribute_num);
1059
1060   if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
1061     return FALSE;
1062
1063   control.id = attribute_num;
1064
1065   if (control.id > SOURCE_PRIV_BASE) {
1066     switch (control.id) {
1067       case MM_CAM_FILTER_WB_SOURCE_PRIV:
1068           err = cam_feature_get (v4l2camsrc->video_fd, CAM_AWB_MODE, &tmp_value);
1069           *value = find_item (gst_v4l2camsrc_wb_map, tmp_value);
1070         break;
1071       case MM_CAM_FILTER_COLOR_TONE_SOURCE_PRIV:
1072           err = cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE, &tmp_value);
1073           *value = find_item (gst_v4l2camsrc_effect_map, tmp_value);
1074         break;
1075       default:
1076         break;
1077     }
1078   }
1079   else {
1080     if (ioctl (v4l2camsrc->video_fd, VIDIOC_G_CTRL, &control) < 0)
1081       goto ctrl_failed1;
1082     *value = control.value;
1083   }
1084
1085   return TRUE;
1086
1087 ctrl_failed1:
1088   {
1089     struct v4l2_ext_controls controls;
1090     struct v4l2_ext_control control;
1091
1092     controls.ctrl_class = V4L2_CTRL_CLASS_USER;
1093     controls.count = 1;
1094     controls.controls = &control;
1095
1096     control.id = attribute_num;
1097
1098     if (ioctl (v4l2camsrc->video_fd, VIDIOC_G_EXT_CTRLS, &controls) < 0)
1099       goto ctrl_failed2;
1100
1101     *value = control.value;
1102
1103     return TRUE;
1104
1105   }
1106
1107   /* ERRORS */
1108 ctrl_failed2:
1109   {
1110     GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1111         ("Failed to get value for control %d on device '%s'.",
1112             attribute_num, v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1113     return FALSE;
1114   }
1115 }
1116
1117 /******************************************************
1118  * gst_v4l2camsrc_set_attribute():
1119  *   try to set the value of one specific attribute
1120  * return value: TRUE on success, FALSE on error
1121  ******************************************************/
1122 gboolean
1123 gst_v4l2camsrc_set_attribute (GstCameraSrc * camsrc,
1124     int attribute_num, const int value)
1125 {
1126   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
1127   struct v4l2_control control;
1128
1129   GST_DEBUG_OBJECT (v4l2camsrc, "setting value of attribute %d to %d",
1130       attribute_num, value);
1131
1132   if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc))
1133     return FALSE;
1134
1135   control.id = attribute_num;
1136   control.value = value;
1137   if (control.id > SOURCE_PRIV_BASE) {
1138     switch (control.id) {
1139       case MM_CAM_FILTER_WB_SOURCE_PRIV:
1140           cam_feature_set (v4l2camsrc->video_fd, CAM_AWB_MODE, gst_v4l2camsrc_wb_map[value]);
1141         break;
1142       case MM_CAM_FILTER_COLOR_TONE_SOURCE_PRIV:
1143           cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE, gst_v4l2camsrc_effect_map[value]);
1144         break;
1145
1146       default:
1147         break;
1148     }
1149   }
1150   else {
1151     if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_CTRL, &control) < 0)
1152       goto ctrl_failed1;
1153   }
1154   return TRUE;
1155
1156 ctrl_failed1:
1157   {
1158     struct v4l2_ext_controls controls;
1159     struct v4l2_ext_control control;
1160
1161     controls.ctrl_class = V4L2_CTRL_CLASS_USER;
1162     controls.count = 1;
1163     controls.controls = &control;
1164
1165     control.id = attribute_num;
1166     control.value = value;
1167
1168     if (ioctl (v4l2camsrc->video_fd, VIDIOC_S_EXT_CTRLS, &controls) < 0)
1169       goto ctrl_failed2;
1170
1171     return TRUE;
1172   }
1173
1174   /* ERRORS */
1175 ctrl_failed2:
1176   {
1177     GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1178         ("Failed to set value %d for control %d on device '%s'.",
1179             value, attribute_num, v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1180     return FALSE;
1181   }
1182 }
1183
1184
1185 /* complete made up ranking, the values themselves are meaningless */
1186 #define YUV_BASE_RANK     1000
1187 #define JPEG_BASE_RANK     500
1188 #define DV_BASE_RANK       200
1189 #define RGB_BASE_RANK      100
1190 #define YUV_ODD_BASE_RANK   50
1191 #define RGB_ODD_BASE_RANK   25
1192 #define BAYER_BASE_RANK     15
1193 #define S910_BASE_RANK      10
1194 #define GREY_BASE_RANK       5
1195 #define PWC_BASE_RANK        1
1196
1197 /* This flag is already used by libv4l2 although
1198  * it was added to the Linux kernel in 2.6.32
1199  */
1200 #ifndef V4L2_FMT_FLAG_EMULATED
1201 #define V4L2_FMT_FLAG_EMULATED 0x0002
1202 #endif
1203
1204 static gint
1205 gst_v4l2camsrc_format_get_rank (const struct v4l2_fmtdesc *fmt)
1206 {
1207   guint32 fourcc = fmt->pixelformat;
1208   gboolean emulated = ((fmt->flags & V4L2_FMT_FLAG_EMULATED) != 0);
1209   gint rank = 0;
1210
1211   switch (fourcc) {
1212     case V4L2_PIX_FMT_MJPEG:
1213       rank = JPEG_BASE_RANK;
1214       break;
1215     case V4L2_PIX_FMT_JPEG:
1216       rank = JPEG_BASE_RANK + 1;
1217       break;
1218     case V4L2_PIX_FMT_MPEG:    /* MPEG          */
1219       rank = JPEG_BASE_RANK + 2;
1220       break;
1221
1222     case V4L2_PIX_FMT_RGB332:
1223     case V4L2_PIX_FMT_RGB555:
1224     case V4L2_PIX_FMT_RGB555X:
1225     case V4L2_PIX_FMT_RGB565:
1226     case V4L2_PIX_FMT_RGB565X:
1227       rank = RGB_ODD_BASE_RANK;
1228       break;
1229
1230     case V4L2_PIX_FMT_RGB24:
1231     case V4L2_PIX_FMT_BGR24:
1232       rank = RGB_BASE_RANK - 1;
1233       break;
1234
1235     case V4L2_PIX_FMT_RGB32:
1236     case V4L2_PIX_FMT_BGR32:
1237       rank = RGB_BASE_RANK;
1238       break;
1239
1240     case V4L2_PIX_FMT_GREY:    /*  8  Greyscale     */
1241       rank = GREY_BASE_RANK;
1242       break;
1243
1244     case V4L2_PIX_FMT_NV12:    /* 12  Y/CbCr 4:2:0  */
1245     case V4L2_PIX_FMT_NV21:    /* 12  Y/CrCb 4:2:0  */
1246     case V4L2_PIX_FMT_YYUV:    /* 16  YUV 4:2:2     */
1247     case V4L2_PIX_FMT_HI240:   /*  8  8-bit color   */
1248     case V4L2_PIX_FMT_NV16:    /* 16 bit YUV 422, Y, UV plane */
1249       rank = YUV_ODD_BASE_RANK;
1250       break;
1251     case V4L2_PIX_FMT_YUV444:  /* YUV 444,  24 bits per pixel */
1252       rank = YUV_BASE_RANK + 0;
1253       break;
1254     case V4L2_PIX_FMT_YVU410:  /* YVU9,  9 bits per pixel */
1255       rank = YUV_BASE_RANK + 3;
1256       break;
1257     case V4L2_PIX_FMT_YUV410:  /* YUV9,  9 bits per pixel */
1258       rank = YUV_BASE_RANK + 2;
1259       break;
1260     case V4L2_PIX_FMT_YUV420:  /* I420, 12 bits per pixel */
1261       rank = YUV_BASE_RANK + 7;
1262       break;
1263     case V4L2_PIX_FMT_YUYV:    /* YUY2, 16 bits per pixel */
1264       rank = YUV_BASE_RANK + 10;
1265       break;
1266     case V4L2_PIX_FMT_YVU420:  /* YV12, 12 bits per pixel */
1267       rank = YUV_BASE_RANK + 6;
1268       break;
1269     case V4L2_PIX_FMT_UYVY:    /* UYVY, 16 bits per pixel */
1270       rank = YUV_BASE_RANK + 9;
1271       break;
1272     case V4L2_PIX_FMT_Y41P:    /* Y41P, 12 bits per pixel */
1273       rank = YUV_BASE_RANK + 5;
1274       break;
1275     case V4L2_PIX_FMT_YUV411P: /* Y41B, 12 bits per pixel */
1276       rank = YUV_BASE_RANK + 4;
1277       break;
1278     case V4L2_PIX_FMT_YUV422P: /* Y42B, 16 bits per pixel */
1279       rank = YUV_BASE_RANK + 8;
1280       break;
1281
1282     case V4L2_PIX_FMT_DV:
1283       rank = DV_BASE_RANK;
1284       break;
1285
1286     case V4L2_PIX_FMT_WNVA:    /* Winnov hw compres */
1287       rank = 0;
1288       break;
1289
1290     case V4L2_PIX_FMT_SBGGR8:
1291     case V4L2_PIX_FMT_SRGGB8:
1292     case V4L2_PIX_FMT_SGBRG8:
1293     case V4L2_PIX_FMT_SGRBG10:
1294     case V4L2_PIX_FMT_SRGGB10:
1295     case V4L2_PIX_FMT_SGBRG10:
1296       rank = BAYER_BASE_RANK;
1297       break;
1298
1299 #ifdef V4L2_PIX_FMT_SN9C10X
1300     case V4L2_PIX_FMT_SN9C10X:
1301       rank = S910_BASE_RANK;
1302       break;
1303 #endif
1304
1305 #ifdef V4L2_PIX_FMT_PWC1
1306     case V4L2_PIX_FMT_PWC1:
1307       rank = PWC_BASE_RANK;
1308       break;
1309 #endif
1310 #ifdef V4L2_PIX_FMT_PWC2
1311     case V4L2_PIX_FMT_PWC2:
1312       rank = PWC_BASE_RANK;
1313       break;
1314 #endif
1315
1316     default:
1317       GST_LOG("Don't know how to rank pixelformat %" GST_FOURCC_FORMAT,
1318                 GST_FOURCC_ARGS(fourcc));
1319       rank = 0;
1320       break;
1321   }
1322
1323   /* All ranks are below 1<<15 so a shift by 15
1324    * will a) make all non-emulated formats larger
1325    * than emulated and b) will not overflow
1326    */
1327   if (!emulated)
1328     rank <<= 15;
1329
1330   return rank;
1331 }
1332
1333 static gint
1334 gst_v4l2camsrc_format_cmp_func (gconstpointer a, gconstpointer b)
1335 {
1336   const struct v4l2_fmtdesc *fa = a;
1337   const struct v4l2_fmtdesc *fb = b;
1338
1339   if (fa->pixelformat == fb->pixelformat)
1340     return 0;
1341
1342   return gst_v4l2camsrc_format_get_rank (fb) -
1343       gst_v4l2camsrc_format_get_rank (fa);
1344 }
1345
1346 static gboolean is_supported_pixelformat(guint32 fourcc)
1347 {
1348   if(fourcc == V4L2_PIX_FMT_NV12
1349       || fourcc == V4L2_PIX_FMT_YUV420
1350       || fourcc == V4L2_PIX_FMT_SGRBG10)
1351     return TRUE;
1352   return FALSE;
1353 }
1354
1355 /******************************************************
1356  * gst_v4l2camsrc_fill_format_list():
1357  *   create list of supported capture formats
1358  * return value: TRUE on success, FALSE on error
1359  ******************************************************/
1360 gboolean
1361 gst_v4l2camsrc_fill_format_list (GstMFLDV4l2CamSrc * v4l2camsrc)
1362 {
1363   gint n;
1364   struct v4l2_fmtdesc *format;
1365
1366   GST_DEBUG_OBJECT (v4l2camsrc, "getting src format enumerations");
1367
1368   /* format enumeration */
1369   for (n = 0;; n++) {
1370     format = g_new0 (struct v4l2_fmtdesc, 1);
1371
1372     format->index = n;
1373     format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1374
1375     if (ioctl (v4l2camsrc->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
1376       if (errno == EINVAL) {
1377         g_free (format);
1378         break;                  /* end of enumeration */
1379       } else {
1380         goto failed;
1381       }
1382     }
1383     if(!is_supported_pixelformat(format->pixelformat)) {
1384       GST_LOG_OBJECT(v4l2camsrc, "  (skipping format %" GST_FOURCC_FORMAT ")",GST_FOURCC_ARGS (format->pixelformat));
1385       continue;
1386     }
1387
1388     GST_LOG_OBJECT (v4l2camsrc, "index:       %u", format->index);
1389     GST_LOG_OBJECT (v4l2camsrc, "type:        %d", format->type);
1390     GST_LOG_OBJECT (v4l2camsrc, "flags:       %08x", format->flags);
1391     GST_LOG_OBJECT (v4l2camsrc, "description: '%s'", format->description);
1392     GST_LOG_OBJECT (v4l2camsrc, "pixelformat: %" GST_FOURCC_FORMAT,
1393         GST_FOURCC_ARGS (format->pixelformat));
1394
1395     /* sort formats according to our preference;  we do this, because caps
1396      * are probed in the order the formats are in the list, and the order of
1397      * formats in the final probed caps matters for things like fixation */
1398     v4l2camsrc->formats = g_slist_insert_sorted (v4l2camsrc->formats, format,
1399         (GCompareFunc) gst_v4l2camsrc_format_cmp_func);
1400   }
1401
1402   GST_DEBUG_OBJECT (v4l2camsrc, "got %d format(s)", n);
1403
1404   return TRUE;
1405
1406   /* ERRORS */
1407 failed:
1408   {
1409     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1410         ("Failed to enumerate possible video formats device '%s' can work with",
1411             v4l2camsrc->videodev),
1412         ("Failed to get number %d in pixelformat enumeration for %s. (%d - %s)",
1413             n, v4l2camsrc->videodev, errno, g_strerror (errno)));
1414     g_free (format);
1415     return FALSE;
1416   }
1417 }
1418
1419 /******************************************************
1420  * gst_v4l2camsrc_clear_format_list():
1421  *   free list of supported capture formats
1422  * return value: TRUE on success, FALSE on error
1423  ******************************************************/
1424 gboolean
1425 gst_v4l2camsrc_clear_format_list (GstMFLDV4l2CamSrc * v4l2camsrc)
1426 {
1427   g_slist_foreach (v4l2camsrc->formats, (GFunc) g_free, NULL);
1428   g_slist_free (v4l2camsrc->formats);
1429   v4l2camsrc->formats = NULL;
1430
1431   return TRUE;
1432 }
1433
1434 /* The frame interval enumeration code first appeared in Linux 2.6.19. */
1435 #ifdef VIDIOC_ENUM_FRAMEINTERVALS
1436 static GstStructure *
1437 gst_v4l2camsrc_probe_caps_for_format_and_size (GstMFLDV4l2CamSrc * v4l2camsrc,
1438     guint32 pixelformat,
1439     guint32 width, guint32 height, const GstStructure * template)
1440 {
1441   gint fd = v4l2camsrc->video_fd;
1442   struct v4l2_frmivalenum ival;
1443   guint32 num, denom;
1444   GstStructure *s;
1445   GValue rates = { 0, };
1446
1447   memset (&ival, 0, sizeof (struct v4l2_frmivalenum));
1448   ival.index = 0;
1449   ival.pixel_format = pixelformat;
1450   ival.width = width;
1451   ival.height = height;
1452
1453   GST_LOG_OBJECT (v4l2camsrc, "get frame interval for %ux%u, %"
1454       GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat));
1455
1456   /* keep in mind that v4l2 gives us frame intervals (durations); we invert the
1457    * fraction to get framerate */
1458   if (ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0)
1459     goto enum_frameintervals_failed;
1460
1461   if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
1462     GValue rate = { 0, };
1463
1464     g_value_init (&rates, GST_TYPE_LIST);
1465     g_value_init (&rate, GST_TYPE_FRACTION);
1466
1467     do {
1468       num = ival.discrete.numerator;
1469       denom = ival.discrete.denominator;
1470
1471       if (num > G_MAXINT || denom > G_MAXINT) {
1472         /* let us hope we don't get here... */
1473         num >>= 1;
1474         denom >>= 1;
1475       }
1476
1477       GST_LOG_OBJECT (v4l2camsrc, "adding discrete framerate: %d/%d",
1478           denom, num);
1479
1480       /* swap to get the framerate */
1481       gst_value_set_fraction (&rate, denom, num);
1482       gst_value_list_append_value (&rates, &rate);
1483
1484       ival.index++;
1485     } while (ioctl (fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
1486
1487     /* FIXME MASSIVE UGLY HACK: Pretend to support 30/1 fps always */
1488     gst_value_set_fraction(&rate, 30, 1);
1489     gst_value_list_append_value(&rates, &rate);
1490
1491   } else if (ival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
1492     GValue min = { 0, };
1493     GValue step = { 0, };
1494     GValue max = { 0, };
1495     gboolean added = FALSE;
1496     guint32 minnum, mindenom;
1497     guint32 maxnum, maxdenom;
1498
1499     g_value_init (&rates, GST_TYPE_LIST);
1500
1501     g_value_init (&min, GST_TYPE_FRACTION);
1502     g_value_init (&step, GST_TYPE_FRACTION);
1503     g_value_init (&max, GST_TYPE_FRACTION);
1504
1505     /* get the min */
1506     minnum = ival.stepwise.min.numerator;
1507     mindenom = ival.stepwise.min.denominator;
1508     if (minnum > G_MAXINT || mindenom > G_MAXINT) {
1509       minnum >>= 1;
1510       mindenom >>= 1;
1511     }
1512     GST_LOG_OBJECT (v4l2camsrc, "stepwise min frame interval: %d/%d", minnum,
1513         mindenom);
1514     gst_value_set_fraction (&min, minnum, mindenom);
1515
1516     /* get the max */
1517     maxnum = ival.stepwise.max.numerator;
1518     maxdenom = ival.stepwise.max.denominator;
1519     if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
1520       maxnum >>= 1;
1521       maxdenom >>= 1;
1522     }
1523
1524     GST_LOG_OBJECT (v4l2camsrc, "stepwise max frame interval: %d/%d", maxnum,
1525         maxdenom);
1526     gst_value_set_fraction (&max, maxnum, maxdenom);
1527
1528     /* get the step */
1529     num = ival.stepwise.step.numerator;
1530     denom = ival.stepwise.step.denominator;
1531     if (num > G_MAXINT || denom > G_MAXINT) {
1532       num >>= 1;
1533       denom >>= 1;
1534     }
1535
1536     if (num == 0 || denom == 0) {
1537       /* in this case we have a wrong fraction or no step, set the step to max
1538        * so that we only add the min value in the loop below */
1539       num = maxnum;
1540       denom = maxdenom;
1541     }
1542
1543     /* since we only have gst_value_fraction_subtract and not add, negate the
1544      * numerator */
1545     GST_LOG_OBJECT (v4l2camsrc, "stepwise step frame interval: %d/%d",
1546         num, denom);
1547
1548     gst_value_set_fraction (&step, -num, denom);
1549
1550     while (gst_value_compare (&min, &max) <= 0) {
1551       GValue rate = { 0, };
1552
1553       num = gst_value_get_fraction_numerator (&min);
1554       denom = gst_value_get_fraction_denominator (&min);
1555       GST_LOG_OBJECT (v4l2camsrc, "adding stepwise framerate: %d/%d",
1556           denom, num);
1557
1558       /* invert to get the framerate */
1559       g_value_init (&rate, GST_TYPE_FRACTION);
1560       gst_value_set_fraction (&rate, denom, num);
1561       gst_value_list_append_value (&rates, &rate);
1562       added = TRUE;
1563
1564       /* we're actually adding because step was negated above. This is because
1565        * there is no _add function... */
1566       if (!gst_value_fraction_subtract (&min, &min, &step)) {
1567         GST_WARNING_OBJECT (v4l2camsrc, "could not step fraction!");
1568         break;
1569       }
1570     }
1571     if (!added) {
1572       /* no range was added, leave the default range from the template */
1573       GST_WARNING_OBJECT (v4l2camsrc, "no range added, leaving default");
1574       g_value_unset (&rates);
1575     }
1576   } else if (ival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
1577     guint32 maxnum, maxdenom;
1578
1579     g_value_init (&rates, GST_TYPE_FRACTION_RANGE);
1580
1581     num = ival.stepwise.min.numerator;
1582     denom = ival.stepwise.min.denominator;
1583     if (num > G_MAXINT || denom > G_MAXINT) {
1584       num >>= 1;
1585       denom >>= 1;
1586     }
1587
1588     maxnum = ival.stepwise.max.numerator;
1589     maxdenom = ival.stepwise.max.denominator;
1590     if (maxnum > G_MAXINT || maxdenom > G_MAXINT) {
1591       maxnum >>= 1;
1592       maxdenom >>= 1;
1593     }
1594
1595     GST_LOG_OBJECT (v4l2camsrc, "continuous frame interval %d/%d to %d/%d",
1596         maxdenom, maxnum, denom, num);
1597
1598     gst_value_set_fraction_range_full (&rates, maxdenom, maxnum, denom, num);
1599   } else {
1600     goto unknown_type;
1601   }
1602
1603 return_data:
1604   s = gst_structure_copy (template);
1605   /* https://projects.maemo.org/bugzilla/show_bug.cgi?id=105590 */
1606   gst_structure_set (s,
1607       "width", G_TYPE_INT, (gint) width,
1608       "height", G_TYPE_INT, (gint) height, NULL);
1609
1610   if (G_IS_VALUE (&rates)) {
1611     /* only change the framerate on the template when we have a valid probed new
1612      * value */
1613     gst_structure_set_value (s, "framerate", &rates);
1614     g_value_unset (&rates);
1615   }
1616   return s;
1617
1618   /* ERRORS */
1619 enum_frameintervals_failed:
1620   {
1621     GST_DEBUG_OBJECT (v4l2camsrc,
1622         "Unable to enumerate intervals for %" GST_FOURCC_FORMAT "@%ux%u",
1623         GST_FOURCC_ARGS (pixelformat), width, height);
1624     goto return_data;
1625   }
1626 unknown_type:
1627   {
1628     /* I don't see how this is actually an error, we ignore the format then */
1629     GST_WARNING_OBJECT (v4l2camsrc,
1630         "Unknown frame interval type at %" GST_FOURCC_FORMAT "@%ux%u: %u",
1631         GST_FOURCC_ARGS (pixelformat), width, height, ival.type);
1632     return NULL;
1633   }
1634 }
1635 #endif /* defined VIDIOC_ENUM_FRAMEINTERVALS */
1636
1637
1638 /*
1639  */
1640 static gint
1641 compare_resolutions (gconstpointer a, gconstpointer b)
1642 {
1643   GstStructure *as = (GstStructure *) a;
1644   GstStructure *bs = (GstStructure *) b;
1645   gint aw, bw, ah, bh;
1646
1647   gst_structure_get_int (as, "width", &aw);
1648   gst_structure_get_int (bs, "width", &bw);
1649   gst_structure_get_int (as, "height", &ah);
1650   gst_structure_get_int (bs, "height", &bh);
1651
1652   /* FIXME: What is the best way to compare resolutions if their aspect
1653    * ratio isn't the same? */
1654   return ((aw - bw) + (ah - bh));
1655 }
1656
1657
1658 /*
1659  */
1660 static gboolean
1661 fractions_are_equal (gint num1, gint den1, gint num2, gint den2)
1662 {
1663   GValue fraction1 = { 0, }, fraction2 = {
1664   0,};
1665
1666   g_value_init (&fraction1, GST_TYPE_FRACTION);
1667   g_value_init (&fraction2, GST_TYPE_FRACTION);
1668   gst_value_set_fraction (&fraction1, num1, den1);
1669   gst_value_set_fraction (&fraction2, num2, den2);
1670   /* we know we don't have to unset the values in this case */
1671   return (gst_value_compare (&fraction1, &fraction2) == GST_VALUE_EQUAL);
1672 }
1673
1674 static guint
1675 gst_v4l2camsrc_get_frame_size (guint32 fourcc, guint * w, guint * h)
1676 {
1677   guint outsize = 0;
1678
1679   switch (fourcc) {
1680     case V4L2_PIX_FMT_YUV420:
1681       outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1682       outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1683       break;
1684     case V4L2_PIX_FMT_YUYV:
1685       outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1686       break;
1687     case V4L2_PIX_FMT_Y41P:
1688       outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1689       break;
1690     case V4L2_PIX_FMT_UYVY:
1691       outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1692       break;
1693     case V4L2_PIX_FMT_YVU420:
1694       outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1695       outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1696       break;
1697     case V4L2_PIX_FMT_YUV411P:
1698       outsize = GST_ROUND_UP_4 (*w) * *h;
1699       outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
1700       break;
1701     case V4L2_PIX_FMT_YUV422P:
1702       outsize = GST_ROUND_UP_4 (*w) * *h;
1703       outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
1704       break;
1705     case V4L2_PIX_FMT_NV12:
1706       outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1707       outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1708       break;
1709     case V4L2_PIX_FMT_NV21:
1710       outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1711       outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1712       break;
1713   }
1714
1715   return outsize;
1716 }
1717
1718 /*
1719  */
1720 static gboolean
1721 gst_v4l2camsrc_configure_device (GstMFLDV4l2CamSrc * v4l2camsrc,
1722     guint32 * pixelformat, guint * width, guint * height,
1723     guint * fps_n, guint * fps_d)
1724 {
1725   gint fd = v4l2camsrc->video_fd;
1726   struct v4l2_format format;
1727   struct v4l2_streamparm stream;
1728   gboolean ret = TRUE;
1729
1730   GST_DEBUG_OBJECT (v4l2camsrc, "Configuring device to %dx%d, format "
1731       "%" GST_FOURCC_FORMAT, *width, *height, GST_FOURCC_ARGS (*pixelformat));
1732
1733   GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
1734
1735   memset (&format, 0x00, sizeof (struct v4l2_format));
1736   format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1737
1738   if (ioctl (fd, VIDIOC_G_FMT, &format) < 0)
1739     goto get_fmt_failed;
1740
1741   if (v4l2camsrc->dump_raw)
1742     format.type = V4L2_BUF_TYPE_PRIVATE;
1743   else
1744     format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1745   format.fmt.pix.width = *width;
1746   format.fmt.pix.height = *height;
1747   format.fmt.pix.pixelformat = *pixelformat;
1748   /* request whole frames; change when gstreamer supports interlaced video
1749    * (INTERLACED mode returns frames where the fields have already been
1750    *  combined, there are other modes for requesting fields individually) */
1751   format.fmt.pix.field = V4L2_FIELD_INTERLACED;
1752
1753   if (ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
1754     if (errno != EINVAL)
1755       goto set_fmt_failed;
1756
1757     /* try again with progressive video */
1758     format.fmt.pix.width = *width;
1759     format.fmt.pix.height = *height;
1760     format.fmt.pix.pixelformat = *pixelformat;
1761     format.fmt.pix.field = V4L2_FIELD_NONE;
1762     if (ioctl (fd, VIDIOC_S_FMT, &format) < 0)
1763       goto set_fmt_failed;
1764   }
1765
1766   if (v4l2camsrc->dump_raw)
1767     v4l2camsrc->raw_output_size = format.fmt.pix.priv;
1768
1769   if (format.fmt.pix.width != *width || format.fmt.pix.height != *height)
1770     goto invalid_dimensions;
1771
1772   if (format.fmt.pix.pixelformat != *pixelformat)
1773     goto invalid_pixelformat;
1774
1775   memset (&stream, 0x00, sizeof (struct v4l2_streamparm));
1776   stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1777   if (ioctl (fd, VIDIOC_G_PARM, &stream) < 0) {
1778     GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1779         ("Could not get parameters on device '%s'",
1780             v4l2camsrc->videodev), GST_ERROR_SYSTEM);
1781     goto done;
1782   }
1783
1784   if (fps_n == NULL || fps_d == NULL) {
1785     GST_LOG_OBJECT (v4l2camsrc, "Framerate will not be set");
1786     goto done;
1787   }
1788
1789   GST_LOG_OBJECT (v4l2camsrc, "Desired framerate: %u/%u", *fps_n, *fps_d);
1790
1791   /* Note: V4L2 provides the frame interval, we have the frame rate */
1792   if (stream.parm.capture.timeperframe.denominator &&
1793       fractions_are_equal (stream.parm.capture.timeperframe.numerator,
1794           stream.parm.capture.timeperframe.denominator, *fps_d, *fps_n)) {
1795     GST_LOG_OBJECT (v4l2camsrc, "Desired framerate already set, nothing to do");
1796     goto done;
1797   }
1798
1799   /* We want to change the frame rate, so check whether we can. Some cheap USB
1800    * cameras don't have the capability */
1801   if ((stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
1802     GST_DEBUG_OBJECT (v4l2camsrc, "Not setting framerate (not supported)");
1803     goto done;
1804   }
1805
1806   GST_LOG_OBJECT (v4l2camsrc, "Setting framerate to %u/%u", *fps_n, *fps_d);
1807
1808   /* Note: V4L2 wants the frame interval, we have the frame rate */
1809   stream.parm.capture.timeperframe.numerator = *fps_d;
1810   stream.parm.capture.timeperframe.denominator = *fps_n;
1811
1812   /* some cheap USB cam's won't accept any change */
1813   if (ioctl (fd, VIDIOC_S_PARM, &stream) < 0) {
1814     GST_ELEMENT_WARNING (v4l2camsrc, RESOURCE, SETTINGS,
1815         ("Video input device did not accept new frame rate setting."),
1816         GST_ERROR_SYSTEM);
1817     goto done;
1818   }
1819
1820   GST_INFO_OBJECT (v4l2camsrc, "Set frame interval to %u/%u",
1821       stream.parm.capture.timeperframe.numerator,
1822       stream.parm.capture.timeperframe.denominator);
1823
1824   cam_set_frame_rate( ((gfloat)stream.parm.capture.timeperframe.denominator / stream.parm.capture.timeperframe.numerator));
1825
1826 done:
1827   v4l2camsrc->max_zoom_factor = 10.0;
1828   v4l2camsrc->frame_byte_size = gst_v4l2camsrc_get_frame_size (*pixelformat,
1829       width, height);
1830   /* v4l2camsrc->frame_byte_size = GST_ROUND_UP_2 (*width) * 2 * (*height); */
1831
1832   if (v4l2camsrc->bayer_downscaling) {
1833     struct v4l2_crop crop;
1834     memset (&v4l2camsrc->vcrop, 0, sizeof (struct v4l2_cropcap));
1835     v4l2camsrc->vcrop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1836     if (ioctl (v4l2camsrc->video_fd, VIDIOC_CROPCAP, &v4l2camsrc->vcrop) < 0) {
1837       GST_DEBUG_OBJECT (v4l2camsrc, "Failed to query crop cap");
1838       goto no_crop;
1839     }
1840
1841     crop.c = v4l2camsrc->vcrop.defrect; /* reset to default */
1842     crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1843     if (-1 == ioctl (fd, VIDIOC_S_CROP, &crop)) {
1844       switch (errno) {
1845         case EINVAL:
1846           GST_DEBUG_OBJECT (v4l2camsrc, "Crop not support\n");
1847           break;
1848         default:
1849           GST_DEBUG_OBJECT (v4l2camsrc, "Crop failed\n");
1850           break;
1851       }
1852     }
1853
1854     goto no_crop;
1855
1856
1857
1858     v4l2camsrc->crop_supported = TRUE;
1859
1860     GST_DEBUG_OBJECT (v4l2camsrc, "got cropping bounds: x:%d, y:%d, w:%d, h:%d",
1861         v4l2camsrc->vcrop.bounds.left,
1862         v4l2camsrc->vcrop.bounds.top,
1863         v4l2camsrc->vcrop.bounds.width, v4l2camsrc->vcrop.bounds.height);
1864
1865     GST_DEBUG_OBJECT (v4l2camsrc, "cropping defrect: x:%d, y:%d, w:%d, h:%d",
1866         v4l2camsrc->vcrop.defrect.left,
1867         v4l2camsrc->vcrop.defrect.top,
1868         v4l2camsrc->vcrop.defrect.width, v4l2camsrc->vcrop.defrect.height);
1869
1870     gst_v4l2camsrc_update_cropping (v4l2camsrc, *width, *height, 1.0);
1871   }
1872
1873 no_crop:
1874   cam_set_capture_fmt (v4l2camsrc->video_fd, *width, *height, *pixelformat);
1875
1876   return ret;
1877
1878   /* ERRORS */
1879 get_fmt_failed:
1880   {
1881     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1882         ("Device '%s' does not support video capture",
1883             v4l2camsrc->videodev),
1884         ("Call to G_FMT failed: (%s)", g_strerror (errno)));
1885     return FALSE;
1886   }
1887 set_fmt_failed:
1888   {
1889     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1890         ("Device '%s' cannot capture at %dx%d",
1891             v4l2camsrc->videodev, *width, *height),
1892         ("Call to S_FMT failed for %" GST_FOURCC_FORMAT " @ %dx%d: %s",
1893             GST_FOURCC_ARGS (*pixelformat), *width, *height,
1894             g_strerror (errno)));
1895     return FALSE;
1896   }
1897 invalid_dimensions:
1898   {
1899     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1900         ("Device '%s' cannot capture at %dx%d",
1901             v4l2camsrc->videodev, *width, *height),
1902         ("Tried to capture at %dx%d, but device returned size %dx%d",
1903             *width, *height, format.fmt.pix.width, format.fmt.pix.height));
1904     return FALSE;
1905   }
1906 invalid_pixelformat:
1907   {
1908     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, SETTINGS,
1909         ("Device '%s' cannot capture in the specified format",
1910             v4l2camsrc->videodev),
1911         ("Tried to capture in %" GST_FOURCC_FORMAT
1912             ", but device returned format" " %" GST_FOURCC_FORMAT,
1913             GST_FOURCC_ARGS (*pixelformat),
1914             GST_FOURCC_ARGS (format.fmt.pix.pixelformat)));
1915     return FALSE;
1916   }
1917 }
1918
1919 static gboolean resolution_is_supported(int w, int h)
1920 {
1921         return (w % 4) == 0 && (h % 4) == 0;
1922 }
1923
1924 #define probe_and_add_for_w_h(w, h)                                     \
1925         do{                                                             \
1926                 GST_LOG(" w=%lu h=%lu",w,h);                            \
1927                 tmp = gst_v4l2camsrc_probe_caps_for_format_and_size(v4l2camsrc, \
1928                                                                 pixelformat, w, h, template); \
1929                 if(tmp)                                                 \
1930                         res = g_list_prepend(res, tmp);                 \
1931         } while(0)
1932
1933
1934 static GList *build_caps_list(GstMFLDV4l2CamSrc * v4l2camsrc,
1935         guint32 pixelformat, const GstStructure * template,
1936         struct v4l2_frmsizeenum *size)
1937 {
1938         GstStructure *tmp = NULL;
1939         GList *res = NULL;
1940         long wl,wh,hl,hh,ws,hs;
1941
1942         wl = size->stepwise.min_width; wh = size->stepwise.max_width; ws = size->stepwise.step_width;
1943         hl = size->stepwise.min_height; hh = size->stepwise.max_height; hs = size->stepwise.step_height;
1944
1945         probe_and_add_for_w_h(wl, hl);
1946         probe_and_add_for_w_h(wh, hh);
1947
1948         tmp = gst_structure_copy(template);
1949         gst_structure_set (tmp,
1950                         "width", GST_TYPE_INT_RANGE, wl, wh,
1951                         "height", GST_TYPE_INT_RANGE, hl, hh,
1952                         NULL);
1953         res = g_list_prepend(res, tmp);
1954
1955         return res;
1956 }
1957
1958
1959 /**
1960  * gst_v4l2camsrc_probe_caps_for_format:
1961  * @v4l2camsrc: #GstMFLDV4l2CamSrc object
1962  * @pixelformat: pixel format fourcc
1963  * @template: GstStructure template to be used for generating the caps
1964  *
1965  * Creates GstCaps object which describes the supported caps of the device.
1966  *
1967  * Returns: GStCaps containing supported video resolutions.
1968  */
1969 GstCaps *
1970 gst_v4l2camsrc_probe_caps_for_format (GstMFLDV4l2CamSrc * v4l2camsrc,
1971     guint32 pixelformat, const GstStructure * template)
1972 {
1973   GstCaps *ret = gst_caps_new_empty ();
1974   gint min_w, max_w, min_h, max_h;
1975   GstStructure *tmp;
1976
1977 #ifdef VIDIOC_ENUM_FRAMESIZES
1978   {
1979     gint fd = v4l2camsrc->video_fd;
1980     struct v4l2_frmsizeenum size;
1981     GList *results = NULL;
1982     gint w, h;
1983
1984     memset (&size, 0, sizeof (struct v4l2_frmsizeenum));
1985     size.index = 0;
1986     size.pixel_format = pixelformat;
1987
1988     if (ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0)
1989       goto enum_framesizes_failed;
1990
1991     if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
1992       do {
1993         w = MIN (size.discrete.width, G_MAXINT);
1994         h = MIN (size.discrete.height, G_MAXINT);
1995
1996         if(resolution_is_supported(w, h)) {
1997                 tmp = gst_v4l2camsrc_probe_caps_for_format_and_size (v4l2camsrc,
1998                         pixelformat, w, h, template);
1999
2000                 if (tmp)
2001                         results = g_list_prepend (results, tmp);
2002         }
2003
2004         size.index++;
2005       } while (ioctl (fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
2006     } else if(size.type == V4L2_FRMSIZE_TYPE_STEPWISE
2007             || size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
2008             results = build_caps_list(v4l2camsrc, pixelformat, template, &size);
2009     } else {
2010       goto unknown_type;
2011     }
2012
2013     /* Sort the resolutions from smallest to largest */
2014     results = g_list_sort (results, compare_resolutions);
2015
2016     while (results != NULL) {
2017       tmp = GST_STRUCTURE (results->data);
2018
2019       gst_caps_merge_structure (ret, tmp);
2020
2021       results = g_list_delete_link (results, results);
2022     }
2023
2024     if (gst_caps_is_empty (ret))
2025       goto enum_framesizes_no_results;
2026
2027     return ret;
2028
2029     /* ERRORS */
2030   enum_framesizes_failed:
2031     {
2032       /* I don't see how this is actually an error */
2033       GST_DEBUG_OBJECT (v4l2camsrc,
2034           "Failed to enumerate frame sizes for pixelformat %" GST_FOURCC_FORMAT
2035           " (%s)", GST_FOURCC_ARGS (pixelformat), g_strerror (errno));
2036       goto default_frame_sizes;
2037     }
2038   enum_framesizes_no_results:
2039     {
2040       /* it's possible that VIDIOC_ENUM_FRAMESIZES is defined but the driver in
2041        * question doesn't actually support it yet */
2042       GST_DEBUG_OBJECT (v4l2camsrc, "No results for pixelformat %"
2043           GST_FOURCC_FORMAT " enumerating frame sizes, trying fallback",
2044           GST_FOURCC_ARGS (pixelformat));
2045       goto default_frame_sizes;
2046     }
2047   unknown_type:
2048     {
2049       GST_WARNING_OBJECT (v4l2camsrc,
2050           "Unknown frame sizeenum type for pixelformat %" GST_FOURCC_FORMAT
2051           ": %u", GST_FOURCC_ARGS (pixelformat), size.type);
2052       goto default_frame_sizes;
2053     }
2054   }
2055 #endif /* defined VIDIOC_ENUM_FRAMESIZES */
2056
2057 default_frame_sizes:
2058
2059   min_w = min_h = 1;
2060   max_w = max_h = GST_CAMERA_SRC_MAX_SIZE;
2061   if (!gst_v4l2camsrc_get_nearest_size (v4l2camsrc, pixelformat,
2062           &min_w, &min_h)) {
2063     GST_WARNING_OBJECT (v4l2camsrc,
2064         "Could not probe minimum capture size for pixelformat %"
2065         GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2066   }
2067   if (!gst_v4l2camsrc_get_nearest_size (v4l2camsrc, pixelformat,
2068           &max_w, &max_h)) {
2069     GST_WARNING_OBJECT (v4l2camsrc,
2070         "Could not probe maximum capture size for pixelformat %"
2071         GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
2072   }
2073
2074   tmp = gst_structure_copy (template);
2075   gst_structure_set (tmp,
2076       "width", GST_TYPE_INT_RANGE, min_w, max_w,
2077       "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL);
2078   gst_caps_append_structure (ret, tmp);
2079
2080   return ret;
2081 }
2082
2083 static void draw_corner_markers_nv12(unsigned char *buf, unsigned w, unsigned h)
2084 {
2085         int i,j;
2086 #define put_dot(x,y) buf[(x)+w*(y)] = (((x+y)&0x01)?0x00:0xff)
2087
2088         for(j = 0; j < 4; ++j)
2089                 for(i = 0; i < 8; ++i) {
2090                         put_dot(i, j); put_dot(w-1-i, j);
2091                         put_dot(j, i); put_dot(j, h-1-i);
2092                         put_dot(i, h-1-j); put_dot(w-1-i, h-1-j);
2093                         put_dot(w-1-j, i); put_dot(w-1-j, h-1-i);
2094                 }
2095 #undef put_dot
2096 }
2097
2098 /* Crop to upper left corner of NV12 frame. */
2099 static gboolean crop_buffer_inplace_nv12(unsigned char *buf, unsigned in_w, unsigned in_h,
2100                                 unsigned out_w, unsigned out_h)
2101 {
2102         unsigned rows;
2103         unsigned char *in, *out;
2104
2105         if(in_w < out_w || in_h < out_h
2106                 || in_w % 4 || out_w % 4
2107                 || in_h % 4 || out_h % 4)
2108                 return FALSE;
2109
2110         in = buf; out = buf;
2111         for(rows = 0; rows < out_h; ++rows) {
2112                 memmove(out, in, out_w);
2113                 in += in_w;
2114                 out += out_w;
2115         }
2116         in = buf + in_w * in_h;
2117         for(rows = 0; rows < out_h / 2; ++rows) {
2118                 memmove(out, in, out_w);
2119                 in += in_w;
2120                 out += out_w;
2121         }
2122
2123         return TRUE;
2124 }
2125
2126 /**
2127  * gst_v4l2camsrc_libmfld_grab_hq_frame:
2128  * @v4l2camsrc: #GstMFLDV4l2CamSrc object
2129  * @buf: Pointer to v4l2_buffer where to place the image frame
2130  *
2131  * Grab a High-Quality image by using libmfldcam.
2132  *
2133  * Returns: TRUE if capture succeeds, FALSE otherwise
2134  */
2135 gboolean
2136 gst_v4l2camsrc_libmfld_grab_hq_frame (GstMFLDV4l2CamSrc * v4l2camsrc,
2137     struct v4l2_buffer * buffer)
2138 {
2139   cam_err_t err;
2140   gboolean ret;
2141   struct cam_capture_settings st;
2142
2143   st.mmap = v4l2camsrc->use_mmap;
2144   st.ae_awb_af = v4l2camsrc->ae_awb_af_enabled;
2145   st.dump_raw = v4l2camsrc->dump_raw;
2146   st.raw_output_size = v4l2camsrc->raw_output_size;
2147   st.dump_image = v4l2camsrc->dump_image;
2148
2149   err = cam_capture_frames (v4l2camsrc->video_fd, buffer, &st);
2150   if (v4l2camsrc->ae_awb_af_enabled)
2151     mfldcam_3a_start ();
2152   ret = (err == CAM_ERR_NONE);
2153
2154   return ret;
2155 }
2156
2157 /******************************************************
2158  * gst_v4l2camsrc_grab_frame ():
2159  *   grab a frame for capturing
2160  * return value: GST_FLOW_OK, GST_FLOW_WRONG_STATE or GST_FLOW_ERROR
2161  ******************************************************/
2162 GstFlowReturn
2163 gst_v4l2camsrc_grab_frame (GstCameraSrc * camsrc, GstBuffer ** buf,
2164     GstCameraCapturePhase phase)
2165 {
2166   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2167
2168 #define NUM_TRIALS 5000
2169   struct v4l2_buffer buffer;
2170   gint32 trials = NUM_TRIALS;
2171   GstBuffer *pool_buffer;
2172   gboolean need_copy = v4l2camsrc->use_copy;
2173   gboolean variable_frame_size = FALSE;  /* FIXME if we ever support JPEG etc */
2174   gint index;
2175   gint ret;
2176   unsigned real_w;
2177
2178   /* wait if all buffers are DQBuf */
2179   g_mutex_lock (v4l2camsrc->device_mutex);
2180   gst_v4l2_buffer_pool_update (v4l2camsrc->pool, v4l2camsrc);
2181   g_mutex_unlock (v4l2camsrc->device_mutex);
2182
2183   memset (&buffer, 0x00, sizeof (buffer));
2184   buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2185
2186   if (v4l2camsrc->use_mmap)
2187     buffer.memory = V4L2_MEMORY_MMAP;
2188   else
2189     buffer.memory = V4L2_MEMORY_USERPTR;
2190
2191   if (phase == GST_CAMERA_CAPTURE) {
2192     gst_camerasrc_send_capture_start_message (camsrc);
2193   }
2194
2195   for (;;) {
2196     ret = gst_poll_wait (v4l2camsrc->poll, V4L2CAMSRC_POLL_TIMEOUT);
2197     if (G_UNLIKELY (ret < 0)) {
2198       if (errno == EBUSY)
2199         goto stopped;
2200       if (errno != EAGAIN && errno != EINTR)
2201         goto select_error;
2202     }
2203
2204     if (G_UNLIKELY (ret == 0)) {
2205       goto timeout;
2206     }
2207     g_mutex_lock (v4l2camsrc->device_mutex);
2208     ret = gst_v4l2camsrc_libmfld_grab_hq_frame (v4l2camsrc, &buffer);
2209     g_mutex_unlock (v4l2camsrc->device_mutex);
2210
2211     if (ret >= 0)
2212       break;
2213
2214     GST_WARNING_OBJECT (v4l2camsrc,
2215         "problem grabbing frame %d (ix=%d), trials=%d, pool-ct=%d, buf.flags=%d",
2216         buffer.sequence, buffer.index, trials,
2217         GST_MINI_OBJECT_REFCOUNT (v4l2camsrc->pool), buffer.flags);
2218
2219     /* if the sync() got interrupted, we can retry */
2220     switch (errno) {
2221       case EAGAIN:
2222         GST_WARNING_OBJECT (v4l2camsrc,
2223             "Non-blocking I/O has been selected using O_NONBLOCK and"
2224             " no buffer was in the outgoing queue. device %s",
2225             v4l2camsrc->videodev);
2226         break;
2227       case EINVAL:
2228         goto einval;
2229       case ENOMEM:
2230         goto enomem;
2231       case EIO:
2232         GST_INFO_OBJECT (v4l2camsrc,
2233             "VIDIOC_DQBUF failed due to an internal error."
2234             " Can also indicate temporary problems like signal loss."
2235             " Note the driver might dequeue an (empty) buffer despite"
2236             " returning an error, or even stop capturing."
2237             " device %s", v4l2camsrc->videodev);
2238         /* have we de-queued a buffer ? */
2239         if (!(buffer.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))) {
2240           /* this fails
2241              if ((buffer.index >= 0) && (buffer.index < v4l2camsrc->breq.count)) {
2242              GST_DEBUG_OBJECT (v4l2camsrc, "reenqueing buffer (ix=%ld)", buffer.index);
2243              gst_v4l2camsrc_queue_frame (v4l2camsrc, buffer.index);
2244              }
2245              else {
2246            */
2247           GST_DEBUG_OBJECT (v4l2camsrc, "reenqueing buffer");
2248           /* FIXME: this is not a good idea, as drivers usualy return the buffer
2249            * with index-number set to 0, thus the re-enque will fail unless it
2250            * was incidentialy 0.
2251            * We could try to re-enque all buffers without handling the ioctl
2252            * return.
2253            */
2254           /*
2255              if (ioctl (v4l2camsrc->video_fd, VIDIOC_QBUF, &buffer) < 0) {
2256              goto qbuf_failed;
2257              }
2258            */
2259           /*} */
2260         }
2261         break;
2262       case EINTR:
2263         GST_WARNING_OBJECT (v4l2camsrc,
2264             "could not sync on a buffer on device %s", v4l2camsrc->videodev);
2265         break;
2266       default:
2267         GST_WARNING_OBJECT (v4l2camsrc,
2268             "Grabbing frame got interrupted on %s. No expected reason.",
2269             v4l2camsrc->videodev);
2270         break;
2271     }
2272
2273     /* check nr. of attempts to capture */
2274     if (--trials == -1) {
2275       goto too_many_trials;
2276     } else {
2277       memset (&buffer, 0x00, sizeof (buffer));
2278       buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2279       if (v4l2camsrc->use_mmap)
2280         buffer.memory = V4L2_MEMORY_MMAP;
2281       else
2282         buffer.memory = V4L2_MEMORY_USERPTR;
2283     }
2284   }
2285
2286   if (phase == GST_CAMERA_CAPTURE) {
2287     gst_camerasrc_send_capture_stop_message (camsrc);
2288   } else  {
2289     /* Send the CAF status message */
2290     GstCameraFocusStatus focus_status;
2291     gboolean lret;
2292     lret = gst_v4l2camsrc_check_focus_status(v4l2camsrc, &focus_status, FALSE);
2293     if (lret) {
2294       GST_LOG_OBJECT (v4l2camsrc, "CAF status: %d", focus_status.status);
2295       if (focus_status.status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS )
2296         gst_camerasrc_send_af_status(GST_CAMERA_SRC (v4l2camsrc) ,CAMERASRC_AUTO_FOCUS_RESULT_FOCUSED);
2297       else if (focus_status.status == GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL )
2298         gst_camerasrc_send_af_status(GST_CAMERA_SRC (v4l2camsrc) ,CAMERASRC_AUTO_FOCUS_RESULT_FAILED);
2299       else {
2300         GST_WARNING_OBJECT (v4l2camsrc, "CAF status erronous: %d send as failed", focus_status.status);
2301         gst_camerasrc_send_af_status(GST_CAMERA_SRC (v4l2camsrc) ,CAMERASRC_AUTO_FOCUS_RESULT_FAILED);
2302       }
2303     }
2304   }
2305
2306
2307   g_mutex_lock (v4l2camsrc->pool->lock);
2308
2309   index = buffer.index;
2310
2311   /* get our GstBuffer with that index from the pool, if the buffer is
2312    * in use (NULL) we have a serious problem (should only be possible in mmap
2313    * case). */
2314   pool_buffer = GST_BUFFER (v4l2camsrc->pool->buffers[index]);
2315
2316   if (G_UNLIKELY (pool_buffer == NULL))
2317     goto no_buffer;
2318
2319   GST_LOG_OBJECT (v4l2camsrc, "grabbed buffer %p at index %d (refct = %d)",
2320       pool_buffer, index, GST_MINI_OBJECT_REFCOUNT (pool_buffer));
2321
2322   /* ref the buffer and requeue, when if becomes writable again */
2323   v4l2camsrc->pool->buffers[index] = NULL;
2324   v4l2camsrc->pool->num_live_buffers++;
2325   v4l2camsrc->pool->queued[index] = 0;
2326
2327   /* SW workaround for ISP padding. */
2328
2329   if(v4l2camsrc->expected_capture_w < 320 && (v4l2camsrc->expected_capture_w % 32 != 0)
2330       && v4l2camsrc->expected_capture_fourcc == V4L2_PIX_FMT_NV12
2331       && !v4l2camsrc->disable_low_res_crop) {
2332
2333     real_w = (v4l2camsrc->expected_capture_w & ~31) + 32;
2334
2335     GST_LOG_OBJECT(v4l2camsrc, "Downscaling padded buffer with cropping (%u,%u) -> (%u,%u)",
2336       real_w, v4l2camsrc->expected_capture_h, v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h);
2337
2338     if(!crop_buffer_inplace_nv12(GST_BUFFER_DATA(pool_buffer),
2339         real_w, v4l2camsrc->expected_capture_h,
2340         v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h)) {
2341       GST_ERROR_OBJECT(v4l2camsrc,"Software crop failed");
2342     }
2343   }
2344
2345   if(v4l2camsrc->draw_corner_markers)
2346     draw_corner_markers_nv12(GST_BUFFER_DATA(pool_buffer),
2347       v4l2camsrc->expected_capture_w, v4l2camsrc->expected_capture_h);
2348
2349   g_mutex_unlock (v4l2camsrc->pool->lock);
2350
2351   /* this can change at every frame, esp. with jpeg */
2352   if(variable_frame_size)
2353           GST_BUFFER_SIZE (pool_buffer) = buffer.bytesused;
2354   else
2355           GST_BUFFER_SIZE (pool_buffer) = v4l2camsrc->frame_byte_size;
2356
2357   GST_BUFFER_OFFSET (pool_buffer) = v4l2camsrc->offset++;
2358   GST_BUFFER_OFFSET_END (pool_buffer) = v4l2camsrc->offset;
2359
2360   /* timestamps, LOCK to get clock and base time. */
2361   {
2362     GstClock *clock;
2363     GstClockTime timestamp;
2364
2365     GST_OBJECT_LOCK (v4l2camsrc);
2366     if ((clock = GST_ELEMENT_CLOCK (v4l2camsrc))) {
2367       /* we have a clock, get base time and ref clock */
2368       timestamp = GST_ELEMENT (v4l2camsrc)->base_time;
2369       gst_object_ref (clock);
2370     } else {
2371       /* no clock, can't set timestamps */
2372       timestamp = GST_CLOCK_TIME_NONE;
2373     }
2374     GST_OBJECT_UNLOCK (v4l2camsrc);
2375
2376     if (clock) {
2377       GstClockTime latency;
2378
2379       /* the time now is the time of the clock minus the base time */
2380       timestamp = gst_clock_get_time (clock) - timestamp;
2381       gst_object_unref (clock);
2382
2383       latency =
2384           gst_util_uint64_scale_int (GST_SECOND, camsrc->fps_d, camsrc->fps_n);
2385
2386       if (timestamp > latency)
2387         timestamp -= latency;
2388       else
2389         timestamp = 0;
2390       GST_BUFFER_DURATION (pool_buffer) = latency;
2391     }
2392     /* activate settings for next frame (Code from v4l2src) */
2393     if (GST_CLOCK_TIME_IS_VALID (camsrc->duration)) {
2394       v4l2camsrc->ctrl_time += camsrc->duration;
2395     } else {
2396       v4l2camsrc->ctrl_time = timestamp;
2397     }
2398     gst_object_sync_values (G_OBJECT (camsrc), v4l2camsrc->ctrl_time);
2399
2400     /* FIXME: use the timestamp from the buffer itself! */
2401     GST_BUFFER_TIMESTAMP (pool_buffer) = timestamp;
2402   }
2403
2404   if (G_UNLIKELY (need_copy)) {
2405     GST_DEBUG_OBJECT (v4l2camsrc, "copying buffer");
2406     *buf = gst_buffer_copy (pool_buffer);
2407     GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY);
2408     /* this will requeue */
2409     gst_buffer_unref (pool_buffer);
2410   } else {
2411     if (v4l2camsrc->pool->is_vaapi_sharing)
2412         GST_BUFFER_DATA(pool_buffer) = (GST_V4L2CAMSRC_BUFFER(pool_buffer))->gbuffer;
2413     *buf = pool_buffer;
2414   }
2415
2416   GST_LOG_OBJECT (v4l2camsrc,
2417       "grabbed frame %d (ix=%d), flags %08x, pool-ct=%d", buffer.sequence,
2418       buffer.index, buffer.flags, v4l2camsrc->pool->num_live_buffers);
2419
2420   return GST_FLOW_OK;
2421
2422   /* ERRORS */
2423 select_error:
2424   {
2425     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ, (NULL),
2426         ("select error %d: %s (%d)", ret, g_strerror (errno), errno));
2427     return GST_FLOW_ERROR;
2428   }
2429 stopped:
2430   {
2431     GST_DEBUG ("stop called");
2432     return GST_FLOW_WRONG_STATE;
2433   }
2434 einval:
2435   {
2436     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2437         ("Failed trying to get video frames from device '%s'.",
2438             v4l2camsrc->videodev),
2439         ("The buffer type is not supported, or the index is out of bounds,"
2440             " or no buffers have been allocated yet, or the userptr"
2441             " or length are invalid. device %s", v4l2camsrc->videodev));
2442     return GST_FLOW_ERROR;
2443   }
2444 enomem:
2445   {
2446     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2447         ("Failed trying to get video frames from device '%s'. Not enough memory.",
2448             v4l2camsrc->videodev), ("insufficient memory to enqueue a user "
2449             "pointer buffer. device %s.", v4l2camsrc->videodev));
2450     return GST_FLOW_ERROR;
2451   }
2452 too_many_trials:
2453   {
2454     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2455         ("Failed trying to get video frames from device '%s'.",
2456             v4l2camsrc->videodev),
2457         ("Failed after %d tries. device %s. system error: %s",
2458             NUM_TRIALS, v4l2camsrc->videodev, g_strerror (errno)));
2459     return GST_FLOW_ERROR;
2460   }
2461 no_buffer:
2462   {
2463     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2464         ("Failed trying to get video frames from device '%s'.",
2465             v4l2camsrc->videodev),
2466         ("No free buffers found in the pool at index %d.", index));
2467     g_mutex_unlock (v4l2camsrc->pool->lock);
2468     return GST_FLOW_ERROR;
2469   }
2470 /*
2471 qbuf_failed:
2472   {
2473     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, WRITE,
2474         ("Could not exchange data with device '%s'.",
2475             v4l2camsrc->videodev),
2476         ("Error queueing buffer on device %s. system error: %s",
2477             v4l2camsrc->videodev, g_strerror (errno)));
2478     return GST_FLOW_ERROR;
2479   }
2480 */
2481 timeout:
2482   {
2483     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, FAILED,
2484         ("Timeout when trying to get video frames from device '%s'.",
2485             v4l2camsrc->videodev), NULL);
2486     return GST_FLOW_ERROR;
2487   }
2488 }
2489
2490
2491 /******************************************************
2492  * gst_v4l2camsrc_set_capture():
2493  *   set capture parameters for certain operation mode
2494  * return value: TRUE on success, FALSE on error
2495  ******************************************************/
2496 gboolean
2497 gst_v4l2camsrc_set_capture (GstCameraSrc * camsrc, GstOperationMode mode,
2498     gboolean try_only, guint32 * pixelformat, guint * width, guint * height,
2499     guint * fps_n, guint * fps_d)
2500 {
2501   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2502   cam_err_t err = CAM_ERR_NONE;
2503   gboolean ret = TRUE;
2504
2505   GST_DEBUG_OBJECT (v4l2camsrc, "mode = %d, try_only = %d", mode, try_only);
2506
2507   v4l2camsrc->expected_capture_w = *width;
2508   v4l2camsrc->expected_capture_h = *height;
2509   v4l2camsrc->expected_capture_fourcc = *pixelformat;
2510
2511   if (mode == GST_PHOTOGRAPHY_OPERATION_MODE_PREVIEW) {
2512     return FALSE;
2513   } else if (mode == GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE) {
2514     GST_DEBUG_OBJECT (v4l2camsrc, "Image capture: %dx%d, format "
2515         "%" GST_FOURCC_FORMAT, *width, *height, GST_FOURCC_ARGS (*pixelformat));
2516
2517     if (try_only) {
2518       /* Round width & height down to be dividable by 8 */
2519       *width = (*width) & ~7;
2520       *height = (*height) & ~7;
2521       ret = TRUE;
2522     } else {
2523       ret = gst_v4l2camsrc_configure_device (v4l2camsrc, pixelformat,
2524           width, height, fps_n, fps_d);
2525
2526       v4l2camsrc->tmp_num_buffers = v4l2camsrc->num_buffers;
2527       v4l2camsrc->num_buffers = 1;
2528
2529       v4l2camsrc->capture_w = *width;
2530       v4l2camsrc->capture_h = *height;
2531       if (fps_n && fps_d) {
2532         v4l2camsrc->capture_fps_n = *fps_n;
2533         v4l2camsrc->capture_fps_d = *fps_d;
2534       }
2535       v4l2camsrc->capture_fourcc = *pixelformat;
2536     }
2537   } else {
2538     /* VIEWFINDER mode */
2539     /* FIXME: handle try_only mode */
2540
2541     v4l2camsrc->num_buffers = v4l2camsrc->tmp_num_buffers;
2542
2543     ret = gst_v4l2camsrc_configure_device (v4l2camsrc, pixelformat,
2544         width, height, fps_n, fps_d);
2545
2546     v4l2camsrc->vf_w = *width;
2547     v4l2camsrc->vf_h = *height;
2548     v4l2camsrc->vf_fourcc = *pixelformat;
2549     if (fps_n && fps_d) {
2550       v4l2camsrc->vf_fps_n = *fps_n;
2551       v4l2camsrc->vf_fps_d = *fps_d;
2552     }
2553   }
2554   if (err != CAM_ERR_NONE)
2555     ret = FALSE;
2556
2557   return ret;
2558 }
2559
2560 /******************************************************
2561  * gst_v4l2camsrc_capture_start():
2562  *   Start capturing frames from the device
2563  * return value: TRUE on success, FALSE on error
2564  ******************************************************/
2565 gboolean
2566 gst_v4l2camsrc_capture_start (GstCameraSrc * camsrc, GstCaps * caps)
2567 {
2568   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2569
2570   gint fd = v4l2camsrc->video_fd;
2571   struct v4l2_requestbuffers breq;
2572   gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2573   cam_capture_mode_t cam_mode;
2574   cam_err_t err;
2575
2576   v4l2camsrc->offset = 0;
2577
2578   /* activate settings for first frame */
2579   v4l2camsrc->ctrl_time = 0;
2580   gst_object_sync_values (G_OBJECT (camsrc), v4l2camsrc->ctrl_time);
2581
2582   memset (&breq, 0, sizeof (struct v4l2_requestbuffers));
2583
2584   GST_DEBUG_OBJECT (v4l2camsrc, "initializing the capture system");
2585
2586   GST_V4L2CAMSRC_CHECK_OPEN (v4l2camsrc);
2587   GST_V4L2CAMSRC_CHECK_NOT_ACTIVE (v4l2camsrc);
2588
2589   if (!(v4l2camsrc->vcap.capabilities & V4L2_CAP_STREAMING))
2590     goto no_capture_method;
2591
2592   GST_DEBUG_OBJECT (v4l2camsrc, "STREAMING, requesting %d CAPTURE buffers",
2593       v4l2camsrc->num_buffers);
2594
2595   err = cam_driver_set_mipi_interrupt(fd,1);
2596   if (err != CAM_ERR_NONE)
2597     GST_DEBUG_OBJECT (v4l2camsrc, "MIPI interrupt enable FAILED !");
2598
2599   breq.count = v4l2camsrc->num_buffers;
2600   breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2601
2602   if(v4l2camsrc->use_mmap && GST_CAPS_IS_SIMPLE(caps)) {
2603     GstStructure *st = gst_caps_get_structure(caps, 0);
2604     if(g_str_has_prefix(gst_structure_get_name(st), "video/x-vaapi-sharing")) {
2605       v4l2camsrc->use_mmap = FALSE;
2606       GST_WARNING_OBJECT(v4l2camsrc, "mmap is not supported with VA shared buffer, turning off");
2607     }
2608   }
2609
2610   if (v4l2camsrc->use_mmap)
2611     breq.memory = V4L2_MEMORY_MMAP;
2612   else
2613     breq.memory = V4L2_MEMORY_USERPTR;
2614
2615   if (ioctl (fd, VIDIOC_REQBUFS, &breq) < 0)
2616     goto reqbufs_failed;
2617
2618   GST_LOG_OBJECT (v4l2camsrc, " count:  %u", breq.count);
2619   GST_LOG_OBJECT (v4l2camsrc, " type:   %d", breq.type);
2620   GST_LOG_OBJECT (v4l2camsrc, " memory: %d", breq.memory);
2621
2622   if (breq.count < GST_V4L2CAMSRC_MIN_BUFFERS)
2623     goto no_buffers;
2624
2625   if (v4l2camsrc->num_buffers != breq.count) {
2626     GST_WARNING_OBJECT (v4l2camsrc, "using %u buffers instead", breq.count);
2627     v4l2camsrc->num_buffers = breq.count;
2628     g_object_notify (G_OBJECT (v4l2camsrc), "queue-size");
2629   }
2630
2631   /* Map the buffers */
2632   GST_LOG_OBJECT (v4l2camsrc, "initiating buffer pool");
2633
2634   if (!(v4l2camsrc->pool =
2635           gst_v4l2camsrc_buffer_pool_new (camsrc, fd, caps)))
2636     goto buffer_pool_new_failed;
2637
2638   GST_INFO_OBJECT (v4l2camsrc, "capturing buffers");
2639
2640   GST_V4L2CAMSRC_SET_ACTIVE (v4l2camsrc);
2641
2642   GST_DEBUG_OBJECT (v4l2camsrc, "starting the capturing");
2643   GST_V4L2CAMSRC_CHECK_ACTIVE (v4l2camsrc);
2644
2645   if (!gst_v4l2camsrc_buffer_pool_activate (v4l2camsrc->pool, v4l2camsrc))
2646     goto pool_activate_failed;
2647
2648   if (ioctl (fd, VIDIOC_STREAMON, &type) < 0)
2649     goto streamon_failed;
2650
2651   v4l2camsrc->is_active = TRUE;
2652   GST_DEBUG_OBJECT (v4l2camsrc, "STREAMON called");
2653
2654   /* Update the focus only when the Sensor is stream on */
2655   if (v4l2camsrc->focus_updated) {
2656     cam_driver_set_focus_posi(v4l2camsrc->video_fd, v4l2camsrc->focus_posi);
2657     v4l2camsrc->focus_updated = FALSE;
2658   }
2659
2660   if (v4l2camsrc->zoom_updated) {
2661     gst_v4l2camsrc_libmfldcam_set_zoom(v4l2camsrc, v4l2camsrc->zoom_factor);
2662     v4l2camsrc->zoom_updated = FALSE;
2663   }
2664
2665    cam_mode = find_item (gst_v4l2camsrc_capture_map,v4l2camsrc->capture_mode);
2666    cam_set_capture_mode (v4l2camsrc->video_fd, cam_mode);
2667
2668   return TRUE;
2669
2670   /* ERRORS */
2671 reqbufs_failed:
2672   {
2673     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2674         ("Could not get buffers from device '%s'.",
2675             v4l2camsrc->videodev),
2676         ("error requesting %d buffers: %s",
2677             v4l2camsrc->num_buffers, g_strerror (errno)));
2678     cam_driver_set_mipi_interrupt(fd, 0);
2679     return FALSE;
2680   }
2681 no_buffers:
2682   {
2683     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2684         ("Could not get enough buffers from device '%s'.",
2685             v4l2camsrc->videodev),
2686         ("we received %d from device '%s', we want at least %d",
2687             breq.count, v4l2camsrc->videodev, GST_V4L2CAMSRC_MIN_BUFFERS));
2688     cam_driver_set_mipi_interrupt(fd, 0);
2689     return FALSE;
2690   }
2691 buffer_pool_new_failed:
2692   {
2693     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2694         ("Could not map buffers from device '%s'",
2695             v4l2camsrc->videodev),
2696         ("Failed to create buffer pool: %s", g_strerror (errno)));
2697     cam_driver_set_mipi_interrupt(fd, 0);
2698     return FALSE;
2699   }
2700 no_capture_method:
2701   {
2702     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, READ,
2703         ("The driver of device '%s' does not support streaming. ",
2704             v4l2camsrc->videodev), (NULL));
2705     cam_driver_set_mipi_interrupt(fd, 0);
2706     return FALSE;
2707   }
2708 pool_activate_failed:
2709   {
2710     /* already errored */
2711     cam_driver_set_mipi_interrupt(fd, 0);
2712     return FALSE;
2713   }
2714 streamon_failed:
2715   {
2716     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, OPEN_READ,
2717         ("Error starting streaming capture from device '%s'.",
2718             v4l2camsrc->videodev), GST_ERROR_SYSTEM);
2719     cam_driver_set_mipi_interrupt(fd, 0);
2720     return FALSE;
2721   }
2722 }
2723
2724 /******************************************************
2725  * gst_v4l2camsrc_capture_stop():
2726  *   stop streaming capture
2727  * return value: TRUE on success, FALSE on error
2728  ******************************************************/
2729 gboolean
2730 gst_v4l2camsrc_capture_stop (GstCameraSrc * camsrc)
2731 {
2732   GstMFLDV4l2CamSrc *v4l2camsrc = GST_V4L2CAMSRC (camsrc);
2733   struct v4l2_requestbuffers breq;
2734   gint fd = v4l2camsrc->video_fd;
2735   cam_err_t err;
2736
2737   gint type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2738
2739   memset(&breq, 0, sizeof(struct v4l2_requestbuffers));
2740
2741   GST_DEBUG_OBJECT (v4l2camsrc, "stopping capturing");
2742
2743   if (!GST_V4L2CAMSRC_IS_OPEN (v4l2camsrc)) {
2744     return TRUE;
2745   }
2746   if (!GST_V4L2CAMSRC_IS_ACTIVE (v4l2camsrc)) {
2747     return TRUE;
2748   }
2749
2750   err = cam_driver_set_mipi_interrupt(fd,0);
2751   if (err != CAM_ERR_NONE)
2752     GST_DEBUG_OBJECT (v4l2camsrc, "MIPI interrupt disable FAILED !");
2753
2754   /* we actually need to sync on all queued buffers but not
2755    * on the non-queued ones */
2756   if (ioctl (v4l2camsrc->video_fd, VIDIOC_STREAMOFF, &type) < 0)
2757     goto streamoff_failed;
2758
2759   GST_DEBUG_OBJECT (v4l2camsrc, "STREAMOFF called");
2760
2761   breq.count = 0;
2762   breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2763   if(v4l2camsrc->use_mmap)
2764           breq.memory = V4L2_MEMORY_MMAP;
2765   else
2766           breq.memory = V4L2_MEMORY_USERPTR;
2767
2768   GST_DEBUG_OBJECT (v4l2camsrc, "REQUEST 0 to finalize buffer");
2769
2770   if(ioctl(v4l2camsrc->video_fd, VIDIOC_REQBUFS, &breq) < 0)
2771     GST_DEBUG_OBJECT (v4l2camsrc, "Failed to REQUEST 0 to finalize buffer");
2772
2773
2774   if (v4l2camsrc->pool) {
2775     gst_v4l2camsrc_buffer_pool_destroy (v4l2camsrc->pool, v4l2camsrc);
2776     v4l2camsrc->pool = NULL;
2777   }
2778
2779   GST_V4L2CAMSRC_SET_INACTIVE (v4l2camsrc);
2780   v4l2camsrc->is_active = FALSE;
2781   mfldcam_3a_stop ();
2782
2783   return TRUE;
2784
2785   /* ERRORS */
2786 streamoff_failed:
2787   {
2788     GST_ELEMENT_ERROR (v4l2camsrc, RESOURCE, CLOSE,
2789         ("Error stopping streaming capture from device '%s'.",
2790             v4l2camsrc->videodev), GST_ERROR_SYSTEM);
2791     return FALSE;
2792   }
2793 }
2794
2795 /*
2796  */
2797 static gboolean
2798 gst_v4l2camsrc_get_nearest_size (GstMFLDV4l2CamSrc * v4l2camsrc,
2799     guint32 pixelformat, gint * width, gint * height)
2800 {
2801   struct v4l2_format fmt;
2802   int fd;
2803   int r;
2804
2805   g_return_val_if_fail (width != NULL, FALSE);
2806   g_return_val_if_fail (height != NULL, FALSE);
2807
2808   GST_LOG_OBJECT (v4l2camsrc,
2809       "getting nearest size to %dx%d with format %" GST_FOURCC_FORMAT,
2810       *width, *height, GST_FOURCC_ARGS (pixelformat));
2811
2812   fd = v4l2camsrc->video_fd;
2813
2814   /* get size delimiters */
2815   memset (&fmt, 0, sizeof (fmt));
2816   fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2817   fmt.fmt.pix.width = *width;
2818   fmt.fmt.pix.height = *height;
2819   fmt.fmt.pix.pixelformat = pixelformat;
2820   fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
2821
2822 /* FIXME: Disable TRY_FMT check, driver is not returning anything useful yet */
2823 #if 0
2824   r = ioctl (fd, VIDIOC_TRY_FMT, &fmt);
2825   if (r < 0 && errno == EINVAL) {
2826     /* try again with progressive video */
2827     fmt.fmt.pix.width = *width;
2828     fmt.fmt.pix.height = *height;
2829     fmt.fmt.pix.pixelformat = pixelformat;
2830     fmt.fmt.pix.field = V4L2_FIELD_NONE;
2831     r = ioctl (fd, VIDIOC_TRY_FMT, &fmt);
2832   }
2833
2834   if (r < 0) {
2835     /* The driver might not implement TRY_FMT, in which case we will try
2836        S_FMT to probe */
2837     if (errno != ENOTTY)
2838       return FALSE;
2839 #endif
2840
2841     /* Only try S_FMT if we're not actively capturing yet, which we shouldn't
2842        be, because we're still probing */
2843     if (GST_V4L2CAMSRC_IS_ACTIVE (v4l2camsrc))
2844       return FALSE;
2845
2846 #if 0
2847     GST_LOG_OBJECT (v4l2camsrc,
2848         "Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
2849 #endif
2850
2851     fmt.fmt.pix.width = *width;
2852     fmt.fmt.pix.height = *height;
2853
2854     r = ioctl (fd, VIDIOC_S_FMT, &fmt);
2855     if (r < 0 && errno == EINVAL) {
2856       /* try again with progressive video */
2857       fmt.fmt.pix.width = *width;
2858       fmt.fmt.pix.height = *height;
2859       fmt.fmt.pix.pixelformat = pixelformat;
2860       fmt.fmt.pix.field = V4L2_FIELD_NONE;
2861       r = ioctl (fd, VIDIOC_S_FMT, &fmt);
2862     }
2863
2864     if (r < 0)
2865       return FALSE;
2866 #if 0
2867   }
2868 #endif
2869
2870   GST_LOG_OBJECT (v4l2camsrc,
2871       "got nearest size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
2872
2873   *width = fmt.fmt.pix.width;
2874   *height = fmt.fmt.pix.height;
2875
2876   return TRUE;
2877 }
2878
2879
2880 /******************************************************
2881  * gst_v4l2camsrc_set_crop():
2882  *   set cropping bounds
2883  * return value: TRUE on success, FALSE on error
2884  ******************************************************/
2885 static gboolean
2886 gst_v4l2camsrc_set_crop (GstMFLDV4l2CamSrc * v4l2camsrc,
2887     gint x, gint y, gint w, gint h)
2888 {
2889   gboolean ret = FALSE;
2890   struct v4l2_crop scrop;
2891   struct v4l2_crop gcrop;
2892   gint cx, cy, cw, ch;
2893   int fd;
2894
2895   fd = v4l2camsrc->video_fd;
2896   cx = v4l2camsrc->vcrop.bounds.left;
2897   cy = v4l2camsrc->vcrop.bounds.top;
2898   cw = v4l2camsrc->vcrop.bounds.width;
2899   ch = v4l2camsrc->vcrop.bounds.height;
2900
2901   memset (&scrop, 0, sizeof (scrop));
2902   scrop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2903
2904   /* Make sure that cropping area stays inside the crop boundaries */
2905   scrop.c.left = x > cx ? x : cx;
2906   scrop.c.top = y > cy ? y : cy;
2907   scrop.c.width = (scrop.c.left + w) < (cx + cw) ? w : cx + cw - scrop.c.left;
2908   scrop.c.height = (scrop.c.top + h) < (cy + ch) ? h : cy + ch - scrop.c.top;
2909
2910   GST_DEBUG_OBJECT (v4l2camsrc,
2911       "Crop request: left = %d, top = %d, w = %d, h = %d",
2912       scrop.c.left, scrop.c.top, scrop.c.width, scrop.c.height);
2913
2914   g_mutex_lock (v4l2camsrc->device_mutex);
2915
2916   if (-1 == ioctl (fd, VIDIOC_S_CROP, &scrop) && errno != EINVAL) {
2917     goto s_crop_failed;
2918   }
2919
2920   if (-1 == ioctl (fd, VIDIOC_G_CROP, &gcrop)) {
2921     goto g_crop_failed;
2922   }
2923
2924   g_mutex_unlock (v4l2camsrc->device_mutex);
2925
2926   GST_DEBUG_OBJECT (v4l2camsrc,
2927       "Crop selected: left = %d, top = %d, w = %d, h = %d",
2928       gcrop.c.left, gcrop.c.top, gcrop.c.width, gcrop.c.height);
2929
2930 #if 0
2931   if (gcrop.c.left != scrop.c.left || gcrop.c.top != scrop.c.top ||
2932       gcrop.c.width != scrop.c.width || gcrop.c.height != scrop.c.height) {
2933     goto crop_not_supported;
2934   }
2935 #endif
2936
2937   ret = TRUE;
2938
2939 done:
2940
2941   return ret;
2942
2943 /* ERRORS */
2944 s_crop_failed:
2945   g_mutex_unlock (v4l2camsrc->device_mutex);
2946   GST_DEBUG_OBJECT (v4l2camsrc, "VIDIOC_S_CROP not supported");
2947   goto done;
2948
2949 g_crop_failed:
2950   g_mutex_unlock (v4l2camsrc->device_mutex);
2951   GST_DEBUG_OBJECT (v4l2camsrc, "VIDIOC_G_CROP not supported");
2952   goto done;
2953
2954 #if 0
2955 crop_not_supported:
2956   g_mutex_unlock (v4l2camsrc->device_mutex);
2957   GST_DEBUG_OBJECT (v4l2camsrc, "Given crop value not accepted");
2958   goto done;
2959 #endif
2960 }
2961
2962
2963 /******************************************************
2964  * gst_v4l2camsrc_update_cropping():
2965  *   update cropping area according to  width, height and zoom factors.
2966  * return value: TRUE on success, FALSE on error
2967  ******************************************************/
2968 static gboolean
2969 gst_v4l2camsrc_update_cropping (GstMFLDV4l2CamSrc * v4l2camsrc, gint width,
2970     gint height, gfloat zoom)
2971 {
2972   gfloat sensor_ar, reso_ar;
2973   gint crop_x, crop_y, crop_w, crop_h;
2974
2975   g_return_val_if_fail (width != 0, FALSE);
2976   g_return_val_if_fail (height != 0, FALSE);
2977   g_return_val_if_fail (zoom != 0, FALSE);
2978
2979   if (zoom < 1.0 || zoom > v4l2camsrc->max_zoom_factor) {
2980     GST_DEBUG_OBJECT (v4l2camsrc, "invalid zoom = %.2f", zoom);
2981     return FALSE;
2982   }
2983   if (!v4l2camsrc->crop_supported) {
2984     GST_DEBUG_OBJECT (v4l2camsrc, "crop not supported");
2985     return FALSE;
2986   }
2987
2988   sensor_ar = v4l2camsrc->vcrop.defrect.width /
2989       v4l2camsrc->vcrop.defrect.height;
2990   reso_ar = width / height;
2991
2992   if (sensor_ar > reso_ar) {
2993     crop_w = (width * v4l2camsrc->vcrop.defrect.height / height) / zoom;
2994     crop_h = MAX (v4l2camsrc->vcrop.defrect.height, height) / zoom;
2995   } else {
2996     crop_w = MAX (v4l2camsrc->vcrop.defrect.width, width) / zoom;
2997     crop_h = (height * v4l2camsrc->vcrop.defrect.width / width) / zoom;
2998   }
2999
3000   crop_x = ABS ((v4l2camsrc->vcrop.defrect.width - crop_w) / 2);
3001   crop_y = ABS ((v4l2camsrc->vcrop.defrect.height - crop_h) / 2);
3002
3003   GST_LOG_OBJECT (v4l2camsrc, "set cropping: x: %d, y: %d, w: %d, h: %d",
3004       crop_x, crop_y, crop_w, crop_h);
3005
3006   return gst_v4l2camsrc_set_crop (v4l2camsrc, crop_x, crop_y, crop_w, crop_h);
3007 }
3008
3009 /***************************************************************************
3010  * New MFLD Camera Code ****************************************************
3011  * *************************************************************************/
3012
3013 /* These map tables help to adapt the general photography interface to
3014  * different device implementations.
3015  *
3016  * Table index = Enumeration value from GstPhotography
3017  * Table value = Device/Implementation -specific setting value
3018  */
3019
3020 static const gint gst_v4l2camsrc_scene_map[] = {
3021   999,                          /* GST_PHOTOGRAPHY_SCENE_MODE_MANUAL */
3022   CAM_GENERAL_SCENE_MODE_CLOSEUP,
3023   CAM_GENERAL_SCENE_MODE_PORTRAIT,
3024   CAM_GENERAL_SCENE_MODE_LANDSCAPE,
3025   CAM_GENERAL_SCENE_MODE_SPORT,
3026   CAM_GENERAL_SCENE_MODE_NIGHT,
3027   CAM_GENERAL_SCENE_MODE_AUTO,
3028   -1
3029 };
3030
3031 static const gint gst_v4l2camsrc_flash_map[] = {
3032   CAM_LIGHT_FLASH_MODE_AUTO,
3033   CAM_LIGHT_FLASH_MODE_OFF,
3034   CAM_LIGHT_FLASH_MODE_ON,
3035   CAM_LIGHT_FLASH_MODE_FILL_IN,
3036   CAM_LIGHT_FLASH_MODE_RED_EYE,
3037   -1
3038 };
3039
3040 static const gint gst_v4l2camsrc_focus_map[] = {
3041   CAM_FOCUS_MODE_AUTO,          /* GST_PHOTOGRAPHY_FOCUS_MODE_AUTO = 0 */
3042   CAM_FOCUS_MODE_MACRO,         /* GST_PHOTOGRAPHY_FOCUS_MODE_MACRO */
3043   CAM_FOCUS_MODE_TOUCH_AUTO,    /* GST_PHOTOGRAPHY_FOCUS_MODE_PORTRAIT */
3044   CAM_FOCUS_MODE_FULL,          /* GST_PHOTOGRAPHY_FOCUS_MODE_INFINITY */
3045   CAM_FOCUS_MODE_AUTO,          /* GST_PHOTOGRAPHY_FOCUS_MODE_HYPERFOCAL */
3046   CAM_FOCUS_MODE_FULL,          /* GST_PHOTOGRAPHY_FOCUS_MODE_EXTENDED */
3047   CAM_FOCUS_MODE_CONTINUOUS,    /* GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_NORMAL */
3048   CAM_FOCUS_MODE_CONTINUOUS,    /* GST_PHOTOGRAPHY_FOCUS_MODE_CONTINUOUS_EXTENDED */
3049   -1
3050 };
3051
3052 static const gint gst_v4l2camsrc_flicker_map[] = {
3053   CAM_GENERAL_FLICKER_REDUCTION_MODE_OFF,       /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_OFF = 0 */
3054   CAM_GENERAL_FLICKER_REDUCTION_MODE_50HZ,      /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ */
3055   CAM_GENERAL_FLICKER_REDUCTION_MODE_60HZ,      /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_60HZ */
3056   CAM_GENERAL_FLICKER_REDUCTION_MODE_AUTO,      /* GST_PHOTOGRAPHY_FLICKER_REDUCTION_AUTO */
3057   -1
3058 };
3059
3060 static const gint gst_v4l2camsrc_iso_map[][2] = {
3061   {CAM_EXPOSURE_ISO_VALUE_1600, 1600},
3062   {CAM_EXPOSURE_ISO_VALUE_800, 800},
3063   {CAM_EXPOSURE_ISO_VALUE_400, 400},
3064   {CAM_EXPOSURE_ISO_VALUE_200, 200},
3065   {CAM_EXPOSURE_ISO_VALUE_100, 100},
3066   {CAM_EXPOSURE_ISO_VALUE_AUTO, 0}
3067 };
3068
3069 static const gint gst_v4l2camsrc_focus_status_map[][2] =
3070 {
3071   { GST_PHOTOGRAPHY_FOCUS_STATUS_NONE,    CAM_FOCUS_STATUS_IDLE },
3072   { GST_PHOTOGRAPHY_FOCUS_STATUS_RUNNING, CAM_FOCUS_STATUS_RUNNING },
3073   { GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS, CAM_FOCUS_STATUS_SUCCESS },
3074   { GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL,    CAM_FOCUS_STATUS_FAIL },
3075   { -1, -1 }
3076 };
3077
3078 static const gchar *cameralib_error_map[] = {
3079   "CAM_ERR_NONE",
3080   "CAM_ERR_PARAM",
3081   "CAM_ERR_UNSUPP",
3082   "CAM_ERR_HW",
3083   "CAM_ERR_SYS",
3084   "CAM_ERR_LEXIT",
3085   "CAM_ERR_DEPRECATED",
3086   "CAM_ERR_INVALID_STATE",
3087   "CAM_ERR_INTERNAL",
3088   "CAM_ERR_NOT_OPEN",
3089   "CAM_ERR_3A"
3090 };
3091
3092 /*
3093  *
3094  */
3095 static cam_exposure_iso_value_t
3096 gst_v4l2camsrc_libmfld_map_iso (guint iso)
3097 {
3098   guint i = 0;
3099
3100   while (gst_v4l2camsrc_iso_map[i][1] != 0) {
3101     if (iso >= gst_v4l2camsrc_iso_map[i][1]) {
3102       break;
3103     }
3104     i++;
3105   }
3106
3107   return gst_v4l2camsrc_iso_map[i][1];
3108 }
3109
3110
3111 /*
3112  *
3113  */
3114 static guint
3115 gst_v4l2camsrc_libmfld_reverse_map_iso (cam_exposure_iso_value_t iso)
3116 {
3117   guint i = 0;
3118
3119   while (gst_v4l2camsrc_iso_map[i][1] != 0) {
3120     if (iso == gst_v4l2camsrc_iso_map[i][0]) {
3121       break;
3122     }
3123     i++;
3124   }
3125
3126   return gst_v4l2camsrc_iso_map[i][1];
3127 }
3128
3129 static const gint gst_v4l2camsrc_shakerisk_map[] = {
3130   GST_PHOTOGRAPHY_SHAKE_RISK_LOW,       /* CAM_EXPOSURE_SHAKE_RISK_LOW = 0 */
3131   GST_PHOTOGRAPHY_SHAKE_RISK_MEDIUM,    /* CAM_EXPOSURE_SHAKE_RISK_MEDIUM */
3132   GST_PHOTOGRAPHY_SHAKE_RISK_HIGH,      /* CAM_EXPOSURE_SHAKE_RISK_HIGH */
3133 };
3134
3135 /*
3136  * Return index of the item in the table.
3137  */
3138 static gint
3139 find_item (const gint table[], const gint item)
3140 {
3141   guint i = 0;
3142
3143   while (table[i] != -1) {
3144     if (table[i] == item)
3145       return i;
3146     i++;
3147   }
3148   return 0;
3149 }
3150
3151 gboolean
3152 gst_v4l2camsrc_read_settings (GstCameraSrc * camsrc,
3153     GstPhotoSettings * photoconf)
3154 {
3155   GstMFLDV4l2CamSrc *v4l2camsrc;
3156   gint32 wbmode, effect, scene, flash, focus;
3157   gint32 flicker;
3158   gint32 ev, iso, aperture, exposure, noise_reduction;
3159   cam_err_t err;
3160
3161   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3162
3163   g_mutex_lock (v4l2camsrc->device_mutex);
3164
3165   if (!v4l2camsrc->initialized) {
3166     GST_DEBUG ("Device not initialized");
3167     g_mutex_unlock (v4l2camsrc->device_mutex);
3168     return FALSE;
3169   }
3170
3171   GST_DEBUG ("Retrieving settings from camera");
3172
3173   err = cam_feature_get (v4l2camsrc->video_fd, CAM_AWB_MODE, &wbmode);
3174   if (err != CAM_ERR_NONE) {
3175     GST_DEBUG ("CAM_AWB_MODE query failed: %s", cameralib_error_map[err]);
3176     goto error;
3177   }
3178
3179   err =
3180       cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE, &effect);
3181   if (err != CAM_ERR_NONE) {
3182     GST_DEBUG ("CAM_GENERAL_EFFECT_TYPE query failed: %s",
3183         cameralib_error_map[err]);
3184     goto error;
3185   }
3186
3187   err = cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_SCENE_MODE, &scene);
3188   if (err != CAM_ERR_NONE) {
3189     GST_DEBUG ("CAM_GENERAL_SCENE_MODE query failed: %s",
3190         cameralib_error_map[err]);
3191     goto error;
3192   }
3193
3194   err = cam_feature_get (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE, &flash);
3195   if (err != CAM_ERR_NONE) {
3196     GST_DEBUG ("CAM_LIGHT_FLASH_MODE query failed: %s",
3197         cameralib_error_map[err]);
3198     goto error;
3199   }
3200
3201   err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION, &ev);
3202   if (err != CAM_ERR_NONE) {
3203     GST_DEBUG ("CAM_EXPOSURE_COMPENSATION query failed: %s",
3204         cameralib_error_map[err]);
3205     goto error;
3206   }
3207
3208   err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE, &iso);
3209   if (err != CAM_ERR_NONE) {
3210     GST_DEBUG ("CAM_EXPOSURE_ISO_VALUE query failed: %s",
3211         cameralib_error_map[err]);
3212     goto error;
3213   }
3214
3215   err = cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_APERTURE,
3216       &aperture);
3217   if (err != CAM_ERR_NONE) {
3218     GST_DEBUG ("CAM_EXPOSURE_MANUAL_APERTURE query failed: %s",
3219         cameralib_error_map[err]);
3220     goto error;
3221   }
3222
3223   err =
3224       cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_TIME,
3225       &exposure);
3226   if (err != CAM_ERR_NONE) {
3227     GST_DEBUG ("CAM_EXPOSURE_MANUAL_TIME query failed: %s",
3228         cameralib_error_map[err]);
3229     goto error;
3230   }
3231
3232   err = cam_feature_get (v4l2camsrc->video_fd, CAM_FOCUS_MODE, &focus);
3233   if (err != CAM_ERR_NONE) {
3234     GST_DEBUG ("CAM_FOCUS_MODE query failed: %s", cameralib_error_map[err]);
3235     goto error;
3236   }
3237
3238   err =
3239       cam_feature_get (v4l2camsrc->video_fd, CAM_GENERAL_FLICKER_REDUCTION_MODE,
3240       &flicker);
3241   if (err != CAM_ERR_NONE) {
3242     GST_DEBUG ("CAM_GENERAL_FLICKER_REDUCTION_MODE query failed: %s",
3243         cameralib_error_map[err]);
3244     goto error;
3245   }
3246
3247   err =
3248       cam_feature_get (v4l2camsrc->video_fd, CAM_NOISE_REDUCTION_MODE,
3249       &noise_reduction);
3250   if (err != CAM_ERR_NONE) {
3251     GST_DEBUG ("CAM_NOISE_REDUCTION query failed: %s",
3252         cameralib_error_map[err]);
3253     goto error;
3254   }
3255
3256   photoconf->wb_mode = find_item (gst_v4l2camsrc_wb_map, wbmode);
3257   photoconf->tone_mode = find_item (gst_v4l2camsrc_effect_map, effect);
3258   photoconf->scene_mode = find_item (gst_v4l2camsrc_scene_map, scene);
3259   photoconf->flash_mode = find_item (gst_v4l2camsrc_flash_map, flash);
3260   photoconf->focus_mode = find_item (gst_v4l2camsrc_focus_map, focus);
3261   photoconf->flicker_mode = find_item (gst_v4l2camsrc_flicker_map, flicker);
3262
3263   photoconf->ev_compensation = (gfloat) ev / 10;
3264   photoconf->iso_speed = gst_v4l2camsrc_libmfld_map_iso (iso);
3265   photoconf->aperture = aperture;
3266   photoconf->exposure = exposure;
3267   photoconf->noise_reduction = noise_reduction;
3268
3269   GST_DEBUG ("Scene mode ext: %d, lib: %d", photoconf->scene_mode, scene);
3270   GST_DEBUG ("Focus mode ext: %d, lib: %d", photoconf->focus_mode, focus);
3271   GST_DEBUG ("Flash mode ext: %d, lib: %d", photoconf->flash_mode, flash);
3272   GST_DEBUG ("ISO: %d, EV_comp: %f (%d)", iso, photoconf->ev_compensation, ev);
3273
3274   g_mutex_unlock (v4l2camsrc->device_mutex);
3275
3276   return TRUE;
3277
3278 /* ERRORS */
3279 error:
3280   {
3281     g_mutex_unlock (v4l2camsrc->device_mutex);
3282     return FALSE;
3283   }
3284 }
3285 gboolean
3286 gst_v4l2camsrc_read_exif (GstCameraSrc * camsrc,
3287     GstCameraControlExifInfo *exif_info)
3288 {
3289   GstMFLDV4l2CamSrc *v4l2camsrc;
3290   cam_err_t err;
3291   struct atomisp_makernote_info maker_note;
3292   unsigned char *buf;
3293
3294   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3295
3296
3297   if (!v4l2camsrc->initialized) {
3298     GST_DEBUG ("Device not initialized");
3299     return FALSE;
3300   }
3301   buf = (unsigned char *)&maker_note;
3302
3303   GST_DEBUG ("Retrieving makernote from atomisp");
3304   err = cam_get_makernote (v4l2camsrc->video_fd, buf, 0);
3305
3306   if(err)
3307      goto error;
3308
3309   /* focal lenght */
3310   exif_info->focal_len_numerator = maker_note.focal_length >> 16;
3311   exif_info->focal_len_denominator = maker_note.focal_length & 0xFFFF;
3312   /* Aperture value (f_num) */
3313   exif_info->aperture_f_num_numerator = maker_note.f_number_curr >> 16;
3314   exif_info->aperture_f_num_denominator = maker_note.f_number_curr & 0xFFFF;
3315   /* isp major, minor,patch level */
3316   exif_info->software_used = v4l2camsrc->vcap.version;
3317   exif_info->colorspace = 65535; /* Uncalibrated (=65535) */
3318   exif_info->metering_mode = 1; /* Average */
3319   cam_feature_get (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE, &exif_info->iso);
3320
3321   //* TODO complete exif info */
3322   exif_info->exposure_time_denominator = 0;
3323   exif_info->exposure_time_numerator = 0;
3324
3325   exif_info->shutter_speed_numerator = 0;
3326   exif_info->shutter_speed_denominator = 0;
3327   exif_info->brigtness_numerator = 0;
3328   exif_info->brightness_denominator = 0;
3329   exif_info->flash = cam_is_flash_used();
3330   GST_DEBUG ("Focal lenght numerator : %d", exif_info->focal_len_numerator);
3331   GST_DEBUG ("Focal lenght denominator : %d", exif_info->focal_len_denominator);
3332   GST_DEBUG ("F num numerator : %d", exif_info->aperture_f_num_numerator);
3333   GST_DEBUG ("F num denominator : %d", exif_info->aperture_f_num_denominator);
3334   GST_DEBUG ("flash used  : %d", exif_info->flash);
3335
3336   return TRUE;
3337
3338 /* ERRORS */
3339 error:
3340   {
3341     g_mutex_unlock (v4l2camsrc->device_mutex);
3342     return FALSE;
3343   }
3344 }
3345
3346 gboolean
3347 gst_v4l2camsrc_set_flash_mode (GstCameraSrc * camsrc,
3348     int value)
3349 {
3350   GstMFLDV4l2CamSrc *v4l2camsrc;
3351   cam_err_t err;
3352   gint32 flash;
3353
3354
3355   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3356
3357   g_mutex_lock (v4l2camsrc->device_mutex);
3358
3359   if (!v4l2camsrc->initialized) {
3360     GST_DEBUG ("Device not initialized");
3361     g_mutex_unlock (v4l2camsrc->device_mutex);
3362     return FALSE;
3363   }
3364
3365   switch (value) {
3366     case GST_CAMERA_STROBE_CAP_NONE:
3367     case GST_CAMERA_STROBE_CAP_OFF:
3368       flash = CAM_LIGHT_FLASH_MODE_OFF;
3369       break;
3370     case GST_CAMERA_STROBE_CAP_ON:
3371       flash = CAM_LIGHT_FLASH_MODE_ON;
3372       break;
3373     case GST_CAMERA_STROBE_CAP_AUTO:
3374       flash = CAM_LIGHT_FLASH_MODE_AUTO;
3375       break;
3376     case GST_CAMERA_STROBE_CAP_REDEYE:
3377       flash = CAM_LIGHT_FLASH_MODE_RED_EYE;
3378       break;
3379     default:
3380       flash = CAM_LIGHT_FLASH_MODE_OFF;
3381       break;
3382    }
3383
3384   GST_DEBUG_OBJECT (v4l2camsrc, "Set flash mode: %d",flash);
3385   err= cam_feature_set (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE,
3386         flash);
3387
3388   if(err)
3389     goto error;
3390
3391   g_mutex_unlock (v4l2camsrc->device_mutex);
3392
3393   return TRUE;
3394
3395 /* ERRORS */
3396 error:
3397   {
3398     g_mutex_unlock (v4l2camsrc->device_mutex);
3399     return FALSE;
3400   }
3401 }
3402
3403 gboolean
3404 gst_v4l2camsrc_write_settings (GstCameraSrc * camsrc,
3405     GstPhotoSettings * photoconf, gboolean scene_override)
3406 {
3407   GstMFLDV4l2CamSrc *v4l2camsrc;
3408   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3409   GST_DEBUG ("Write settings to libmfldcamd");
3410
3411   g_mutex_lock (v4l2camsrc->device_mutex);
3412
3413   if (!v4l2camsrc->initialized) {
3414     g_mutex_unlock (v4l2camsrc->device_mutex);
3415     GST_DEBUG ("Device not initialized");
3416     return FALSE;
3417   }
3418
3419   if (scene_override &&
3420       photoconf->scene_mode != GST_PHOTOGRAPHY_SCENE_MODE_MANUAL) {
3421     /* If scene override flag is set, we just leave the new settings in use */
3422     GST_DEBUG ("SCENE OVERRIDE, ext=%d", photoconf->scene_mode);
3423         cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_SCENE_MODE,
3424                 gst_v4l2camsrc_scene_map[photoconf->scene_mode]);
3425   } else {
3426     GST_DEBUG ("Normal settings");
3427     cam_feature_set (v4l2camsrc->video_fd, CAM_AWB_MODE,
3428         gst_v4l2camsrc_wb_map[photoconf->wb_mode]);
3429
3430     cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_EFFECT_TYPE,
3431         gst_v4l2camsrc_effect_map[photoconf->tone_mode]);
3432
3433     cam_feature_set (v4l2camsrc->video_fd, CAM_LIGHT_FLASH_MODE,
3434         gst_v4l2camsrc_flash_map[photoconf->flash_mode]);
3435
3436     /* These will set exposure mode to MANUAL, is value is != 0 */
3437     cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_TIME,
3438         photoconf->exposure);
3439     cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_MANUAL_APERTURE,
3440         photoconf->aperture);
3441
3442     cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_COMPENSATION,
3443         (gint) (photoconf->ev_compensation * 10));
3444
3445     cam_feature_set (v4l2camsrc->video_fd, CAM_EXPOSURE_ISO_VALUE,
3446                 gst_v4l2camsrc_libmfld_reverse_map_iso (photoconf->iso_speed));
3447
3448     cam_feature_set (v4l2camsrc->video_fd, CAM_FOCUS_MODE,
3449         gst_v4l2camsrc_focus_map[photoconf->focus_mode]);
3450
3451     cam_feature_set (v4l2camsrc->video_fd, CAM_GENERAL_FLICKER_REDUCTION_MODE,
3452         gst_v4l2camsrc_flicker_map[photoconf->flicker_mode]);
3453
3454     cam_feature_set (v4l2camsrc->video_fd, CAM_NOISE_REDUCTION_MODE,
3455         photoconf->noise_reduction);
3456   }
3457   g_mutex_unlock (v4l2camsrc->device_mutex);
3458
3459   return TRUE;
3460 }
3461
3462 gboolean
3463 gst_v4l2camsrc_set_AeAafwindow (GstCameraSrc * camsrc, GstCameraSrc3a_window window)
3464 {
3465   GstMFLDV4l2CamSrc *v4l2camsrc;
3466   gboolean ret = TRUE;
3467
3468   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3469
3470   GST_DEBUG_OBJECT(v4l2camsrc,"ae-af-window-setting: x_left:%d, x_right:%d,"
3471          "y_bottom:%d, y_top:%d, weight:%d.\n",
3472          window.x_left,window.x_right,
3473          window.y_bottom, window.y_top,
3474          window.weight);
3475
3476   v4l2camsrc->af_window = v4l2camsrc->ae_window  = *(GstCameraWindow*)&window;
3477
3478   if (v4l2camsrc->is_active) {
3479    g_mutex_lock (v4l2camsrc->device_mutex);
3480    cam_set_af_ae_window((advci_window *) (&v4l2camsrc->af_window));
3481    g_mutex_unlock (v4l2camsrc->device_mutex);
3482   }
3483
3484   return ret;
3485 }
3486
3487 gboolean
3488 gst_v4l2camsrc_set_autofocus (GstCameraSrc * camsrc, gboolean on)
3489 {
3490   GstMFLDV4l2CamSrc *v4l2camsrc;
3491   gboolean ret = FALSE;
3492   cam_err_t err = CAM_ERR_NONE;
3493
3494   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3495   g_mutex_lock (v4l2camsrc->device_mutex);
3496   err= cam_set_autofocus(on);
3497   ret = (err == CAM_ERR_NONE);
3498   g_mutex_unlock (v4l2camsrc->device_mutex);
3499
3500   GST_DEBUG ("setting autofocus: %s", ret ? "ok" : "failed");
3501   return ret;
3502 }
3503 /*
3504  *
3505  */
3506 GstPhotoCaps
3507 gst_v4l2camsrc_get_capabilities (GstCameraSrc * camsrc)
3508 {
3509   GstPhotoCaps pcaps;
3510
3511   pcaps = GST_PHOTOGRAPHY_CAPS_ZOOM | GST_PHOTOGRAPHY_CAPS_EV_COMP |
3512       GST_PHOTOGRAPHY_CAPS_WB_MODE | GST_PHOTOGRAPHY_CAPS_TONE |
3513       GST_PHOTOGRAPHY_CAPS_SCENE | GST_PHOTOGRAPHY_CAPS_FLASH |
3514       GST_PHOTOGRAPHY_CAPS_FOCUS | GST_PHOTOGRAPHY_CAPS_APERTURE |
3515       GST_PHOTOGRAPHY_CAPS_EXPOSURE | GST_PHOTOGRAPHY_CAPS_SHAKE |
3516       GST_PHOTOGRAPHY_CAPS_ISO_SPEED;
3517
3518   return pcaps;
3519 }
3520
3521 /*
3522  *
3523  */
3524 gboolean
3525 gst_v4l2camsrc_check_focus_status (GstMFLDV4l2CamSrc * v4l2camsrc,
3526                                    GstCameraFocusStatus *fs, gboolean detailed)
3527 {
3528   gboolean ret = FALSE;
3529   cam_focus_status_t status;
3530   gboolean update;
3531
3532   GST_DEBUG_OBJECT (v4l2camsrc, "Retrieving focus status");
3533
3534   update = cam_checkfocus_status (&status, (v4l2camsrc->debug_flags & GST_CAMERASRC_DEBUG_FLAGS_AUTO_FOCUS));
3535
3536   if (update == TRUE) {
3537     fs->status = cam_find_item_new (gst_v4l2camsrc_focus_status_map, status, TRUE);
3538     ret =  TRUE;
3539
3540     GST_DEBUG_OBJECT (v4l2camsrc, "Focus status: %d", fs->status);
3541   }
3542   return ret;
3543 }
3544
3545 gboolean
3546 gst_v4l2camsrc_set_capture_mode (GstCameraSrc * camsrc,
3547     GstCameraSrcCaptureMode mode)
3548 {
3549   GstMFLDV4l2CamSrc *v4l2camsrc;
3550   gboolean ret = FALSE;
3551   int err; //cam_err_t err;
3552   cam_capture_mode_t cam_mode;
3553   static const gchar *cmodes[] = { "VIEWFINDER", "STILL", "VIDEO" };
3554   struct v4l2_streamparm parm;
3555   int binary;
3556   gint fd;
3557
3558   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3559
3560   fd = v4l2camsrc->video_fd;
3561
3562   cam_mode = find_item (gst_v4l2camsrc_capture_map, mode);
3563
3564   g_mutex_lock (v4l2camsrc->device_mutex);
3565
3566   if (v4l2camsrc->initialized) {
3567     v4l2camsrc->capture_mode = mode;
3568     GST_DEBUG ("Setting isp capture mode: %s", cmodes[mode]);
3569     memset (&parm, 0x00, sizeof (struct v4l2_streamparm));
3570
3571     parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3572     err = ioctl(fd, VIDIOC_G_PARM, &parm);
3573     if (err < 0) {
3574       GST_DEBUG("Unable to get frame rate: %s (%d).\n",
3575       strerror(errno), errno);
3576       goto done;
3577     }
3578     GST_DEBUG("Current frame rate: %u/%u\n",
3579         parm.parm.capture.timeperframe.numerator,
3580         parm.parm.capture.timeperframe.denominator);
3581
3582     GST_DEBUG("Current run mode: %04x\n", parm.parm.capture.capturemode);
3583
3584     switch (mode) {
3585       case GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER:
3586         binary = CI_MODE_PREVIEW;
3587         break;;
3588       case GST_CAMERA_SRC_CAPTURE_MODE_STILL:
3589         binary = CI_MODE_STILL_CAPTURE;
3590         break;
3591       case GST_CAMERA_SRC_CAPTURE_MODE_VIDEO:
3592         binary = CI_MODE_VIDEO;
3593         break;
3594       default:
3595         binary = CI_MODE_PREVIEW;
3596         break;
3597     }
3598     parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
3599     parm.parm.capture.capturemode = binary;
3600
3601     GST_DEBUG("New run mode: %04x\n", parm.parm.capture.capturemode);
3602
3603     if (ioctl (fd, VIDIOC_S_PARM, &parm) < 0) {
3604       GST_DEBUG("Switch Mode failed !\n");
3605     }
3606
3607     ret = (err >= 0);
3608     GST_DEBUG_OBJECT (v4l2camsrc, "Setting capture mode done: %s",
3609         ret ? "OK" : "FAIL");
3610   }
3611   else {
3612     GST_DEBUG_OBJECT (v4l2camsrc, "Device not initialized");
3613   }
3614
3615 done:
3616   g_mutex_unlock (v4l2camsrc->device_mutex);
3617
3618   return ret;
3619 }
3620
3621 gboolean gst_v4l2camsrc_set_strobe_state (GstCameraSrc * camsrc,
3622     gboolean state)
3623
3624 {
3625   GstMFLDV4l2CamSrc *v4l2camsrc;
3626   gint fd;
3627   cam_err_t err = CAM_ERR_NONE;
3628
3629   v4l2camsrc = GST_V4L2CAMSRC (camsrc);
3630   fd = v4l2camsrc->video_fd;
3631
3632   err  = cam_set_flash (fd, state);
3633   return(err == CAM_ERR_NONE);
3634 }
3635 gboolean
3636 gst_libmfldcam_capture_correction_update (GstMFLDV4l2CamSrc * v4l2camsrc)
3637 {
3638   int fd = v4l2camsrc->video_fd;
3639   gboolean ret;
3640
3641   if (!v4l2camsrc->cc_updated)
3642     return TRUE;
3643
3644   if (v4l2camsrc->gdc_enabled)
3645     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_GDC, TRUE);
3646   else
3647     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_GDC, FALSE);
3648
3649   if (ret)
3650     goto set_cc_failed;
3651
3652   if (v4l2camsrc->cac_enabled)
3653     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_CAC, TRUE);
3654   else
3655     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_CAC, FALSE);
3656
3657   if (ret)
3658     goto set_cc_failed;
3659
3660   if (v4l2camsrc->dvs_enabled)
3661     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_DVS, TRUE);
3662   else
3663     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_DVS, FALSE);
3664
3665   if (ret)
3666     goto set_cc_failed;
3667
3668   if (v4l2camsrc->ee_enabled)
3669     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_EE, TRUE);
3670   else
3671     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_EE, FALSE);
3672
3673   if (ret)
3674     goto set_cc_failed;
3675
3676   if (v4l2camsrc->sc_enabled)
3677     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_SC, TRUE);
3678   else
3679     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_SC, FALSE);
3680
3681   if (ret)
3682     goto set_cc_failed;
3683
3684   if (v4l2camsrc->blc_enabled)
3685     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BLC, TRUE);
3686   else
3687     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BLC, FALSE);
3688
3689   if (v4l2camsrc->bpd_enabled)
3690     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BPD, TRUE);
3691   else
3692     ret = cam_set_capture_correction (fd, CAM_CAPTURE_CORRECTION_BPD, FALSE);
3693
3694   if (ret)
3695     goto set_cc_failed;
3696
3697   v4l2camsrc->cc_updated = FALSE;
3698
3699   if (ret)
3700     goto set_cc_failed;
3701
3702
3703   return TRUE;
3704
3705 set_cc_failed:
3706   GST_WARNING_OBJECT (v4l2camsrc, "Set capture correction failed \n");
3707   return FALSE;
3708
3709 }
3710
3711 /**
3712  * gst_v4l2camsrc_libmfldcam_set_zoom:
3713  * @v4l2camsrc: #GstMFLDV4l2CamSrc object.
3714  * @zoom: Desired zoom factor.
3715  *
3716  * Set the zoom factor for captured image.
3717  *
3718  * Returns: TRUE on success.
3719  */
3720 gboolean
3721 gst_v4l2camsrc_libmfldcam_set_zoom (GstMFLDV4l2CamSrc * v4l2camsrc, gfloat zoom)
3722 {
3723   cam_err_t err = CAM_ERR_NONE;
3724   gboolean ret;
3725
3726   GST_DEBUG_OBJECT (v4l2camsrc, "ZOOM: %f", zoom);
3727
3728   err = cam_set_zoom (v4l2camsrc->video_fd, zoom);
3729   /* ret = err == CAM_ERR_NONE; */
3730   ret = TRUE;
3731
3732   GST_DEBUG_OBJECT (v4l2camsrc, "Setting zoom: %s", ret ? "SUCCESS" : "FAIL");
3733
3734   return ret;
3735 }
3736
3737 gboolean
3738 gst_v4l2camsrc_libmfldcam_get_makernote (GstMFLDV4l2CamSrc * v4l2camsrc, unsigned char *buf, unsigned size)
3739 {
3740   cam_err_t err = CAM_ERR_NONE;
3741
3742   GST_DEBUG_OBJECT (v4l2camsrc, "%s, !!!!!!line:%d\n", __func__, __LINE__);
3743
3744   err = cam_get_makernote (v4l2camsrc->video_fd, buf, size);
3745   return err;
3746 }
3747
3748 gboolean
3749 gst_v4l2camsrc_libmfldcam_get_focus_posi(GstMFLDV4l2CamSrc * v4l2camsrc, unsigned *posi)
3750 {
3751   cam_err_t err = CAM_ERR_NONE;
3752   err = cam_get_focus_posi(v4l2camsrc->video_fd, posi);
3753   if(err != CAM_ERR_NONE)
3754     return FALSE;
3755
3756   return TRUE;
3757 }
3758
3759 /**
3760  * @v4l2camsrc: #GstMFLDV4l2CamSrc object
3761  *
3762  * configure driver default settings and set the opened ISP fd to libmfldcam
3763  */
3764 gboolean
3765 gst_v4l2camsrc_libmfldcam_init (GstMFLDV4l2CamSrc * v4l2camsrc)
3766 {
3767   cam_err_t err;
3768   struct v4l2_input input;
3769   int ret;
3770   char *name, *space;
3771
3772   memset(&input, 0, sizeof(input));
3773   if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_PRIMARY)
3774     input.index = V2L2_CAMERA_INPUT_SENSOR_PRIMARY;
3775   else
3776     input.index = V2L2_CAMERA_INPUT_SENSOR_SECONDARY;
3777
3778   ret = ioctl(v4l2camsrc->video_fd, VIDIOC_ENUMINPUT, &input);
3779   if (ret < 0) {
3780     return FALSE;
3781   }
3782   name = (char*)input.name;
3783   space = strchr(name, ' ');
3784   if (space > name) {
3785       name[space - name] = '\0';
3786   }
3787   GST_DEBUG_OBJECT (v4l2camsrc, "sensor name %s", name);
3788
3789   err = cam_driver_init (v4l2camsrc->video_fd, name);
3790
3791   if (err != CAM_ERR_NONE) {
3792     GST_WARNING ("libmfldcam initialization failed");
3793     return FALSE;
3794   }
3795   if (v4l2camsrc->cc_updated)
3796     gst_libmfldcam_capture_correction_update (v4l2camsrc);
3797
3798   if (v4l2camsrc->gamma_updated) {
3799     cam_set_tone_control (v4l2camsrc->video_fd, CAM_GAMMA_VALUE,
3800         &v4l2camsrc->tone);
3801     cam_set_tone_control (v4l2camsrc->video_fd, CAM_BRIGHTNESS_VALUE,
3802         &v4l2camsrc->tone);
3803     cam_set_tone_control (v4l2camsrc->video_fd, CAM_CONTRAST_VALUE,
3804         &v4l2camsrc->tone);
3805     v4l2camsrc->gamma_updated = FALSE;
3806   }
3807
3808   /* Set the default settings here */
3809   //FIXME
3810   GST_DEBUG_OBJECT (v4l2camsrc, "Configure default settings %s",
3811       v4l2camsrc->videodev);
3812
3813   gst_v4l2camsrc_set_attribute (GST_CAMERA_SRC (v4l2camsrc),V4L2_CID_VFLIP,v4l2camsrc->vflip);
3814   if (v4l2camsrc->input_sensor == GST_CAMERA_INPUT_SENSOR_SECONDARY) {
3815     gst_v4l2camsrc_set_attribute (GST_CAMERA_SRC (v4l2camsrc),V4L2_CID_HFLIP,v4l2camsrc->hflip);
3816     gst_v4l2camsrc_set_attribute (GST_CAMERA_SRC (v4l2camsrc),V4L2_CID_POWER_LINE_FREQUENCY,CAM_GENERAL_FLICKER_REDUCTION_MODE_50HZ);
3817   }
3818
3819   v4l2camsrc->initialized = TRUE;
3820   v4l2camsrc->is_open = TRUE;
3821   return TRUE;
3822 }
3823
3824 gboolean
3825 gst_v4l2camsrc_libmfldcam_deinit (GstMFLDV4l2CamSrc * v4l2camsrc)
3826 {
3827   //FIXME : determin whether is it initialized
3828   cam_err_t err;
3829   err = cam_driver_deinit (v4l2camsrc->video_fd);
3830   if (err != CAM_ERR_NONE) {
3831     GST_WARNING ("libmfldcam initialization failed");
3832     return FALSE;
3833   }
3834   //FIXME
3835   v4l2camsrc->is_open = FALSE;
3836   return TRUE;
3837 }