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