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