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