• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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