1 /* GStreamer
2 *
3 * unit test for level
4 *
5 * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 /* suppress warnings for deprecated API such as GValueArray
24 * with newer GLib versions (>= 2.31.0) */
25 #define GLIB_DISABLE_DEPRECATION_WARNINGS
26
27 #include <gst/audio/audio.h>
28 #include <gst/check/gstcheck.h>
29
30 /* For ease of programming we use globals to keep refs for our floating
31 * src and sink pads we create; otherwise we always have to do get_pad,
32 * get_peer, and then remove references in every test function */
33 static GstPad *mysrcpad, *mysinkpad;
34
35 #define LEVEL_CAPS_TEMPLATE_STRING \
36 "audio/x-raw, " \
37 "format = (string) { "GST_AUDIO_NE(S16)", "GST_AUDIO_NE(F32)" }, " \
38 "layout = (string) interleaved, " \
39 "rate = (int) [ 1, MAX ], " \
40 "channels = (int) [ 1, 8 ]"
41
42 /* we use rate = 1000 here for easy buffer size calculations */
43 #define LEVEL_S16_CAPS_STRING \
44 "audio/x-raw, " \
45 "format = (string) "GST_AUDIO_NE(S16)", " \
46 "layout = (string) interleaved, " \
47 "rate = (int) 1000, " \
48 "channels = (int) 2, " \
49 "channel-mask = (bitmask) 3"
50
51 #define LEVEL_F32_CAPS_STRING \
52 "audio/x-raw, " \
53 "format = (string) "GST_AUDIO_NE(F32)", " \
54 "layout = (string) interleaved, " \
55 "rate = (int) 1000, " \
56 "channels = (int) 2, " \
57 "channel-mask = (bitmask) 3"
58
59 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
60 GST_PAD_SINK,
61 GST_PAD_ALWAYS,
62 GST_STATIC_CAPS (LEVEL_CAPS_TEMPLATE_STRING)
63 );
64 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
65 GST_PAD_SRC,
66 GST_PAD_ALWAYS,
67 GST_STATIC_CAPS (LEVEL_CAPS_TEMPLATE_STRING)
68 );
69
70 /* takes over reference for outcaps */
71 static GstElement *
setup_level(const gchar * caps_str)72 setup_level (const gchar * caps_str)
73 {
74 GstElement *level;
75 GstCaps *caps;
76
77 GST_DEBUG ("setup_level");
78 level = gst_check_setup_element ("level");
79 mysrcpad = gst_check_setup_src_pad (level, &srctemplate);
80 mysinkpad = gst_check_setup_sink_pad (level, &sinktemplate);
81 gst_pad_set_active (mysrcpad, TRUE);
82 gst_pad_set_active (mysinkpad, TRUE);
83
84 caps = gst_caps_from_string (caps_str);
85 gst_check_setup_events (mysrcpad, level, caps, GST_FORMAT_TIME);
86 gst_caps_unref (caps);
87
88 return level;
89 }
90
91 static void
cleanup_level(GstElement * level)92 cleanup_level (GstElement * level)
93 {
94 GST_DEBUG ("cleanup_level");
95
96 gst_check_drop_buffers ();
97 gst_pad_set_active (mysrcpad, FALSE);
98 gst_pad_set_active (mysinkpad, FALSE);
99 gst_check_teardown_src_pad (level);
100 gst_check_teardown_sink_pad (level);
101 gst_check_teardown_element (level);
102 }
103
104 /* create a 0.1 sec buffer stereo buffer */
105 static GstBuffer *
create_s16_buffer(gint16 val_l,gint16 val_r)106 create_s16_buffer (gint16 val_l, gint16 val_r)
107 {
108 GstBuffer *buf = gst_buffer_new_and_alloc (2 * 100 * sizeof (gint16));
109 GstMapInfo map;
110 gint j;
111 gint16 *data;
112
113 gst_buffer_map (buf, &map, GST_MAP_WRITE);
114 data = (gint16 *) map.data;
115 for (j = 0; j < 100; ++j) {
116 *(data++) = val_l;
117 *(data++) = val_r;
118 }
119 gst_buffer_unmap (buf, &map);
120 GST_BUFFER_TIMESTAMP (buf) = G_GUINT64_CONSTANT (0);
121 return buf;
122 }
123
124 static GstBuffer *
create_f32_buffer(gfloat val_l,gfloat val_r)125 create_f32_buffer (gfloat val_l, gfloat val_r)
126 {
127 GstBuffer *buf = gst_buffer_new_and_alloc (2 * 100 * sizeof (gfloat));
128 GstMapInfo map;
129 gint j;
130 gfloat *data;
131
132 gst_buffer_map (buf, &map, GST_MAP_WRITE);
133 data = (gfloat *) map.data;
134 for (j = 0; j < 100; ++j) {
135 *(data++) = val_l;
136 *(data++) = val_r;
137 }
138 gst_buffer_unmap (buf, &map);
139 GST_BUFFER_TIMESTAMP (buf) = G_GUINT64_CONSTANT (0);
140 return buf;
141 }
142
143 /* tests */
144
GST_START_TEST(test_ref_counts)145 GST_START_TEST (test_ref_counts)
146 {
147 GstElement *level;
148 GstBuffer *inbuffer, *outbuffer;
149 GstBus *bus;
150 GstMessage *message;
151
152 level = setup_level (LEVEL_S16_CAPS_STRING);
153 g_object_set (level, "post-messages", TRUE,
154 "interval", (guint64) GST_SECOND / 10, NULL);
155 fail_unless (gst_element_set_state (level,
156 GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
157 "could not set to playing");
158 /* create a bus to get the level message on */
159 bus = gst_bus_new ();
160 ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
161 gst_element_set_bus (level, bus);
162 ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
163
164 /* create a fake 0.1 sec buffer with a half-amplitude block signal */
165 inbuffer = create_s16_buffer (16536, 16536);
166 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
167
168 /* pushing gives away my reference ... */
169 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
170 /* ... but it ends up being collected on the global buffer list */
171 ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
172 fail_unless_equals_int (g_list_length (buffers), 1);
173 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
174 fail_unless (inbuffer == outbuffer);
175
176 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
177 ASSERT_OBJECT_REFCOUNT (message, "message", 1);
178
179 fail_unless (message != NULL);
180 fail_unless (GST_MESSAGE_SRC (message) == GST_OBJECT (level));
181 fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT);
182
183 /* clean up */
184 /* flush current messages,and future state change messages */
185 gst_bus_set_flushing (bus, TRUE);
186
187 /* message has a ref to the element */
188 ASSERT_OBJECT_REFCOUNT (level, "level", 2);
189 gst_message_unref (message);
190 ASSERT_OBJECT_REFCOUNT (level, "level", 1);
191
192 gst_element_set_bus (level, NULL);
193 ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
194 gst_object_unref (bus);
195 fail_unless (gst_element_set_state (level,
196 GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
197 ASSERT_OBJECT_REFCOUNT (level, "level", 1);
198 cleanup_level (level);
199 }
200
201 GST_END_TEST;
202
GST_START_TEST(test_message_is_valid)203 GST_START_TEST (test_message_is_valid)
204 {
205 GstElement *level;
206 GstBuffer *inbuffer;
207 GstBus *bus;
208 GstMessage *message;
209 const GstStructure *structure;
210 GstClockTime endtime, ts, duration;
211
212 level = setup_level (LEVEL_S16_CAPS_STRING);
213 g_object_set (level, "post-messages", TRUE,
214 "interval", (guint64) GST_SECOND / 10, NULL);
215 gst_element_set_state (level, GST_STATE_PLAYING);
216 /* create a bus to get the level message on */
217 bus = gst_bus_new ();
218 gst_element_set_bus (level, bus);
219
220 /* create a fake 0.1 sec buffer with a half-amplitude block signal and push */
221 inbuffer = create_s16_buffer (16536, 16536);
222 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
223
224 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
225 fail_unless (message != NULL);
226 structure = gst_message_get_structure (message);
227 fail_if (structure == NULL);
228 fail_unless_equals_string (gst_structure_get_name (structure), "level");
229 fail_unless (gst_structure_get_clock_time (structure, "endtime", &endtime));
230 fail_unless (gst_structure_get_clock_time (structure, "timestamp", &ts));
231 fail_unless (gst_structure_get_clock_time (structure, "duration", &duration));
232
233 /* clean up */
234 /* flush current messages,and future state change messages */
235 gst_bus_set_flushing (bus, TRUE);
236 gst_message_unref (message);
237 gst_element_set_bus (level, NULL);
238 gst_object_unref (bus);
239 gst_element_set_state (level, GST_STATE_NULL);
240 cleanup_level (level);
241 }
242
243 GST_END_TEST;
244
GST_START_TEST(test_int16)245 GST_START_TEST (test_int16)
246 {
247 GstElement *level;
248 GstBuffer *inbuffer, *outbuffer;
249 GstBus *bus;
250 GstMessage *message;
251 const GstStructure *structure;
252 gint i, j;
253 const GValue *list, *value;
254 gdouble dB;
255 const gchar *fields[3] = { "rms", "peak", "decay" };
256
257 level = setup_level (LEVEL_S16_CAPS_STRING);
258 g_object_set (level, "post-messages", TRUE,
259 "interval", (guint64) GST_SECOND / 10, NULL);
260 gst_element_set_state (level, GST_STATE_PLAYING);
261 /* create a bus to get the level message on */
262 bus = gst_bus_new ();
263 gst_element_set_bus (level, bus);
264
265 /* create a fake 0.1 sec buffer with a half-amplitude block signal */
266 inbuffer = create_s16_buffer (16536, 16536);
267
268 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
269 fail_unless_equals_int (g_list_length (buffers), 1);
270 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
271 fail_unless (inbuffer == outbuffer);
272
273 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
274 structure = gst_message_get_structure (message);
275
276 /* block wave of half amplitude has -5.94 dB for rms, peak and decay */
277 for (i = 0; i < 2; ++i) {
278 for (j = 0; j < 3; ++j) {
279 GValueArray *arr;
280
281 list = gst_structure_get_value (structure, fields[j]);
282 arr = g_value_get_boxed (list);
283 value = g_value_array_get_nth (arr, i);
284 dB = g_value_get_double (value);
285 GST_DEBUG ("%s is %lf", fields[j], dB);
286 fail_if (dB < -6.1);
287 fail_if (dB > -5.9);
288 }
289 }
290
291 /* clean up */
292 /* flush current messages,and future state change messages */
293 gst_bus_set_flushing (bus, TRUE);
294 gst_message_unref (message);
295 gst_element_set_bus (level, NULL);
296 gst_object_unref (bus);
297 gst_element_set_state (level, GST_STATE_NULL);
298 cleanup_level (level);
299 }
300
301 GST_END_TEST;
302
GST_START_TEST(test_int16_panned)303 GST_START_TEST (test_int16_panned)
304 {
305 GstElement *level;
306 GstBuffer *inbuffer, *outbuffer;
307 GstBus *bus;
308 GstMessage *message;
309 const GstStructure *structure;
310 gint i, j;
311 const GValue *list, *value;
312 gdouble dB;
313 const gchar *fields[3] = { "rms", "peak", "decay" };
314
315 level = setup_level (LEVEL_S16_CAPS_STRING);
316 g_object_set (level, "post-messages", TRUE,
317 "interval", (guint64) GST_SECOND / 30, NULL);
318 gst_element_set_state (level, GST_STATE_PLAYING);
319 /* create a bus to get the level message on */
320 bus = gst_bus_new ();
321 gst_element_set_bus (level, bus);
322
323 /* create a fake 0.1 sec buffer with a half-amplitude block signal */
324 inbuffer = create_s16_buffer (0, 16536);
325
326 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
327 fail_unless_equals_int (g_list_length (buffers), 1);
328 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
329 fail_unless (inbuffer == outbuffer);
330
331 /* do multiple messages per buffer, to verify that the inner loop in level
332 * advances the read-index correctly, see
333 * https://bugzilla.gnome.org/show_bug.cgi?id=754144
334 */
335 for (i = 0; i < 3; i++) {
336 GST_DEBUG ("get message number %d", i);
337 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
338 structure = gst_message_get_structure (message);
339
340 /* silence has 0 dB for rms, peak and decay */
341 for (j = 0; j < 3; ++j) {
342 GValueArray *arr;
343
344 list = gst_structure_get_value (structure, fields[j]);
345 arr = g_value_get_boxed (list);
346 value = g_value_array_get_nth (arr, 0);
347 dB = g_value_get_double (value);
348 GST_DEBUG ("%s[0] is %lf", fields[j], dB);
349 #ifdef HAVE_ISINF
350 fail_unless (isinf (dB));
351 #elif defined (HAVE_FPCLASS)
352 fail_unless (fpclass (dB) == FP_NINF);
353 #endif
354 }
355 /* block wave of half amplitude has -5.94 dB for rms, peak and decay */
356 for (j = 0; j < 3; ++j) {
357 GValueArray *arr;
358
359 list = gst_structure_get_value (structure, fields[j]);
360 arr = g_value_get_boxed (list);
361 value = g_value_array_get_nth (arr, 1);
362 dB = g_value_get_double (value);
363 GST_DEBUG ("%s[1] is %lf", fields[j], dB);
364 fail_if (dB < -6.1);
365 fail_if (dB > -5.9);
366 }
367 gst_message_unref (message);
368 }
369
370 /* clean up */
371 /* flush current messages,and future state change messages */
372 gst_bus_set_flushing (bus, TRUE);
373 gst_element_set_bus (level, NULL);
374 gst_object_unref (bus);
375 gst_element_set_state (level, GST_STATE_NULL);
376 cleanup_level (level);
377 }
378
379 GST_END_TEST;
380
GST_START_TEST(test_float)381 GST_START_TEST (test_float)
382 {
383 GstElement *level;
384 GstBuffer *inbuffer, *outbuffer;
385 GstBus *bus;
386 GstMessage *message;
387 const GstStructure *structure;
388 gint i, j;
389 const GValue *list, *value;
390 gdouble dB;
391 const gchar *fields[3] = { "rms", "peak", "decay" };
392
393 level = setup_level (LEVEL_F32_CAPS_STRING);
394 g_object_set (level, "post-messages", TRUE,
395 "interval", (guint64) GST_SECOND / 10, NULL);
396 gst_element_set_state (level, GST_STATE_PLAYING);
397 /* create a bus to get the level message on */
398 bus = gst_bus_new ();
399 gst_element_set_bus (level, bus);
400
401 /* create a fake 0.1 sec buffer with a half-amplitude block signal */
402 inbuffer = create_f32_buffer (0.5, 0.5);
403
404 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
405 fail_unless_equals_int (g_list_length (buffers), 1);
406 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
407 fail_unless (inbuffer == outbuffer);
408
409 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
410 structure = gst_message_get_structure (message);
411
412 /* block wave of half amplitude has -5.94 dB for rms, peak and decay */
413 for (i = 0; i < 2; ++i) {
414 for (j = 0; j < 3; ++j) {
415 GValueArray *arr;
416
417 list = gst_structure_get_value (structure, fields[j]);
418 arr = g_value_get_boxed (list);
419 value = g_value_array_get_nth (arr, i);
420 dB = g_value_get_double (value);
421 GST_DEBUG ("%s is %lf", fields[j], dB);
422 fail_if (dB < -6.1);
423 fail_if (dB > -5.9);
424 }
425 }
426
427 /* clean up */
428 /* flush current messages,and future state change messages */
429 gst_bus_set_flushing (bus, TRUE);
430 gst_message_unref (message);
431 gst_element_set_bus (level, NULL);
432 gst_object_unref (bus);
433 gst_element_set_state (level, GST_STATE_NULL);
434 cleanup_level (level);
435 }
436
437 GST_END_TEST;
438
GST_START_TEST(test_message_on_eos)439 GST_START_TEST (test_message_on_eos)
440 {
441 GstElement *level;
442 GstBuffer *inbuffer, *outbuffer;
443 GstEvent *event;
444 GstBus *bus;
445 GstMessage *message;
446 const GstStructure *structure;
447 gint i, j;
448 const GValue *list, *value;
449 gdouble dB;
450
451 level = setup_level (LEVEL_S16_CAPS_STRING);
452 g_object_set (level, "post-messages", TRUE,
453 "interval", (guint64) GST_SECOND / 5, NULL);
454 gst_element_set_state (level, GST_STATE_PLAYING);
455 /* create a bus to get the level message on */
456 bus = gst_bus_new ();
457 gst_element_set_bus (level, bus);
458
459 /* create a fake 0.1 sec buffer with a half-amplitude block signal */
460 inbuffer = create_s16_buffer (16536, 16536);
461
462 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
463 fail_unless_equals_int (g_list_length (buffers), 1);
464 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
465 fail_unless (inbuffer == outbuffer);
466
467 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, 0);
468
469 event = gst_event_new_eos ();
470 fail_unless (gst_pad_push_event (mysrcpad, event) == TRUE);
471
472 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, 0);
473 fail_unless (message != NULL);
474 structure = gst_message_get_structure (message);
475 fail_unless_equals_string (gst_structure_get_name (structure), "level");
476
477 /* block wave of half amplitude has -5.94 dB for rms, peak and decay */
478 for (i = 0; i < 2; ++i) {
479 const gchar *fields[3] = { "rms", "peak", "decay" };
480 for (j = 0; j < 3; ++j) {
481 GValueArray *arr;
482
483 list = gst_structure_get_value (structure, fields[j]);
484 arr = g_value_get_boxed (list);
485 value = g_value_array_get_nth (arr, i);
486 dB = g_value_get_double (value);
487 GST_DEBUG ("%s is %lf", fields[j], dB);
488 fail_if (dB < -6.1);
489 fail_if (dB > -5.9);
490 }
491 }
492
493 /* clean up */
494 /* flush current messages,and future state change messages */
495 gst_bus_set_flushing (bus, TRUE);
496 gst_message_unref (message);
497 gst_element_set_bus (level, NULL);
498 gst_object_unref (bus);
499 gst_element_set_state (level, GST_STATE_NULL);
500 cleanup_level (level);
501 }
502
503 GST_END_TEST;
504
GST_START_TEST(test_message_count)505 GST_START_TEST (test_message_count)
506 {
507 GstElement *level;
508 GstBuffer *inbuffer, *outbuffer;
509 GstBus *bus;
510 GstMessage *message;
511
512 level = setup_level (LEVEL_S16_CAPS_STRING);
513 g_object_set (level, "post-messages", TRUE,
514 "interval", (guint64) GST_SECOND / 20, NULL);
515 gst_element_set_state (level, GST_STATE_PLAYING);
516 /* create a bus to get the level message on */
517 bus = gst_bus_new ();
518 gst_element_set_bus (level, bus);
519
520 /* create a fake 0.1 sec buffer with a half-amplitude block signal */
521 inbuffer = create_s16_buffer (16536, 16536);
522
523 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
524 fail_unless_equals_int (g_list_length (buffers), 1);
525 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
526 fail_unless (inbuffer == outbuffer);
527
528 /* we should get two messages per buffer */
529 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
530 fail_unless (message != NULL);
531 gst_message_unref (message);
532 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
533 fail_unless (message != NULL);
534 gst_message_unref (message);
535
536 gst_element_set_bus (level, NULL);
537 gst_object_unref (bus);
538 gst_element_set_state (level, GST_STATE_NULL);
539 cleanup_level (level);
540 }
541
542 GST_END_TEST;
543
GST_START_TEST(test_message_timestamps)544 GST_START_TEST (test_message_timestamps)
545 {
546 GstElement *level;
547 GstBuffer *inbuffer, *outbuffer;
548 GstBus *bus;
549 GstMessage *message;
550 const GstStructure *structure;
551 GstClockTime ts1, dur1, ts2;
552
553 level = setup_level (LEVEL_S16_CAPS_STRING);
554 g_object_set (level, "post-messages", TRUE,
555 "interval", (guint64) GST_SECOND / 20, NULL);
556 gst_element_set_state (level, GST_STATE_PLAYING);
557 /* create a bus to get the level message on */
558 bus = gst_bus_new ();
559 gst_element_set_bus (level, bus);
560
561 /* create a fake 0.1 sec buffer with a half-amplitude block signal */
562 inbuffer = create_s16_buffer (16536, 16536);
563
564 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
565 fail_unless_equals_int (g_list_length (buffers), 1);
566 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
567 fail_unless (inbuffer == outbuffer);
568
569 /* check that timestamp + duration is contiguous to the next timestamp */
570 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
571 structure = gst_message_get_structure (message);
572 gst_structure_get_clock_time (structure, "timestamp", &ts1);
573 gst_structure_get_clock_time (structure, "duration", &dur1);
574 gst_message_unref (message);
575
576 message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
577 structure = gst_message_get_structure (message);
578 gst_structure_get_clock_time (structure, "timestamp", &ts2);
579 gst_message_unref (message);
580
581 fail_unless_equals_int64 (ts1 + dur1, ts2);
582
583 gst_element_set_bus (level, NULL);
584 gst_object_unref (bus);
585 gst_element_set_state (level, GST_STATE_NULL);
586 cleanup_level (level);
587 }
588
589 GST_END_TEST;
590
GST_START_TEST(test_rtp_audio_level_meta)591 GST_START_TEST (test_rtp_audio_level_meta)
592 {
593 GstElement *level;
594 GstBuffer *inbuffer, *outbuffer;
595 GstAudioLevelMeta *meta;
596
597 level = setup_level (LEVEL_S16_CAPS_STRING);
598 g_object_set (level, "post-messages", FALSE, "audio-level-meta", TRUE, NULL);
599 gst_element_set_state (level, GST_STATE_PLAYING);
600
601 /* create a fake 0.1 sec buffer with a half-amplitude block signal */
602 inbuffer = create_s16_buffer (16536, 16536);
603
604 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
605 fail_unless_equals_int (g_list_length (buffers), 1);
606 fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
607 fail_unless (inbuffer == outbuffer);
608
609 /* level added the meta */
610 meta = gst_buffer_get_audio_level_meta (outbuffer);
611 fail_unless (meta);
612 fail_unless_equals_int (meta->voice_activity, 0);
613 fail_unless_equals_int (meta->level, 5);
614
615 /* same but with input buffer already having the meta so level will update it */
616 inbuffer = create_s16_buffer (16536, 16536);
617 gst_buffer_add_audio_level_meta (inbuffer, 0, TRUE);
618
619 fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
620 fail_unless_equals_int (g_list_length (buffers), 2);
621 fail_if ((outbuffer = (GstBuffer *) buffers->next->data) == NULL);
622 fail_unless (inbuffer == outbuffer);
623
624 /* level updated the meta */
625 meta = gst_buffer_get_audio_level_meta (outbuffer);
626 fail_unless (meta);
627 fail_unless_equals_int (meta->voice_activity, 1);
628 fail_unless_equals_int (meta->level, 5);
629
630 /* clean up */
631 /* flush current messages,and future state change messages */
632 gst_element_set_state (level, GST_STATE_NULL);
633 cleanup_level (level);
634 }
635
636 GST_END_TEST;
637
638 static Suite *
level_suite(void)639 level_suite (void)
640 {
641 Suite *s = suite_create ("level");
642 TCase *tc_chain = tcase_create ("general");
643
644 suite_add_tcase (s, tc_chain);
645 tcase_add_test (tc_chain, test_ref_counts);
646 tcase_add_test (tc_chain, test_message_is_valid);
647 tcase_add_test (tc_chain, test_int16);
648 tcase_add_test (tc_chain, test_int16_panned);
649 tcase_add_test (tc_chain, test_float);
650 tcase_add_test (tc_chain, test_message_on_eos);
651 tcase_add_test (tc_chain, test_message_count);
652 tcase_add_test (tc_chain, test_message_timestamps);
653 tcase_add_test (tc_chain, test_rtp_audio_level_meta);
654
655 return s;
656 }
657
658 GST_CHECK_MAIN (level);
659