add mutex for capture viewfinder request.
[adaptation/intel_mfld/gst-plugins-atomisp.git] / gst-libs / gst / camera / gstmfldcamerasrc.c
1 /* GStreamer
2  *
3  * Copyright (C) 2001-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 <http://meego.com/>
7  *
8  * gstcamerasrc.c: Abstract camera base class
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 /**
27  * SECTION:gstcamerasrc
28  * @short_description: Base class for camera sources
29  *
30  * <refsect2>
31  * camerasrc is a generic base class for video source elements.
32  * </refsect2>
33  * <refsect2>
34  * <title>Capturing modes</title>
35  * <para>
36  * GstCameraSrc provides three different operating modes: VIEWFINDER, IMAGE and
37  * VIDEO capturing. This mode is selected by using "capture-mode" property.
38  * Viewfinder mode is used for capturing preview frames before performing the
39  * high-quality image capture, or before starting video recording. Image and
40  * video modes should be switched just before starting the corresponding
41  * action. GstCameraSrc itself doesn't make any difference between these modes,
42  * and this setting is mainly targeted for subclasses (see below).
43  * </para>
44  * </refsect2>
45  * <refsect2>
46  * <title>Image capture</title>
47  * <para>
48  * In order to capture and image of higher quality than negotiated in element's
49  * source pad, #GstPhotography's prepare_for_capture() must be called. It
50  * Takes a #GstCaps object as a parameter. These caps will define the desired
51  * high-quality capture resolution. However, this resolution is just a
52  * suggestion; GstCameraSrc uses the given #GstPhotoCapturePrepared callback
53  * to inform the selected capturing resolution back to the application. During
54  * this callback application also has responsibility to adjust image pipeline
55  * capsfilters according to this resolution. After HQ image is captured and
56  * pushed, GstCameraSrc switches automatically back to old viewfinder resolution.
57  * </para>
58  * </refsect2>
59  * <refsect2>
60  * <title>Video capture</title>
61  * <para>
62  * By default GstCameraSrc works just like v4l2src, so it can be used for normal
63  * video stream capturing as well. There is no separate GstPhotography API
64  * function for starting video capturing (in contrary to image capturing), but
65  * the notification is just given by setting the #GstCameraSrc:capture-mode
66  * to video.
67  * </para>
68  * </refsect2>
69  * <refsect2>
70  * <title>Messages</title>
71  * <para>
72  * During capturing process GstCameraSrc sends a bunch of GstMessages to bus:
73  * <itemizedlist>
74  * <listitem>
75  * <para>
76  * GST_PHOTOGRAPHY_AUTOFOCUS_DONE is sent when application has started
77  * autofocus operation and it finishes. This message contains following fields:
78  * "status" is an integer which contains GstFocusStatus enumeration value.
79  * It tells whether the focusing succeeded or failed.
80  * "focus-window-rows" and "focus-window-columns" are integers and they tell
81  * the focus matrix size.
82  * "focus-windows" is a GArray containing a list of integers. They define
83  * window numbers where the focus is. Window numbering starts from one, which
84  * is top-left window, increasing from left-to-right, top-to-bottom order. This
85  * field is only valid when focusing status is SUCCESS.
86  * "focus-window-coverage" field is an integer and it tells the percentage how
87  * big area from wiewfinder window was used for autofocusing.
88  * </para>
89  * </listitem>
90  * <listitem>
91  * <para>
92  * GST_PHOTOGRAPHY_SHAKE_RISK is sent during autofocusing process. It keeps
93  * application updated about the possible risk for shaken image. Sending of
94  * this message is done in subclasses, so it is implementation-specific and
95  * may not be always sent.
96  * </para>
97  * </listitem>
98  * <listitem>
99  * <para>
100  * "photo-capture-start" is sent just before the actual high-quality capture
101  * operation is about to happen.
102  * </para>
103  * </listitem>
104  * <listitem>
105  * <para>
106  * "photo-capture-end" is sent immediately after high-quality image has been
107  * captured. This can be used for example for playing the shutter sound
108  * in sync with the capture operation.
109  * </para>
110  * </listitem>
111  * <listitem>
112  * <para>
113  * "caf-update" messages are sent when camera subsystem supports continuous
114  * autofocusing (CAF). The message contains information about CAF status. It
115  * has one G_TYPE_INT field called "status" and its content is one of the
116  * values defined in GstPhotography API's GstFocusStatus enumeration.
117  * </para>
118  * </listitem>
119  * </itemizedlist>
120  * </para>
121  * </refsect2>
122  * <refsect2>
123  * <title>Supported formats</title>
124  * <para>
125  * Currently GstCameraSrc only supports UYVY and YUY2 color formats.
126  * </para>
127  * </refsect2>
128  * <refsect2>
129  * <title>Subclasses</title>
130  * <para>
131  * Hardware-specific imaging functionalities are implemented in subclasses.
132  * GstCameraSrc provides vmethods for this purpose. Subclasses tasks are to
133  * are handle e.g. autofocusing, flash, image capturing,
134  * post-processing and all other non-V4L2 standard operations. Subclass
135  * can also implement the API only partially; by default GstCameraSrc uses dummy
136  * functions for all vmethods that are not implemented by the subclass.
137  * </para>
138  * </refsect2>
139  */
140
141 #ifdef HAVE_CONFIG_H
142 #include <config.h>
143 #endif
144
145 #include <string.h>
146 #include <sys/time.h>
147 #include <unistd.h>
148
149 #include <gst/tag/tag.h>
150
151 #include "gstmfldcameracolorbalance.h"
152 #include "gstmfldcameraphotoiface.h"
153 #include "gstmfldcameracontroliface.h"
154 #include "videodev.h"
155 #include <linux/videodev2.h>
156
157
158 GST_DEBUG_CATEGORY (gst_camerasrc_debug);
159 #define GST_CAT_DEFAULT gst_camerasrc_debug
160
161
162 #define DEFAULT_PROP_ALWAYS_COPY        FALSE
163
164 #define MIN_ZOOM 0.0
165 #define MAX_ZOOM 1000.0
166 #define ZOOM_1X 100.0
167
168 GST_IMPLEMENT_CAMERA_SRC_COLOR_BALANCE_METHODS (GstCameraSrc, gst_camsrc);
169 GST_IMPLEMENT_CAMERA_SRC_PHOTO_METHODS (GstCameraSrc, gst_camsrc);
170 GST_IMPLEMENT_CAMERA_SRC_CAMERA_CONTROL_METHODS (GstCameraSrc, gst_camsrc);
171
172
173 /* Enumerations */
174 enum {
175   /*signal*/
176   SIGNAL_STILL_CAPTURE,
177   SIGNAL_NEGO_COMPLETE,
178   LAST_SIGNAL
179 };
180
181 static guint gst_camerasrc_signals[LAST_SIGNAL] = { 0 };
182
183 static gboolean
184 gst_camerasrc_iface_supported (GstImplementsInterface * iface, GType iface_type)
185 {
186   GstCameraSrc *camsrc;
187   GstCameraSrcClass *bclass;
188
189   camsrc = GST_CAMERA_SRC (iface);
190   bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
191
192   g_assert (iface_type == GST_TYPE_PHOTOGRAPHY ||
193       iface_type == GST_TYPE_COLOR_BALANCE  || iface_type == GST_TYPE_CAMERA_CONTROL );
194
195   /* We implement GstPhotography in NULL state as well */
196   if (iface_type == GST_TYPE_PHOTOGRAPHY)
197     return TRUE;
198
199   else if (!bclass->is_open (camsrc))
200     return FALSE;
201
202   return TRUE;
203 }
204
205 static void
206 gst_camerasrc_interface_init (GstImplementsInterfaceClass * klass)
207 {
208   /*
209    * default virtual functions 
210    */
211   klass->supported = gst_camerasrc_iface_supported;
212 }
213
214 void
215 gst_camerasrc_init_interfaces (GType type)
216 {
217   static const GInterfaceInfo camsrc_iface_info = {
218     (GInterfaceInitFunc) gst_camerasrc_interface_init,
219     NULL,
220     NULL,
221   };
222   static const GInterfaceInfo camsrc_photo_info = {
223     (GInterfaceInitFunc) gst_camsrc_photo_interface_init,
224     NULL,
225     NULL,
226   };
227   static const GInterfaceInfo camsrc_colorbalance_info = {
228     (GInterfaceInitFunc) gst_camsrc_color_balance_interface_init,
229     NULL,
230     NULL,
231   };
232
233   static const GInterfaceInfo camsrc_cameracontrol_info = {
234     (GInterfaceInitFunc) gst_camsrc_camera_control_interface_init,
235     NULL,
236     NULL,
237   };
238
239   g_type_add_interface_static (type,
240       GST_TYPE_IMPLEMENTS_INTERFACE, &camsrc_iface_info);
241   g_type_add_interface_static (type, GST_TYPE_PHOTOGRAPHY, &camsrc_photo_info);
242   g_type_add_interface_static (type,
243       GST_TYPE_COLOR_BALANCE, &camsrc_colorbalance_info);
244   g_type_add_interface_static (type,
245       GST_TYPE_CAMERA_CONTROL, &camsrc_cameracontrol_info);
246 }
247
248
249 GType
250 gst_camerasrc_capture_mode_get_type (void)
251 {
252   static GType gst_camerasrc_capture_mode_type = 0;
253   static GEnumValue gst_camerasrc_capture_modes[] = {
254     {GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER, "Viewfinder mode", "viewfinder"},
255     {GST_CAMERA_SRC_CAPTURE_MODE_STILL, "Still image capture mode", "still"},
256     {GST_CAMERA_SRC_CAPTURE_MODE_VIDEO, "Video capturing mode", "video"},
257     {0, NULL, NULL},
258   };
259
260   if (G_UNLIKELY (!gst_camerasrc_capture_mode_type)) {
261     gst_camerasrc_capture_mode_type =
262         g_enum_register_static ("GstCameraCaptureMode",
263         gst_camerasrc_capture_modes);
264   }
265   return gst_camerasrc_capture_mode_type;
266 }
267
268 GType
269 gst_camerasrc_viewfinder_mode_get_type (void)
270 {
271   static GType gst_camerasrc_viewfinder_mode_type = 0;
272   static GEnumValue gst_camerasrc_viewfinder_modes[] = {
273     {GST_CAMERA_SRC_VIEWFINDER_MODE_STILL, "Still image capture mode", "still"},
274     {GST_CAMERA_SRC_VIEWFINDER_MODE_VIDEO, "Video capturing mode", "video"},
275     {0, NULL, NULL},
276   };
277
278   if (G_UNLIKELY (!gst_camerasrc_viewfinder_mode_type)) {
279     gst_camerasrc_viewfinder_mode_type =
280         g_enum_register_static ("GstCameraViewfinderMode",
281         gst_camerasrc_viewfinder_modes);
282   }
283   return gst_camerasrc_viewfinder_mode_type;
284 }
285
286 GST_BOILERPLATE_FULL (GstCameraSrc, gst_camerasrc, GstPushSrc,
287     GST_TYPE_PUSH_SRC, gst_camerasrc_init_interfaces);
288
289 static void gst_camerasrc_dispose (GObject * object);
290
291 /* element methods */
292 static GstStateChangeReturn
293 gst_camerasrc_change_state (GstElement * element, GstStateChange transition);
294
295 /* basesrc methods */
296 static gboolean gst_camerasrc_start (GstBaseSrc * src);
297
298 static gboolean gst_camerasrc_unlock (GstBaseSrc * src);
299
300 static gboolean gst_camerasrc_unlock_stop (GstBaseSrc * src);
301
302 static gboolean gst_camerasrc_stop (GstBaseSrc * src);
303
304 static gboolean gst_camerasrc_set_caps (GstBaseSrc * src, GstCaps * caps);
305
306 static GstCaps *gst_camerasrc_get_caps (GstBaseSrc * src);
307
308 static gboolean gst_camerasrc_query (GstBaseSrc * bsrc, GstQuery * query);
309
310 static GstFlowReturn gst_camerasrc_create (GstPushSrc * src, GstBuffer ** out);
311
312 static void gst_camerasrc_fixate (GstBaseSrc * basesrc, GstCaps * caps);
313
314 static gboolean gst_camerasrc_negotiate (GstBaseSrc * basesrc);
315
316 static void gst_camerasrc_set_property (GObject * object, guint prop_id,
317     const GValue * value, GParamSpec * pspec);
318
319 static void gst_camerasrc_get_property (GObject * object, guint prop_id,
320     GValue * value, GParamSpec * pspec);
321
322 static void gst_camerasrc_override_photo_properties (GObjectClass *
323     gobject_class);
324
325 static void gst_camerasrc_default_functions_init (GstCameraSrcClass *
326     camera_class);
327
328 static gboolean gst_camerasrc_event (GstBaseSrc * src, GstEvent * event);
329
330 static gboolean gst_camerasrc_send_event (GstElement * element,
331     GstEvent * event);
332
333 static void gst_camerasrc_update_max_zoom (GstCameraSrc * camerasrc);
334
335 /*
336  */
337 static void
338 gst_camerasrc_base_init (gpointer g_class)
339 {
340 //   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
341   gst_tag_register_musicbrainz_tags ();
342
343   GST_DEBUG_CATEGORY_INIT (gst_camerasrc_debug, "camerasrc", 0,
344       "camerasrc element");
345 }
346
347
348 /* VOID:OBJECT,OBJECT (generated by 'glib-genmarshal') */
349 #define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
350 void gst_camerasrc_VOID__OBJECT_OBJECT(GClosure *closure,
351                                        GValue *return_value,
352                                        guint n_param_values,
353                                        const GValue *param_values,
354                                        gpointer invocation_hint,
355                                        gpointer marshal_data)
356 {
357         typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT)(gpointer data1,
358                                                          gpointer arg_1,
359                                                          gpointer arg_2,
360                                                          gpointer arg_3,
361                                                          gpointer data2);
362         register GMarshalFunc_VOID__OBJECT_OBJECT callback;
363         register GCClosure *cc = (GCClosure*) closure;
364         register gpointer data1, data2;
365
366         g_return_if_fail (n_param_values == 4);
367
368         if (G_CCLOSURE_SWAP_DATA(closure)) {
369                 data1 = closure->data;
370                 data2 = g_value_peek_pointer(param_values + 0);
371         } else {
372                 data1 = g_value_peek_pointer(param_values + 0);
373                 data2 = closure->data;
374         }
375
376         callback = (GMarshalFunc_VOID__OBJECT_OBJECT)(marshal_data ? marshal_data : cc->callback);
377
378         callback(data1,
379                  g_marshal_value_peek_object(param_values + 1),
380                  g_marshal_value_peek_object(param_values + 2),
381                  g_marshal_value_peek_object(param_values + 3),
382                  data2);
383 }
384
385 int gst_camerasrc_send_af_status(GstCameraSrc *camsrc , int state)
386 {
387   GstMessage *m = NULL;
388   GstStructure *s = NULL;
389
390   GST_INFO_OBJECT(camsrc, "autofocus callback: state [%d]", state);
391
392   s = gst_structure_new("camerasrc-AF",
393                       "focus-state", G_TYPE_INT, state,
394                       NULL);
395
396   m = gst_message_new_element(GST_OBJECT(camsrc), s);
397   gst_element_post_message(GST_ELEMENT(camsrc), m);
398
399   return 0;
400 }
401 /*
402  */
403 static void
404 gst_camerasrc_class_init (GstCameraSrcClass * klass)
405 {
406   GObjectClass *gobject_class;
407   GstElementClass *element_class;
408   GstBaseSrcClass *basesrc_class;
409   GstPushSrcClass *pushsrc_class;
410
411   gobject_class = G_OBJECT_CLASS (klass);
412   element_class = GST_ELEMENT_CLASS (klass);
413   basesrc_class = GST_BASE_SRC_CLASS (klass);
414   pushsrc_class = GST_PUSH_SRC_CLASS (klass);
415
416   gobject_class->dispose = gst_camerasrc_dispose;
417   gobject_class->set_property = gst_camerasrc_set_property;
418   gobject_class->get_property = gst_camerasrc_get_property;
419
420   element_class->change_state = gst_camerasrc_change_state;
421   element_class->send_event = gst_camerasrc_send_event;
422
423   g_object_class_install_property (gobject_class, PROP_ALWAYS_COPY,
424       g_param_spec_boolean ("always-copy", "Always Copy",
425           "If the buffer will or not be used directly from mmap",
426           DEFAULT_PROP_ALWAYS_COPY,
427           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
428
429   g_object_class_install_property (gobject_class, PROP_MAKER_NOTE,
430       g_param_spec_boolean ("maker-note", "Maker Note",
431           "Whether send the maker note with image during the capture",
432           FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
433           GST_PARAM_CONTROLLABLE));
434
435   g_object_class_install_property (gobject_class, PROP_CAPTURE_WIDTH,
436       g_param_spec_int ("capture-width", "Capture Widht",
437           "Image width used in capture mode.In case capture is done when pipeline is already running in viewfinder mode", 0,
438       G_MAXINT, 0,
439       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
440
441   g_object_class_install_property (gobject_class, PROP_CAPTURE_HEIGHT,
442       g_param_spec_int ("capture-height", "Capture Height",
443           "Image height used in capture mode. In case capture is done when pipeline is already running in viewfinder mode", 0,
444       G_MAXINT, 0,
445       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
446
447   g_object_class_install_property(gobject_class, PROP_CAPTURE_FOURCC,
448       g_param_spec_uint("capture-fourcc", "Capture format",
449          "Fourcc value for capture format",0,
450      G_MAXUINT, 0,
451      G_PARAM_READWRITE  | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
452
453   g_object_class_install_property(gobject_class, PROP_CAPTURE_COUNT,
454       g_param_spec_uint("capture-count", "Capture count",
455          "image count taken in capture",0,
456      G_MAXUINT, 0,
457      G_PARAM_READWRITE  | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
458
459   g_object_class_install_property(gobject_class, PROP_REQ_NEGOTIATION,
460       g_param_spec_boolean("req-negotiation", "Request re-negotiation",
461         "Request to negotiate while on playing",
462       FALSE,
463       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE ));
464
465   g_object_class_install_property(gobject_class, PROP_SIGNAL_STILL_CAPTURE,
466       g_param_spec_boolean("signal-still-capture", "Signal  Still Capture",
467         "Send a signal before pushing the buffer",
468       FALSE,
469       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE ));
470
471   /**
472    * GstCameraSrc:capture-mode:
473    *
474    * Defines capturing mode to be used. This information is needed by extension
475    * modules, which control hardware-specific functionality.
476    */
477   g_object_class_install_property (gobject_class, PROP_CAPTURE_MODE,
478       g_param_spec_enum ("capture-mode", "Capturing mode",
479           "Defines what kind of capturing mode to be used",
480           GST_TYPE_CAMERA_SRC_CAPTURE_MODE,
481           GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER,
482           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
483
484   /**
485    * GstCameraSrc:viewfinder-mode:
486    *
487    * Defines which mode viewfinder should run in. This information is needed
488    * by extension modules, which control hardware-specific functionality.
489    */
490   g_object_class_install_property (gobject_class, PROP_VIEWFINDER_MODE,
491       g_param_spec_enum ("viewfinder-mode", "Viewfinder mode",
492           "Defines in what mode viewfinder should be run",
493           GST_TYPE_CAMERA_SRC_VIEWFINDER_MODE,
494           GST_CAMERA_SRC_VIEWFINDER_MODE_STILL,
495           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
496
497
498    /**
499     * GstCameraSrc::nego-complete:
500     * @camerasrc: the camerasrc instance
501     * @start: when re-negotiation is finished.
502     *
503     */
504    gst_camerasrc_signals[SIGNAL_NEGO_COMPLETE] =
505      g_signal_new("nego-complete",
506                G_TYPE_FROM_CLASS (klass),
507                G_SIGNAL_RUN_LAST,
508                G_STRUCT_OFFSET(GstCameraSrcClass, nego_complete),
509                NULL,
510                NULL,
511                gst_marshal_VOID__VOID,
512                G_TYPE_NONE, 0);
513
514         /**
515         * GstCameraSrc::still-capture:
516         * @camerasrc: the camerasrc instance
517         * @buffer: the buffer that will be pushed - Main
518         * @buffer: the buffer that will be pushed - Thumbnail
519         * @buffer: the buffer that will be pushed - Screennail
520         *
521         * This signal gets emitted before sending the buffer.
522         */
523         gst_camerasrc_signals[SIGNAL_STILL_CAPTURE] =
524                 g_signal_new("still-capture",
525                              G_TYPE_FROM_CLASS(klass),
526                              G_SIGNAL_RUN_LAST,
527                              G_STRUCT_OFFSET(GstCameraSrcClass, still_capture),
528                              NULL,
529                              NULL,
530                              gst_camerasrc_VOID__OBJECT_OBJECT,
531                              G_TYPE_NONE,
532                              3, /* Number of parameter */
533                              GST_TYPE_BUFFER,  /* Main image buffer */
534                              GST_TYPE_BUFFER,  /* Thumbnail image buffer */
535                              GST_TYPE_BUFFER); /* Screennail image buffer */
536
537
538
539   gst_camerasrc_override_photo_properties (gobject_class);
540
541   basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_camerasrc_get_caps);
542   basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_camerasrc_set_caps);
543   basesrc_class->start = GST_DEBUG_FUNCPTR (gst_camerasrc_start);
544   basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_camerasrc_unlock);
545   basesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_camerasrc_unlock_stop);
546   basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_camerasrc_stop);
547   basesrc_class->query = GST_DEBUG_FUNCPTR (gst_camerasrc_query);
548   basesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_camerasrc_fixate);
549   basesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_camerasrc_negotiate);
550   basesrc_class->event = GST_DEBUG_FUNCPTR (gst_camerasrc_event);
551
552   pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_camerasrc_create);
553
554   /* Initialize vmethods with default implementations */
555   gst_camerasrc_default_functions_init (klass);
556 }
557
558 /*
559  */
560 static void
561 gst_camerasrc_init (GstCameraSrc * camerasrc, GstCameraSrcClass * klass)
562 {
563   /* number of buffers requested */
564   camerasrc->always_copy = DEFAULT_PROP_ALWAYS_COPY;
565
566   camerasrc->state_lock = g_mutex_new ();
567   camerasrc->af_lock = g_mutex_new ();
568
569   gst_base_src_set_format (GST_BASE_SRC (camerasrc), GST_FORMAT_TIME);
570   gst_base_src_set_live (GST_BASE_SRC (camerasrc), TRUE);
571
572   /* Photo interface */
573   camerasrc->photoconf.zoom = 1.0;
574   camerasrc->photoconf.ev_compensation = 0.0;
575   camerasrc->photoconf.exposure = 0;    /* 0 = auto */
576   camerasrc->photoconf.aperture = 0;    /* 0 = auto */
577   camerasrc->photoconf.iso_speed = 0;   /* 0 = auto */
578   camerasrc->photoconf.wb_mode = GST_PHOTOGRAPHY_WB_MODE_AUTO;
579   camerasrc->photoconf.scene_mode = GST_PHOTOGRAPHY_SCENE_MODE_MANUAL;
580   camerasrc->photoconf.flash_mode = GST_PHOTOGRAPHY_FLASH_MODE_OFF;
581   camerasrc->photoconf.tone_mode = GST_PHOTOGRAPHY_COLOUR_TONE_MODE_NORMAL;
582   camerasrc->photoconf.flicker_mode = GST_PHOTOGRAPHY_FLICKER_REDUCTION_50HZ;
583   camerasrc->photoconf.focus_mode = GST_PHOTOGRAPHY_FOCUS_MODE_AUTO;
584   camerasrc->photoconf.noise_reduction = GST_PHOTOGRAPHY_NOISE_REDUCTION_YCC |
585       GST_PHOTOGRAPHY_NOISE_REDUCTION_BAYER;
586
587   camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
588   camerasrc->capture_mode = GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER;
589   camerasrc->viewfinder_mode = GST_CAMERA_SRC_VIEWFINDER_MODE_STILL;
590   camerasrc->capture_resolution_set = FALSE;
591   camerasrc->preview_resolution_set = FALSE;
592   camerasrc->req_negotiation = FALSE;
593   camerasrc->signal_still_capture = FALSE;
594
595   camerasrc->capture_w = 0;
596   camerasrc->capture_h = 0;
597   camerasrc->capture_fps_n = 0;
598   camerasrc->capture_fps_d = 0;
599   camerasrc->capture_fourcc = 0;
600   camerasrc->capture_count = 1;
601   camerasrc->capture_counter = 1;
602
603   camerasrc->preview_w = 0;
604   camerasrc->preview_h = 0;
605   camerasrc->preview_fourcc = 0;
606
607   camerasrc->requested_af_mode = AF_NONE_REQUESTED;
608   camerasrc->maker_note = FALSE;
609 }
610
611 /*
612  */
613 static void
614 gst_camerasrc_dispose (GObject * object)
615 {
616   GstCameraSrc *camerasrc = GST_CAMERA_SRC_CAST (object);
617
618   if (camerasrc->vf_caps) {
619     gst_caps_unref (camerasrc->vf_caps);
620     camerasrc->vf_caps = NULL;
621   }
622   if (camerasrc->state_lock) {
623     g_mutex_free (camerasrc->state_lock);
624     camerasrc->state_lock = NULL;
625   }
626   if (camerasrc->af_lock) {
627     g_mutex_free (camerasrc->af_lock);
628     camerasrc->af_lock = NULL;
629   }
630   gst_camerasrc_clear_color_channels (camerasrc);
631
632   gst_camerasrc_clear_cameracontrol_channels (camerasrc);
633
634   G_OBJECT_CLASS (parent_class)->dispose (object);
635 }
636
637 static void
638 gst_camerasrc_override_photo_properties (GObjectClass * gobject_class)
639 {
640   g_object_class_override_property (gobject_class, PROP_WB_MODE,
641       GST_PHOTOGRAPHY_PROP_WB_MODE);
642
643   g_object_class_override_property (gobject_class, PROP_COLOUR_TONE,
644       GST_PHOTOGRAPHY_PROP_COLOUR_TONE);
645
646   g_object_class_override_property (gobject_class, PROP_SCENE_MODE,
647       GST_PHOTOGRAPHY_PROP_SCENE_MODE);
648
649   g_object_class_override_property (gobject_class, PROP_FLASH_MODE,
650       GST_PHOTOGRAPHY_PROP_FLASH_MODE);
651
652   g_object_class_override_property (gobject_class, PROP_CAPABILITIES,
653       GST_PHOTOGRAPHY_PROP_CAPABILITIES);
654
655   g_object_class_override_property (gobject_class, PROP_EV_COMP,
656       GST_PHOTOGRAPHY_PROP_EV_COMP);
657
658   g_object_class_override_property (gobject_class, PROP_ISO_SPEED,
659       GST_PHOTOGRAPHY_PROP_ISO_SPEED);
660
661   g_object_class_override_property (gobject_class, PROP_APERTURE,
662       GST_PHOTOGRAPHY_PROP_APERTURE);
663
664   g_object_class_override_property (gobject_class, PROP_EXPOSURE,
665       GST_PHOTOGRAPHY_PROP_EXPOSURE);
666
667   g_object_class_override_property (gobject_class, PROP_ZOOM,
668       GST_PHOTOGRAPHY_PROP_ZOOM);
669
670   g_object_class_override_property (gobject_class, PROP_FLICKER_MODE,
671       GST_PHOTOGRAPHY_PROP_FLICKER_MODE);
672
673   g_object_class_override_property (gobject_class, PROP_FOCUS_MODE,
674       GST_PHOTOGRAPHY_PROP_FOCUS_MODE);
675
676   g_object_class_override_property (gobject_class, PROP_NOISE_REDUCTION,
677       GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION);
678
679   g_object_class_override_property (gobject_class, PROP_IMAGE_CAPTURE_CAPS,
680       GST_PHOTOGRAPHY_PROP_IMAGE_CAPTURE_SUPPORTED_CAPS);
681
682   g_object_class_override_property (gobject_class, PROP_IMAGE_PREVIEW_CAPS,
683       GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
684
685   g_object_class_override_property (gobject_class, PROP_AUTOFOCUS,
686       GST_PHOTOGRAPHY_PROP_AUTOFOCUS);
687 }
688
689
690 /*
691  */
692 static void
693 gst_camerasrc_set_property (GObject * object,
694     guint prop_id, const GValue * value, GParamSpec * pspec)
695 {
696   GstCameraSrc *camerasrc;
697   GstCameraSrcClass *bclass;
698
699   camerasrc = GST_CAMERA_SRC_CAST (object);
700   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
701
702   if (gst_camerasrc_photo_set_property (camerasrc, prop_id, value))
703     return;
704
705   switch (prop_id) {
706     case PROP_ALWAYS_COPY:
707       camerasrc->always_copy = g_value_get_boolean (value);
708       break;
709     case PROP_MAKER_NOTE:
710       camerasrc->maker_note = g_value_get_boolean (value);
711       break;
712     case PROP_CAPTURE_MODE:
713       camerasrc->capture_mode = g_value_get_enum (value);
714       GST_INFO_OBJECT (camerasrc, "Setting capture mode: %d",
715           camerasrc->capture_mode);
716
717       if (camerasrc->capture_mode == GST_CAMERA_SRC_CAPTURE_MODE_VIDEO &&
718           bclass->is_active (camerasrc)) {
719         /* Stop autofocus in video mode */
720         bclass->set_autofocus (camerasrc, FALSE);
721         /* AutoExposure must be run always in video mode */
722         bclass->set_autoexposure (camerasrc, TRUE);
723       }
724       if (bclass->set_capture_mode) {
725         bclass->set_capture_mode (camerasrc, camerasrc->capture_mode);
726       }
727       break;
728
729     case PROP_VIEWFINDER_MODE:
730       camerasrc->viewfinder_mode = g_value_get_enum (value);
731       GST_INFO_OBJECT (camerasrc, "Setting viewfinder mode: %d",
732           camerasrc->viewfinder_mode);
733
734       if (bclass->set_vfinder_mode) {
735         bclass->set_vfinder_mode (camerasrc, camerasrc->viewfinder_mode);
736       }
737       break;
738     case PROP_CAPTURE_WIDTH:
739       camerasrc->capture_w = g_value_get_int (value);
740       GST_DEBUG_OBJECT (camerasrc, "Capture width %d",
741            camerasrc->capture_w);
742       /* both width & height should be set before setting flag to TRUE */
743       if(camerasrc->capture_h != 0)
744          camerasrc->capture_resolution_set = TRUE;
745       break;
746     case PROP_CAPTURE_HEIGHT:
747       camerasrc->capture_h = g_value_get_int (value);
748       GST_DEBUG_OBJECT (camerasrc, "Capture Height: %d",
749           camerasrc->capture_h);
750       /* both width & height should be set before setting flag to TRUE */
751       if(camerasrc->capture_w != 0)
752          camerasrc->capture_resolution_set = TRUE;
753       break;
754     case PROP_CAPTURE_FOURCC:
755       camerasrc->capture_fourcc = g_value_get_uint (value);
756       GST_DEBUG_OBJECT (camerasrc, "Capture fourcc: %d",
757           camerasrc->capture_fourcc);
758       break;
759     case PROP_CAPTURE_COUNT:
760       camerasrc->capture_count = g_value_get_uint (value);
761       GST_DEBUG_OBJECT (camerasrc, "Capture count: %d",
762           camerasrc->capture_count);
763       break;
764     case PROP_REQ_NEGOTIATION:
765       camerasrc->req_negotiation = g_value_get_boolean(value);
766       GST_DEBUG_OBJECT (camerasrc, "negotaion request %d",
767           camerasrc->req_negotiation);
768       break;
769     case PROP_SIGNAL_STILL_CAPTURE:
770       camerasrc->signal_still_capture = g_value_get_boolean(value);
771       break;
772     default:
773       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
774       break;
775   }
776 }
777
778 /*
779  */
780 static void
781 gst_camerasrc_get_property (GObject * object,
782     guint prop_id, GValue * value, GParamSpec * pspec)
783 {
784   GstCameraSrc *camerasrc = GST_CAMERA_SRC_CAST (object);
785
786   if (gst_camerasrc_photo_get_property (camerasrc, prop_id, value))
787     return;
788
789   switch (prop_id) {
790     case PROP_ALWAYS_COPY:
791       g_value_set_boolean (value, camerasrc->always_copy);
792       break;
793     case PROP_MAKER_NOTE:
794       g_value_set_boolean (value, camerasrc->maker_note);
795       break;
796     case PROP_CAPTURE_MODE:
797       g_value_set_enum (value, camerasrc->capture_mode);
798       break;
799     case PROP_VIEWFINDER_MODE:
800       g_value_set_enum (value, camerasrc->viewfinder_mode);
801       break;
802     case PROP_CAPTURE_WIDTH:
803       g_value_set_int (value, camerasrc->capture_w);
804       break;
805     case PROP_CAPTURE_HEIGHT:
806       g_value_set_int (value, camerasrc->capture_h);
807       break;
808    case PROP_CAPTURE_FOURCC:
809       g_value_set_uint (value, camerasrc->capture_fourcc);
810       break;
811     case PROP_CAPTURE_COUNT:
812       g_value_set_uint (value, camerasrc->capture_count);
813       break;
814    case PROP_REQ_NEGOTIATION:
815       g_value_set_boolean(value, camerasrc->req_negotiation);
816       break;
817     case PROP_SIGNAL_STILL_CAPTURE:
818       g_value_set_boolean (value,  camerasrc->signal_still_capture);
819       break;
820     default:
821       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
822       break;
823   }
824 }
825
826 /* this function is a bit of a last resort */
827 static void
828 gst_camerasrc_fixate (GstBaseSrc * basesrc, GstCaps * caps)
829 {
830   GstStructure *structure;
831
832   gint i;
833
834   GST_DEBUG_OBJECT (basesrc, "fixating caps %" GST_PTR_FORMAT, caps);
835
836   for (i = 0; i < gst_caps_get_size (caps); ++i) {
837     const GValue *v;
838
839     structure = gst_caps_get_structure (caps, i);
840
841     /* FIXME such sizes? we usually fixate to something in the 320x200
842      * range... */
843     /* We are fixating to greatest possble size (limited to GST_CAMERA_SRC_MAX_SIZE)
844        and the maximum framerate resolution for that size */
845     gst_structure_fixate_field_nearest_int (structure, "width",
846         GST_CAMERA_SRC_MAX_SIZE);
847     gst_structure_fixate_field_nearest_int (structure, "height",
848         GST_CAMERA_SRC_MAX_SIZE);
849     gst_structure_fixate_field_nearest_fraction (structure, "framerate",
850         G_MAXINT, 1);
851
852     v = gst_structure_get_value (structure, "format");
853     if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) {
854       guint32 fourcc;
855
856       g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST);
857
858       fourcc = gst_value_get_fourcc (gst_value_list_get_value (v, 0));
859       gst_structure_set (structure, "format", GST_TYPE_FOURCC, fourcc, NULL);
860     }
861   }
862
863   GST_DEBUG_OBJECT (basesrc, "fixated caps %" GST_PTR_FORMAT, caps);
864 }
865
866 /*
867  */
868 static gboolean
869 gst_camerasrc_negotiate (GstBaseSrc * basesrc)
870 {
871   GstCaps *thiscaps;
872
873   GstCaps *caps = NULL;
874
875   GstCaps *peercaps = NULL;
876
877   gboolean result = FALSE;
878
879   /* first see what is possible on our source pad */
880   thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
881   GST_DEBUG_OBJECT (basesrc, "caps of src suppressed on DEBUG (>= 5 to see)");
882   GST_LOG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
883   /* nothing or anything is allowed, we're done */
884   if (thiscaps == NULL || gst_caps_is_any (thiscaps))
885     goto no_nego_needed;
886
887   /* get the peer caps */
888   peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
889   GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
890   if (peercaps && !gst_caps_is_any (peercaps)) {
891     GstCaps *icaps = NULL;
892     int i;
893
894     /* Prefer the first caps we are compatible with that the peer proposed */
895     for (i = 0; i < gst_caps_get_size (peercaps); i++) {
896       /* get intersection */
897       GstCaps *ipcaps = gst_caps_copy_nth (peercaps, i);
898
899       GST_DEBUG_OBJECT (basesrc, "peer: %" GST_PTR_FORMAT, ipcaps);
900
901       icaps = gst_caps_intersect (thiscaps, ipcaps);
902       gst_caps_unref (ipcaps);
903
904       if (!gst_caps_is_empty (icaps))
905         break;
906
907       gst_caps_unref (icaps);
908       icaps = NULL;
909     }
910
911     GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, icaps);
912     if (icaps) {
913       /* If there are multiple intersections pick the one with the smallest
914        * resolution strictly bigger then the first peer caps */
915       if (gst_caps_get_size (icaps) > 1) {
916         GstStructure *s = gst_caps_get_structure (peercaps, 0);
917
918         int best = 0;
919
920         int twidth, theight;
921
922         int width = G_MAXINT, height = G_MAXINT;
923
924         if (gst_structure_get_int (s, "width", &twidth)
925             && gst_structure_get_int (s, "height", &theight)) {
926
927           /* Walk the structure backwards to get the first entry of the
928            * smallest resolution bigger (or equal to) the preferred resolution)
929            */
930           for (i = gst_caps_get_size (icaps) - 1; i >= 0; i--) {
931             GstStructure *is = gst_caps_get_structure (icaps, i);
932
933             int w, h;
934
935             if (gst_structure_get_int (is, "width", &w)
936                 && gst_structure_get_int (is, "height", &h)) {
937               if (w >= twidth && w <= width && h >= theight && h <= height) {
938                 width = w;
939                 height = h;
940                 best = i;
941               }
942             }
943           }
944         }
945
946         caps = gst_caps_copy_nth (icaps, best);
947         gst_caps_unref (icaps);
948       } else {
949         caps = icaps;
950       }
951     }
952     gst_caps_unref (thiscaps);
953     gst_caps_unref (peercaps);
954   } else {
955     /* no peer or peer have ANY caps, work with our own caps then */
956     caps = thiscaps;
957   }
958   if (caps) {
959     caps = gst_caps_make_writable (caps);
960     gst_caps_truncate (caps);
961
962     /* now fixate */
963     if (!gst_caps_is_empty (caps)) {
964       gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
965       GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
966
967       if (gst_caps_is_any (caps)) {
968         /* hmm, still anything, so element can do anything and
969          * nego is not needed */
970         result = TRUE;
971       } else if (gst_caps_is_fixed (caps)) {
972         /* yay, fixed caps, use those then */
973         result = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
974         GST_DEBUG_OBJECT (basesrc, "Set caps returned: %d", result);
975       }
976     }
977     gst_caps_unref (caps);
978   }
979   return result;
980
981 no_nego_needed:
982   {
983     GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
984     if (thiscaps)
985       gst_caps_unref (thiscaps);
986     return TRUE;
987   }
988 }
989
990
991 /*
992  */
993 static GstCaps *
994 gst_camerasrc_get_caps (GstBaseSrc * src)
995 {
996   GstCameraSrc *camerasrc;
997   GstCameraSrcClass *bclass;
998
999   camerasrc = GST_CAMERA_SRC_CAST (src);
1000   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1001
1002   if (!bclass->is_open (camerasrc) || !bclass->get_caps) {
1003     return gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
1004             (camerasrc)));
1005   }
1006
1007   return bclass->get_caps (camerasrc);
1008 }
1009
1010
1011 /**
1012  * gst_camerasrc_get_caps_info:
1013  * @caps: given input caps
1014  * @four_cc: location for the fourcc
1015  * @w/@h: location for width and height
1016  * @fps_n/@fps_d: location for framerate
1017  *
1018  * Collect data for the given caps.
1019  */
1020 static gboolean
1021 gst_camerasrc_get_caps_info (GstCameraSrc * camerasrc, GstCaps * caps,
1022     guint32 * four_cc, guint * w, guint * h, guint * fps_n, guint * fps_d,
1023     guint * size)
1024 {
1025   GstCameraSrcClass *bclass;
1026   GstStructure *structure;
1027   const GValue *framerate;
1028   const gchar *mimetype;
1029   guint32 fourcc;
1030   guint outsize;
1031
1032   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1033
1034   /* default unknown values */
1035   fourcc = 0;
1036   outsize = 0;
1037
1038   structure = gst_caps_get_structure (caps, 0);
1039
1040   mimetype = gst_structure_get_name (structure);
1041
1042   if (!gst_structure_get_int (structure, "width", (gint *) w))
1043     return FALSE;
1044
1045   if (!gst_structure_get_int (structure, "height", (gint *) h))
1046     return FALSE;
1047
1048   framerate = gst_structure_get_value (structure, "framerate");
1049   if (!framerate)
1050     return FALSE;
1051
1052   *fps_n = gst_value_get_fraction_numerator (framerate);
1053   *fps_d = gst_value_get_fraction_denominator (framerate);
1054
1055   if (!strcmp (mimetype, "video/x-raw-yuv")) {
1056     gst_structure_get_fourcc (structure, "format", &fourcc);
1057
1058     switch (fourcc) {
1059       case GST_MAKE_FOURCC ('I', '4', '2', '0'):
1060       case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
1061         fourcc = V4L2_PIX_FMT_YUV420;
1062         outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1063         outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1064         break;
1065       case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
1066         fourcc = V4L2_PIX_FMT_YUYV;
1067         outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1068         break;
1069       case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
1070         fourcc = V4L2_PIX_FMT_Y41P;
1071         outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1072         break;
1073       case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
1074         fourcc = V4L2_PIX_FMT_UYVY;
1075         outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1076         break;
1077       case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
1078         fourcc = V4L2_PIX_FMT_YVU420;
1079         outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1080         outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1081         break;
1082       case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
1083         fourcc = V4L2_PIX_FMT_YUV411P;
1084         outsize = GST_ROUND_UP_4 (*w) * *h;
1085         outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
1086         break;
1087       case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
1088         fourcc = V4L2_PIX_FMT_YUV422P;
1089         outsize = GST_ROUND_UP_4 (*w) * *h;
1090         outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
1091         break;
1092       case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
1093         fourcc = V4L2_PIX_FMT_NV12;
1094         outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1095         outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1096         break;
1097       case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
1098         fourcc = V4L2_PIX_FMT_NV21;
1099         outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1100         outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1101         break;
1102 #ifdef V4L2_PIX_FMT_YVYU
1103       case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
1104         fourcc = V4L2_PIX_FMT_YVYU;
1105         outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1106         break;
1107 #endif
1108     }
1109   } else if (!strcmp (mimetype, "video/x-raw-rgb")) {
1110     gint depth, endianness, r_mask;
1111
1112     gst_structure_get_int (structure, "depth", &depth);
1113     gst_structure_get_int (structure, "endianness", &endianness);
1114     gst_structure_get_int (structure, "red_mask", &r_mask);
1115
1116     switch (depth) {
1117       case 8:
1118         fourcc = V4L2_PIX_FMT_RGB332;
1119         break;
1120       case 15:
1121         fourcc = (endianness == G_LITTLE_ENDIAN) ?
1122             V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X;
1123         break;
1124       case 16:
1125         fourcc = (endianness == G_LITTLE_ENDIAN) ?
1126             V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X;
1127         break;
1128       case 24:
1129         fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24;
1130         break;
1131       case 32:
1132         fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32;
1133         break;
1134     }
1135   } else if (strcmp (mimetype, "video/x-raw-bayer") == 0) {
1136     gst_structure_get_fourcc (structure, "format", &fourcc);
1137     switch (fourcc) {
1138       case GST_MAKE_FOURCC ('B', 'A', '8', '1'):
1139         fourcc = V4L2_PIX_FMT_SBGGR8;
1140         break;
1141       case GST_MAKE_FOURCC ('G', 'B', 'R', 'G'):
1142         fourcc = V4L2_PIX_FMT_SGBRG8;
1143         break;
1144       case GST_MAKE_FOURCC ('G', 'R', 'B', 'G'):
1145         fourcc = V4L2_PIX_FMT_SGRBG8;
1146         break;
1147       case GST_MAKE_FOURCC ('R', 'G', 'G', 'B'):
1148         fourcc = V4L2_PIX_FMT_SRGGB8;
1149         break;
1150       case GST_MAKE_FOURCC ('B', 'G', '1', '0'):
1151         fourcc = V4L2_PIX_FMT_SBGGR10;
1152         break;
1153       case GST_MAKE_FOURCC ('G', 'B', '1', '0'):
1154         fourcc = V4L2_PIX_FMT_SGBRG10;
1155         break;
1156       case GST_MAKE_FOURCC ('B', 'A', '1', '0'):
1157         fourcc = V4L2_PIX_FMT_SGRBG10;
1158         break;
1159       case GST_MAKE_FOURCC ('R', 'G', '1', '0'):
1160         fourcc = V4L2_PIX_FMT_SRGGB10;
1161         break;
1162       case GST_MAKE_FOURCC ('B', 'Y', 'R', '2'):
1163         fourcc = V4L2_PIX_FMT_SBGGR16;
1164         break;
1165     }
1166   } else if (strcmp (mimetype, "video/x-raw-gray") == 0) {
1167     fourcc = V4L2_PIX_FMT_GREY;
1168   }
1169
1170   if (fourcc == 0)
1171     return FALSE;
1172
1173   *four_cc = fourcc;
1174
1175   return TRUE;
1176 }
1177
1178
1179 /**
1180  * gst_camerasrc_get_caps_from_info:
1181  * @camsrc: #GstCameraSrc object
1182  * @fourcc: fourcc code
1183  * @width: width to be set
1184  * @height: height to be set
1185  * @fps_n: FPS numerator to be set or 0
1186  * @fps_d: FPS denominator to be set or 0
1187  *
1188  * Converts given parameters into GstCaps structure.
1189  *
1190  * Returns: GstCaps representing the given values.
1191  */
1192 GstCaps *
1193 gst_camerasrc_get_caps_from_info (GstCameraSrc * camsrc, guint32 fourcc,
1194     guint width, guint height, guint fps_n, guint fps_d)
1195 {
1196   GstCaps *newcaps;
1197   GstStructure *s;
1198
1199   s = gst_structure_new ("video/x-raw-yuv",
1200       "format", GST_TYPE_FOURCC, fourcc,
1201       "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
1202
1203   if (fps_n != 0 && fps_d != 0) {
1204     gst_structure_set (s, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
1205   }
1206
1207   newcaps = gst_caps_new_empty ();
1208   gst_caps_append_structure (newcaps, s);
1209
1210   return newcaps;
1211 }
1212
1213
1214 /*
1215  */
1216 static gboolean
1217 gst_camerasrc_configure_device (GstCameraSrc * camerasrc, guint * w, guint * h,
1218     guint32 * fourcc, guint * fps_n, guint * fps_d, GstCaps * buffer_caps)
1219 {
1220   GstCameraSrcClass *bclass;
1221   GstOperationMode opmode;
1222
1223   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1224
1225   /* Stop the capturing */
1226   if (!bclass->stop (camerasrc))
1227     return FALSE;
1228
1229   GST_DEBUG_OBJECT (camerasrc, "trying to set_capture %dx%d at %d/%d fps",
1230       *w, *h, *fps_n, *fps_d);
1231
1232   if (bclass->set_vfinder_mode) {
1233     bclass->set_vfinder_mode (camerasrc, camerasrc->viewfinder_mode);
1234   }
1235   if (bclass->set_capture_mode) {
1236     bclass->set_capture_mode (camerasrc, camerasrc->capture_mode);
1237   }
1238
1239   opmode = camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE ?
1240       GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE :
1241       GST_PHOTOGRAPHY_OPERATION_MODE_VIEWFINDER;
1242
1243   if (!bclass->set_capture (camerasrc, opmode, FALSE, fourcc, w, h,
1244           fps_n, fps_d)) {
1245     GST_ELEMENT_ERROR (camerasrc, RESOURCE, SETTINGS,
1246         ("Failed configuring device for capturing"), (NULL));
1247     return FALSE;
1248   }
1249
1250   gst_camerasrc_update_max_zoom (camerasrc);
1251
1252   /* Only start the driver when not in HQ capture mode, since in HQ mode */
1253   /* we have already called start_capture() above */
1254
1255   if (!bclass->start (camerasrc, buffer_caps))
1256     return FALSE;
1257
1258   if (camerasrc->photo_capture_phase != GST_CAMERA_CAPTURE) {
1259
1260     if (!bclass->write_settings (camerasrc, &camerasrc->photoconf, FALSE)) {
1261       GST_ELEMENT_ERROR (camerasrc, RESOURCE, SETTINGS,
1262           ("Failed to configure driver module"), (NULL));
1263
1264       return FALSE;
1265     }
1266   }
1267
1268   return TRUE;
1269 }
1270
1271
1272 /*
1273  */
1274 static gboolean
1275 gst_camerasrc_init_from_caps (GstCameraSrc * camerasrc, GstCaps * caps)
1276 {
1277   guint w = 0, h = 0;
1278   guint32 fourcc;
1279   guint fps_n, fps_d;
1280   guint size;
1281   gboolean ret;
1282
1283   /* we want our own type of fourcc codes */
1284   if (!gst_camerasrc_get_caps_info (camerasrc, caps, &fourcc, &w, &h, &fps_n,
1285           &fps_d, &size)) {
1286     GST_DEBUG_OBJECT (camerasrc,
1287         "can't get capture format from caps %" GST_PTR_FORMAT, caps);
1288     return FALSE;
1289   }
1290
1291   ret = gst_camerasrc_configure_device (camerasrc, &w, &h, &fourcc,
1292       &fps_n, &fps_d, caps);
1293
1294   if (ret) {
1295     camerasrc->current_w = w;
1296     camerasrc->current_h = h;
1297     camerasrc->fps_n = fps_n;
1298     camerasrc->fps_d = fps_d;
1299     camerasrc->current_fourcc = fourcc;
1300
1301     camerasrc->duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
1302     GST_DEBUG_OBJECT (camerasrc, "Buffer duration: %" GST_TIME_FORMAT,
1303         GST_TIME_ARGS (camerasrc->duration));
1304
1305 //      camerasrc->frame_byte_size = size;
1306   }
1307
1308   return ret;
1309 }
1310
1311 /*
1312  */
1313 static gboolean
1314 gst_camerasrc_set_caps (GstBaseSrc * src, GstCaps * caps)
1315 {
1316   GstCameraSrc *camerasrc;
1317   GstCameraSrcClass *bclass;
1318
1319   camerasrc = GST_CAMERA_SRC_CAST (src);
1320   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1321
1322   GST_DEBUG_OBJECT (camerasrc, "set_caps called: %" GST_PTR_FORMAT, caps);
1323
1324   /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
1325   if (!bclass->is_open (camerasrc))
1326     return FALSE;
1327
1328   return gst_camerasrc_init_from_caps (camerasrc, caps);
1329 }
1330
1331 /*
1332  */
1333 static gboolean
1334 gst_camerasrc_query (GstBaseSrc * bsrc, GstQuery * query)
1335 {
1336   GstCameraSrc *src;
1337   GstCameraSrcClass *bclass;
1338   gboolean res = FALSE;
1339   guint num_buffers;
1340
1341   src = GST_CAMERA_SRC_CAST (bsrc);
1342   bclass = GST_CAMERA_SRC_GET_CLASS (src);
1343
1344   switch (GST_QUERY_TYPE (query)) {
1345     case GST_QUERY_LATENCY:{
1346       GstClockTime max_latency;
1347
1348       /* device must be open */
1349       if (!bclass->is_open (src)) {
1350         GST_WARNING_OBJECT (src,
1351             "Can't give latency since device isn't open !");
1352         goto done;
1353       }
1354
1355       /* we must have a framerate */
1356       if (src->fps_n <= 0 || src->fps_d <= 0) {
1357         GST_WARNING_OBJECT (src,
1358             "Can't give latency since framerate isn't fixated !");
1359         goto done;
1360       }
1361
1362       num_buffers = bclass->get_num_buffers (src);
1363       /* max latency is total duration of the frame buffer */
1364       max_latency = num_buffers * src->duration;
1365
1366       GST_DEBUG_OBJECT (bsrc,
1367           "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
1368           GST_TIME_ARGS (src->duration), GST_TIME_ARGS (max_latency));
1369
1370       /* we are always live, the min latency is 1 frame and the max latency is
1371        * the complete buffer of frames. */
1372       gst_query_set_latency (query, TRUE, src->duration, max_latency);
1373
1374       res = TRUE;
1375       break;
1376     }
1377     default:
1378       res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
1379       break;
1380   }
1381
1382 done:
1383
1384   return res;
1385 }
1386
1387 static gboolean
1388 gst_camerasrc_start (GstBaseSrc * src)
1389 {
1390 //   GstCameraSrc *camerasrc = GST_CAMERA_SRC_CAST (src);
1391
1392   return TRUE;
1393 }
1394
1395 /*
1396  */
1397 static gboolean
1398 gst_camerasrc_stop (GstBaseSrc * src)
1399 {
1400   GstCameraSrc *camerasrc;
1401   GstCameraSrcClass *bclass;
1402
1403   camerasrc = GST_CAMERA_SRC_CAST (src);
1404   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1405
1406   GST_DEBUG_OBJECT (camerasrc, "Stopping");
1407
1408   bclass->stop (camerasrc);
1409
1410   camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1411
1412   return TRUE;
1413 }
1414
1415 static gboolean
1416 gst_camerasrc_unlock (GstBaseSrc * src)
1417 {
1418   GstCameraSrcClass *pclass;
1419   GstCameraSrc *camerasrc;
1420   gboolean ret = TRUE;
1421
1422   camerasrc = GST_CAMERA_SRC_CAST (src);
1423   pclass = GST_CAMERA_SRC_GET_CLASS (src);
1424
1425   GST_DEBUG_OBJECT (camerasrc, "Unlock");
1426
1427   if (pclass->unlock)
1428     ret = pclass->unlock (camerasrc);
1429
1430   return ret;
1431 }
1432
1433 static gboolean
1434 gst_camerasrc_unlock_stop (GstBaseSrc * src)
1435 {
1436   GstCameraSrcClass *pclass;
1437   GstCameraSrc *camerasrc;
1438   gboolean ret = TRUE;
1439
1440   camerasrc = GST_CAMERA_SRC_CAST (src);
1441   pclass = GST_CAMERA_SRC_GET_CLASS (src);
1442
1443   GST_DEBUG_OBJECT (camerasrc, "Unlock stop");
1444
1445   if (pclass->unlock_stop)
1446     ret = pclass->unlock_stop (camerasrc);
1447
1448   return ret;
1449 }
1450
1451
1452 /*
1453  * gst_camerasrc_send_image_tags:
1454  * @camerasrc: #GstCameraSrc object.
1455  *
1456  */
1457 static gboolean
1458 gst_camerasrc_send_image_tags (GstCameraSrc * camerasrc)
1459 {
1460   GstTagMergeMode mode;
1461   GstCameraSrcClass *bclass;
1462   guint iso, wbalance;
1463   GstEvent *tagevent;
1464   GstTagList *tlist;
1465   gfloat zoom;
1466
1467   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1468
1469   tlist = gst_tag_list_new ();
1470   zoom = camerasrc->photoconf.zoom;
1471   iso = camerasrc->photoconf.iso_speed;
1472   wbalance =
1473       (camerasrc->photoconf.wb_mode == GST_PHOTOGRAPHY_WB_MODE_AUTO) ? 0 : 1;
1474
1475   gst_tag_register_musicbrainz_tags();
1476
1477   mode = GST_TAG_MERGE_REPLACE;
1478   gst_tag_list_add(tlist, mode, GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, (gdouble)zoom, NULL);
1479   gst_tag_list_add(tlist, mode, GST_TAG_CAPTURING_ISO_SPEED, iso, NULL);
1480
1481   if(camerasrc->maker_note)
1482   {
1483     int handle;
1484     gboolean ret;
1485     GstBuffer *pmakerbuf = NULL;
1486     unsigned buf_size;
1487     unsigned num_afwindows, num_awbgrid;
1488
1489     num_afwindows = 1;
1490     num_awbgrid = 1;
1491     ret = bclass->makernote_init(camerasrc, &buf_size, num_afwindows, 0, 0, num_awbgrid, &handle);
1492     if(TRUE == ret)
1493     {
1494       pmakerbuf = gst_buffer_new_and_alloc(buf_size);
1495
1496       ret = bclass->makernote_deal(camerasrc, pmakerbuf, num_afwindows, num_awbgrid, handle);
1497       if(TRUE == ret)
1498       {
1499         gst_tag_list_add(tlist, mode, GST_TAG_APPLICATION_DATA, pmakerbuf, NULL);
1500       }
1501
1502       bclass->makernote_uninit(camerasrc, handle);
1503       gst_buffer_unref(pmakerbuf);
1504     }
1505   }
1506
1507   if (bclass->fill_image_tags)
1508     bclass->fill_image_tags (camerasrc, tlist);
1509
1510   tagevent = gst_event_new_tag (gst_tag_list_copy (tlist));
1511   gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc), tagevent);
1512   GST_DEBUG_OBJECT (camerasrc, "image tags sent: %" GST_PTR_FORMAT, tlist);
1513   gst_tag_list_free (tlist);
1514
1515   return TRUE;
1516 }
1517
1518
1519 /*
1520  * gst_camerasrc_send_preview:
1521  * @camsrc: #GstCameraSrc object
1522  *
1523  * Sends HQ image preview image (snapshot) as a GstMessage.
1524  *
1525  * Returns: TRUE on success.
1526  */
1527 static gboolean
1528 gst_camerasrc_send_preview (GstCameraSrc * camsrc)
1529 {
1530   GstCameraSrcClass *bclass;
1531   GstBuffer *buf = NULL;
1532   GstStructure *msg_s = NULL;
1533   GstCaps *prvcaps = NULL;
1534   GstMessage *msg = NULL;
1535   gboolean ret = FALSE;
1536
1537   bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
1538
1539   if (bclass->get_preview_image) {
1540     ret = bclass->get_preview_image (camsrc, &buf);
1541   }
1542
1543   if (ret) {
1544     GST_DEBUG_OBJECT (camsrc, "Sending preview image");
1545     prvcaps = gst_caps_new_simple ("video/x-raw-yuv",
1546         "format", GST_TYPE_FOURCC, camsrc->preview_fourcc,
1547         "width", G_TYPE_INT, camsrc->preview_w,
1548         "height", G_TYPE_INT, camsrc->preview_h,
1549         "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
1550
1551     gst_buffer_set_caps (buf, prvcaps);
1552
1553     /* Send custom preview image GstMessage */
1554     msg_s = gst_structure_new (GST_CAMERA_SRC_PREVIEW_IMAGE, "buffer",
1555         GST_TYPE_BUFFER, buf, NULL);
1556
1557     msg = gst_message_new_element (GST_OBJECT (camsrc), msg_s);
1558
1559     if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
1560       GST_WARNING ("This element has no bus, therefore no message sent!");
1561     }
1562
1563     gst_caps_unref (prvcaps);
1564   } else {
1565     GST_DEBUG_OBJECT (camsrc, "Retrieving preview image failed");
1566   }
1567
1568   /* if we still have valid settings for preview, reserve a new buffer */
1569   if (camsrc->preview_resolution_set) {
1570     GST_DEBUG_OBJECT (camsrc, "Reserving a new preview buffer");
1571     bclass->set_capture (camsrc, GST_PHOTOGRAPHY_OPERATION_MODE_PREVIEW, FALSE,
1572         &camsrc->preview_fourcc, &camsrc->preview_w, &camsrc->preview_h,
1573         NULL, NULL);
1574   }
1575
1576   if (buf) {
1577     gst_buffer_unref (buf);
1578   }
1579
1580   return ret;
1581 }
1582
1583
1584 /*
1585  * gst_camerasrc_set_capture_caps:
1586  * @camerasrc: #GstCameraSrc object.
1587  *
1588  * Set the capture caps on element's src pad.
1589  *
1590  * Returns: TRUE on success.
1591  */
1592 static gboolean
1593 gst_camerasrc_set_capture_caps (GstCameraSrc * camerasrc)
1594 {
1595   GstCameraSrcClass *bclass;
1596   GstCaps *newcaps = NULL;
1597   gboolean ret = TRUE;
1598
1599   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1600
1601   GST_DEBUG_OBJECT (camerasrc, "Calling set_capture()");
1602
1603   /* Try what resolution the subclass can capture */
1604   ret = bclass->set_capture (camerasrc,
1605       GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE, TRUE,
1606       &camerasrc->capture_fourcc, &camerasrc->capture_w, &camerasrc->capture_h,
1607       &camerasrc->capture_fps_n, &camerasrc->capture_fps_d);
1608
1609   if (!ret) {
1610     goto done;
1611   }
1612
1613   /* FIXME: FPS definition should be removed from capture caps */
1614   newcaps = gst_camerasrc_get_caps_from_info (camerasrc,
1615       camerasrc->capture_fourcc, camerasrc->capture_w, camerasrc->capture_h,
1616       camerasrc->capture_fps_n, camerasrc->capture_fps_d);
1617
1618   GST_DEBUG_OBJECT (camerasrc, "Set capture caps: %" GST_PTR_FORMAT, newcaps);
1619
1620   /* Notify application that we are ready now. This must be called before */
1621   /* the set_caps() call below, since application needs to know the new caps */
1622   /* so that it can adjust the caps filter to accept new format before */
1623   /* srcpad caps are actually changed */
1624   gst_camerasrc_photo_ready_for_capture (camerasrc, newcaps);
1625
1626   camerasrc->vf_caps =
1627       gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1628
1629   /* This causes caps nego and switches resolution to hi-res mode */
1630   /* FIXME: Do we even need to set this? Application has already set the
1631    * capsfilter */
1632   if (!gst_caps_is_equal (camerasrc->vf_caps, newcaps)) {
1633     GST_DEBUG_OBJECT (camerasrc, "Setting image capture caps");
1634     ret = gst_pad_set_caps (GST_BASE_SRC_PAD (camerasrc), newcaps);
1635     GST_DEBUG_OBJECT (camerasrc, "Setting image capture caps FINISHED");
1636   } else {
1637     GST_DEBUG_OBJECT (camerasrc, "Forcing the re-initialization");
1638     ret = gst_camerasrc_configure_device (camerasrc, &camerasrc->current_w,
1639         &camerasrc->current_h, &camerasrc->current_fourcc, &camerasrc->fps_n,
1640         &camerasrc->fps_d, newcaps);
1641     gst_caps_unref (camerasrc->vf_caps);
1642     camerasrc->vf_caps = NULL;
1643   }
1644
1645   gst_caps_unref (newcaps);
1646
1647 done:
1648
1649   return ret;
1650 }
1651
1652
1653 /*
1654  *
1655  */
1656 static void
1657 gst_camerasrc_apply_timestamp (GstCameraSrc * camerasrc, GstBuffer * buf)
1658 {
1659   GstClock *clock;
1660   GstClockTime timestamp;
1661
1662   GST_OBJECT_LOCK (camerasrc);
1663   if ((clock = GST_ELEMENT_CLOCK (camerasrc))) {
1664     /* we have a clock, get base time and ref clock */
1665     timestamp = GST_ELEMENT (camerasrc)->base_time;
1666     gst_object_ref (clock);
1667   } else {
1668     /* no clock, can't set timestamps */
1669     timestamp = GST_CLOCK_TIME_NONE;
1670   }
1671   GST_OBJECT_UNLOCK (camerasrc);
1672
1673   if (clock) {
1674     /* the time now is the time of the clock minus the base time */
1675     timestamp = gst_clock_get_time (clock) - timestamp;
1676     gst_object_unref (clock);
1677
1678     if (timestamp > camerasrc->duration)
1679       timestamp -= camerasrc->duration;
1680     else
1681       timestamp = 0;
1682   }
1683
1684   /* we could also use the timestamp from the buffer itself */
1685   GST_BUFFER_TIMESTAMP (buf) = timestamp;
1686   GST_BUFFER_DURATION (buf) = camerasrc->duration;
1687 }
1688
1689
1690 /*
1691  */
1692 static GstFlowReturn
1693 gst_camerasrc_create (GstPushSrc * src, GstBuffer ** buf)
1694 {
1695   GstCameraSrcClass *bclass;
1696   GstCameraSrc *camerasrc;
1697   GstBaseSrcClass *basesrc_class;
1698
1699   GstBuffer *buf_cap_signal1 = NULL;      /*output main buffer for capture signal*/
1700
1701   gboolean still_capture_initialised = FALSE;
1702   GstFlowReturn ret = GST_FLOW_OK;
1703   GstBuffer *temp;
1704
1705   camerasrc = GST_CAMERA_SRC_CAST (src);
1706   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1707   basesrc_class = GST_BASE_SRC_CLASS (bclass);
1708
1709   if (camerasrc->req_negotiation) {
1710     GST_DEBUG_OBJECT(camerasrc, "negotiation start");
1711     basesrc_class->negotiate(GST_BASE_SRC(camerasrc));
1712     camerasrc->req_negotiation = FALSE;
1713     g_signal_emit(G_OBJECT(camerasrc), gst_camerasrc_signals[SIGNAL_NEGO_COMPLETE], (GQuark)NULL);
1714     GST_DEBUG_OBJECT (camerasrc, "negotiation stop");
1715    }
1716
1717
1718 start_over:
1719
1720   g_mutex_lock (camerasrc->state_lock);
1721
1722   if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_START) {
1723     /* Tell subclass to stop flushing buffers */
1724     if (bclass->unlock_stop) {
1725       GST_DEBUG_OBJECT (camerasrc, "Stop flushing, capture is starting");
1726       bclass->unlock_stop (camerasrc);
1727     }
1728
1729     camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE;
1730
1731     GST_DEBUG_OBJECT (camerasrc,
1732         "Flushing old buffers before starting HQ capture");
1733     gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc),
1734         gst_event_new_flush_start ());
1735     gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc),
1736         gst_event_new_flush_stop ());
1737
1738     if (!gst_camerasrc_set_capture_caps (camerasrc)) {
1739       goto hq_capture_failed;
1740     }
1741     still_capture_initialised = TRUE;
1742   }
1743
1744   else if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_DONE) {
1745
1746     gboolean ret;
1747
1748     camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1749     camerasrc->requested_af_mode = AF_OFF_REQUESTED;
1750     camerasrc->capture_mode = GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER;
1751     GST_DEBUG_OBJECT (camerasrc, "capture done. switching to viewfinder");
1752
1753     /* Set the normal viewfinder resolution back */
1754     if (camerasrc->vf_caps) {
1755       GST_DEBUG_OBJECT (camerasrc, "set VF caps");
1756       ret = gst_pad_set_caps (GST_BASE_SRC_PAD (camerasrc), camerasrc->vf_caps);
1757       gst_caps_unref (camerasrc->vf_caps);
1758       camerasrc->vf_caps = NULL;
1759     } else {
1760       GstCaps *tmp;
1761
1762       tmp = gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1763
1764       /* Reconfigure the device to run viewfinder again */
1765       ret = gst_camerasrc_configure_device (camerasrc, &camerasrc->current_w,
1766           &camerasrc->current_h, &camerasrc->current_fourcc, &camerasrc->fps_n,
1767           &camerasrc->fps_d, tmp);
1768
1769       gst_caps_unref (tmp);
1770     }
1771
1772     if (!ret) {
1773       GST_WARNING_OBJECT (camerasrc, "Reinitializing viewfinder failed");
1774       g_mutex_unlock (camerasrc->state_lock);
1775       return GST_FLOW_ERROR;
1776     }
1777
1778     GST_DEBUG_OBJECT (camerasrc, "viewfinder running");
1779   }
1780
1781   g_mutex_lock (camerasrc->af_lock);
1782
1783   /* Handle AF requests only in VIEWFINDER and AUTOFOCUS states */
1784   if ((camerasrc->photo_capture_phase == GST_CAMERA_VIEWFINDER ||
1785           camerasrc->photo_capture_phase == GST_CAMERA_AUTOFOCUS ||
1786           camerasrc->photo_capture_phase == GST_CAMERA_AUTOFOCUS_DONE) &&
1787       camerasrc->requested_af_mode != AF_NONE_REQUESTED) {
1788     if (camerasrc->requested_af_mode == AF_ON_REQUESTED) {
1789       gboolean ret;
1790
1791       /* In still capture mode AE will be locked during AF operation */
1792       if (camerasrc->viewfinder_mode == GST_CAMERA_SRC_VIEWFINDER_MODE_STILL) {
1793         bclass->set_autoexposure (camerasrc, FALSE);
1794       }
1795       ret = bclass->set_autofocus (camerasrc, TRUE);
1796
1797       if (ret) {
1798         camerasrc->photo_capture_phase = GST_CAMERA_AUTOFOCUS;
1799       } else {
1800         /* Starting AF failed, so start AE again */
1801         bclass->set_autoexposure (camerasrc, TRUE);
1802       }
1803     } else {
1804       bclass->set_autofocus (camerasrc, FALSE);
1805       bclass->set_autoexposure (camerasrc, TRUE);
1806       camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1807     }
1808
1809     camerasrc->requested_af_mode = AF_NONE_REQUESTED;
1810   }
1811
1812   g_mutex_unlock (camerasrc->af_lock);
1813   g_mutex_unlock (camerasrc->state_lock);
1814
1815   ret = bclass->grab_frame (camerasrc, &temp, camerasrc->photo_capture_phase);
1816
1817   g_mutex_lock (camerasrc->state_lock);
1818
1819   if (ret != GST_FLOW_OK) {
1820     /* _prepare_for_capture() may have interrupted frame grabbing. */
1821     if (ret == GST_FLOW_WRONG_STATE &&
1822         camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_START) {
1823       g_mutex_unlock (camerasrc->state_lock);
1824       ret = GST_FLOW_OK;
1825       goto start_over;
1826     } else {
1827       g_mutex_unlock (camerasrc->state_lock);
1828       goto leave;
1829     }
1830   }
1831
1832   *buf = temp;
1833
1834   /* Post-capture phase */
1835
1836   if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE) {
1837     GstCaps *src_caps;
1838
1839     src_caps = gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1840     gst_buffer_set_caps (*buf, src_caps);
1841     gst_caps_unref (src_caps);
1842
1843     /* Restore the original number of buffers after capture is done */
1844     /* FIXME: Commented out */
1845 //     camerasrc->num_buffers = tmp_num_buffers;
1846
1847 //    gst_camerasrc_send_image_tags (camerasrc);
1848
1849     gst_camerasrc_send_preview (camerasrc);
1850
1851     camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_DONE;
1852   }
1853
1854   if(GST_CAMERA_SRC_CAPTURE_MODE_STILL == camerasrc->capture_mode) {
1855     gst_camerasrc_send_image_tags (camerasrc);
1856     if ((camerasrc->signal_still_capture == TRUE) && (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_DONE)  && (still_capture_initialised == TRUE)) {
1857       still_capture_initialised = FALSE;
1858       /*call signal*/
1859       /* alloc buffer for capture callback */
1860       buf_cap_signal1 = gst_buffer_new ();
1861
1862       GST_BUFFER_DATA(buf_cap_signal1) = GST_BUFFER_DATA(*buf);
1863       GST_BUFFER_SIZE(buf_cap_signal1) = GST_BUFFER_SIZE(*buf);
1864       GST_BUFFER_CAPS(buf_cap_signal1) = gst_caps_new_simple("video/x-raw-yuv",
1865                                        "format", GST_TYPE_FOURCC, camerasrc->capture_fourcc,
1866                                        "width", G_TYPE_INT,  camerasrc->capture_w,
1867                                        "height", G_TYPE_INT,camerasrc->capture_h,
1868                                         NULL);
1869
1870       GST_LOG_OBJECT (camerasrc, "CALL: capture callback");
1871       g_mutex_unlock (camerasrc->state_lock);
1872       g_signal_emit( G_OBJECT (camerasrc),
1873                gst_camerasrc_signals[SIGNAL_STILL_CAPTURE],
1874                0,
1875                buf_cap_signal1,
1876                NULL,
1877                NULL );
1878       GST_LOG_OBJECT (camerasrc, "RETURN: capture callback");
1879       g_mutex_lock (camerasrc->state_lock);
1880
1881
1882        if(--camerasrc->capture_counter > 0) {
1883           camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_START;
1884           GST_DEBUG_OBJECT (camerasrc, "do some more captures count %d",camerasrc->capture_counter);
1885        }
1886        else
1887           camerasrc->photo_capture_phase =  GST_CAMERA_CAPTURE_DONE;
1888
1889       g_mutex_unlock (camerasrc->state_lock);
1890       goto start_over;
1891     }
1892   }
1893
1894   if (GST_BUFFER_TIMESTAMP (*buf) == GST_CLOCK_TIME_NONE) {
1895     gst_camerasrc_apply_timestamp (camerasrc, *buf);
1896   }
1897
1898 done:
1899
1900   g_mutex_unlock (camerasrc->state_lock);
1901
1902 leave:
1903   return ret;
1904
1905   /* ERRORS */
1906 hq_capture_failed:
1907   GST_ELEMENT_ERROR (camerasrc, RESOURCE, READ,
1908       ("Error during HQ capture"), (NULL));
1909   ret = GST_FLOW_ERROR;
1910   goto done;
1911 }
1912
1913
1914 static GstStateChangeReturn
1915 gst_camerasrc_change_state (GstElement * element, GstStateChange transition)
1916 {
1917   GstCameraSrcClass *bclass;
1918   GstCameraSrc *camerasrc;
1919   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1920
1921   camerasrc = GST_CAMERA_SRC_CAST (element);
1922   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1923
1924   GST_LOG_OBJECT (camerasrc, "State change: %s -> %s",
1925       gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
1926       gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
1927
1928   switch (transition) {
1929     case GST_STATE_CHANGE_NULL_TO_READY:
1930       /* Open the device */
1931       if (!bclass->open (camerasrc))
1932         return GST_STATE_CHANGE_FAILURE;
1933       break;
1934     default:
1935       break;
1936   }
1937
1938   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1939
1940   switch (transition) {
1941     case GST_STATE_CHANGE_READY_TO_NULL:
1942       if (bclass->is_open (camerasrc)) {
1943         bclass->close (camerasrc);
1944       }
1945       camerasrc->capture_w = camerasrc->preview_w = camerasrc->current_w = 0;
1946       camerasrc->capture_h = camerasrc->preview_h = camerasrc->current_h = 0;
1947       camerasrc->capture_fourcc = camerasrc->preview_fourcc = 0;
1948       camerasrc->current_fourcc = 0;
1949       camerasrc->fps_d = camerasrc->fps_n = 0;
1950       camerasrc->capture_resolution_set = FALSE;
1951       camerasrc->preview_resolution_set = FALSE;
1952
1953       /* Notify that preview caps have changed (to NULL) */
1954       g_object_notify (G_OBJECT (camerasrc),
1955           GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
1956
1957       break;
1958     default:
1959       break;
1960   }
1961
1962   return ret;
1963 }
1964
1965
1966 /**
1967  * gst_camerasrc_add_color_channel:
1968  * @camsrc: #GstCameraSrc object.
1969  * @channel: #GstColorBalanceChannel object.
1970  *
1971  * Add a new color channel to list.
1972  */
1973 void
1974 gst_camerasrc_add_color_channel (GstCameraSrc * camsrc,
1975     GstColorBalanceChannel * channel)
1976 {
1977   camsrc->colors = g_list_append (camsrc->colors, (gpointer) channel);
1978 }
1979
1980
1981 /**
1982  * gst_camerasrc_clear_color_channels:
1983  * @camsrc: #GstCameraSrc object.
1984  *
1985  * Delete all color channels.
1986  */
1987 void
1988 gst_camerasrc_clear_color_channels (GstCameraSrc * camsrc)
1989 {
1990   g_list_foreach (camsrc->colors, (GFunc) g_object_unref, NULL);
1991   g_list_free (camsrc->colors);
1992   camsrc->colors = NULL;
1993 }
1994
1995 /**
1996  * gst_camerasrc_add_cameracontrol_channel:
1997  * @camsrc: #GstCameraSrc object.
1998  * @channel: #GstColorBalanceChannel object.
1999  *
2000  * Add a new cameracontrol channel to list.
2001  */
2002 void
2003 gst_camerasrc_add_cameracontrol_channel (GstCameraSrc * camsrc,
2004     GstCameraControlChannel * channel)
2005 {
2006   camsrc->camera_controls = g_list_append (camsrc->camera_controls, (gpointer) channel);
2007 }
2008
2009 /**
2010  * gst_camerasrc_clear_cameracontrol_channels:
2011  * @camsrc: #GstCameraSrc object.
2012  *
2013  * Delete all cameracontrol channels.
2014  */
2015
2016 void
2017 gst_camerasrc_clear_cameracontrol_channels (GstCameraSrc * camsrc)
2018 {
2019   g_list_foreach (camsrc->camera_controls, (GFunc) g_object_unref, NULL);
2020   g_list_free (camsrc->camera_controls);
2021   camsrc->camera_controls = NULL;
2022 }
2023
2024 /**
2025  * gst_camerasrc_send_capture_start_message:
2026  * @camsrc: GstCameraSrc object
2027  *
2028  * Sends a GstMessage notification to GstBus that capture operation is
2029  * about to start.
2030  */
2031 void
2032 gst_camerasrc_send_capture_start_message (GstCameraSrc * camsrc)
2033 {
2034   GstStructure *s;
2035   GstMessage *msg;
2036
2037   GST_DEBUG_OBJECT (camsrc, "Sending capture-start message");
2038
2039   /* Send custom GstMessage "photo-capture-start" */
2040   s = gst_structure_new (GST_CAMERA_SRC_CAPTURE_START, NULL);
2041   msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2042
2043   if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2044     GST_WARNING ("This element has no bus, therefore no message sent!");
2045   }
2046
2047   GST_LOG_OBJECT (camsrc, "Capture-start message sent");
2048 }
2049
2050
2051 /**
2052  * gst_camerasrc_send_capture_stop_message:
2053  * @camsrc: GstCameraSrc object
2054  *
2055  * Sends a GstMessage notification to GstBus that capture operation has
2056  * just finished.
2057  */
2058 void
2059 gst_camerasrc_send_capture_stop_message (GstCameraSrc * camsrc)
2060 {
2061   GstStructure *s;
2062   GstMessage *msg;
2063
2064   GST_DEBUG_OBJECT (camsrc, "Sending capture-stop message");
2065
2066   /* Send custom GstMessage "photo-capture-end" */
2067   s = gst_structure_new (GST_CAMERA_SRC_CAPTURE_END, NULL);
2068   msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2069
2070   if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2071     GST_WARNING ("This element has no bus, therefore no message sent!");
2072   }
2073
2074   GST_LOG_OBJECT (camsrc, "Capture-stop message sent");
2075 }
2076
2077
2078 /**
2079  * gst_camerasrc_af_update:
2080  * @camsrc: #GstCameraSrc object.
2081  * @fs: #GstCameraFocusStatus structure. Owned by caller.
2082  *
2083  * Tell GstCameraSrc that previously started autofocus operation has finished.
2084  */
2085 void
2086 gst_camerasrc_af_update (GstCameraSrc * camsrc, GstCameraFocusStatus * fs)
2087 {
2088   GstCameraSrcClass *bclass;
2089
2090   bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
2091
2092   g_mutex_lock (camsrc->state_lock);
2093   g_mutex_lock (camsrc->af_lock);
2094
2095   if (fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS ||
2096       fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL) {
2097     GstStructure *s;
2098     GstMessage *msg;
2099
2100     GST_DEBUG_OBJECT (camsrc, "autofocusing ended");
2101
2102     /* Send custom GstMessage "autofocus-done" */
2103     s = gst_structure_new (GST_PHOTOGRAPHY_AUTOFOCUS_DONE,
2104         "status", G_TYPE_INT, fs->status, NULL);
2105
2106     /* If autofocus succeeded, send the bitmask that defines focused
2107      * windows too */
2108     if (fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS) {
2109       GArray *windows;
2110       guint i;
2111
2112       windows = g_array_new (FALSE, FALSE, sizeof (gint));
2113       for (i = 0; i < fs->num_windows; i++) {
2114         GST_DEBUG_OBJECT (camsrc, "focus window: %d", fs->windows[i]);
2115         g_array_append_val (windows, fs->windows[i]);
2116       }
2117
2118       gst_structure_set (s,
2119           //"focus-windows", G_TYPE_ARRAY, windows,
2120           "focus-window-rows", G_TYPE_INT, fs->focus_rows,
2121           "focus-window-columns", G_TYPE_INT, fs->focus_columns,
2122           "focus-window-coverage", G_TYPE_INT, fs->coverage, NULL);
2123
2124       GST_DEBUG_OBJECT (camsrc, "focus rows: %d", fs->focus_rows);
2125       GST_DEBUG_OBJECT (camsrc, "focus columns: %d", fs->focus_columns);
2126       GST_DEBUG_OBJECT (camsrc, "focus coverage: %d", fs->coverage);
2127     }
2128
2129     msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2130
2131     if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2132       GST_WARNING ("This element has no bus, therefore no message sent!");
2133     }
2134
2135     /* In still capture mode we don't turn off AF algorithm yet, since it  */
2136     /* would enable CAF. Instead, it is turned off when application        */
2137     /* explicitly calls set_autofocus (FALSE), which in turn raises        */
2138     /* af_requested = OFF flag and AF is finally stopped.                  */
2139
2140     /* In video capture mode AF will be stopped immediately to enable AE   */
2141     if (camsrc->viewfinder_mode == GST_CAMERA_SRC_VIEWFINDER_MODE_VIDEO) {
2142       bclass->set_autofocus (camsrc, FALSE);
2143     }
2144
2145     /* We don't turn on autoexposure here either. This way AE stays        */
2146     /* "locked" until application explicitly calls set_autofocus (FALSE).  */
2147
2148     camsrc->photo_capture_phase = GST_CAMERA_AUTOFOCUS_DONE;
2149   }
2150
2151   g_mutex_unlock (camsrc->af_lock);
2152   g_mutex_unlock (camsrc->state_lock);
2153 }
2154
2155
2156 /**
2157  * gst_camerasrc_caf_update:
2158  * @camsrc: GstCameraSrc object.
2159  * @fs: #GstCameraFocusStatus structure. Owned by caller.
2160  *
2161  * Tell GstCameraSrc that continuous autofocus algorithm has changed its state.
2162  * Sends a GstMessage notification to GstBus indicating a change in
2163  * continuous autofocus status.
2164  */
2165 void
2166 gst_camerasrc_caf_update (GstCameraSrc * camsrc, GstCameraFocusStatus * fs)
2167 {
2168   GstStructure *s;
2169   GstMessage *msg;
2170
2171   GST_DEBUG_OBJECT (camsrc, "Sending CAF status: %d", fs->status);
2172
2173   /* Send custom GstMessage "caf-update" */
2174   s = gst_structure_new (GST_CAMERA_SRC_CAF_STATUS, NULL);
2175   gst_structure_set (s, "status", G_TYPE_INT, fs->status, NULL);
2176   msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2177
2178   if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2179     GST_WARNING ("This element has no bus, therefore no message sent!");
2180   }
2181
2182   GST_LOG_OBJECT (camsrc, "CAF update message sent");
2183 }
2184
2185
2186 /**
2187  * gst_camerasrc_shake_update:
2188  * @camsrc: GstCameraSrc object.
2189  * @risk: GstPhotoShakeRisk value.
2190  *
2191  * Tell GstCameraSrc that shake risk has changed. Sends a GstMessage
2192  * notification to GstBus indicating a change in shake risk status.
2193  */
2194 void
2195 gst_camerasrc_shake_update (GstCameraSrc * camsrc, GstPhotoShakeRisk risk)
2196 {
2197   GstStructure *s;
2198   GstMessage *msg;
2199
2200   GST_DEBUG_OBJECT (camsrc, "Sending shake risk update: %d", risk);
2201
2202   /* Send custom GstMessage telling the changed shake risk level */
2203   s = gst_structure_new (GST_PHOTOGRAPHY_SHAKE_RISK, NULL);
2204   gst_structure_set (s, "shake_risk", G_TYPE_INT, risk, NULL);
2205   msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2206
2207   if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2208     GST_WARNING ("This element has no bus, therefore no message sent!");
2209   }
2210
2211   GST_LOG_OBJECT (camsrc, "Shake indicator message sent");
2212 }
2213
2214
2215 /* Tag helper functions */
2216
2217 /**
2218  * gst_camerasrc_exposure_mode_from_exif_value:
2219  * @value: exposure mode in EXIF format.
2220  *
2221  * Convert exposure mode to string.
2222  *
2223  * Returns: String representation of the scene capture type, or NULL if invalid
2224  * value was given. Possible values: "auto-exposure", "manual-exposure" and
2225  * "auto-bracket".
2226  */
2227 const gchar *
2228 gst_camerasrc_exposure_mode_from_exif_value (gint value)
2229 {
2230   switch (value) {
2231     case 0:
2232       return "auto-exposure";
2233     case 1:
2234       return "manual-exposure";
2235     case 2:
2236       return "auto-bracket";
2237     default:
2238       GST_WARNING ("Invalid exif exposure mode: %d", value);
2239       return NULL;
2240   }
2241 }
2242
2243 /**
2244  * gst_camerasrc_scene_capture_type_from_exif_value:
2245  * @value: scene capture type in EXIF format.
2246  *
2247  * Convert scene capture type to string.
2248  *
2249  * Returns: String representation of the scene capture type, or NULL if invalid
2250  * value was given. Possible values: "standard", "landscape", "portrait" and
2251  * "night-scene".
2252  */
2253 const gchar *
2254 gst_camerasrc_scene_capture_type_from_exif_value (gint value)
2255 {
2256   switch (value) {
2257     case 0:
2258       return "standard";
2259     case 1:
2260       return "landscape";
2261     case 2:
2262       return "portrait";
2263     case 3:
2264       return "night-scene";
2265     default:
2266       GST_WARNING ("Invalid exif scene capture type: %d", value);
2267       return NULL;
2268   }
2269 }
2270
2271
2272 /**
2273  * gst_camerasrc_gain_adjustment_from_exif_value:
2274  * @value: gain adjustment type in EXIF format.
2275  *
2276  * Convert gain adjustment type to string.
2277  *
2278  * Returns: String representation of the gain adjustment type, or NULL if
2279  * invalid value was given. Possible values: "none", "low-gain-up",
2280  * "high-gain-up", "low-gain-down" and "high-gain-down".
2281  */
2282 const gchar *
2283 gst_camerasrc_gain_adjustment_from_exif_value (gint value)
2284 {
2285   switch (value) {
2286     case 0:
2287       return "none";
2288     case 1:
2289       return "low-gain-up";
2290     case 2:
2291       return "high-gain-up";
2292     case 3:
2293       return "low-gain-down";
2294     case 4:
2295       return "high-gain-down";
2296     default:
2297       GST_WARNING ("Invalid exif gain control type: %d", value);
2298       return NULL;
2299   }
2300 }
2301
2302
2303 /**
2304  * gst_camerasrc_contrast_from_exif_value:
2305  * @value: contrast type in EXIF format.
2306  *
2307  * Convert contrast type to string.
2308  *
2309  * Returns: String representation of the contrast type, or NULL if invalid
2310  * value was given. Possible values: "normal", "soft" and "hard".
2311  */
2312 const gchar *
2313 gst_camerasrc_contrast_from_exif_value (gint value)
2314 {
2315   switch (value) {
2316     case 0:
2317       return "normal";
2318     case 1:
2319       return "soft";
2320     case 2:
2321       return "hard";
2322     default:
2323       GST_WARNING ("Invalid contrast type: %d", value);
2324       return NULL;
2325   }
2326 }
2327
2328
2329 /**
2330  * gst_camerasrc_saturation_from_exif_value:
2331  * @value: saturation type in EXIF format.
2332  *
2333  * Convert saturation type to string.
2334  *
2335  * Returns: String representation of the saturation type, or NULL if invalid
2336  * value was given. Possible values: "normal", "low-saturation" and
2337  * "high-saturation".
2338  */
2339 const gchar *
2340 gst_camerasrc_saturation_from_exif_value (gint value)
2341 {
2342   switch (value) {
2343     case 0:
2344       return "normal";
2345     case 1:
2346       return "low-saturation";
2347     case 2:
2348       return "high-saturation";
2349     default:
2350       GST_WARNING ("Invalid saturation type: %d", value);
2351       return NULL;
2352   }
2353 }
2354
2355
2356 /**
2357  * gst_camerasrc_flash_mode_from_exif_value:
2358  * @value: flash EXIF field
2359  *
2360  * Convert "flash" EXIF field into text string.
2361  *
2362  * Returns: String representation of the flash mode, or NULL if invalid
2363  * value was given. Possible values: "always", "never" and "auto".
2364  */
2365 const gchar *
2366 gst_camerasrc_flash_mode_from_exif_value (gint value)
2367 {
2368   // frame_info_t
2369
2370   // bits 3 and 4 indicate the flash mode,
2371   //
2372   // Values for bits 3 and 4 indicating the camera's flash mode.
2373   // 00b              =   unknown
2374   // 01b              =   Compulsory flash firing
2375   // 10b              =   Compulsory flash suppression
2376   // 11b              =   Auto mode
2377   //
2378
2379   /* Bit numbering in EXIF spec starts from 0 */
2380   value >>= 3;
2381
2382   switch (value & 0x3) {
2383     case 1:
2384       return "always";
2385     case 2:
2386       return "never";
2387     case 3:
2388       return "auto";
2389     default:
2390       GST_WARNING ("Invalid flash mode type: %d", value);
2391       return NULL;
2392   }
2393 }
2394
2395
2396 /**
2397  * gst_camerasrc_sharpness_from_exif_value:
2398  * @value: sharpness type in EXIF format.
2399  *
2400  * Convert sharpness type to string.
2401  *
2402  * Returns: String representation of the sharpness type, or NULL if invalid
2403  * value was given. Possible values: "normal", "soft" and "hard".
2404  */
2405 const gchar *
2406 gst_camerasrc_sharpness_from_exif_value (gint value)
2407 {
2408   switch (value) {
2409     case 0:
2410       return "normal";
2411     case 1:
2412       return "soft";
2413     case 2:
2414       return "hard";
2415     default:
2416       GST_WARNING ("Invalid sharpness type: %d", value);
2417       return NULL;
2418   }
2419 }
2420
2421
2422 /**
2423  * gst_camerasrc_metering_mode_from_exif_value:
2424  * @value: metering mode type in EXIF format.
2425  *
2426  * Convert metering mode type to string.
2427  *
2428  * Returns: String representation of the metering mode type, or NULL if invalid
2429  * value was given. Possible values: "unknown", "average",
2430  * "center-weighted-average", "spot", "multi-spot", "pattern", "partial" and
2431  * "other".
2432  */
2433 const gchar *
2434 gst_camerasrc_metering_mode_from_exif_value (gint value)
2435 {
2436   switch (value) {
2437     case 0:
2438       return "unknown";
2439     case 1:
2440       return "average";
2441     case 2:
2442       return "center-weighted-average";
2443     case 3:
2444       return "spot";
2445     case 4:
2446       return "multi-spot";
2447     case 5:
2448       return "pattern";
2449     case 6:
2450       return "partial";
2451     case 255:
2452       return "other";
2453     default:
2454       GST_WARNING ("Invalid metering mode type: %d", value);
2455       return NULL;
2456   }
2457 }
2458
2459
2460 /**
2461  * gst_camerasrc_file_source_from_exif_value:
2462  * @value: FileSource type in EXIF format.
2463  *
2464  * Convert FileSource type to string.
2465  *
2466  * Returns: String representation of the FileSource type, or NULL if invalid
2467  * value was given. Possible values: "dsc", "transparent-scanner",
2468  * "reflex-scanner" and "other".
2469  */
2470 const gchar *
2471 gst_camerasrc_file_source_from_exif_value (gint value)
2472 {
2473   switch (value) {
2474     case 0:
2475       return "other";
2476     case 1:
2477       return "transparent-scanner";
2478     case 2:
2479       return "reflex-scanner";
2480     case 3:
2481       return "dsc";
2482     default:
2483       GST_WARNING ("Invalid file source type: %d", value);
2484       return NULL;
2485   }
2486 }
2487
2488
2489 /* Default implementations for vmethods */
2490
2491 static GstPhotoCaps
2492 gst_camerasrc_default_capabilities (GstCameraSrc * camsrc)
2493 {
2494   return GST_PHOTOGRAPHY_CAPS_NONE;
2495 }
2496
2497 static gboolean
2498 gst_camerasrc_default_ret_true_with_settings (GstCameraSrc * camsrc,
2499     GstPhotoSettings * photoconf)
2500 {
2501   return TRUE;
2502 }
2503
2504 static gboolean
2505 gst_camerasrc_default_write_settings (GstCameraSrc * camsrc,
2506     GstPhotoSettings * photoconf, gboolean scene_mode_override)
2507 {
2508   return TRUE;
2509 }
2510
2511 static gboolean
2512 gst_camerasrc_default_set_onoff (GstCameraSrc * camsrc, gboolean on_off)
2513 {
2514   return TRUE;
2515 }
2516
2517 static GstCaps *
2518 gst_camerasrc_default_get_caps (GstCameraSrc * camsrc, GstOperationMode mode)
2519 {
2520   GST_DEBUG_OBJECT (camsrc, "Returning NULL caps for mode %d", mode);
2521
2522   return NULL;
2523 }
2524 static gboolean
2525 gst_camerasrc_default_read_exif (GstCameraSrc *camsrc,
2526     GstCameraControlExifInfo *exif_info)
2527 {
2528   GST_DEBUG_OBJECT (camsrc, "default implementation of exif read called return defaults  %d");
2529   // TODO: fill with default values
2530   return TRUE;
2531 }
2532
2533 static gboolean
2534 gst_camerasrc_default_set_flash_mode (GstCameraSrc *camsrc, int value)
2535 {
2536   return TRUE;
2537 }
2538
2539 static void
2540 gst_camerasrc_default_functions_init (GstCameraSrcClass * camera_class)
2541 {
2542   camera_class->get_capabilities = gst_camerasrc_default_capabilities;
2543   camera_class->set_autofocus = gst_camerasrc_default_set_onoff;
2544   camera_class->set_autoexposure = gst_camerasrc_default_set_onoff;
2545   camera_class->read_settings = gst_camerasrc_default_ret_true_with_settings;
2546   camera_class->write_settings = gst_camerasrc_default_write_settings;
2547   camera_class->get_supported_caps = gst_camerasrc_default_get_caps;
2548   camera_class->set_flash_mode = gst_camerasrc_default_set_flash_mode;
2549   camera_class->read_exif = gst_camerasrc_default_read_exif;
2550
2551   GST_DEBUG ("Default functions set");
2552 }
2553
2554
2555 static gboolean
2556 gst_camerasrc_handle_event (GstCameraSrc * camerasrc, GstEvent * event)
2557 {
2558   GstCameraSrcClass *bclass;
2559   gboolean ret = FALSE;
2560
2561   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
2562   GST_LOG_OBJECT (camerasrc, "handling %s event", GST_EVENT_TYPE_NAME (event));
2563
2564   if (bclass->event) {
2565     ret = bclass->event (camerasrc, event);
2566   }
2567
2568   return ret;
2569 }
2570
2571
2572 /*
2573  * gst_camerasrc_send_event:
2574  * @element: GstElement object.
2575  * @event: GstEvent to be handled.
2576  *
2577  * Returns: TRUE if the event was handled.
2578  */
2579 static gboolean
2580 gst_camerasrc_send_event (GstElement * element, GstEvent * event)
2581 {
2582   GstCameraSrc *camerasrc;
2583   gboolean ret = FALSE;
2584
2585   camerasrc = GST_CAMERA_SRC_CAST (element);
2586
2587   GST_LOG_OBJECT (camerasrc, "got %s event", GST_EVENT_TYPE_NAME (event));
2588
2589   switch (GST_EVENT_TYPE (event)) {
2590     case GST_EVENT_CUSTOM_UPSTREAM:
2591       ret = gst_camerasrc_handle_event (camerasrc, event);
2592       break;
2593     default:
2594       break;
2595   }
2596
2597   if (!ret) {
2598     ret = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
2599   }
2600
2601   return ret;
2602 }
2603
2604
2605 /*
2606  * gst_camerasrc_event:
2607  * @src: #GstBaseSrc object.
2608  * @event: #GetEvent object.
2609  *
2610  * Returns: TRUE of the event was handled.
2611  */
2612 static gboolean
2613 gst_camerasrc_event (GstBaseSrc * src, GstEvent * event)
2614 {
2615   GstCameraSrc *camerasrc;
2616   gboolean ret;
2617
2618   camerasrc = GST_CAMERA_SRC_CAST (src);
2619   ret = gst_camerasrc_handle_event (camerasrc, event);
2620
2621   if (!ret) {
2622     ret = GST_BASE_SRC_CLASS (parent_class)->event (src, event);
2623   }
2624
2625   return ret;
2626 }
2627
2628
2629 /**
2630  * gst_camerasrc_update_max_zoom:
2631  * @camerasrc: #GstCameraSrc object.
2632  *
2633  * Check and update zoom property maximum value.
2634  */
2635 static void
2636 gst_camerasrc_update_max_zoom (GstCameraSrc * camerasrc)
2637 {
2638   GstCameraSrcClass *bclass;
2639   GObjectClass *oclass;
2640   GParamSpec *pspec;
2641   GParamSpecFloat *pspec_f;
2642   gfloat maxzoom = 10.0;
2643
2644   oclass = G_OBJECT_GET_CLASS (camerasrc);
2645   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
2646   pspec = g_object_class_find_property (oclass, "zoom");
2647
2648   if (bclass->get_max_zoom) {
2649     if (!bclass->get_max_zoom (camerasrc, &maxzoom)) {
2650       maxzoom = 10.0;
2651     }
2652   }
2653
2654   /* Update gobject property */
2655   if (pspec && (G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_FLOAT)) {
2656     pspec_f = G_PARAM_SPEC_FLOAT (pspec);
2657     pspec_f->maximum = maxzoom;
2658     GST_DEBUG_OBJECT (camerasrc, "set maximum zoom as %f", pspec_f->maximum);
2659     /* Check if new maximum zoom is lower than current zoom level */
2660     if (pspec_f->maximum < camerasrc->photoconf.zoom) {
2661       GST_DEBUG_OBJECT (camerasrc, "current zoom level too high: %f",
2662           camerasrc->photoconf.zoom);
2663       g_object_set (G_OBJECT (camerasrc), "zoom", pspec_f->maximum, NULL);
2664     }
2665   } else {
2666     GST_WARNING_OBJECT (camerasrc, "updating maximum zoom failed");
2667   }
2668 }