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