1 /* GStreamer
2  *
3  * unit test for camerabin basic operations
4  * Copyright (C) 2010 Nokia Corporation <multimedia@maemo.org>
5  * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
6  *
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27 
28 #include <glib.h>
29 #include <glib/gstdio.h>
30 #include <gst/gst.h>
31 #include <gst/video/video.h>
32 #include <gst/check/gstcheck.h>
33 #include <gst/basecamerabinsrc/gstbasecamerasrc.h>
34 #include <gst/base/gstpushsrc.h>
35 #include <gst/interfaces/photography.h>
36 #include <gst/pbutils/encoding-profile.h>
37 
38 #define IMAGE_FILENAME "image"
39 #define VIDEO_FILENAME "video"
40 #define CAPTURE_COUNT 3
41 #define VIDEO_DURATION 5
42 
43 #define VIDEO_PAD_SUPPORTED_CAPS "video/x-raw, format=RGB, width=600, height=480"
44 #define IMAGE_PAD_SUPPORTED_CAPS "video/x-raw, format=RGB, width=800, height=600"
45 
46 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
47     GST_PAD_SRC,
48     GST_PAD_ALWAYS,
49     GST_STATIC_CAPS ("video/x-raw, format=RGB"));
50 
51 static GstStaticPadTemplate vfsrc_template =
52 GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME,
53     GST_PAD_SRC,
54     GST_PAD_ALWAYS,
55     GST_STATIC_CAPS_ANY);
56 
57 static GstStaticPadTemplate imgsrc_template =
58 GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME,
59     GST_PAD_SRC,
60     GST_PAD_ALWAYS,
61     GST_STATIC_CAPS_ANY);
62 
63 static GstStaticPadTemplate vidsrc_template =
64 GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME,
65     GST_PAD_SRC,
66     GST_PAD_ALWAYS,
67     GST_STATIC_CAPS_ANY);
68 
69 /* custom test camera src element */
70 #define GST_TYPE_TEST_CAMERA_SRC \
71   (gst_test_camera_src_get_type())
72 #define GST_TEST_CAMERA_SRC(obj) \
73   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEST_CAMERA_SRC,GstTestCameraSrc))
74 #define GST_TEST_CAMERA_SRC_CLASS(klass) \
75   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEST_CAMERA_SRC,GstTestCameraSrcClass))
76 #define GST_TEST_CAMERA_SRC_CAST(obj) ((GstTestCameraSrc *)obj)
77 
78 typedef struct _GstTestCameraSrc GstTestCameraSrc;
79 typedef struct _GstTestCameraSrcClass GstTestCameraSrcClass;
80 struct _GstTestCameraSrc
81 {
82   GstBaseCameraSrc element;
83 
84   GstPad *vfpad;
85   GstPad *vidpad;
86   GstPad *imgpad;
87 
88   GstCameraBinMode mode;
89 };
90 
91 struct _GstTestCameraSrcClass
92 {
93   GstBaseCameraSrcClass parent_class;
94 };
95 
96 GType gst_test_camera_src_get_type (void);
97 
98 G_DEFINE_TYPE (GstTestCameraSrc, gst_test_camera_src, GST_TYPE_BASE_CAMERA_SRC);
99 
100 static gboolean
gst_test_camera_src_set_mode(GstBaseCameraSrc * src,GstCameraBinMode mode)101 gst_test_camera_src_set_mode (GstBaseCameraSrc * src, GstCameraBinMode mode)
102 {
103   GstTestCameraSrc *self = GST_TEST_CAMERA_SRC (src);
104 
105   self->mode = mode;
106   return TRUE;
107 }
108 
109 static gboolean
gst_test_camera_src_query(GstPad * pad,GstObject * parent,GstQuery * query)110 gst_test_camera_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
111 {
112   GstTestCameraSrc *self = (GstTestCameraSrc *) GST_PAD_PARENT (pad);
113   GstCaps *result = NULL;
114   gboolean ret = FALSE;
115 
116   switch (GST_QUERY_TYPE (query)) {
117     case GST_QUERY_CAPS:
118       if (pad == self->vfpad) {
119         result = gst_caps_new_any ();
120       } else if (pad == self->vidpad) {
121         result = gst_caps_from_string (VIDEO_PAD_SUPPORTED_CAPS);
122       } else if (pad == self->imgpad) {
123         result = gst_caps_from_string (IMAGE_PAD_SUPPORTED_CAPS);
124       } else {
125         g_assert_not_reached ();
126       }
127       if (result) {
128         GstCaps *filter;
129 
130         gst_query_parse_caps (query, &filter);
131         if (filter) {
132           GstCaps *tmp;
133           tmp = gst_caps_intersect (result, filter);
134           gst_caps_replace (&result, tmp);
135           gst_caps_unref (tmp);
136         }
137         gst_query_set_caps_result (query, result);
138         gst_caps_unref (result);
139         ret = TRUE;
140       }
141       break;
142     default:
143       break;
144   }
145 
146   return ret;
147 }
148 
149 static void
gst_test_camera_src_class_init(GstTestCameraSrcClass * klass)150 gst_test_camera_src_class_init (GstTestCameraSrcClass * klass)
151 {
152   GstBaseCameraSrcClass *gstbasecamera_class;
153   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
154 
155   gstbasecamera_class = GST_BASE_CAMERA_SRC_CLASS (klass);
156   gstbasecamera_class->set_mode = gst_test_camera_src_set_mode;
157 
158   gst_element_class_set_static_metadata (gstelement_class,
159       "Test Camera Src",
160       "Camera/Src",
161       "Some test camera src",
162       "Thiago Santos <thiago.sousa.santos@collabora.com>");
163 
164   gst_element_class_add_static_pad_template (gstelement_class,
165       &vidsrc_template);
166   gst_element_class_add_static_pad_template (gstelement_class,
167       &imgsrc_template);
168   gst_element_class_add_static_pad_template (gstelement_class, &vfsrc_template);
169 }
170 
171 static void
gst_test_camera_src_init(GstTestCameraSrc * self)172 gst_test_camera_src_init (GstTestCameraSrc * self)
173 {
174   GstElementClass *gstelement_class = GST_ELEMENT_GET_CLASS (self);
175   GstPadTemplate *template;
176 
177   /* create pads */
178   template = gst_element_class_get_pad_template (gstelement_class,
179       GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME);
180   self->vfpad = gst_pad_new_from_template (template,
181       GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME);
182   gst_element_add_pad (GST_ELEMENT_CAST (self), self->vfpad);
183 
184   template = gst_element_class_get_pad_template (gstelement_class,
185       GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME);
186   self->imgpad = gst_pad_new_from_template (template,
187       GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME);
188   gst_element_add_pad (GST_ELEMENT_CAST (self), self->imgpad);
189 
190   template = gst_element_class_get_pad_template (gstelement_class,
191       GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME);
192   self->vidpad = gst_pad_new_from_template (template,
193       GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME);
194   gst_element_add_pad (GST_ELEMENT_CAST (self), self->vidpad);
195 
196   /* add get caps functions */
197   gst_pad_set_query_function (self->vfpad, gst_test_camera_src_query);
198   gst_pad_set_query_function (self->vidpad, gst_test_camera_src_query);
199   gst_pad_set_query_function (self->imgpad, gst_test_camera_src_query);
200 }
201 
202 /* end of custom test camera src element */
203 
204 /* custom video source element that implements GstPhotography iface */
205 
206 #define GST_TYPE_TEST_VIDEO_SRC \
207   (gst_test_video_src_get_type())
208 #define GST_TEST_VIDEO_SRC(obj) \
209   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEST_VIDEO_SRC,GstTestVideoSrc))
210 #define GST_TEST_VIDEO_SRC_CLASS(klass) \
211   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEST_VIDEO_SRC,GstTestVideoSrcClass))
212 #define GST_TEST_VIDEO_SRC_CAST(obj) ((GstTestVideoSrc *)obj)
213 
214 typedef struct _GstTestVideoSrc GstTestVideoSrc;
215 typedef struct _GstTestVideoSrcClass GstTestVideoSrcClass;
216 struct _GstTestVideoSrc
217 {
218   GstPushSrc element;
219 
220   gint width, height;
221   GstCaps *caps;
222 
223   /* if TRUE, this element will only output resolutions with       *
224    * same width and height (square frames). This allows us testing *
225    * extra cropping feature with GstPhotography interface captures */
226   gboolean enable_resolution_restriction;
227 };
228 
229 struct _GstTestVideoSrcClass
230 {
231   GstPushSrcClass parent_class;
232 };
233 
234 GType gst_test_video_src_get_type (void);
235 
236 enum
237 {
238   PROP_0,
239   PROP_WB_MODE,
240   PROP_COLOR_TONE,
241   PROP_SCENE_MODE,
242   PROP_FLASH_MODE,
243   PROP_FLICKER_MODE,
244   PROP_FOCUS_MODE,
245   PROP_CAPABILITIES,
246   PROP_EV_COMP,
247   PROP_ISO_SPEED,
248   PROP_APERTURE,
249   PROP_EXPOSURE_TIME,
250   PROP_IMAGE_PREVIEW_SUPPORTED_CAPS,
251   PROP_IMAGE_CAPTURE_SUPPORTED_CAPS,
252   PROP_ZOOM,
253   PROP_COLOR_TEMPERATURE,
254   PROP_WHITE_POINT,
255   PROP_ANALOG_GAIN,
256   PROP_LENS_FOCUS,
257   PROP_MIN_EXPOSURE_TIME,
258   PROP_MAX_EXPORURE_TIME,
259   PROP_NOISE_REDUCTION
260 };
261 
262 static gboolean
gst_test_video_src_prepare_for_capture(GstPhotography * photo,GstPhotographyCapturePrepared func,GstCaps * capture_caps,gpointer user_data)263 gst_test_video_src_prepare_for_capture (GstPhotography * photo,
264     GstPhotographyCapturePrepared func, GstCaps * capture_caps,
265     gpointer user_data)
266 {
267   GstCaps *caps;
268   GstTestVideoSrc *testvideosrc = GST_TEST_VIDEO_SRC (photo);
269 
270   if (testvideosrc->enable_resolution_restriction) {
271     GstStructure *str = gst_caps_get_structure (capture_caps, 0);
272     gint width, height;
273 
274     gst_structure_get_int (str, "width", &width);
275     gst_structure_get_int (str, "height", &height);
276 
277     width = height = MAX (width, height);
278     str = gst_structure_copy (str);
279     gst_structure_set (str, "width", G_TYPE_INT, width, "height", G_TYPE_INT,
280         height, NULL);
281     caps = gst_caps_new_full (str, NULL);
282     caps = gst_caps_fixate (caps);
283     fail_unless (testvideosrc->caps == NULL);
284     testvideosrc->caps = gst_caps_ref (caps);
285   } else {
286     caps = gst_caps_ref (capture_caps);
287   }
288 
289   func (user_data, caps);
290   gst_caps_unref (caps);
291   return TRUE;
292 }
293 
294 static void
gst_test_video_src_photography_init(gpointer g_iface,gpointer iface_data)295 gst_test_video_src_photography_init (gpointer g_iface, gpointer iface_data)
296 {
297   GstPhotographyInterface *iface = g_iface;
298 
299   iface->prepare_for_capture = gst_test_video_src_prepare_for_capture;
300 }
301 
302 G_DEFINE_TYPE_WITH_CODE (GstTestVideoSrc, gst_test_video_src, GST_TYPE_PUSH_SRC,
303     G_IMPLEMENT_INTERFACE (GST_TYPE_PHOTOGRAPHY,
304         gst_test_video_src_photography_init));
305 
306 static void
gst_test_video_src_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)307 gst_test_video_src_get_property (GObject * object,
308     guint prop_id, GValue * value, GParamSpec * pspec)
309 {
310   /* don't care */
311 }
312 
313 static void
gst_test_video_src_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)314 gst_test_video_src_set_property (GObject * object,
315     guint prop_id, const GValue * value, GParamSpec * pspec)
316 {
317   /* don't care */
318 }
319 
320 static gboolean
gst_test_video_src_set_caps(GstBaseSrc * src,GstCaps * caps)321 gst_test_video_src_set_caps (GstBaseSrc * src, GstCaps * caps)
322 {
323   GstTestVideoSrc *self = GST_TEST_VIDEO_SRC (src);
324   GstStructure *structure = gst_caps_get_structure (caps, 0);
325 
326 
327   fail_unless (gst_structure_get_int (structure, "width", &self->width));
328   fail_unless (gst_structure_get_int (structure, "height", &self->height));
329 
330   return TRUE;
331 }
332 
333 static GstFlowReturn
gst_test_video_src_alloc(GstPushSrc * src,GstBuffer ** buf)334 gst_test_video_src_alloc (GstPushSrc * src, GstBuffer ** buf)
335 {
336   GstTestVideoSrc *self = GST_TEST_VIDEO_SRC (src);
337   guint8 *data;
338   gsize data_size;
339 
340   if (self->caps) {
341     gst_base_src_set_caps (GST_BASE_SRC (self), self->caps);
342     gst_caps_unref (self->caps);
343     self->caps = NULL;
344   }
345 
346   data_size = self->width * self->height * 3;   /* RGB size */
347   data = g_malloc (data_size);
348   *buf = gst_buffer_new_wrapped (data, data_size);
349 
350   return GST_FLOW_OK;
351 }
352 
353 static GstFlowReturn
gst_test_video_src_fill(GstPushSrc * src,GstBuffer * buf)354 gst_test_video_src_fill (GstPushSrc * src, GstBuffer * buf)
355 {
356   /* NOP */
357   return GST_FLOW_OK;
358 }
359 
360 static void
gst_test_video_src_class_init(GstTestVideoSrcClass * klass)361 gst_test_video_src_class_init (GstTestVideoSrcClass * klass)
362 {
363   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
364   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
365   GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
366   GstPushSrcClass *gstpushsrc_class = GST_PUSH_SRC_CLASS (klass);
367 
368   gst_element_class_set_static_metadata (gstelement_class,
369       "Test Camera Video Src",
370       "Video/Src",
371       "Test camera video src", "Thiago Santos <thiagoss@osg.samsung.com>");
372 
373   gst_element_class_add_static_pad_template (gstelement_class, &src_template);
374 
375   gobject_class->get_property = gst_test_video_src_get_property;
376   gobject_class->set_property = gst_test_video_src_set_property;
377 
378   gstbasesrc_class->set_caps = gst_test_video_src_set_caps;
379   gstpushsrc_class->alloc = gst_test_video_src_alloc;
380   gstpushsrc_class->fill = gst_test_video_src_fill;
381 
382   /* photography interface properties */
383   g_object_class_override_property (gobject_class, PROP_WB_MODE,
384       GST_PHOTOGRAPHY_PROP_WB_MODE);
385   g_object_class_override_property (gobject_class, PROP_COLOR_TONE,
386       GST_PHOTOGRAPHY_PROP_COLOR_TONE);
387   g_object_class_override_property (gobject_class, PROP_SCENE_MODE,
388       GST_PHOTOGRAPHY_PROP_SCENE_MODE);
389   g_object_class_override_property (gobject_class, PROP_FLASH_MODE,
390       GST_PHOTOGRAPHY_PROP_FLASH_MODE);
391   g_object_class_override_property (gobject_class, PROP_FLICKER_MODE,
392       GST_PHOTOGRAPHY_PROP_FLICKER_MODE);
393   g_object_class_override_property (gobject_class, PROP_FOCUS_MODE,
394       GST_PHOTOGRAPHY_PROP_FOCUS_MODE);
395   g_object_class_override_property (gobject_class, PROP_CAPABILITIES,
396       GST_PHOTOGRAPHY_PROP_CAPABILITIES);
397   g_object_class_override_property (gobject_class, PROP_EV_COMP,
398       GST_PHOTOGRAPHY_PROP_EV_COMP);
399   g_object_class_override_property (gobject_class, PROP_ISO_SPEED,
400       GST_PHOTOGRAPHY_PROP_ISO_SPEED);
401   g_object_class_override_property (gobject_class, PROP_APERTURE,
402       GST_PHOTOGRAPHY_PROP_APERTURE);
403   g_object_class_override_property (gobject_class, PROP_EXPOSURE_TIME,
404       GST_PHOTOGRAPHY_PROP_EXPOSURE_TIME);
405   g_object_class_override_property (gobject_class,
406       PROP_IMAGE_PREVIEW_SUPPORTED_CAPS,
407       GST_PHOTOGRAPHY_PROP_IMAGE_PREVIEW_SUPPORTED_CAPS);
408   g_object_class_override_property (gobject_class,
409       PROP_IMAGE_CAPTURE_SUPPORTED_CAPS,
410       GST_PHOTOGRAPHY_PROP_IMAGE_CAPTURE_SUPPORTED_CAPS);
411   g_object_class_override_property (gobject_class, PROP_ZOOM,
412       GST_PHOTOGRAPHY_PROP_ZOOM);
413   g_object_class_override_property (gobject_class, PROP_COLOR_TEMPERATURE,
414       GST_PHOTOGRAPHY_PROP_COLOR_TEMPERATURE);
415   g_object_class_override_property (gobject_class, PROP_WHITE_POINT,
416       GST_PHOTOGRAPHY_PROP_WHITE_POINT);
417   g_object_class_override_property (gobject_class, PROP_ANALOG_GAIN,
418       GST_PHOTOGRAPHY_PROP_ANALOG_GAIN);
419   g_object_class_override_property (gobject_class, PROP_LENS_FOCUS,
420       GST_PHOTOGRAPHY_PROP_LENS_FOCUS);
421   g_object_class_override_property (gobject_class, PROP_MIN_EXPOSURE_TIME,
422       GST_PHOTOGRAPHY_PROP_MIN_EXPOSURE_TIME);
423   g_object_class_override_property (gobject_class, PROP_MAX_EXPORURE_TIME,
424       GST_PHOTOGRAPHY_PROP_MAX_EXPOSURE_TIME);
425   g_object_class_override_property (gobject_class, PROP_NOISE_REDUCTION,
426       GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION);
427 }
428 
429 static void
gst_test_video_src_init(GstTestVideoSrc * self)430 gst_test_video_src_init (GstTestVideoSrc * self)
431 {
432   gst_base_src_set_format (GST_BASE_SRC (self), GST_FORMAT_TIME);
433 }
434 
435 /* end of custom test camera src element */
436 /* end of custom video source element that implements GstPhotography iface */
437 
438 
439 static GstElement *camera;
440 static GstElement *testsrc;
441 static GstBus *bus = NULL;
442 static GMainLoop *main_loop;
443 static gint capture_count = 0;
444 guint32 test_id = 0;
445 static gchar *image_filename;
446 static gchar *video_filename;
447 
448 static GstSample *preview_sample;
449 static gchar *preview_filename;
450 static GstCaps *preview_caps;
451 static GstTagList *tags_found;
452 
453 static gboolean
454 validity_bus_cb (GstBus * bus, GstMessage * message, gpointer data);
455 
456 static GstMessage *wait_for_element_message (GstElement * camera,
457     const gchar * name, GstClockTime timeout);
458 
459 static void
validate_taglist_foreach(const GstTagList * list,const gchar * tag,gpointer user_data)460 validate_taglist_foreach (const GstTagList * list, const gchar * tag,
461     gpointer user_data)
462 {
463   GstTagList *other = GST_TAG_LIST (user_data);
464 
465   const GValue *val1 = gst_tag_list_get_value_index (list, tag, 0);
466   const GValue *val2 = gst_tag_list_get_value_index (other, tag, 0);
467 
468   GST_DEBUG ("checking tag '%s'", tag);
469 
470   fail_if (val1 == NULL);
471   fail_if (val2 == NULL);
472 
473   fail_unless (gst_value_compare (val1, val2) == GST_VALUE_EQUAL);
474 }
475 
476 
477 /* helper function for filenames */
478 static gchar *
make_test_file_name(const gchar * base_name,gint num)479 make_test_file_name (const gchar * base_name, gint num)
480 {
481   /* num == -1 means to keep the %d in the resulting string to be used on
482    * multifilesink like location */
483   if (num == -1) {
484     return g_strdup_printf ("%s" G_DIR_SEPARATOR_S
485         "gstcamerabintest_%s_%u_%%03d.cap", g_get_tmp_dir (), base_name,
486         test_id);
487   } else {
488     return g_strdup_printf ("%s" G_DIR_SEPARATOR_S
489         "gstcamerabintest_%s_%u_%03d.cap", g_get_tmp_dir (), base_name,
490         test_id, num);
491   }
492 }
493 
494 static const gchar *
make_const_file_name(const gchar * filename,gint num)495 make_const_file_name (const gchar * filename, gint num)
496 {
497   static gchar file_name[1000];
498 
499   /* num == -1 means to keep the %d in the resulting string to be used on
500    * multifilesink like location */
501   g_snprintf (file_name, 999, filename, num);
502 
503   return file_name;
504 }
505 
506 /* configuration */
507 
508 static gboolean
capture_bus_cb(GstBus * bus,GstMessage * message,gpointer data)509 capture_bus_cb (GstBus * bus, GstMessage * message, gpointer data)
510 {
511   GMainLoop *loop = (GMainLoop *) data;
512   const GstStructure *st;
513 
514   switch (GST_MESSAGE_TYPE (message)) {
515     case GST_MESSAGE_ERROR:{
516       GError *err = NULL;
517       gchar *debug = NULL;
518 
519       gst_message_parse_error (message, &err, &debug);
520       GST_WARNING ("ERROR: %s [%s]", err->message, debug);
521       g_error_free (err);
522       g_free (debug);
523       /* Write debug graph to file */
524       GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camera),
525           GST_DEBUG_GRAPH_SHOW_ALL, "camerabin.error");
526 
527       fail_if (TRUE, "error while capturing");
528       g_main_loop_quit (loop);
529       break;
530     }
531     case GST_MESSAGE_WARNING:{
532       GError *err = NULL;
533       gchar *debug = NULL;
534 
535       gst_message_parse_warning (message, &err, &debug);
536       GST_WARNING ("WARNING: %s [%s]", err->message, debug);
537       g_error_free (err);
538       g_free (debug);
539       /* Write debug graph to file */
540       GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camera),
541           GST_DEBUG_GRAPH_SHOW_ALL, "camerabin.warning");
542       break;
543     }
544     case GST_MESSAGE_EOS:
545       GST_DEBUG ("eos");
546       g_main_loop_quit (loop);
547       break;
548     default:
549       st = gst_message_get_structure (message);
550       if (st && gst_structure_has_name (st, "image-done")) {
551         GST_INFO ("image captured");
552       } else if (st && gst_structure_has_name (st,
553               GST_BASE_CAMERA_SRC_PREVIEW_MESSAGE_NAME)) {
554         GstSample *sample;
555         const GValue *value;
556 
557         value = gst_structure_get_value (st, "sample");
558         fail_unless (value != NULL);
559         sample = gst_value_get_sample (value);
560 
561         if (preview_sample)
562           gst_sample_unref (preview_sample);
563         preview_sample = gst_sample_ref (sample);
564         g_free (preview_filename);
565         preview_filename = g_strdup (gst_structure_get_string (st, "location"));
566       }
567       break;
568   }
569   return TRUE;
570 }
571 
572 static void
check_preview_image(GstElement * camera,const gchar * filename,gint index)573 check_preview_image (GstElement * camera, const gchar * filename, gint index)
574 {
575   gchar *prev_filename = NULL;
576 
577   if (!preview_sample && camera) {
578     GstMessage *msg = wait_for_element_message (camera,
579         GST_BASE_CAMERA_SRC_PREVIEW_MESSAGE_NAME, GST_CLOCK_TIME_NONE);
580     fail_unless (msg != NULL);
581     gst_message_unref (msg);
582   }
583   fail_unless (preview_sample != NULL);
584   if (filename) {
585     if (index >= 0) {
586       prev_filename = g_strdup_printf (filename, index);
587     } else {
588       prev_filename = g_strdup (filename);
589     }
590     fail_unless (preview_filename != NULL);
591     fail_unless (strcmp (preview_filename, prev_filename) == 0);
592   }
593   if (preview_caps) {
594     fail_unless (gst_sample_get_caps (preview_sample) != NULL);
595     fail_unless (gst_caps_can_intersect (gst_sample_get_caps (preview_sample),
596             preview_caps));
597   }
598   g_free (prev_filename);
599 
600   /* clean up preview info for next capture */
601   g_free (preview_filename);
602   preview_filename = NULL;
603   if (preview_sample)
604     gst_sample_unref (preview_sample);
605   preview_sample = NULL;
606 }
607 
608 static void
extract_jpeg_tags(const gchar * filename,gint num)609 extract_jpeg_tags (const gchar * filename, gint num)
610 {
611   GstBus *bus;
612   GMainLoop *loop = g_main_loop_new (NULL, FALSE);
613   const gchar *filepath = make_const_file_name (filename, num);
614   gchar *pipeline_str = g_strdup_printf ("filesrc location=%s ! "
615       "jpegparse ! fakesink", filepath);
616   GstElement *pipeline;
617 
618   pipeline = gst_parse_launch (pipeline_str, NULL);
619   fail_unless (pipeline != NULL);
620   g_free (pipeline_str);
621 
622   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
623   gst_bus_add_watch (bus, (GstBusFunc) validity_bus_cb, loop);
624 
625   gst_element_set_state (pipeline, GST_STATE_PLAYING);
626   g_main_loop_run (loop);
627   gst_element_set_state (pipeline, GST_STATE_NULL);
628 
629   gst_bus_remove_watch (bus);
630   gst_object_unref (bus);
631   gst_object_unref (pipeline);
632   g_main_loop_unref (loop);
633 }
634 
635 static void
setup_camerabin_common(void)636 setup_camerabin_common (void)
637 {
638   test_id = g_random_int ();
639 
640   main_loop = g_main_loop_new (NULL, TRUE);
641 
642   camera = gst_check_setup_element ("camerabin");
643   fail_unless (camera != NULL, "failed to create camerabin element");
644 
645   bus = gst_pipeline_get_bus (GST_PIPELINE (camera));
646   gst_bus_add_watch (bus, (GstBusFunc) capture_bus_cb, main_loop);
647 
648   tags_found = NULL;
649   capture_count = 0;
650   image_filename = make_test_file_name (IMAGE_FILENAME, -1);
651   video_filename = make_test_file_name (VIDEO_FILENAME, -1);
652 }
653 
654 static void
setup_wrappercamerabinsrc_videotestsrc(void)655 setup_wrappercamerabinsrc_videotestsrc (void)
656 {
657   GstElement *vfbin;
658   GstElement *fakevideosink;
659   GstElement *src;
660   GstElement *testsrc;
661   GstElement *audiosrc;
662 
663   GST_INFO ("init");
664 
665   setup_camerabin_common ();
666 
667   fakevideosink = gst_element_factory_make ("fakesink", NULL);
668   fail_unless (fakevideosink != NULL, "failed to create fakesink element");
669   src = gst_element_factory_make ("wrappercamerabinsrc", NULL);
670   fail_unless (src != NULL, "failed to create wrappercamerabinsrc element");
671   testsrc = gst_element_factory_make ("videotestsrc", NULL);
672   fail_unless (testsrc != NULL, "failed to create videotestsrc element");
673   audiosrc = gst_element_factory_make ("audiotestsrc", NULL);
674   fail_unless (audiosrc != NULL, "failed to create audiotestsrc element");
675 
676   preview_caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT,
677       320, "height", G_TYPE_INT, 240, NULL);
678 
679   g_object_set (G_OBJECT (testsrc), "is-live", TRUE, NULL);
680   g_object_set (G_OBJECT (audiosrc), "is-live", TRUE, NULL);
681   g_object_set (G_OBJECT (src), "video-source", testsrc, NULL);
682   g_object_set (G_OBJECT (camera), "camera-source", src, "preview-caps",
683       preview_caps, "post-previews", TRUE, "audio-source", audiosrc, NULL);
684   gst_object_unref (src);
685   gst_object_unref (testsrc);
686   gst_object_unref (audiosrc);
687 
688   vfbin = gst_bin_get_by_name (GST_BIN (camera), "vf-bin");
689   g_object_set (G_OBJECT (vfbin), "video-sink", fakevideosink, NULL);
690   gst_object_unref (vfbin);
691   gst_object_unref (fakevideosink);
692 
693   GST_INFO ("init finished");
694 }
695 
696 static void
setup_test_camerasrc(void)697 setup_test_camerasrc (void)
698 {
699   GstElement *vfbin;
700   GstElement *fakevideosink;
701   GstElement *src;
702   GstElement *audiosrc;
703 
704   GST_INFO ("init");
705 
706   setup_camerabin_common ();
707 
708   fakevideosink = gst_element_factory_make ("fakesink", NULL);
709   fail_unless (fakevideosink != NULL, "failed to create fakesink element");
710   src = gst_element_factory_make ("wrappercamerabinsrc", NULL);
711   fail_unless (src != NULL, "failed to create wrappercamerabinsrc element");
712   testsrc = g_object_new (GST_TYPE_TEST_VIDEO_SRC, NULL);
713   fail_unless (testsrc != NULL, "failed to create testvideosrc element");
714   g_object_set (testsrc, "name", "testsrc", NULL);
715   audiosrc = gst_element_factory_make ("audiotestsrc", NULL);
716   fail_unless (audiosrc != NULL, "failed to create audiotestsrc element");
717 
718   preview_caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT,
719       320, "height", G_TYPE_INT, 240, NULL);
720 
721   g_object_set (G_OBJECT (audiosrc), "is-live", TRUE, NULL);
722   g_object_set (G_OBJECT (src), "video-source", testsrc, NULL);
723   g_object_set (G_OBJECT (camera), "camera-source", src, "preview-caps",
724       preview_caps, "post-previews", TRUE, "audio-source", audiosrc, NULL);
725   gst_object_unref (src);
726   gst_object_unref (testsrc);
727   gst_object_unref (audiosrc);
728 
729   vfbin = gst_bin_get_by_name (GST_BIN (camera), "vf-bin");
730   g_object_set (G_OBJECT (vfbin), "video-sink", fakevideosink, NULL);
731   gst_object_unref (vfbin);
732   gst_object_unref (fakevideosink);
733 
734   GST_INFO ("init finished");
735 }
736 
737 static void
teardown(void)738 teardown (void)
739 {
740   gst_element_set_state (camera, GST_STATE_NULL);
741 
742   if (camera)
743     gst_check_teardown_element (camera);
744   camera = NULL;
745 
746   if (bus) {
747     gst_bus_remove_watch (bus);
748     gst_object_unref (bus);
749   }
750 
751   if (main_loop)
752     g_main_loop_unref (main_loop);
753   main_loop = NULL;
754 
755   if (preview_caps)
756     gst_caps_unref (preview_caps);
757   preview_caps = NULL;
758 
759   if (preview_sample)
760     gst_sample_unref (preview_sample);
761   preview_sample = NULL;
762 
763   g_free (preview_filename);
764   preview_filename = NULL;
765 
766   if (tags_found)
767     gst_tag_list_unref (tags_found);
768   tags_found = NULL;
769 
770   g_free (video_filename);
771   video_filename = NULL;
772 
773   g_free (image_filename);
774   image_filename = NULL;
775 
776   GST_INFO ("done");
777 }
778 
779 static gboolean
validity_bus_cb(GstBus * bus,GstMessage * message,gpointer data)780 validity_bus_cb (GstBus * bus, GstMessage * message, gpointer data)
781 {
782   GMainLoop *loop = (GMainLoop *) data;
783   switch (GST_MESSAGE_TYPE (message)) {
784     case GST_MESSAGE_ERROR:{
785       GError *err = NULL;
786       gchar *debug = NULL;
787 
788       gst_message_parse_error (message, &err, &debug);
789 
790       GST_ERROR ("Error: %s : %s", err->message, debug);
791       g_error_free (err);
792       g_free (debug);
793 
794       fail_if (TRUE, "validating captured data failed");
795       g_main_loop_quit (loop);
796     }
797       break;
798     case GST_MESSAGE_EOS:
799       g_main_loop_quit (loop);
800       GST_DEBUG ("eos");
801       break;
802     case GST_MESSAGE_TAG:{
803       GstTagList *taglist = NULL;
804 
805       gst_message_parse_tag (message, &taglist);
806       if (tags_found) {
807         gst_tag_list_insert (tags_found, taglist, GST_TAG_MERGE_REPLACE);
808         gst_tag_list_unref (taglist);
809       } else {
810         tags_found = taglist;
811       }
812       GST_DEBUG ("tags: %" GST_PTR_FORMAT, tags_found);
813     }
814       break;
815     default:
816       break;
817   }
818   return TRUE;
819 }
820 
821 /* checks that tags in @tags_a are in @tags_b */
822 static gboolean
taglist_is_subset(GstTagList * tags_a,GstTagList * tags_b)823 taglist_is_subset (GstTagList * tags_a, GstTagList * tags_b)
824 {
825   gst_tag_list_foreach (tags_a, validate_taglist_foreach, tags_b);
826   return TRUE;
827 }
828 
829 /* Validate captured files by playing them with playbin
830  * and checking that no errors occur. */
831 #define WITH_AUDIO TRUE
832 #define NO_AUDIO FALSE
833 static gboolean
check_file_validity(const gchar * filename,gint num,GstTagList * taglist,gint width,gint height,gboolean has_audio)834 check_file_validity (const gchar * filename, gint num, GstTagList * taglist,
835     gint width, gint height, gboolean has_audio)
836 {
837   GstBus *bus;
838   GstPad *pad;
839   GstCaps *caps;
840   gint caps_width, caps_height;
841   GstState state;
842 
843   GMainLoop *loop = g_main_loop_new (NULL, FALSE);
844   GstElement *playbin = gst_element_factory_make ("playbin", NULL);
845   GstElement *fakevideo = gst_element_factory_make ("fakesink", NULL);
846   GstElement *fakeaudio = gst_element_factory_make ("fakesink", NULL);
847   gchar *uri = g_strconcat ("file://", make_const_file_name (filename, num),
848       NULL);
849 
850   GST_DEBUG ("checking uri: %s", uri);
851   g_object_set (G_OBJECT (playbin), "uri", uri, "video-sink", fakevideo,
852       "audio-sink", fakeaudio, NULL);
853 
854   bus = gst_pipeline_get_bus (GST_PIPELINE (playbin));
855   gst_bus_add_watch (bus, (GstBusFunc) validity_bus_cb, loop);
856 
857   gst_element_set_state (playbin, GST_STATE_PAUSED);
858   gst_element_get_state (playbin, &state, NULL, GST_SECOND * 3);
859 
860   if (width != 0 && height != 0) {
861     g_signal_emit_by_name (playbin, "get-video-pad", 0, &pad, NULL);
862     g_assert (pad != NULL);
863     caps = gst_pad_get_current_caps (pad);
864 
865     g_assert (gst_structure_get_int (gst_caps_get_structure (caps, 0),
866             "width", &caps_width));
867     g_assert (gst_structure_get_int (gst_caps_get_structure (caps, 0),
868             "height", &caps_height));
869 
870     g_assert (width == caps_width);
871     g_assert (height == caps_height);
872 
873     gst_caps_unref (caps);
874     gst_object_unref (pad);
875   }
876   if (has_audio) {
877     g_signal_emit_by_name (playbin, "get-audio-pad", 0, &pad, NULL);
878     g_assert (pad != NULL);
879     gst_object_unref (pad);
880   }
881 
882   gst_element_set_state (playbin, GST_STATE_PLAYING);
883   g_main_loop_run (loop);
884   gst_element_set_state (playbin, GST_STATE_NULL);
885 
886   /* special handling for images (jpg) as jpegparse isn't plugged by
887    * default due to its current low rank */
888   if (taglist && strstr (filename, "image")) {
889     extract_jpeg_tags (filename, num);
890   }
891 
892   if (taglist) {
893     fail_unless (tags_found != NULL);
894     fail_unless (taglist_is_subset (taglist, tags_found));
895   }
896 
897   g_free (uri);
898   gst_bus_remove_watch (bus);
899   gst_object_unref (bus);
900   gst_object_unref (playbin);
901   g_main_loop_unref (loop);
902 
903   return TRUE;
904 }
905 
906 static void
remove_file(const gchar * fn_template,guint num)907 remove_file (const gchar * fn_template, guint num)
908 {
909   const gchar *fn;
910 
911   fn = make_const_file_name (fn_template, num);
912   GST_INFO ("removing %s", fn);
913   g_unlink (fn);
914 }
915 
916 static GstPadProbeReturn
filter_buffer_count(GstPad * pad,GstPadProbeInfo * info,gpointer data)917 filter_buffer_count (GstPad * pad, GstPadProbeInfo * info, gpointer data)
918 {
919   gint *counter = data;
920 
921   (*counter)++;
922 
923   return GST_PAD_PROBE_OK;
924 }
925 
926 static GstMessage *
wait_for_element_message(GstElement * camera,const gchar * name,GstClockTime timeout)927 wait_for_element_message (GstElement * camera, const gchar * name,
928     GstClockTime timeout)
929 {
930   GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (camera));
931   GstMessage *msg;
932 
933   while (1) {
934     msg = gst_bus_timed_pop_filtered (bus, timeout, GST_MESSAGE_ERROR |
935         GST_MESSAGE_EOS | GST_MESSAGE_ELEMENT);
936 
937     if (msg) {
938       if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ELEMENT) {
939         const GstStructure *st = gst_message_get_structure (msg);
940         if (gst_structure_has_name (st,
941                 GST_BASE_CAMERA_SRC_PREVIEW_MESSAGE_NAME)) {
942           GstSample *sample;
943           const GValue *value;
944 
945           value = gst_structure_get_value (st, "sample");
946           fail_unless (value != NULL);
947           sample = gst_value_get_sample (value);
948 
949           if (preview_sample)
950             gst_sample_unref (preview_sample);
951           preview_sample = gst_sample_ref (sample);
952           g_free (preview_filename);
953           preview_filename =
954               g_strdup (gst_structure_get_string (st, "location"));
955         }
956 
957         if (gst_structure_has_name (st, name))
958           break;
959         else
960           gst_message_unref (msg);
961       } else {
962         gst_message_unref (msg);
963         msg = NULL;
964         break;
965       }
966     }
967   }
968 
969   gst_object_unref (bus);
970   return msg;
971 }
972 
973 static void
wait_for_idle_state(void)974 wait_for_idle_state (void)
975 {
976   gboolean idle = FALSE;
977 
978   /* not the ideal way, but should be enough for testing */
979   while (idle == FALSE) {
980     g_object_get (camera, "idle", &idle, NULL);
981     if (idle)
982       break;
983 
984     GST_LOG ("waiting for idle state..");
985     g_usleep (G_USEC_PER_SEC / 5);
986   }
987   fail_unless (idle);
988 }
989 
990 static void
run_single_image_capture_test(GstCaps * viewfinder_caps,GstCaps * image_caps)991 run_single_image_capture_test (GstCaps * viewfinder_caps, GstCaps * image_caps)
992 {
993   gboolean idle;
994   GstMessage *msg;
995   if (!camera)
996     return;
997 
998   /* set still image mode */
999   g_object_set (camera, "mode", 1, "location", image_filename, NULL);
1000 
1001   if (viewfinder_caps)
1002     g_object_set (camera, "viewfinder-caps", viewfinder_caps, NULL);
1003   if (image_caps)
1004     g_object_set (camera, "image-capture-caps", image_caps, NULL);
1005 
1006   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1007       GST_STATE_CHANGE_FAILURE) {
1008     GST_WARNING ("setting camerabin to PLAYING failed");
1009     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1010     gst_object_unref (camera);
1011     camera = NULL;
1012   }
1013   GST_INFO ("starting capture");
1014   fail_unless (camera != NULL);
1015   g_object_get (camera, "idle", &idle, NULL);
1016   fail_unless (idle);
1017   g_signal_emit_by_name (camera, "start-capture", NULL);
1018 
1019   msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE);
1020   fail_unless (msg != NULL);
1021   gst_message_unref (msg);
1022 
1023   /* check that we got a preview image */
1024   check_preview_image (camera, image_filename, 0);
1025 
1026   wait_for_idle_state ();
1027   gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1028   check_file_validity (image_filename, 0, NULL, 0, 0, NO_AUDIO);
1029   remove_file (image_filename, 0);
1030 }
1031 
GST_START_TEST(test_single_image_capture)1032 GST_START_TEST (test_single_image_capture)
1033 {
1034   run_single_image_capture_test (NULL, NULL);
1035 }
1036 
1037 GST_END_TEST;
1038 
1039 
1040 /* Verify that incompatible caps can be used in viewfinder and image capture
1041  * at the same time */
GST_START_TEST(test_single_image_capture_with_different_caps)1042 GST_START_TEST (test_single_image_capture_with_different_caps)
1043 {
1044   GstCaps *vf_caps =
1045       gst_caps_from_string ("video/x-raw, width=480, height=320");
1046   GstCaps *img_caps =
1047       gst_caps_from_string ("video/x-raw, width=800, height=600");
1048   run_single_image_capture_test (vf_caps, img_caps);
1049   gst_caps_unref (vf_caps);
1050   gst_caps_unref (img_caps);
1051 }
1052 
1053 GST_END_TEST;
1054 
1055 
GST_START_TEST(test_multiple_image_captures)1056 GST_START_TEST (test_multiple_image_captures)
1057 {
1058   gboolean idle;
1059   gint i;
1060   gint widths[] = { 800, 640, 1280 };
1061   gint heights[] = { 600, 480, 1024 };
1062 
1063   if (!camera)
1064     return;
1065 
1066   /* set still image mode */
1067   g_object_set (camera, "mode", 1, "location", image_filename, NULL);
1068 
1069   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1070       GST_STATE_CHANGE_FAILURE) {
1071     GST_WARNING ("setting camerabin to PLAYING failed");
1072     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1073     gst_object_unref (camera);
1074     camera = NULL;
1075   }
1076   fail_unless (camera != NULL);
1077   g_object_get (camera, "idle", &idle, NULL);
1078   fail_unless (idle);
1079   GST_INFO ("starting capture");
1080 
1081   for (i = 0; i < 3; i++) {
1082     GstMessage *msg;
1083     GstCaps *caps;
1084 
1085     caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT,
1086         widths[i], "height", G_TYPE_INT, heights[i], NULL);
1087 
1088     g_object_set (camera, "image-capture-caps", caps, NULL);
1089     gst_caps_unref (caps);
1090 
1091     g_signal_emit_by_name (camera, "start-capture", NULL);
1092 
1093     msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE);
1094     fail_unless (msg != NULL);
1095     if (msg)
1096       gst_message_unref (msg);
1097 
1098     check_preview_image (camera, image_filename, i);
1099   }
1100 
1101   wait_for_idle_state ();
1102   gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1103   for (i = 0; i < 3; i++) {
1104     check_file_validity (image_filename, i, NULL, widths[i], heights[i],
1105         NO_AUDIO);
1106     remove_file (image_filename, i);
1107   }
1108 }
1109 
1110 GST_END_TEST;
1111 
GST_START_TEST(test_single_video_recording)1112 GST_START_TEST (test_single_video_recording)
1113 {
1114   GstMessage *msg;
1115   gboolean idle;
1116   if (!camera)
1117     return;
1118 
1119   /* Set video recording mode */
1120   g_object_set (camera, "mode", 2, "location", video_filename, NULL);
1121 
1122   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1123       GST_STATE_CHANGE_FAILURE) {
1124     GST_WARNING ("setting camerabin to PLAYING failed");
1125     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1126     gst_object_unref (camera);
1127     camera = NULL;
1128   }
1129 
1130   GST_INFO ("starting capture");
1131   fail_unless (camera != NULL);
1132   g_object_get (camera, "idle", &idle, NULL);
1133   fail_unless (idle);
1134   g_signal_emit_by_name (camera, "start-capture", NULL);
1135 
1136   g_object_get (camera, "idle", &idle, NULL);
1137   fail_unless (!idle);
1138 
1139   /* Record for one seconds  */
1140   g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit,
1141       main_loop);
1142   g_main_loop_run (main_loop);
1143 
1144   g_signal_emit_by_name (camera, "stop-capture", NULL);
1145 
1146   check_preview_image (camera, video_filename, 0);
1147 
1148   msg = wait_for_element_message (camera, "video-done", GST_CLOCK_TIME_NONE);
1149   fail_unless (msg != NULL);
1150   gst_message_unref (msg);
1151 
1152   wait_for_idle_state ();
1153   gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1154 
1155   check_file_validity (video_filename, 0, NULL, 0, 0, WITH_AUDIO);
1156   remove_file (video_filename, 0);
1157 
1158 }
1159 
1160 GST_END_TEST;
1161 
GST_START_TEST(test_multiple_video_recordings)1162 GST_START_TEST (test_multiple_video_recordings)
1163 {
1164   gboolean idle;
1165   gint i;
1166   gint widths[] = { 800, 640, 1280 };
1167   gint heights[] = { 600, 480, 1024 };
1168   gint fr[] = { 20, 30, 5 };
1169 
1170   if (!camera)
1171     return;
1172 
1173   /* Set video recording mode */
1174   g_object_set (camera, "mode", 2, "location", video_filename, NULL);
1175 
1176   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1177       GST_STATE_CHANGE_FAILURE) {
1178     GST_WARNING ("setting camerabin to PLAYING failed");
1179     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1180     gst_object_unref (camera);
1181     camera = NULL;
1182   }
1183 
1184   GST_INFO ("starting capture");
1185   fail_unless (camera != NULL);
1186   g_object_get (camera, "idle", &idle, NULL);
1187   fail_unless (idle);
1188   for (i = 0; i < 3; i++) {
1189     GstMessage *msg;
1190     GstCaps *caps;
1191 
1192     caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT,
1193         widths[i], "height", G_TYPE_INT, heights[i], "framerate",
1194         GST_TYPE_FRACTION, fr[i], 1, NULL);
1195 
1196     g_object_set (camera, "video-capture-caps", caps, NULL);
1197 
1198     gst_caps_unref (caps);
1199 
1200     GST_LOG ("starting #%d with caps %" GST_PTR_FORMAT, i, caps);
1201     g_signal_emit_by_name (camera, "start-capture", NULL);
1202 
1203     g_object_get (camera, "idle", &idle, NULL);
1204     fail_unless (!idle);
1205 
1206     g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit,
1207         main_loop);
1208     g_main_loop_run (main_loop);
1209 
1210     GST_LOG ("stopping run %d", i);
1211     g_signal_emit_by_name (camera, "stop-capture", NULL);
1212 
1213     msg = wait_for_element_message (camera, "video-done", GST_CLOCK_TIME_NONE);
1214     fail_unless (msg != NULL);
1215     gst_message_unref (msg);
1216 
1217     GST_LOG ("video done, checking preview image");
1218     check_preview_image (camera, video_filename, i);
1219 
1220     GST_LOG ("waiting for idle state");
1221     wait_for_idle_state ();
1222     GST_LOG ("finished run %d", i);
1223   }
1224   gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1225 
1226   for (i = 0; i < 3; i++) {
1227     check_file_validity (video_filename, i, NULL, widths[i], heights[i],
1228         WITH_AUDIO);
1229     remove_file (video_filename, i);
1230   }
1231 }
1232 
1233 GST_END_TEST;
1234 
GST_START_TEST(test_image_video_cycle)1235 GST_START_TEST (test_image_video_cycle)
1236 {
1237   gint i;
1238 
1239   if (!camera)
1240     return;
1241 
1242   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1243       GST_STATE_CHANGE_FAILURE) {
1244     GST_WARNING ("setting camerabin to PLAYING failed");
1245     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1246     gst_object_unref (camera);
1247     camera = NULL;
1248   }
1249 
1250   GST_INFO ("starting capture");
1251   for (i = 0; i < 2; i++) {
1252     GstMessage *msg;
1253     const gchar *img_filename;
1254     const gchar *vid_filename;
1255 
1256     wait_for_idle_state ();
1257 
1258     /* take a picture */
1259     img_filename = make_const_file_name (image_filename, i);
1260     g_object_set (camera, "mode", 1, NULL);
1261     g_object_set (camera, "location", img_filename, NULL);
1262     g_signal_emit_by_name (camera, "start-capture", NULL);
1263 
1264     msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE);
1265     fail_unless (msg != NULL);
1266     gst_message_unref (msg);
1267 
1268     check_preview_image (camera, img_filename, i);
1269 
1270     /* now go to video */
1271     vid_filename = make_const_file_name (video_filename, i);
1272     g_object_set (camera, "mode", 2, NULL);
1273     g_object_set (camera, "location", vid_filename, NULL);
1274 
1275     g_signal_emit_by_name (camera, "start-capture", NULL);
1276     g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit,
1277         main_loop);
1278     g_main_loop_run (main_loop);
1279     g_signal_emit_by_name (camera, "stop-capture", NULL);
1280 
1281     msg = wait_for_element_message (camera, "video-done", GST_CLOCK_TIME_NONE);
1282     fail_unless (msg != NULL);
1283     gst_message_unref (msg);
1284 
1285     check_preview_image (camera, vid_filename, i);
1286   }
1287 
1288   wait_for_idle_state ();
1289   gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1290 
1291   /* validate all the files */
1292   for (i = 0; i < 2; i++) {
1293     check_file_validity (image_filename, i, NULL, 0, 0, NO_AUDIO);
1294     remove_file (image_filename, i);
1295     check_file_validity (video_filename, i, NULL, 0, 0, WITH_AUDIO);
1296     remove_file (video_filename, i);
1297   }
1298 }
1299 
1300 GST_END_TEST;
1301 
1302 
GST_START_TEST(test_image_capture_previews)1303 GST_START_TEST (test_image_capture_previews)
1304 {
1305   gint i;
1306   gint widths[] = { 800, 640, 1280 };
1307   gint heights[] = { 600, 480, 1024 };
1308 
1309   if (!camera)
1310     return;
1311 
1312   /* set still image mode */
1313   g_object_set (camera, "mode", 1, "location", image_filename, NULL);
1314 
1315   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1316       GST_STATE_CHANGE_FAILURE) {
1317     GST_WARNING ("setting camerabin to PLAYING failed");
1318     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1319     gst_object_unref (camera);
1320     camera = NULL;
1321   }
1322   fail_unless (camera != NULL);
1323   GST_INFO ("starting capture");
1324 
1325   for (i = 0; i < 3; i++) {
1326     GstMessage *msg;
1327     GstCaps *caps;
1328 
1329     caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT,
1330         widths[i], "height", G_TYPE_INT, heights[i], NULL);
1331 
1332     g_object_set (camera, "preview-caps", caps, NULL);
1333     gst_caps_replace (&preview_caps, caps);
1334     gst_caps_unref (caps);
1335 
1336     g_signal_emit_by_name (camera, "start-capture", NULL);
1337 
1338     msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE);
1339     fail_unless (msg != NULL);
1340     gst_message_unref (msg);
1341 
1342     check_preview_image (camera, image_filename, i);
1343     remove_file (image_filename, i);
1344 
1345     if (preview_sample)
1346       gst_sample_unref (preview_sample);
1347     preview_sample = NULL;
1348     gst_caps_replace (&preview_caps, NULL);
1349   }
1350 
1351   gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1352 }
1353 
1354 GST_END_TEST;
1355 
1356 
GST_START_TEST(test_image_capture_with_tags)1357 GST_START_TEST (test_image_capture_with_tags)
1358 {
1359   gint i;
1360   GstTagList *taglists[3];
1361 
1362   if (!camera)
1363     return;
1364 
1365   taglists[0] = gst_tag_list_new (GST_TAG_COMMENT, "test1",
1366       GST_TAG_GEO_LOCATION_LATITUDE, 36.6, GST_TAG_GEO_LOCATION_LONGITUDE,
1367       -12.5,
1368       GST_TAG_COPYRIGHT, "My copyright notice",
1369       GST_TAG_DEVICE_MANUFACTURER, "MyFavoriteBrand",
1370       GST_TAG_DEVICE_MODEL, "123v42.1",
1371       GST_TAG_DESCRIPTION, "some description",
1372       GST_TAG_APPLICATION_NAME, "camerabin test",
1373       GST_TAG_GEO_LOCATION_ELEVATION, 300.85, NULL);
1374   taglists[1] = gst_tag_list_new (GST_TAG_COMMENT, "test2",
1375       GST_TAG_GEO_LOCATION_LATITUDE, 1.6, GST_TAG_GEO_LOCATION_LONGITUDE,
1376       0.0,
1377       GST_TAG_COPYRIGHT, "some cp",
1378       GST_TAG_DEVICE_MANUFACTURER, "ABRAND",
1379       GST_TAG_DEVICE_MODEL, "abcd",
1380       GST_TAG_DESCRIPTION, "desc",
1381       GST_TAG_APPLICATION_NAME, "another cam test",
1382       GST_TAG_GEO_LOCATION_ELEVATION, 10.0, NULL);
1383   taglists[2] = gst_tag_list_new (GST_TAG_COMMENT, "test3",
1384       GST_TAG_GEO_LOCATION_LATITUDE, 1.3, GST_TAG_GEO_LOCATION_LONGITUDE,
1385       -5.0,
1386       GST_TAG_COPYRIGHT, "CC",
1387       GST_TAG_DEVICE_MANUFACTURER, "Homemade",
1388       GST_TAG_DEVICE_MODEL, "xpto",
1389       GST_TAG_DESCRIPTION, "another  description",
1390       GST_TAG_APPLICATION_NAME, "cam2 test",
1391       GST_TAG_GEO_LOCATION_ELEVATION, 0.0, NULL);
1392 
1393   /* set still image mode */
1394   g_object_set (camera, "mode", 1, "location", image_filename, NULL);
1395 
1396   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1397       GST_STATE_CHANGE_FAILURE) {
1398     GST_WARNING ("setting camerabin to PLAYING failed");
1399     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1400     gst_object_unref (camera);
1401     camera = NULL;
1402   }
1403   fail_unless (camera != NULL);
1404   GST_INFO ("starting capture");
1405 
1406   for (i = 0; i < 3; i++) {
1407     GstMessage *msg;
1408     gst_tag_setter_merge_tags (GST_TAG_SETTER (camera), taglists[i],
1409         GST_TAG_MERGE_REPLACE);
1410 
1411     g_signal_emit_by_name (camera, "start-capture", NULL);
1412 
1413     msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE);
1414     fail_unless (msg != NULL);
1415     gst_message_unref (msg);
1416   }
1417 
1418   gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1419 
1420   for (i = 0; i < 3; i++) {
1421     check_file_validity (image_filename, i, taglists[i], 0, 0, NO_AUDIO);
1422     gst_tag_list_unref (taglists[i]);
1423     remove_file (image_filename, i);
1424   }
1425 }
1426 
1427 GST_END_TEST;
1428 
1429 
GST_START_TEST(test_video_capture_with_tags)1430 GST_START_TEST (test_video_capture_with_tags)
1431 {
1432   gint i;
1433   GstTagList *taglists[3];
1434 
1435   if (!camera)
1436     return;
1437 
1438   taglists[0] = gst_tag_list_new (GST_TAG_COMMENT, "test1", NULL);
1439   taglists[1] = gst_tag_list_new (GST_TAG_COMMENT, "test2", NULL);
1440   taglists[2] = gst_tag_list_new (GST_TAG_COMMENT, "test3", NULL);
1441 
1442   /* set video mode */
1443   g_object_set (camera, "mode", 2, "location", video_filename, NULL);
1444 
1445   /* set a profile that has xmp support for more tags being saved */
1446   {
1447     GstEncodingContainerProfile *profile;
1448     GstCaps *caps;
1449 
1450     caps =
1451         gst_caps_new_simple ("video/quicktime", "variant", G_TYPE_STRING,
1452         "apple", NULL);
1453     profile = gst_encoding_container_profile_new ("qt", "jpeg+qt", caps, NULL);
1454     gst_caps_unref (caps);
1455 
1456     caps = gst_caps_new_simple ("image/jpeg", NULL, NULL);
1457     if (!gst_encoding_container_profile_add_profile (profile,
1458             (GstEncodingProfile *) gst_encoding_video_profile_new (caps,
1459                 NULL, NULL, 1))) {
1460       GST_WARNING_OBJECT (camera, "Failed to create encoding profiles");
1461     }
1462     gst_caps_unref (caps);
1463 
1464     g_object_set (camera, "video-profile", profile, NULL);
1465     gst_encoding_profile_unref (profile);
1466   }
1467 
1468   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1469       GST_STATE_CHANGE_FAILURE) {
1470     GST_WARNING ("setting camerabin to PLAYING failed");
1471     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1472     gst_object_unref (camera);
1473     camera = NULL;
1474   }
1475   fail_unless (camera != NULL);
1476   GST_INFO ("starting capture");
1477 
1478   for (i = 0; i < 3; i++) {
1479     GstMessage *msg;
1480 
1481     gst_tag_setter_merge_tags (GST_TAG_SETTER (camera), taglists[i],
1482         GST_TAG_MERGE_REPLACE);
1483 
1484     g_signal_emit_by_name (camera, "start-capture", NULL);
1485 
1486     g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop);
1487     g_main_loop_run (main_loop);
1488 
1489     g_signal_emit_by_name (camera, "stop-capture", NULL);
1490 
1491     msg = wait_for_element_message (camera, "video-done", GST_CLOCK_TIME_NONE);
1492     fail_unless (msg != NULL);
1493     gst_message_unref (msg);
1494   }
1495 
1496   gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1497 
1498   for (i = 0; i < 3; i++) {
1499     check_file_validity (video_filename, i, taglists[i], 0, 0, NO_AUDIO);
1500     gst_tag_list_unref (taglists[i]);
1501     remove_file (video_filename, i);
1502   }
1503 }
1504 
1505 GST_END_TEST;
1506 
1507 
GST_START_TEST(test_supported_caps)1508 GST_START_TEST (test_supported_caps)
1509 {
1510   GstCaps *padcaps = NULL;
1511   GstCaps *expectedcaps;
1512   GstElement *src;
1513 
1514   if (!camera)
1515     return;
1516 
1517   src = g_object_new (GST_TYPE_TEST_CAMERA_SRC, NULL);
1518   g_object_set (camera, "camera-source", src, NULL);
1519   gst_object_unref (src);
1520 
1521   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1522       GST_STATE_CHANGE_FAILURE) {
1523     GST_WARNING ("setting camerabin to PLAYING failed");
1524     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1525     gst_object_unref (camera);
1526     camera = NULL;
1527   }
1528   g_assert (camera != NULL);
1529 
1530   expectedcaps = gst_caps_from_string (VIDEO_PAD_SUPPORTED_CAPS);
1531   g_object_get (G_OBJECT (camera), "video-capture-supported-caps", &padcaps,
1532       NULL);
1533   g_assert (expectedcaps != NULL);
1534   g_assert (padcaps != NULL);
1535   g_assert (gst_caps_is_equal (padcaps, expectedcaps));
1536   gst_caps_unref (expectedcaps);
1537   gst_caps_unref (padcaps);
1538 
1539   expectedcaps = gst_caps_from_string (IMAGE_PAD_SUPPORTED_CAPS);
1540   g_object_get (G_OBJECT (camera), "image-capture-supported-caps", &padcaps,
1541       NULL);
1542   g_assert (expectedcaps != NULL);
1543   g_assert (padcaps != NULL);
1544   g_assert (gst_caps_is_equal (padcaps, expectedcaps));
1545   gst_caps_unref (expectedcaps);
1546   gst_caps_unref (padcaps);
1547 
1548   gst_element_set_state (camera, GST_STATE_NULL);
1549 }
1550 
1551 GST_END_TEST;
1552 
1553 
GST_START_TEST(test_idle_property)1554 GST_START_TEST (test_idle_property)
1555 {
1556   GstMessage *msg;
1557   gboolean idle;
1558   if (!camera)
1559     return;
1560 
1561   /* Set video recording mode */
1562   g_object_set (camera, "mode", 2, "location", video_filename, NULL);
1563 
1564   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1565       GST_STATE_CHANGE_FAILURE) {
1566     GST_WARNING ("setting camerabin to PLAYING failed");
1567     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1568     gst_object_unref (camera);
1569     camera = NULL;
1570   }
1571 
1572   GST_INFO ("starting capture");
1573   fail_unless (camera != NULL);
1574   g_object_get (camera, "idle", &idle, NULL);
1575   fail_unless (idle);
1576   g_signal_emit_by_name (camera, "start-capture", NULL);
1577   g_object_get (camera, "idle", &idle, NULL);
1578   fail_unless (!idle);
1579 
1580   /* emit a second start-capture that should be ignored */
1581   g_signal_emit_by_name (camera, "start-capture", NULL);
1582   g_object_get (camera, "idle", &idle, NULL);
1583   fail_unless (!idle);
1584 
1585   /* Record for one seconds  */
1586   g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit,
1587       main_loop);
1588   g_main_loop_run (main_loop);
1589 
1590   g_signal_emit_by_name (camera, "stop-capture", NULL);
1591 
1592   msg = wait_for_element_message (camera, "video-done", GST_CLOCK_TIME_NONE);
1593   fail_unless (msg != NULL);
1594   gst_message_unref (msg);
1595 
1596   check_preview_image (camera, video_filename, 0);
1597 
1598   wait_for_idle_state ();
1599 
1600   gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1601 
1602   check_file_validity (video_filename, 0, NULL, 0, 0, WITH_AUDIO);
1603   remove_file (video_filename, 0);
1604 }
1605 
1606 GST_END_TEST;
1607 
1608 
GST_START_TEST(test_image_custom_filter)1609 GST_START_TEST (test_image_custom_filter)
1610 {
1611   GstElement *vf_filter;
1612   GstElement *image_filter;
1613   GstElement *preview_filter;
1614   GstPad *pad;
1615   gint vf_probe_counter = 0;
1616   gint image_probe_counter = 0;
1617   gint preview_probe_counter = 0;
1618 
1619   if (!camera)
1620     return;
1621 
1622   vf_filter = gst_element_factory_make ("identity", "vf-filter");
1623   image_filter = gst_element_factory_make ("identity", "img-filter");
1624   preview_filter = gst_element_factory_make ("identity", "preview-filter");
1625 
1626   pad = gst_element_get_static_pad (vf_filter, "src");
1627   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
1628       &vf_probe_counter, NULL);
1629   gst_object_unref (pad);
1630 
1631   pad = gst_element_get_static_pad (image_filter, "src");
1632   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
1633       &image_probe_counter, NULL);
1634   gst_object_unref (pad);
1635 
1636   pad = gst_element_get_static_pad (preview_filter, "src");
1637   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
1638       &preview_probe_counter, NULL);
1639   gst_object_unref (pad);
1640 
1641   /* set still image mode and filters */
1642   g_object_set (camera, "mode", 1,
1643       "location", image_filename,
1644       "viewfinder-filter", vf_filter, "image-filter", image_filter,
1645       "preview-filter", preview_filter, NULL);
1646 
1647   gst_object_unref (vf_filter);
1648   gst_object_unref (preview_filter);
1649   gst_object_unref (image_filter);
1650 
1651   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1652       GST_STATE_CHANGE_FAILURE) {
1653     GST_WARNING ("setting camerabin to PLAYING failed");
1654     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1655     gst_object_unref (camera);
1656     camera = NULL;
1657   }
1658   GST_INFO ("starting capture");
1659   fail_unless (camera != NULL);
1660   g_signal_emit_by_name (camera, "start-capture", NULL);
1661 
1662   g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop);
1663   g_main_loop_run (main_loop);
1664 
1665   /* check that we got a preview image */
1666   check_preview_image (camera, image_filename, 0);
1667 
1668   gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1669   check_file_validity (image_filename, 0, NULL, 0, 0, NO_AUDIO);
1670   remove_file (image_filename, 0);
1671 
1672   fail_unless (vf_probe_counter > 0);
1673   fail_unless (image_probe_counter == 1);
1674   fail_unless (preview_probe_counter == 1);
1675 }
1676 
1677 GST_END_TEST;
1678 
1679 
GST_START_TEST(test_video_custom_filter)1680 GST_START_TEST (test_video_custom_filter)
1681 {
1682   GstElement *vf_filter;
1683   GstElement *video_filter;
1684   GstElement *preview_filter;
1685   GstElement *audio_filter;
1686   GstPad *pad;
1687   gint vf_probe_counter = 0;
1688   gint video_probe_counter = 0;
1689   gint preview_probe_counter = 0;
1690   gint audio_probe_counter = 0;
1691 
1692   if (!camera)
1693     return;
1694 
1695   vf_filter = gst_element_factory_make ("identity", "vf-filter");
1696   video_filter = gst_element_factory_make ("identity", "video-filter");
1697   preview_filter = gst_element_factory_make ("identity", "preview-filter");
1698   audio_filter = gst_element_factory_make ("identity", "audio-filter");
1699 
1700   pad = gst_element_get_static_pad (vf_filter, "src");
1701   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
1702       &vf_probe_counter, NULL);
1703   gst_object_unref (pad);
1704 
1705   pad = gst_element_get_static_pad (video_filter, "src");
1706   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
1707       &video_probe_counter, NULL);
1708   gst_object_unref (pad);
1709 
1710   pad = gst_element_get_static_pad (audio_filter, "src");
1711   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
1712       &audio_probe_counter, NULL);
1713   gst_object_unref (pad);
1714 
1715   pad = gst_element_get_static_pad (preview_filter, "src");
1716   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, filter_buffer_count,
1717       &preview_probe_counter, NULL);
1718   gst_object_unref (pad);
1719 
1720   /* set still image mode and filters */
1721   g_object_set (camera, "mode", 2,
1722       "location", video_filename,
1723       "viewfinder-filter", vf_filter, "video-filter", video_filter,
1724       "preview-filter", preview_filter, "audio-filter", audio_filter, NULL);
1725 
1726   gst_object_unref (vf_filter);
1727   gst_object_unref (preview_filter);
1728   gst_object_unref (video_filter);
1729   gst_object_unref (audio_filter);
1730 
1731   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1732       GST_STATE_CHANGE_FAILURE) {
1733     GST_WARNING ("setting camerabin to PLAYING failed");
1734     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1735     gst_object_unref (camera);
1736     camera = NULL;
1737   }
1738   GST_INFO ("starting capture");
1739   fail_unless (camera != NULL);
1740   g_signal_emit_by_name (camera, "start-capture", NULL);
1741 
1742   g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit,
1743       main_loop);
1744   g_main_loop_run (main_loop);
1745   g_signal_emit_by_name (camera, "stop-capture", NULL);
1746 
1747   /* check that we got a preview image */
1748   check_preview_image (camera, video_filename, 0);
1749 
1750   gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1751   check_file_validity (video_filename, 0, NULL, 0, 0, WITH_AUDIO);
1752   remove_file (video_filename, 0);
1753 
1754   fail_unless (vf_probe_counter > 0);
1755   fail_unless (video_probe_counter > 0);
1756   fail_unless (audio_probe_counter > 0);
1757   fail_unless (preview_probe_counter == 1);
1758 }
1759 
1760 GST_END_TEST;
1761 
1762 #define LOCATION_SWITCHING_FILENAMES_COUNT 5
1763 
1764 static gboolean
image_location_switch_do_capture(gpointer data)1765 image_location_switch_do_capture (gpointer data)
1766 {
1767   gchar **filenames = data;
1768   if (capture_count >= LOCATION_SWITCHING_FILENAMES_COUNT) {
1769     g_main_loop_quit (main_loop);
1770   }
1771 
1772   g_object_set (camera, "location", filenames[capture_count], NULL);
1773   g_signal_emit_by_name (camera, "start-capture", NULL);
1774   capture_count++;
1775   return FALSE;
1776 }
1777 
1778 static void
image_location_switch_readyforcapture(GObject * obj,GParamSpec * pspec,gpointer user_data)1779 image_location_switch_readyforcapture (GObject * obj, GParamSpec * pspec,
1780     gpointer user_data)
1781 {
1782   gboolean ready;
1783 
1784   g_object_get (obj, "ready-for-capture", &ready, NULL);
1785   if (ready) {
1786     g_idle_add (image_location_switch_do_capture, user_data);
1787   }
1788 };
1789 
1790 /*
1791  * Tests that setting the location and then doing an image
1792  * capture will set this capture resulting filename to the
1793  * correct location.
1794  *
1795  * There was a bug in which setting the location, issuing a capture
1796  * and then setting a new location would cause this capture to have
1797  * the location set after this capture. This test should prevent it
1798  * from happening again.
1799  */
GST_START_TEST(test_image_location_switching)1800 GST_START_TEST (test_image_location_switching)
1801 {
1802   gchar *filenames[LOCATION_SWITCHING_FILENAMES_COUNT + 1];
1803   gint i;
1804   glong notify_id;
1805   GstCaps *caps;
1806   GstElement *src;
1807   GstMessage *msg;
1808 
1809   if (!camera)
1810     return;
1811 
1812   g_object_get (camera, "camera-source", &src, NULL);
1813 
1814   for (i = 0; i < LOCATION_SWITCHING_FILENAMES_COUNT; i++) {
1815     filenames[i] = make_test_file_name ("image-switching-filename-test", i);
1816   }
1817   filenames[LOCATION_SWITCHING_FILENAMES_COUNT] = NULL;
1818 
1819   /* set still image mode */
1820   g_object_set (camera, "mode", 1, NULL);
1821   caps = gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT,
1822       800, "height", G_TYPE_INT, 600, NULL);
1823   g_object_set (camera, "image-capture-caps", caps, NULL);
1824   gst_caps_unref (caps);
1825 
1826   if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
1827       GST_STATE_CHANGE_FAILURE) {
1828     GST_WARNING ("setting camerabin to PLAYING failed");
1829     gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1830     gst_object_unref (camera);
1831     camera = NULL;
1832   }
1833   fail_unless (camera != NULL);
1834   GST_INFO ("starting capture");
1835 
1836   notify_id = g_signal_connect (G_OBJECT (src),
1837       "notify::ready-for-capture",
1838       G_CALLBACK (image_location_switch_readyforcapture), filenames);
1839 
1840   g_idle_add (image_location_switch_do_capture, filenames);
1841   g_main_loop_run (main_loop);
1842 
1843   while (1) {
1844     const gchar *filename;
1845 
1846     msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE);
1847     fail_unless (msg != NULL);
1848 
1849     filename =
1850         gst_structure_get_string (gst_message_get_structure (msg), "filename");
1851     if (strcmp (filename,
1852             filenames[LOCATION_SWITCHING_FILENAMES_COUNT - 1]) == 0) {
1853       gst_message_unref (msg);
1854       break;
1855     }
1856     gst_message_unref (msg);
1857   }
1858 
1859   gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL);
1860 
1861   for (i = 0; i < LOCATION_SWITCHING_FILENAMES_COUNT; i++) {
1862     GST_INFO ("Checking for file: %s", filenames[i]);
1863     fail_unless (g_file_test (filenames[i], G_FILE_TEST_IS_REGULAR));
1864   }
1865 
1866   for (i = 0; i < LOCATION_SWITCHING_FILENAMES_COUNT; i++) {
1867     g_unlink (filenames[i]);
1868     g_free (filenames[i]);
1869   }
1870   g_signal_handler_disconnect (src, notify_id);
1871   gst_object_unref (src);
1872 }
1873 
1874 GST_END_TEST;
1875 
1876 
GST_START_TEST(test_photography_iface_image_capture)1877 GST_START_TEST (test_photography_iface_image_capture)
1878 {
1879   run_single_image_capture_test (NULL, NULL);
1880 }
1881 
1882 GST_END_TEST;
1883 
1884 
GST_START_TEST(test_photography_iface_image_capture_with_caps)1885 GST_START_TEST (test_photography_iface_image_capture_with_caps)
1886 {
1887   GstCaps *caps = gst_caps_from_string ("video/x-raw, width=800, height=600");
1888 
1889   run_single_image_capture_test (NULL, caps);
1890   gst_caps_unref (caps);
1891 }
1892 
1893 GST_END_TEST;
1894 
1895 
GST_START_TEST(test_photography_iface_image_capture_with_caps_and_restriction)1896 GST_START_TEST (test_photography_iface_image_capture_with_caps_and_restriction)
1897 {
1898   GstCaps *caps = gst_caps_from_string ("video/x-raw, width=800, height=600");
1899 
1900   /* the source will actually provide an image with 800x800 resolution */
1901   GST_TEST_VIDEO_SRC (testsrc)->enable_resolution_restriction = TRUE;
1902 
1903   run_single_image_capture_test (NULL, caps);
1904   gst_caps_unref (caps);
1905 }
1906 
1907 GST_END_TEST;
1908 
1909 
1910 typedef struct _TestCaseDef
1911 {
1912   const gchar *name;
1913   gpointer setup_func;
1914 } TestCaseDef;
1915 
1916 TestCaseDef tests[] = {
1917   {"wrappercamerabinsrc", setup_wrappercamerabinsrc_videotestsrc}
1918 };
1919 
1920 static Suite *
camerabin_suite(void)1921 camerabin_suite (void)
1922 {
1923   GstRegistry *reg = gst_registry_get ();
1924   Suite *s = suite_create ("camerabin");
1925   gint i;
1926   TCase *tc_generic = tcase_create ("generic");
1927   TCase *tc_phography_iface = tcase_create ("photography-iface");
1928 
1929   if (!gst_registry_check_feature_version (reg, "jpegenc", 1, 0, 0)
1930       || !gst_registry_check_feature_version (reg, "theoraenc", 1, 0, 0)
1931       || !gst_registry_check_feature_version (reg, "vorbisenc", 1, 0, 0)
1932       || !gst_registry_check_feature_version (reg, "oggmux", 1, 0, 0)) {
1933     GST_WARNING ("Skipping camerabin tests because some required element is "
1934         " missing (jpegenc, theoraenc, vorbisenc, oggmux)");
1935     goto end;
1936   }
1937 
1938   suite_add_tcase (s, tc_generic);
1939   tcase_add_checked_fixture (tc_generic, setup_wrappercamerabinsrc_videotestsrc,
1940       teardown);
1941   tcase_add_test (tc_generic, test_supported_caps);
1942 
1943   for (i = 0; i < G_N_ELEMENTS (tests); i++) {
1944     TCase *tc_basic = tcase_create (tests[i].name);
1945     suite_add_tcase (s, tc_basic);
1946 
1947     /* Increase timeout due to video recording */
1948     tcase_set_timeout (tc_basic, 60);
1949     tcase_add_checked_fixture (tc_basic, tests[i].setup_func, teardown);
1950 
1951     tcase_add_test (tc_basic, test_single_image_capture);
1952     tcase_add_test (tc_basic, test_single_image_capture_with_different_caps);
1953     tcase_add_test (tc_basic, test_single_video_recording);
1954     tcase_add_test (tc_basic, test_image_video_cycle);
1955     tcase_add_test (tc_basic, test_multiple_image_captures);
1956     tcase_add_test (tc_basic, test_multiple_video_recordings);
1957 
1958     tcase_add_test (tc_basic, test_image_capture_previews);
1959     tcase_add_test (tc_basic, test_image_capture_with_tags);
1960 
1961     tcase_add_test (tc_basic, test_video_capture_with_tags);
1962 
1963     tcase_add_test (tc_basic, test_idle_property);
1964 
1965     tcase_add_test (tc_basic, test_image_custom_filter);
1966     tcase_add_test (tc_basic, test_video_custom_filter);
1967 
1968     tcase_add_test (tc_basic, test_image_location_switching);
1969   }
1970 
1971   /* This is the GstPhotography interface test case. It was added in 0.10
1972    * to make it easy for integrating with hardware and providing lower
1973    * delays from action to capture.
1974    * There is also has a feature in wrappercamerabinsrc that allows
1975    * captures with the interface to have a different(higher) resolution than
1976    * requested and wrappercamerabinsrc will crop to the requested one.
1977    * This doesn't make sense and seems to be very hardware specific but we
1978    * can't simply remove it at this point.
1979    *
1980    * FIXME 2.0: revisit GstPhotography interface and its interaction with
1981    * camerabin */
1982   suite_add_tcase (s, tc_phography_iface);
1983   tcase_add_checked_fixture (tc_phography_iface, setup_test_camerasrc,
1984       teardown);
1985   tcase_add_test (tc_phography_iface, test_photography_iface_image_capture);
1986   tcase_add_test (tc_phography_iface,
1987       test_photography_iface_image_capture_with_caps);
1988   tcase_add_test (tc_phography_iface,
1989       test_photography_iface_image_capture_with_caps_and_restriction);
1990 
1991 end:
1992   return s;
1993 }
1994 
1995 GST_CHECK_MAIN (camerabin);
1996