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