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