buffer-sharing: align small resolution stride to 32
[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     if (gst_structure_has_name(structure, "video/x-vaapi-sharing")) {
894         gint stride = 0;
895         gst_structure_get_int(structure, "width", &stride);
896         /* row stride need width aligned to 32*/
897         stride = ((stride+31)&(~31));
898         gst_structure_set (structure, "row-stride", G_TYPE_INT, stride, NULL);
899     }
900   }
901
902   GST_DEBUG_OBJECT (basesrc, "fixated caps %" GST_PTR_FORMAT, caps);
903 }
904
905 /*
906  */
907 static gboolean
908 gst_camerasrc_negotiate (GstBaseSrc * basesrc)
909 {
910   GstCaps *thiscaps;
911
912   GstCaps *caps = NULL;
913
914   GstCaps *peercaps = NULL;
915
916   gboolean result = FALSE;
917
918   /* first see what is possible on our source pad */
919   thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
920   GST_DEBUG_OBJECT (basesrc, "caps of src suppressed on DEBUG (>= 5 to see)");
921   GST_LOG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
922   /* nothing or anything is allowed, we're done */
923   if (thiscaps == NULL || gst_caps_is_any (thiscaps))
924     goto no_nego_needed;
925
926   /* get the peer caps */
927   peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
928   GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
929   if (peercaps && !gst_caps_is_any (peercaps)) {
930     GstCaps *icaps = NULL;
931     int i;
932
933     /* Prefer the first caps we are compatible with that the peer proposed */
934     for (i = 0; i < gst_caps_get_size (peercaps); i++) {
935       /* get intersection */
936       GstCaps *ipcaps = gst_caps_copy_nth (peercaps, i);
937
938       GST_DEBUG_OBJECT (basesrc, "peer: %" GST_PTR_FORMAT, ipcaps);
939
940       icaps = gst_caps_intersect (thiscaps, ipcaps);
941       gst_caps_unref (ipcaps);
942
943       if (!gst_caps_is_empty (icaps))
944         break;
945
946       gst_caps_unref (icaps);
947       icaps = NULL;
948     }
949
950     GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, icaps);
951     if (icaps) {
952       /* If there are multiple intersections pick the one with the smallest
953        * resolution strictly bigger then the first peer caps */
954       if (gst_caps_get_size (icaps) > 1) {
955         GstStructure *s = gst_caps_get_structure (peercaps, 0);
956
957         int best = 0;
958
959         int twidth, theight;
960
961         int width = G_MAXINT, height = G_MAXINT;
962
963         if (gst_structure_get_int (s, "width", &twidth)
964             && gst_structure_get_int (s, "height", &theight)) {
965
966           /* Walk the structure backwards to get the first entry of the
967            * smallest resolution bigger (or equal to) the preferred resolution)
968            */
969           for (i = gst_caps_get_size (icaps) - 1; i >= 0; i--) {
970             GstStructure *is = gst_caps_get_structure (icaps, i);
971
972             int w, h;
973
974             if (gst_structure_get_int (is, "width", &w)
975                 && gst_structure_get_int (is, "height", &h)) {
976               if (w >= twidth && w <= width && h >= theight && h <= height) {
977                 width = w;
978                 height = h;
979                 best = i;
980               }
981             }
982           }
983         }
984
985         caps = gst_caps_copy_nth (icaps, best);
986         gst_caps_unref (icaps);
987       } else {
988         caps = icaps;
989       }
990     }
991     gst_caps_unref (thiscaps);
992     gst_caps_unref (peercaps);
993   } else {
994     /* no peer or peer have ANY caps, work with our own caps then */
995     caps = thiscaps;
996   }
997   if (caps) {
998     caps = gst_caps_make_writable (caps);
999     gst_caps_truncate (caps);
1000
1001     /* now fixate */
1002     if (!gst_caps_is_empty (caps)) {
1003       GstStructure *s = gst_caps_get_structure (caps, 0);
1004       /* set row-stride for vaapi-sharing */
1005       if (s && gst_structure_has_name(s, "video/x-vaapi-sharing")) {
1006         if (!gst_structure_has_field(s, "row-stride")) {
1007             gst_structure_set (s, "row-stride", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL);
1008         }
1009       }
1010       gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
1011       GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
1012
1013       if (gst_caps_is_any (caps)) {
1014         /* hmm, still anything, so element can do anything and
1015          * nego is not needed */
1016         result = TRUE;
1017       } else if (gst_caps_is_fixed (caps)) {
1018         /* yay, fixed caps, use those then */
1019         result = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
1020         GST_DEBUG_OBJECT (basesrc, "Set caps returned: %d", result);
1021       }
1022     }
1023     gst_caps_unref (caps);
1024   }
1025   return result;
1026
1027 no_nego_needed:
1028   {
1029     GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
1030     if (thiscaps)
1031       gst_caps_unref (thiscaps);
1032     return TRUE;
1033   }
1034 }
1035
1036
1037 /*
1038  */
1039 static GstCaps *
1040 gst_camerasrc_get_caps (GstBaseSrc * src)
1041 {
1042   GstCameraSrc *camerasrc;
1043   GstCameraSrcClass *bclass;
1044
1045   camerasrc = GST_CAMERA_SRC_CAST (src);
1046   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1047
1048   if (!bclass->is_open (camerasrc) || !bclass->get_caps) {
1049     return gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
1050             (camerasrc)));
1051   }
1052
1053   return bclass->get_caps (camerasrc);
1054 }
1055
1056
1057 /**
1058  * gst_camerasrc_get_caps_info:
1059  * @caps: given input caps
1060  * @four_cc: location for the fourcc
1061  * @w/@h: location for width and height
1062  * @fps_n/@fps_d: location for framerate
1063  *
1064  * Collect data for the given caps.
1065  */
1066 static gboolean
1067 gst_camerasrc_get_caps_info (GstCameraSrc * camerasrc, GstCaps * caps,
1068     guint32 * four_cc, guint * w, guint * h, guint * fps_n, guint * fps_d,
1069     guint * size)
1070 {
1071   GstCameraSrcClass *bclass;
1072   GstStructure *structure;
1073   const GValue *framerate;
1074   const gchar *mimetype;
1075   guint32 fourcc;
1076   guint outsize;
1077
1078   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1079
1080   /* default unknown values */
1081   fourcc = 0;
1082   outsize = 0;
1083
1084   structure = gst_caps_get_structure (caps, 0);
1085
1086   mimetype = gst_structure_get_name (structure);
1087
1088   if (!gst_structure_get_int (structure, "width", (gint *) w))
1089     return FALSE;
1090
1091   if (!gst_structure_get_int (structure, "height", (gint *) h))
1092     return FALSE;
1093
1094   framerate = gst_structure_get_value (structure, "framerate");
1095   if (!framerate)
1096     return FALSE;
1097
1098   *fps_n = gst_value_get_fraction_numerator (framerate);
1099   *fps_d = gst_value_get_fraction_denominator (framerate);
1100
1101   if (!strcmp (mimetype, "video/x-vaapi-sharing")) {
1102     fourcc = V4L2_PIX_FMT_NV12;
1103     outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1104     outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1105   } else if (!strcmp (mimetype, "video/x-raw-yuv")) {
1106     gst_structure_get_fourcc (structure, "format", &fourcc);
1107
1108     switch (fourcc) {
1109       case GST_MAKE_FOURCC ('I', '4', '2', '0'):
1110       case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
1111         fourcc = V4L2_PIX_FMT_YUV420;
1112         outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1113         outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1114         break;
1115       case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
1116         fourcc = V4L2_PIX_FMT_YUYV;
1117         outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1118         break;
1119       case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
1120         fourcc = V4L2_PIX_FMT_Y41P;
1121         outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1122         break;
1123       case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
1124         fourcc = V4L2_PIX_FMT_UYVY;
1125         outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1126         break;
1127       case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
1128         fourcc = V4L2_PIX_FMT_YVU420;
1129         outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1130         outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
1131         break;
1132       case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
1133         fourcc = V4L2_PIX_FMT_YUV411P;
1134         outsize = GST_ROUND_UP_4 (*w) * *h;
1135         outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
1136         break;
1137       case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
1138         fourcc = V4L2_PIX_FMT_YUV422P;
1139         outsize = GST_ROUND_UP_4 (*w) * *h;
1140         outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
1141         break;
1142       case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
1143         fourcc = V4L2_PIX_FMT_NV12;
1144         outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1145         outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1146         break;
1147       case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
1148         fourcc = V4L2_PIX_FMT_NV21;
1149         outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
1150         outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
1151         break;
1152 #ifdef V4L2_PIX_FMT_YVYU
1153       case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
1154         fourcc = V4L2_PIX_FMT_YVYU;
1155         outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
1156         break;
1157 #endif
1158     }
1159   } else if (!strcmp (mimetype, "video/x-raw-rgb")) {
1160     gint depth, endianness, r_mask;
1161
1162     gst_structure_get_int (structure, "depth", &depth);
1163     gst_structure_get_int (structure, "endianness", &endianness);
1164     gst_structure_get_int (structure, "red_mask", &r_mask);
1165
1166     switch (depth) {
1167       case 8:
1168         fourcc = V4L2_PIX_FMT_RGB332;
1169         break;
1170       case 15:
1171         fourcc = (endianness == G_LITTLE_ENDIAN) ?
1172             V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X;
1173         break;
1174       case 16:
1175         fourcc = (endianness == G_LITTLE_ENDIAN) ?
1176             V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X;
1177         break;
1178       case 24:
1179         fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24;
1180         break;
1181       case 32:
1182         fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32;
1183         break;
1184     }
1185   } else if (strcmp (mimetype, "video/x-raw-bayer") == 0) {
1186     gst_structure_get_fourcc (structure, "format", &fourcc);
1187     switch (fourcc) {
1188       case GST_MAKE_FOURCC ('B', 'A', '8', '1'):
1189         fourcc = V4L2_PIX_FMT_SBGGR8;
1190         break;
1191       case GST_MAKE_FOURCC ('G', 'B', 'R', 'G'):
1192         fourcc = V4L2_PIX_FMT_SGBRG8;
1193         break;
1194       case GST_MAKE_FOURCC ('G', 'R', 'B', 'G'):
1195         fourcc = V4L2_PIX_FMT_SGRBG8;
1196         break;
1197       case GST_MAKE_FOURCC ('R', 'G', 'G', 'B'):
1198         fourcc = V4L2_PIX_FMT_SRGGB8;
1199         break;
1200       case GST_MAKE_FOURCC ('B', 'G', '1', '0'):
1201         fourcc = V4L2_PIX_FMT_SBGGR10;
1202         break;
1203       case GST_MAKE_FOURCC ('G', 'B', '1', '0'):
1204         fourcc = V4L2_PIX_FMT_SGBRG10;
1205         break;
1206       case GST_MAKE_FOURCC ('B', 'A', '1', '0'):
1207         fourcc = V4L2_PIX_FMT_SGRBG10;
1208         break;
1209       case GST_MAKE_FOURCC ('R', 'G', '1', '0'):
1210         fourcc = V4L2_PIX_FMT_SRGGB10;
1211         break;
1212       case GST_MAKE_FOURCC ('B', 'Y', 'R', '2'):
1213         fourcc = V4L2_PIX_FMT_SBGGR16;
1214         break;
1215     }
1216   } else if (strcmp (mimetype, "video/x-raw-gray") == 0) {
1217     fourcc = V4L2_PIX_FMT_GREY;
1218   }
1219
1220   if (fourcc == 0)
1221     return FALSE;
1222
1223   *four_cc = fourcc;
1224
1225   return TRUE;
1226 }
1227
1228
1229 /**
1230  * gst_camerasrc_get_caps_from_info:
1231  * @camsrc: #GstCameraSrc object
1232  * @fourcc: fourcc code
1233  * @width: width to be set
1234  * @height: height to be set
1235  * @fps_n: FPS numerator to be set or 0
1236  * @fps_d: FPS denominator to be set or 0
1237  *
1238  * Converts given parameters into GstCaps structure.
1239  *
1240  * Returns: GstCaps representing the given values.
1241  */
1242 GstCaps *
1243 gst_camerasrc_get_caps_from_info (GstCameraSrc * camsrc, guint32 fourcc,
1244     guint width, guint height, guint fps_n, guint fps_d)
1245 {
1246   GstCaps *newcaps;
1247   GstStructure *s;
1248
1249   s = gst_structure_new ("video/x-raw-yuv",
1250       "format", GST_TYPE_FOURCC, fourcc,
1251       "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
1252
1253   if (fps_n != 0 && fps_d != 0) {
1254     gst_structure_set (s, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
1255   }
1256
1257   newcaps = gst_caps_new_empty ();
1258   gst_caps_append_structure (newcaps, s);
1259
1260   return newcaps;
1261 }
1262
1263
1264 /*
1265  */
1266 static gboolean
1267 gst_camerasrc_configure_device (GstCameraSrc * camerasrc, guint * w, guint * h,
1268     guint32 * fourcc, guint * fps_n, guint * fps_d, GstCaps * buffer_caps)
1269 {
1270   GstCameraSrcClass *bclass;
1271   GstOperationMode opmode;
1272
1273   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1274
1275   /* Stop the capturing */
1276   if (!bclass->stop (camerasrc))
1277     return FALSE;
1278
1279   GST_DEBUG_OBJECT (camerasrc, "trying to set_capture %dx%d at %d/%d fps",
1280       *w, *h, *fps_n, *fps_d);
1281
1282   if (bclass->set_vfinder_mode) {
1283     bclass->set_vfinder_mode (camerasrc, camerasrc->viewfinder_mode);
1284   }
1285   if (bclass->set_capture_mode) {
1286     bclass->set_capture_mode (camerasrc, camerasrc->capture_mode);
1287   }
1288
1289   opmode = camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE ?
1290       GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE :
1291       GST_PHOTOGRAPHY_OPERATION_MODE_VIEWFINDER;
1292
1293   if (!bclass->set_capture (camerasrc, opmode, FALSE, fourcc, w, h,
1294           fps_n, fps_d)) {
1295     GST_ELEMENT_ERROR (camerasrc, RESOURCE, SETTINGS,
1296         ("Failed configuring device for capturing"), (NULL));
1297     return FALSE;
1298   }
1299
1300   gst_camerasrc_update_max_zoom (camerasrc);
1301
1302   /* Only start the driver when not in HQ capture mode, since in HQ mode */
1303   /* we have already called start_capture() above */
1304
1305   if (!bclass->start (camerasrc, buffer_caps))
1306     return FALSE;
1307
1308   if (camerasrc->photo_capture_phase != GST_CAMERA_CAPTURE) {
1309
1310     if (!bclass->write_settings (camerasrc, &camerasrc->photoconf, FALSE)) {
1311       GST_ELEMENT_ERROR (camerasrc, RESOURCE, SETTINGS,
1312           ("Failed to configure driver module"), (NULL));
1313
1314       return FALSE;
1315     }
1316   }
1317
1318   return TRUE;
1319 }
1320
1321
1322 /*
1323  */
1324 static gboolean
1325 gst_camerasrc_init_from_caps (GstCameraSrc * camerasrc, GstCaps * caps)
1326 {
1327   guint w = 0, h = 0;
1328   guint32 fourcc;
1329   guint fps_n, fps_d;
1330   guint size;
1331   gboolean ret;
1332
1333   /* we want our own type of fourcc codes */
1334   if (!gst_camerasrc_get_caps_info (camerasrc, caps, &fourcc, &w, &h, &fps_n,
1335           &fps_d, &size)) {
1336     GST_DEBUG_OBJECT (camerasrc,
1337         "can't get capture format from caps %" GST_PTR_FORMAT, caps);
1338     return FALSE;
1339   }
1340
1341   ret = gst_camerasrc_configure_device (camerasrc, &w, &h, &fourcc,
1342       &fps_n, &fps_d, caps);
1343
1344   if (ret) {
1345     camerasrc->current_w = w;
1346     camerasrc->current_h = h;
1347     camerasrc->fps_n = fps_n;
1348     camerasrc->fps_d = fps_d;
1349     camerasrc->current_fourcc = fourcc;
1350
1351     camerasrc->duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
1352     GST_DEBUG_OBJECT (camerasrc, "Buffer duration: %" GST_TIME_FORMAT,
1353         GST_TIME_ARGS (camerasrc->duration));
1354
1355 //      camerasrc->frame_byte_size = size;
1356   }
1357
1358   return ret;
1359 }
1360
1361 /*
1362  */
1363 static gboolean
1364 gst_camerasrc_set_caps (GstBaseSrc * src, GstCaps * caps)
1365 {
1366   GstCameraSrc *camerasrc;
1367   GstCameraSrcClass *bclass;
1368
1369   camerasrc = GST_CAMERA_SRC_CAST (src);
1370   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1371
1372   GST_DEBUG_OBJECT (camerasrc, "set_caps called: %" GST_PTR_FORMAT, caps);
1373
1374   /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
1375   if (!bclass->is_open (camerasrc))
1376     return FALSE;
1377
1378   return gst_camerasrc_init_from_caps (camerasrc, caps);
1379 }
1380
1381 /*
1382  */
1383 static gboolean
1384 gst_camerasrc_query (GstBaseSrc * bsrc, GstQuery * query)
1385 {
1386   GstCameraSrc *src;
1387   GstCameraSrcClass *bclass;
1388   gboolean res = FALSE;
1389   guint num_buffers;
1390
1391   src = GST_CAMERA_SRC_CAST (bsrc);
1392   bclass = GST_CAMERA_SRC_GET_CLASS (src);
1393
1394   switch (GST_QUERY_TYPE (query)) {
1395     case GST_QUERY_LATENCY:{
1396       GstClockTime max_latency;
1397
1398       /* device must be open */
1399       if (!bclass->is_open (src)) {
1400         GST_WARNING_OBJECT (src,
1401             "Can't give latency since device isn't open !");
1402         goto done;
1403       }
1404
1405       /* we must have a framerate */
1406       if (src->fps_n <= 0 || src->fps_d <= 0) {
1407         GST_WARNING_OBJECT (src,
1408             "Can't give latency since framerate isn't fixated !");
1409         goto done;
1410       }
1411
1412       num_buffers = bclass->get_num_buffers (src);
1413       /* max latency is total duration of the frame buffer */
1414       max_latency = num_buffers * src->duration;
1415
1416       GST_DEBUG_OBJECT (bsrc,
1417           "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
1418           GST_TIME_ARGS (src->duration), GST_TIME_ARGS (max_latency));
1419
1420       /* we are always live, the min latency is 1 frame and the max latency is
1421        * the complete buffer of frames. */
1422       gst_query_set_latency (query, TRUE, src->duration, max_latency);
1423
1424       res = TRUE;
1425       break;
1426     }
1427     default:
1428       res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
1429       break;
1430   }
1431
1432 done:
1433
1434   return res;
1435 }
1436
1437 static gboolean
1438 gst_camerasrc_start (GstBaseSrc * src)
1439 {
1440 //   GstCameraSrc *camerasrc = GST_CAMERA_SRC_CAST (src);
1441
1442   return TRUE;
1443 }
1444
1445 /*
1446  */
1447 static gboolean
1448 gst_camerasrc_stop (GstBaseSrc * src)
1449 {
1450   GstCameraSrc *camerasrc;
1451   GstCameraSrcClass *bclass;
1452
1453   camerasrc = GST_CAMERA_SRC_CAST (src);
1454   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1455
1456   GST_DEBUG_OBJECT (camerasrc, "Stopping");
1457
1458   bclass->stop (camerasrc);
1459
1460   camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1461
1462   return TRUE;
1463 }
1464
1465 static gboolean
1466 gst_camerasrc_unlock (GstBaseSrc * src)
1467 {
1468   GstCameraSrcClass *pclass;
1469   GstCameraSrc *camerasrc;
1470   gboolean ret = TRUE;
1471
1472   camerasrc = GST_CAMERA_SRC_CAST (src);
1473   pclass = GST_CAMERA_SRC_GET_CLASS (src);
1474
1475   GST_DEBUG_OBJECT (camerasrc, "Unlock");
1476
1477   if (pclass->unlock)
1478     ret = pclass->unlock (camerasrc);
1479
1480   return ret;
1481 }
1482
1483 static gboolean
1484 gst_camerasrc_unlock_stop (GstBaseSrc * src)
1485 {
1486   GstCameraSrcClass *pclass;
1487   GstCameraSrc *camerasrc;
1488   gboolean ret = TRUE;
1489
1490   camerasrc = GST_CAMERA_SRC_CAST (src);
1491   pclass = GST_CAMERA_SRC_GET_CLASS (src);
1492
1493   GST_DEBUG_OBJECT (camerasrc, "Unlock stop");
1494
1495   if (pclass->unlock_stop)
1496     ret = pclass->unlock_stop (camerasrc);
1497
1498   return ret;
1499 }
1500
1501
1502 /*
1503  * gst_camerasrc_send_image_tags:
1504  * @camerasrc: #GstCameraSrc object.
1505  *
1506  */
1507 static gboolean
1508 gst_camerasrc_send_image_tags (GstCameraSrc * camerasrc)
1509 {
1510   GstTagMergeMode mode;
1511   GstCameraSrcClass *bclass;
1512   guint iso, wbalance;
1513   GstEvent *tagevent;
1514   GstTagList *tlist;
1515   gfloat zoom;
1516
1517   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1518
1519   tlist = gst_tag_list_new ();
1520   zoom = camerasrc->photoconf.zoom;
1521   iso = camerasrc->photoconf.iso_speed;
1522   wbalance =
1523       (camerasrc->photoconf.wb_mode == GST_PHOTOGRAPHY_WB_MODE_AUTO) ? 0 : 1;
1524
1525   gst_tag_register_musicbrainz_tags();
1526
1527   mode = GST_TAG_MERGE_REPLACE;
1528   gst_tag_list_add(tlist, mode, GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, (gdouble)zoom, NULL);
1529   gst_tag_list_add(tlist, mode, GST_TAG_CAPTURING_ISO_SPEED, iso, NULL);
1530
1531   if(camerasrc->maker_note)
1532   {
1533     int handle;
1534     gboolean ret;
1535     GstBuffer *pmakerbuf = NULL;
1536     unsigned buf_size;
1537     unsigned num_afwindows, num_awbgrid;
1538
1539     num_afwindows = 1;
1540     num_awbgrid = 1;
1541     ret = bclass->makernote_init(camerasrc, &buf_size, num_afwindows, 0, 0, num_awbgrid, &handle);
1542     if(TRUE == ret)
1543     {
1544       pmakerbuf = gst_buffer_new_and_alloc(buf_size);
1545
1546       ret = bclass->makernote_deal(camerasrc, pmakerbuf, num_afwindows, num_awbgrid, handle);
1547       if(TRUE == ret)
1548       {
1549         gst_tag_list_add(tlist, mode, GST_TAG_APPLICATION_DATA, pmakerbuf, NULL);
1550       }
1551
1552       bclass->makernote_uninit(camerasrc, handle);
1553       gst_buffer_unref(pmakerbuf);
1554     }
1555   }
1556
1557   if (bclass->fill_image_tags)
1558     bclass->fill_image_tags (camerasrc, tlist);
1559
1560   tagevent = gst_event_new_tag (gst_tag_list_copy (tlist));
1561   gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc), tagevent);
1562   GST_DEBUG_OBJECT (camerasrc, "image tags sent: %" GST_PTR_FORMAT, tlist);
1563   gst_tag_list_free (tlist);
1564
1565   return TRUE;
1566 }
1567
1568
1569 /*
1570  * gst_camerasrc_send_preview:
1571  * @camsrc: #GstCameraSrc object
1572  *
1573  * Sends HQ image preview image (snapshot) as a GstMessage.
1574  *
1575  * Returns: TRUE on success.
1576  */
1577 static gboolean
1578 gst_camerasrc_send_preview (GstCameraSrc * camsrc)
1579 {
1580   GstCameraSrcClass *bclass;
1581   GstBuffer *buf = NULL;
1582   GstStructure *msg_s = NULL;
1583   GstCaps *prvcaps = NULL;
1584   GstMessage *msg = NULL;
1585   gboolean ret = FALSE;
1586
1587   bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
1588
1589   if (bclass->get_preview_image) {
1590     ret = bclass->get_preview_image (camsrc, &buf);
1591   }
1592
1593   if (ret) {
1594     GST_DEBUG_OBJECT (camsrc, "Sending preview image");
1595     prvcaps = gst_caps_new_simple ("video/x-raw-yuv",
1596         "format", GST_TYPE_FOURCC, camsrc->preview_fourcc,
1597         "width", G_TYPE_INT, camsrc->preview_w,
1598         "height", G_TYPE_INT, camsrc->preview_h,
1599         "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
1600
1601     gst_buffer_set_caps (buf, prvcaps);
1602
1603     /* Send custom preview image GstMessage */
1604     msg_s = gst_structure_new (GST_CAMERA_SRC_PREVIEW_IMAGE, "buffer",
1605         GST_TYPE_BUFFER, buf, NULL);
1606
1607     msg = gst_message_new_element (GST_OBJECT (camsrc), msg_s);
1608
1609     if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
1610       GST_WARNING ("This element has no bus, therefore no message sent!");
1611     }
1612
1613     gst_caps_unref (prvcaps);
1614   } else {
1615     GST_DEBUG_OBJECT (camsrc, "Retrieving preview image failed");
1616   }
1617
1618   /* if we still have valid settings for preview, reserve a new buffer */
1619   if (camsrc->preview_resolution_set) {
1620     GST_DEBUG_OBJECT (camsrc, "Reserving a new preview buffer");
1621     bclass->set_capture (camsrc, GST_PHOTOGRAPHY_OPERATION_MODE_PREVIEW, FALSE,
1622         &camsrc->preview_fourcc, &camsrc->preview_w, &camsrc->preview_h,
1623         NULL, NULL);
1624   }
1625
1626   if (buf) {
1627     gst_buffer_unref (buf);
1628   }
1629
1630   return ret;
1631 }
1632
1633
1634 /*
1635  * gst_camerasrc_set_capture_caps:
1636  * @camerasrc: #GstCameraSrc object.
1637  *
1638  * Set the capture caps on element's src pad.
1639  *
1640  * Returns: TRUE on success.
1641  */
1642 static gboolean
1643 gst_camerasrc_set_capture_caps (GstCameraSrc * camerasrc)
1644 {
1645   GstCameraSrcClass *bclass;
1646   GstCaps *newcaps = NULL;
1647   gboolean ret = TRUE;
1648
1649   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1650
1651   GST_DEBUG_OBJECT (camerasrc, "Calling set_capture()");
1652
1653   /* Try what resolution the subclass can capture */
1654   ret = bclass->set_capture (camerasrc,
1655       GST_PHOTOGRAPHY_OPERATION_MODE_IMAGE_CAPTURE, TRUE,
1656       &camerasrc->capture_fourcc, &camerasrc->capture_w, &camerasrc->capture_h,
1657       &camerasrc->capture_fps_n, &camerasrc->capture_fps_d);
1658
1659   if (!ret) {
1660     goto done;
1661   }
1662
1663   /* FIXME: FPS definition should be removed from capture caps */
1664   newcaps = gst_camerasrc_get_caps_from_info (camerasrc,
1665       camerasrc->capture_fourcc, camerasrc->capture_w, camerasrc->capture_h,
1666       camerasrc->capture_fps_n, camerasrc->capture_fps_d);
1667
1668   GST_DEBUG_OBJECT (camerasrc, "Set capture caps: %" GST_PTR_FORMAT, newcaps);
1669
1670   /* Notify application that we are ready now. This must be called before */
1671   /* the set_caps() call below, since application needs to know the new caps */
1672   /* so that it can adjust the caps filter to accept new format before */
1673   /* srcpad caps are actually changed */
1674   gst_camerasrc_photo_ready_for_capture (camerasrc, newcaps);
1675
1676   camerasrc->vf_caps =
1677       gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1678
1679   /* This causes caps nego and switches resolution to hi-res mode */
1680   /* FIXME: Do we even need to set this? Application has already set the
1681    * capsfilter */
1682   if (!gst_caps_is_equal (camerasrc->vf_caps, newcaps)) {
1683     GST_DEBUG_OBJECT (camerasrc, "Setting image capture caps");
1684     ret = gst_pad_set_caps (GST_BASE_SRC_PAD (camerasrc), newcaps);
1685     GST_DEBUG_OBJECT (camerasrc, "Setting image capture caps FINISHED");
1686   } else {
1687     GST_DEBUG_OBJECT (camerasrc, "Forcing the re-initialization");
1688     ret = gst_camerasrc_configure_device (camerasrc, &camerasrc->current_w,
1689         &camerasrc->current_h, &camerasrc->current_fourcc, &camerasrc->fps_n,
1690         &camerasrc->fps_d, newcaps);
1691     gst_caps_unref (camerasrc->vf_caps);
1692     camerasrc->vf_caps = NULL;
1693   }
1694
1695   gst_caps_unref (newcaps);
1696
1697 done:
1698
1699   return ret;
1700 }
1701
1702
1703 /*
1704  *
1705  */
1706 static void
1707 gst_camerasrc_apply_timestamp (GstCameraSrc * camerasrc, GstBuffer * buf)
1708 {
1709   GstClock *clock;
1710   GstClockTime timestamp;
1711
1712   GST_OBJECT_LOCK (camerasrc);
1713   if ((clock = GST_ELEMENT_CLOCK (camerasrc))) {
1714     /* we have a clock, get base time and ref clock */
1715     timestamp = GST_ELEMENT (camerasrc)->base_time;
1716     gst_object_ref (clock);
1717   } else {
1718     /* no clock, can't set timestamps */
1719     timestamp = GST_CLOCK_TIME_NONE;
1720   }
1721   GST_OBJECT_UNLOCK (camerasrc);
1722
1723   if (clock) {
1724     /* the time now is the time of the clock minus the base time */
1725     timestamp = gst_clock_get_time (clock) - timestamp;
1726     gst_object_unref (clock);
1727
1728     if (timestamp > camerasrc->duration)
1729       timestamp -= camerasrc->duration;
1730     else
1731       timestamp = 0;
1732   }
1733
1734   /* we could also use the timestamp from the buffer itself */
1735   GST_BUFFER_TIMESTAMP (buf) = timestamp;
1736   GST_BUFFER_DURATION (buf) = camerasrc->duration;
1737 }
1738
1739
1740 /*
1741  */
1742 static GstFlowReturn
1743 gst_camerasrc_create (GstPushSrc * src, GstBuffer ** buf)
1744 {
1745   GstCameraSrcClass *bclass;
1746   GstCameraSrc *camerasrc;
1747   GstBaseSrcClass *basesrc_class;
1748
1749   GstBuffer *buf_cap_signal1 = NULL;      /*output main buffer for capture signal*/
1750
1751   gboolean still_capture_initialised = FALSE;
1752   GstFlowReturn ret = GST_FLOW_OK;
1753   GstBuffer *temp;
1754
1755   camerasrc = GST_CAMERA_SRC_CAST (src);
1756   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1757   basesrc_class = GST_BASE_SRC_CLASS (bclass);
1758
1759   if (camerasrc->req_negotiation) {
1760     GST_DEBUG_OBJECT(camerasrc, "negotiation start");
1761     basesrc_class->negotiate(GST_BASE_SRC(camerasrc));
1762     camerasrc->req_negotiation = FALSE;
1763     g_signal_emit(G_OBJECT(camerasrc), gst_camerasrc_signals[CAMERA_IN_SIGNAL_NEGO_COMPLETE], (GQuark)NULL);
1764     GST_DEBUG_OBJECT (camerasrc, "negotiation stop");
1765    }
1766
1767
1768 start_over:
1769
1770   g_mutex_lock (camerasrc->state_lock);
1771
1772   if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_START) {
1773     /* Tell subclass to stop flushing buffers */
1774     if (bclass->unlock_stop) {
1775       GST_DEBUG_OBJECT (camerasrc, "Stop flushing, capture is starting");
1776       bclass->unlock_stop (camerasrc);
1777     }
1778
1779     camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE;
1780
1781     GST_DEBUG_OBJECT (camerasrc,
1782         "Flushing old buffers before starting HQ capture");
1783     gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc),
1784         gst_event_new_flush_start ());
1785     gst_pad_push_event (GST_BASE_SRC_PAD (camerasrc),
1786         gst_event_new_flush_stop ());
1787
1788     if (!gst_camerasrc_set_capture_caps (camerasrc)) {
1789       goto hq_capture_failed;
1790     }
1791     still_capture_initialised = TRUE;
1792   }
1793
1794   else if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_DONE) {
1795
1796     gboolean ret;
1797
1798     camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1799     camerasrc->requested_af_mode = AF_OFF_REQUESTED;
1800     camerasrc->capture_mode = GST_CAMERA_SRC_CAPTURE_MODE_VIEWFINDER;
1801     GST_DEBUG_OBJECT (camerasrc, "capture done. switching to viewfinder");
1802
1803     /* Set the normal viewfinder resolution back */
1804     if (camerasrc->vf_caps) {
1805       GST_DEBUG_OBJECT (camerasrc, "set VF caps");
1806       ret = gst_pad_set_caps (GST_BASE_SRC_PAD (camerasrc), camerasrc->vf_caps);
1807       gst_caps_unref (camerasrc->vf_caps);
1808       camerasrc->vf_caps = NULL;
1809     } else {
1810       GstCaps *tmp;
1811
1812       tmp = gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1813
1814       /* Reconfigure the device to run viewfinder again */
1815       ret = gst_camerasrc_configure_device (camerasrc, &camerasrc->current_w,
1816           &camerasrc->current_h, &camerasrc->current_fourcc, &camerasrc->fps_n,
1817           &camerasrc->fps_d, tmp);
1818
1819       gst_caps_unref (tmp);
1820     }
1821
1822     if (!ret) {
1823       GST_WARNING_OBJECT (camerasrc, "Reinitializing viewfinder failed");
1824       g_mutex_unlock (camerasrc->state_lock);
1825       return GST_FLOW_ERROR;
1826     }
1827
1828     GST_DEBUG_OBJECT (camerasrc, "viewfinder running");
1829   }
1830
1831   g_mutex_lock (camerasrc->af_lock);
1832
1833   /* Handle AF requests only in VIEWFINDER and AUTOFOCUS states */
1834   if ((camerasrc->photo_capture_phase == GST_CAMERA_VIEWFINDER ||
1835           camerasrc->photo_capture_phase == GST_CAMERA_AUTOFOCUS ||
1836           camerasrc->photo_capture_phase == GST_CAMERA_AUTOFOCUS_DONE) &&
1837       camerasrc->requested_af_mode != AF_NONE_REQUESTED) {
1838     if (camerasrc->requested_af_mode == AF_ON_REQUESTED) {
1839       gboolean ret;
1840
1841       ret = bclass->set_autofocus (camerasrc, TRUE);
1842       if (ret) {
1843         camerasrc->photo_capture_phase = GST_CAMERA_AUTOFOCUS;
1844       }
1845     } else {
1846       camerasrc->photo_capture_phase = GST_CAMERA_VIEWFINDER;
1847     }
1848
1849     camerasrc->requested_af_mode = AF_NONE_REQUESTED;
1850   }
1851
1852   g_mutex_unlock (camerasrc->af_lock);
1853   g_mutex_unlock (camerasrc->state_lock);
1854
1855   ret = bclass->grab_frame (camerasrc, &temp, camerasrc->photo_capture_phase);
1856
1857   g_mutex_lock (camerasrc->state_lock);
1858
1859   if (ret != GST_FLOW_OK) {
1860     /* _prepare_for_capture() may have interrupted frame grabbing. */
1861     if (ret == GST_FLOW_WRONG_STATE &&
1862         camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_START) {
1863       g_mutex_unlock (camerasrc->state_lock);
1864       ret = GST_FLOW_OK;
1865       goto start_over;
1866     } else {
1867       g_mutex_unlock (camerasrc->state_lock);
1868       goto leave;
1869     }
1870   }
1871
1872   *buf = temp;
1873
1874   /* Post-capture phase */
1875
1876   if (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE) {
1877     GstCaps *src_caps;
1878
1879     src_caps = gst_pad_get_negotiated_caps (GST_BASE_SRC_PAD (camerasrc));
1880     gst_buffer_set_caps (*buf, src_caps);
1881     gst_caps_unref (src_caps);
1882
1883     /* Restore the original number of buffers after capture is done */
1884     /* FIXME: Commented out */
1885 //     camerasrc->num_buffers = tmp_num_buffers;
1886
1887 //    gst_camerasrc_send_image_tags (camerasrc);
1888
1889     gst_camerasrc_send_preview (camerasrc);
1890
1891     camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_DONE;
1892   }
1893
1894   if(GST_CAMERA_SRC_CAPTURE_MODE_STILL == camerasrc->capture_mode) {
1895     gst_camerasrc_send_image_tags (camerasrc);
1896     if ((camerasrc->signal_still_capture == TRUE) && (camerasrc->photo_capture_phase == GST_CAMERA_CAPTURE_DONE)  && (still_capture_initialised == TRUE)) {
1897       still_capture_initialised = FALSE;
1898       /*call signal*/
1899       /* alloc buffer for capture callback */
1900       buf_cap_signal1 = gst_buffer_new ();
1901
1902       GST_BUFFER_DATA(buf_cap_signal1) = GST_BUFFER_DATA(*buf);
1903       GST_BUFFER_SIZE(buf_cap_signal1) = GST_BUFFER_SIZE(*buf);
1904       GST_BUFFER_CAPS(buf_cap_signal1) = gst_caps_new_simple("video/x-raw-yuv",
1905                                        "format", GST_TYPE_FOURCC, camerasrc->capture_fourcc,
1906                                        "width", G_TYPE_INT,  camerasrc->capture_w,
1907                                        "height", G_TYPE_INT,camerasrc->capture_h,
1908                                         NULL);
1909
1910       GST_LOG_OBJECT (camerasrc, "CALL: capture callback");
1911       g_mutex_unlock (camerasrc->state_lock);
1912       g_signal_emit( G_OBJECT (camerasrc),
1913                gst_camerasrc_signals[CAMERA_IN_SIGNAL_STILL_CAPTURE],
1914                0,
1915                buf_cap_signal1,
1916                NULL,
1917                NULL );
1918       GST_LOG_OBJECT (camerasrc, "RETURN: capture callback");
1919       g_mutex_lock (camerasrc->state_lock);
1920
1921
1922        if(--camerasrc->capture_counter > 0) {
1923           camerasrc->photo_capture_phase = GST_CAMERA_CAPTURE_START;
1924           GST_DEBUG_OBJECT (camerasrc, "do some more captures count %d",camerasrc->capture_counter);
1925        }
1926        else
1927           camerasrc->photo_capture_phase =  GST_CAMERA_CAPTURE_DONE;
1928
1929       g_mutex_unlock (camerasrc->state_lock);
1930       goto start_over;
1931     }
1932   }
1933
1934   if (GST_BUFFER_TIMESTAMP (*buf) == GST_CLOCK_TIME_NONE) {
1935     gst_camerasrc_apply_timestamp (camerasrc, *buf);
1936   }
1937
1938 done:
1939
1940   g_mutex_unlock (camerasrc->state_lock);
1941
1942 leave:
1943   return ret;
1944
1945   /* ERRORS */
1946 hq_capture_failed:
1947   GST_ELEMENT_ERROR (camerasrc, RESOURCE, READ,
1948       ("Error during HQ capture"), (NULL));
1949   ret = GST_FLOW_ERROR;
1950   goto done;
1951 }
1952
1953
1954 static GstStateChangeReturn
1955 gst_camerasrc_change_state (GstElement * element, GstStateChange transition)
1956 {
1957   GstCameraSrcClass *bclass;
1958   GstCameraSrc *camerasrc;
1959   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1960
1961   camerasrc = GST_CAMERA_SRC_CAST (element);
1962   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
1963
1964   GST_LOG_OBJECT (camerasrc, "State change: %s -> %s",
1965       gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
1966       gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
1967
1968   switch (transition) {
1969     case GST_STATE_CHANGE_NULL_TO_READY:
1970       /* Open the device */
1971       if (!bclass->open (camerasrc))
1972         return GST_STATE_CHANGE_FAILURE;
1973       break;
1974     default:
1975       break;
1976   }
1977
1978   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1979
1980   switch (transition) {
1981     case GST_STATE_CHANGE_READY_TO_NULL:
1982       if (bclass->is_open (camerasrc)) {
1983         bclass->close (camerasrc);
1984       }
1985       camerasrc->capture_w = camerasrc->preview_w = camerasrc->current_w = 0;
1986       camerasrc->capture_h = camerasrc->preview_h = camerasrc->current_h = 0;
1987       camerasrc->capture_fourcc = camerasrc->preview_fourcc = 0;
1988       camerasrc->current_fourcc = 0;
1989       camerasrc->fps_d = camerasrc->fps_n = 0;
1990       camerasrc->capture_resolution_set = FALSE;
1991       camerasrc->preview_resolution_set = FALSE;
1992
1993       /* Notify that preview caps have changed (to NULL) */
1994       g_object_notify (G_OBJECT (camerasrc),
1995           GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
1996
1997       break;
1998     default:
1999       break;
2000   }
2001
2002   return ret;
2003 }
2004
2005
2006 /**
2007  * gst_camerasrc_add_color_channel:
2008  * @camsrc: #GstCameraSrc object.
2009  * @channel: #GstColorBalanceChannel object.
2010  *
2011  * Add a new color channel to list.
2012  */
2013 void
2014 gst_camerasrc_add_color_channel (GstCameraSrc * camsrc,
2015     GstColorBalanceChannel * channel)
2016 {
2017   camsrc->colors = g_list_append (camsrc->colors, (gpointer) channel);
2018 }
2019
2020
2021 /**
2022  * gst_camerasrc_clear_color_channels:
2023  * @camsrc: #GstCameraSrc object.
2024  *
2025  * Delete all color channels.
2026  */
2027 void
2028 gst_camerasrc_clear_color_channels (GstCameraSrc * camsrc)
2029 {
2030   g_list_foreach (camsrc->colors, (GFunc) g_object_unref, NULL);
2031   g_list_free (camsrc->colors);
2032   camsrc->colors = NULL;
2033 }
2034
2035 /**
2036  * gst_camerasrc_add_cameracontrol_channel:
2037  * @camsrc: #GstCameraSrc object.
2038  * @channel: #GstColorBalanceChannel object.
2039  *
2040  * Add a new cameracontrol channel to list.
2041  */
2042 void
2043 gst_camerasrc_add_cameracontrol_channel (GstCameraSrc * camsrc,
2044     GstCameraControlChannel * channel)
2045 {
2046   camsrc->camera_controls = g_list_append (camsrc->camera_controls, (gpointer) channel);
2047 }
2048
2049 /**
2050  * gst_camerasrc_clear_cameracontrol_channels:
2051  * @camsrc: #GstCameraSrc object.
2052  *
2053  * Delete all cameracontrol channels.
2054  */
2055
2056 void
2057 gst_camerasrc_clear_cameracontrol_channels (GstCameraSrc * camsrc)
2058 {
2059   g_list_foreach (camsrc->camera_controls, (GFunc) g_object_unref, NULL);
2060   g_list_free (camsrc->camera_controls);
2061   camsrc->camera_controls = NULL;
2062 }
2063
2064 /**
2065  * gst_camerasrc_send_capture_start_message:
2066  * @camsrc: GstCameraSrc object
2067  *
2068  * Sends a GstMessage notification to GstBus that capture operation is
2069  * about to start.
2070  */
2071 void
2072 gst_camerasrc_send_capture_start_message (GstCameraSrc * camsrc)
2073 {
2074   GstStructure *s;
2075   GstMessage *msg;
2076
2077   GST_DEBUG_OBJECT (camsrc, "Sending capture-start message");
2078
2079   /* Send custom GstMessage "photo-capture-start" */
2080   s = gst_structure_new (GST_CAMERA_SRC_CAPTURE_START, NULL);
2081   msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2082
2083   if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2084     GST_WARNING ("This element has no bus, therefore no message sent!");
2085   }
2086
2087   GST_LOG_OBJECT (camsrc, "Capture-start message sent");
2088 }
2089
2090
2091 /**
2092  * gst_camerasrc_send_capture_stop_message:
2093  * @camsrc: GstCameraSrc object
2094  *
2095  * Sends a GstMessage notification to GstBus that capture operation has
2096  * just finished.
2097  */
2098 void
2099 gst_camerasrc_send_capture_stop_message (GstCameraSrc * camsrc)
2100 {
2101   GstStructure *s;
2102   GstMessage *msg;
2103
2104   GST_DEBUG_OBJECT (camsrc, "Sending capture-stop message");
2105
2106   /* Send custom GstMessage "photo-capture-end" */
2107   s = gst_structure_new (GST_CAMERA_SRC_CAPTURE_END, NULL);
2108   msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2109
2110   if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2111     GST_WARNING ("This element has no bus, therefore no message sent!");
2112   }
2113
2114   GST_LOG_OBJECT (camsrc, "Capture-stop message sent");
2115 }
2116
2117
2118 /**
2119  * gst_camerasrc_af_update:
2120  * @camsrc: #GstCameraSrc object.
2121  * @fs: #GstCameraFocusStatus structure. Owned by caller.
2122  *
2123  * Tell GstCameraSrc that previously started autofocus operation has finished.
2124  */
2125 void
2126 gst_camerasrc_af_update (GstCameraSrc * camsrc, GstCameraFocusStatus * fs)
2127 {
2128   GstCameraSrcClass *bclass;
2129
2130   bclass = GST_CAMERA_SRC_GET_CLASS (camsrc);
2131
2132   g_mutex_lock (camsrc->state_lock);
2133   g_mutex_lock (camsrc->af_lock);
2134
2135   if (fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS ||
2136       fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL) {
2137     GstStructure *s;
2138     GstMessage *msg;
2139
2140     GST_DEBUG_OBJECT (camsrc, "autofocusing ended");
2141
2142     /* Send custom GstMessage "autofocus-done" */
2143     s = gst_structure_new (GST_PHOTOGRAPHY_AUTOFOCUS_DONE,
2144         "status", G_TYPE_INT, fs->status, NULL);
2145
2146     /* If autofocus succeeded, send the bitmask that defines focused
2147      * windows too */
2148     if (fs->status == GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS) {
2149       GArray *windows;
2150       guint i;
2151
2152       windows = g_array_new (FALSE, FALSE, sizeof (gint));
2153       for (i = 0; i < fs->num_windows; i++) {
2154         GST_DEBUG_OBJECT (camsrc, "focus window: %d", fs->windows[i]);
2155         g_array_append_val (windows, fs->windows[i]);
2156       }
2157
2158       gst_structure_set (s,
2159           //"focus-windows", G_TYPE_ARRAY, windows,
2160           "focus-window-rows", G_TYPE_INT, fs->focus_rows,
2161           "focus-window-columns", G_TYPE_INT, fs->focus_columns,
2162           "focus-window-coverage", G_TYPE_INT, fs->coverage, NULL);
2163
2164       GST_DEBUG_OBJECT (camsrc, "focus rows: %d", fs->focus_rows);
2165       GST_DEBUG_OBJECT (camsrc, "focus columns: %d", fs->focus_columns);
2166       GST_DEBUG_OBJECT (camsrc, "focus coverage: %d", fs->coverage);
2167     }
2168
2169     msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2170
2171     if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2172       GST_WARNING ("This element has no bus, therefore no message sent!");
2173     }
2174
2175     camsrc->photo_capture_phase = GST_CAMERA_AUTOFOCUS_DONE;
2176   }
2177
2178   g_mutex_unlock (camsrc->af_lock);
2179   g_mutex_unlock (camsrc->state_lock);
2180 }
2181
2182
2183 /**
2184  * gst_camerasrc_caf_update:
2185  * @camsrc: GstCameraSrc object.
2186  * @fs: #GstCameraFocusStatus structure. Owned by caller.
2187  *
2188  * Tell GstCameraSrc that continuous autofocus algorithm has changed its state.
2189  * Sends a GstMessage notification to GstBus indicating a change in
2190  * continuous autofocus status.
2191  */
2192 void
2193 gst_camerasrc_caf_update (GstCameraSrc * camsrc, GstCameraFocusStatus * fs)
2194 {
2195   GstStructure *s;
2196   GstMessage *msg;
2197
2198   GST_DEBUG_OBJECT (camsrc, "Sending CAF status: %d", fs->status);
2199
2200   /* Send custom GstMessage "caf-update" */
2201   s = gst_structure_new (GST_CAMERA_SRC_CAF_STATUS, NULL);
2202   gst_structure_set (s, "status", G_TYPE_INT, fs->status, NULL);
2203   msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2204
2205   if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2206     GST_WARNING ("This element has no bus, therefore no message sent!");
2207   }
2208
2209   GST_LOG_OBJECT (camsrc, "CAF update message sent");
2210 }
2211
2212
2213 /**
2214  * gst_camerasrc_shake_update:
2215  * @camsrc: GstCameraSrc object.
2216  * @risk: GstPhotoShakeRisk value.
2217  *
2218  * Tell GstCameraSrc that shake risk has changed. Sends a GstMessage
2219  * notification to GstBus indicating a change in shake risk status.
2220  */
2221 void
2222 gst_camerasrc_shake_update (GstCameraSrc * camsrc, GstPhotoShakeRisk risk)
2223 {
2224   GstStructure *s;
2225   GstMessage *msg;
2226
2227   GST_DEBUG_OBJECT (camsrc, "Sending shake risk update: %d", risk);
2228
2229   /* Send custom GstMessage telling the changed shake risk level */
2230   s = gst_structure_new (GST_PHOTOGRAPHY_SHAKE_RISK, NULL);
2231   gst_structure_set (s, "shake_risk", G_TYPE_INT, risk, NULL);
2232   msg = gst_message_new_element (GST_OBJECT (camsrc), s);
2233
2234   if (gst_element_post_message (GST_ELEMENT (camsrc), msg) == FALSE) {
2235     GST_WARNING ("This element has no bus, therefore no message sent!");
2236   }
2237
2238   GST_LOG_OBJECT (camsrc, "Shake indicator message sent");
2239 }
2240
2241
2242 /* Tag helper functions */
2243
2244 /**
2245  * gst_camerasrc_exposure_mode_from_exif_value:
2246  * @value: exposure mode in EXIF format.
2247  *
2248  * Convert exposure mode to string.
2249  *
2250  * Returns: String representation of the scene capture type, or NULL if invalid
2251  * value was given. Possible values: "auto-exposure", "manual-exposure" and
2252  * "auto-bracket".
2253  */
2254 const gchar *
2255 gst_camerasrc_exposure_mode_from_exif_value (gint value)
2256 {
2257   switch (value) {
2258     case 0:
2259       return "auto-exposure";
2260     case 1:
2261       return "manual-exposure";
2262     case 2:
2263       return "auto-bracket";
2264     default:
2265       GST_WARNING ("Invalid exif exposure mode: %d", value);
2266       return NULL;
2267   }
2268 }
2269
2270 /**
2271  * gst_camerasrc_scene_capture_type_from_exif_value:
2272  * @value: scene capture type in EXIF format.
2273  *
2274  * Convert scene capture type to string.
2275  *
2276  * Returns: String representation of the scene capture type, or NULL if invalid
2277  * value was given. Possible values: "standard", "landscape", "portrait" and
2278  * "night-scene".
2279  */
2280 const gchar *
2281 gst_camerasrc_scene_capture_type_from_exif_value (gint value)
2282 {
2283   switch (value) {
2284     case 0:
2285       return "standard";
2286     case 1:
2287       return "landscape";
2288     case 2:
2289       return "portrait";
2290     case 3:
2291       return "night-scene";
2292     default:
2293       GST_WARNING ("Invalid exif scene capture type: %d", value);
2294       return NULL;
2295   }
2296 }
2297
2298
2299 /**
2300  * gst_camerasrc_gain_adjustment_from_exif_value:
2301  * @value: gain adjustment type in EXIF format.
2302  *
2303  * Convert gain adjustment type to string.
2304  *
2305  * Returns: String representation of the gain adjustment type, or NULL if
2306  * invalid value was given. Possible values: "none", "low-gain-up",
2307  * "high-gain-up", "low-gain-down" and "high-gain-down".
2308  */
2309 const gchar *
2310 gst_camerasrc_gain_adjustment_from_exif_value (gint value)
2311 {
2312   switch (value) {
2313     case 0:
2314       return "none";
2315     case 1:
2316       return "low-gain-up";
2317     case 2:
2318       return "high-gain-up";
2319     case 3:
2320       return "low-gain-down";
2321     case 4:
2322       return "high-gain-down";
2323     default:
2324       GST_WARNING ("Invalid exif gain control type: %d", value);
2325       return NULL;
2326   }
2327 }
2328
2329
2330 /**
2331  * gst_camerasrc_contrast_from_exif_value:
2332  * @value: contrast type in EXIF format.
2333  *
2334  * Convert contrast type to string.
2335  *
2336  * Returns: String representation of the contrast type, or NULL if invalid
2337  * value was given. Possible values: "normal", "soft" and "hard".
2338  */
2339 const gchar *
2340 gst_camerasrc_contrast_from_exif_value (gint value)
2341 {
2342   switch (value) {
2343     case 0:
2344       return "normal";
2345     case 1:
2346       return "soft";
2347     case 2:
2348       return "hard";
2349     default:
2350       GST_WARNING ("Invalid contrast type: %d", value);
2351       return NULL;
2352   }
2353 }
2354
2355
2356 /**
2357  * gst_camerasrc_saturation_from_exif_value:
2358  * @value: saturation type in EXIF format.
2359  *
2360  * Convert saturation type to string.
2361  *
2362  * Returns: String representation of the saturation type, or NULL if invalid
2363  * value was given. Possible values: "normal", "low-saturation" and
2364  * "high-saturation".
2365  */
2366 const gchar *
2367 gst_camerasrc_saturation_from_exif_value (gint value)
2368 {
2369   switch (value) {
2370     case 0:
2371       return "normal";
2372     case 1:
2373       return "low-saturation";
2374     case 2:
2375       return "high-saturation";
2376     default:
2377       GST_WARNING ("Invalid saturation type: %d", value);
2378       return NULL;
2379   }
2380 }
2381
2382
2383 /**
2384  * gst_camerasrc_flash_mode_from_exif_value:
2385  * @value: flash EXIF field
2386  *
2387  * Convert "flash" EXIF field into text string.
2388  *
2389  * Returns: String representation of the flash mode, or NULL if invalid
2390  * value was given. Possible values: "always", "never" and "auto".
2391  */
2392 const gchar *
2393 gst_camerasrc_flash_mode_from_exif_value (gint value)
2394 {
2395   // frame_info_t
2396
2397   // bits 3 and 4 indicate the flash mode,
2398   //
2399   // Values for bits 3 and 4 indicating the camera's flash mode.
2400   // 00b              =   unknown
2401   // 01b              =   Compulsory flash firing
2402   // 10b              =   Compulsory flash suppression
2403   // 11b              =   Auto mode
2404   //
2405
2406   /* Bit numbering in EXIF spec starts from 0 */
2407   value >>= 3;
2408
2409   switch (value & 0x3) {
2410     case 1:
2411       return "always";
2412     case 2:
2413       return "never";
2414     case 3:
2415       return "auto";
2416     default:
2417       GST_WARNING ("Invalid flash mode type: %d", value);
2418       return NULL;
2419   }
2420 }
2421
2422
2423 /**
2424  * gst_camerasrc_sharpness_from_exif_value:
2425  * @value: sharpness type in EXIF format.
2426  *
2427  * Convert sharpness type to string.
2428  *
2429  * Returns: String representation of the sharpness type, or NULL if invalid
2430  * value was given. Possible values: "normal", "soft" and "hard".
2431  */
2432 const gchar *
2433 gst_camerasrc_sharpness_from_exif_value (gint value)
2434 {
2435   switch (value) {
2436     case 0:
2437       return "normal";
2438     case 1:
2439       return "soft";
2440     case 2:
2441       return "hard";
2442     default:
2443       GST_WARNING ("Invalid sharpness type: %d", value);
2444       return NULL;
2445   }
2446 }
2447
2448
2449 /**
2450  * gst_camerasrc_metering_mode_from_exif_value:
2451  * @value: metering mode type in EXIF format.
2452  *
2453  * Convert metering mode type to string.
2454  *
2455  * Returns: String representation of the metering mode type, or NULL if invalid
2456  * value was given. Possible values: "unknown", "average",
2457  * "center-weighted-average", "spot", "multi-spot", "pattern", "partial" and
2458  * "other".
2459  */
2460 const gchar *
2461 gst_camerasrc_metering_mode_from_exif_value (gint value)
2462 {
2463   switch (value) {
2464     case 0:
2465       return "unknown";
2466     case 1:
2467       return "average";
2468     case 2:
2469       return "center-weighted-average";
2470     case 3:
2471       return "spot";
2472     case 4:
2473       return "multi-spot";
2474     case 5:
2475       return "pattern";
2476     case 6:
2477       return "partial";
2478     case 255:
2479       return "other";
2480     default:
2481       GST_WARNING ("Invalid metering mode type: %d", value);
2482       return NULL;
2483   }
2484 }
2485
2486
2487 /**
2488  * gst_camerasrc_file_source_from_exif_value:
2489  * @value: FileSource type in EXIF format.
2490  *
2491  * Convert FileSource type to string.
2492  *
2493  * Returns: String representation of the FileSource type, or NULL if invalid
2494  * value was given. Possible values: "dsc", "transparent-scanner",
2495  * "reflex-scanner" and "other".
2496  */
2497 const gchar *
2498 gst_camerasrc_file_source_from_exif_value (gint value)
2499 {
2500   switch (value) {
2501     case 0:
2502       return "other";
2503     case 1:
2504       return "transparent-scanner";
2505     case 2:
2506       return "reflex-scanner";
2507     case 3:
2508       return "dsc";
2509     default:
2510       GST_WARNING ("Invalid file source type: %d", value);
2511       return NULL;
2512   }
2513 }
2514
2515
2516 /* Default implementations for vmethods */
2517
2518 static GstPhotoCaps
2519 gst_camerasrc_default_capabilities (GstCameraSrc * camsrc)
2520 {
2521   return GST_PHOTOGRAPHY_CAPS_NONE;
2522 }
2523
2524 static gboolean
2525 gst_camerasrc_default_ret_true_with_settings (GstCameraSrc * camsrc,
2526     GstPhotoSettings * photoconf)
2527 {
2528   return TRUE;
2529 }
2530
2531 static gboolean
2532 gst_camerasrc_default_write_settings (GstCameraSrc * camsrc,
2533     GstPhotoSettings * photoconf, gboolean scene_mode_override)
2534 {
2535   return TRUE;
2536 }
2537
2538 static gboolean
2539 gst_camerasrc_default_set_onoff (GstCameraSrc * camsrc, gboolean on_off)
2540 {
2541   return TRUE;
2542 }
2543
2544 static GstCaps *
2545 gst_camerasrc_default_get_caps (GstCameraSrc * camsrc, GstOperationMode mode)
2546 {
2547   GST_DEBUG_OBJECT (camsrc, "Returning NULL caps for mode %d", mode);
2548
2549   return NULL;
2550 }
2551 static gboolean
2552 gst_camerasrc_default_read_exif (GstCameraSrc *camsrc,
2553     GstCameraControlExifInfo *exif_info)
2554 {
2555   GST_DEBUG_OBJECT (camsrc, "default implementation of exif read called return defaults  %d");
2556   // TODO: fill with default values
2557   return TRUE;
2558 }
2559
2560 static gboolean
2561 gst_camerasrc_default_set_flash_mode (GstCameraSrc *camsrc, int value)
2562 {
2563   return TRUE;
2564 }
2565
2566 static void
2567 gst_camerasrc_default_functions_init (GstCameraSrcClass * camera_class)
2568 {
2569   camera_class->get_capabilities = gst_camerasrc_default_capabilities;
2570   camera_class->set_autofocus = gst_camerasrc_default_set_onoff;
2571   camera_class->read_settings = gst_camerasrc_default_ret_true_with_settings;
2572   camera_class->write_settings = gst_camerasrc_default_write_settings;
2573   camera_class->get_supported_caps = gst_camerasrc_default_get_caps;
2574   camera_class->set_flash_mode = gst_camerasrc_default_set_flash_mode;
2575   camera_class->read_exif = gst_camerasrc_default_read_exif;
2576
2577   GST_DEBUG ("Default functions set");
2578 }
2579
2580
2581 static gboolean
2582 gst_camerasrc_handle_event (GstCameraSrc * camerasrc, GstEvent * event)
2583 {
2584   GstCameraSrcClass *bclass;
2585   gboolean ret = FALSE;
2586
2587   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
2588   GST_LOG_OBJECT (camerasrc, "handling %s event", GST_EVENT_TYPE_NAME (event));
2589
2590   if (bclass->event) {
2591     ret = bclass->event (camerasrc, event);
2592   }
2593
2594   return ret;
2595 }
2596
2597
2598 /*
2599  * gst_camerasrc_send_event:
2600  * @element: GstElement object.
2601  * @event: GstEvent to be handled.
2602  *
2603  * Returns: TRUE if the event was handled.
2604  */
2605 static gboolean
2606 gst_camerasrc_send_event (GstElement * element, GstEvent * event)
2607 {
2608   GstCameraSrc *camerasrc;
2609   gboolean ret = FALSE;
2610
2611   camerasrc = GST_CAMERA_SRC_CAST (element);
2612
2613   GST_LOG_OBJECT (camerasrc, "got %s event", GST_EVENT_TYPE_NAME (event));
2614
2615   switch (GST_EVENT_TYPE (event)) {
2616     case GST_EVENT_CUSTOM_UPSTREAM:
2617       ret = gst_camerasrc_handle_event (camerasrc, event);
2618       break;
2619     default:
2620       break;
2621   }
2622
2623   if (!ret) {
2624     ret = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
2625   }
2626
2627   return ret;
2628 }
2629
2630
2631 /*
2632  * gst_camerasrc_event:
2633  * @src: #GstBaseSrc object.
2634  * @event: #GetEvent object.
2635  *
2636  * Returns: TRUE of the event was handled.
2637  */
2638 static gboolean
2639 gst_camerasrc_event (GstBaseSrc * src, GstEvent * event)
2640 {
2641   GstCameraSrc *camerasrc;
2642   gboolean ret;
2643
2644   camerasrc = GST_CAMERA_SRC_CAST (src);
2645   ret = gst_camerasrc_handle_event (camerasrc, event);
2646
2647   if (!ret) {
2648     ret = GST_BASE_SRC_CLASS (parent_class)->event (src, event);
2649   }
2650
2651   return ret;
2652 }
2653
2654
2655 /**
2656  * gst_camerasrc_update_max_zoom:
2657  * @camerasrc: #GstCameraSrc object.
2658  *
2659  * Check and update zoom property maximum value.
2660  */
2661 static void
2662 gst_camerasrc_update_max_zoom (GstCameraSrc * camerasrc)
2663 {
2664   GstCameraSrcClass *bclass;
2665   GObjectClass *oclass;
2666   GParamSpec *pspec;
2667   GParamSpecFloat *pspec_f;
2668   gfloat maxzoom = 10.0;
2669
2670   oclass = G_OBJECT_GET_CLASS (camerasrc);
2671   bclass = GST_CAMERA_SRC_GET_CLASS (camerasrc);
2672   pspec = g_object_class_find_property (oclass, "zoom");
2673
2674   if (bclass->get_max_zoom) {
2675     if (!bclass->get_max_zoom (camerasrc, &maxzoom)) {
2676       maxzoom = 10.0;
2677     }
2678   }
2679
2680   /* Update gobject property */
2681   if (pspec && (G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_FLOAT)) {
2682     pspec_f = G_PARAM_SPEC_FLOAT (pspec);
2683     pspec_f->maximum = maxzoom;
2684     GST_DEBUG_OBJECT (camerasrc, "set maximum zoom as %f", pspec_f->maximum);
2685     /* Check if new maximum zoom is lower than current zoom level */
2686     if (pspec_f->maximum < camerasrc->photoconf.zoom) {
2687       GST_DEBUG_OBJECT (camerasrc, "current zoom level too high: %f",
2688           camerasrc->photoconf.zoom);
2689       g_object_set (G_OBJECT (camerasrc), "zoom", pspec_f->maximum, NULL);
2690     }
2691   } else {
2692     GST_WARNING_OBJECT (camerasrc, "updating maximum zoom failed");
2693   }
2694 }