level.c 6.29 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/* GStreamer
 *
 * unit test for level
 *
 * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <unistd.h>

#include <gst/check/gstcheck.h>

GList *buffers = NULL;
gboolean have_eos = FALSE;

/* For ease of programming we use globals to keep refs for our floating
 * src and sink pads we create; otherwise we always have to do get_pad,
 * get_peer, and then remove references in every test function */
GstPad *mysrcpad, *mysinkpad;

#define LEVEL_CAPS_TEMPLATE_STRING \
  "audio/x-raw-int, " \
    "rate = (int) [ 1, MAX ], " \
    "channels = (int) [ 1, 8 ], " \
    "endianness = (int) BYTE_ORDER, " \
    "width = (int) {8, 16}, " \
    "depth = (int) {8, 16}, " \
    "signed = (boolean) true"

#define LEVEL_CAPS_STRING \
  "audio/x-raw-int, " \
    "rate = (int) 1000, " \
    "channels = (int) 2, " \
    "endianness = (int) BYTE_ORDER, " \
    "width = (int) 16, " \
    "depth = (int) 16, " \
    "signed = (boolean) true"


static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS (LEVEL_CAPS_TEMPLATE_STRING)
    );
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS (LEVEL_CAPS_TEMPLATE_STRING)
    );

/* takes over reference for outcaps */
GstElement *
setup_level ()
{
  GstElement *level;

  GST_DEBUG ("setup_level");
  level = gst_check_setup_element ("level");
  mysrcpad = gst_check_setup_src_pad (level, &srctemplate, NULL);
  mysinkpad = gst_check_setup_sink_pad (level, &sinktemplate, NULL);
75
76
  gst_pad_set_active (mysrcpad, TRUE);
  gst_pad_set_active (mysinkpad, TRUE);
77
78
79
80
81
82
83
84
85

  return level;
}

void
cleanup_level (GstElement * level)
{
  GST_DEBUG ("cleanup_level");

86
87
  gst_pad_set_active (mysrcpad, FALSE);
  gst_pad_set_active (mysinkpad, FALSE);
88
89
90
91
92
93
94
95
96
97
98
  gst_check_teardown_src_pad (level);
  gst_check_teardown_sink_pad (level);
  gst_check_teardown_element (level);
}


GST_START_TEST (test_int16)
{
  GstElement *level;
  GstBuffer *inbuffer, *outbuffer;
  GstBus *bus;
99
  GstCaps *caps;
100
101
102
103
104
  GstMessage *message;
  const GstStructure *structure;
  int i, j;
  gint16 *data;
  const GValue *list, *value;
105
  GstClockTime endtime;
106
107
108
  gdouble dB;

  level = setup_level ();
109
  g_object_set (level, "message", TRUE, "interval", GST_SECOND / 10, NULL);
110
111

  fail_unless (gst_element_set_state (level,
112
113
          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
      "could not set to playing");
114
115
116
117
118
119
120
121

  /* create a fake 0.1 sec buffer with a half-amplitude block signal */
  inbuffer = gst_buffer_new_and_alloc (400);
  data = (gint16 *) GST_BUFFER_DATA (inbuffer);
  for (j = 0; j < 200; ++j) {
    *data = 16536;
    ++data;
  }
122
123
124
  caps = gst_caps_from_string (LEVEL_CAPS_STRING);
  gst_buffer_set_caps (inbuffer, caps);
  gst_caps_unref (caps);
125
126
127
128
  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);

  /* create a bus to get the level message on */
  bus = gst_bus_new ();
129
  ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
130
  gst_element_set_bus (level, bus);
131
  ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
132
133
134
135
136
137
138
139
140

  /* pushing gives away my reference ... */
  fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
  /* ... but it ends up being collected on the global buffer list */
  ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
  fail_unless_equals_int (g_list_length (buffers), 1);
  fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
  fail_unless (inbuffer == outbuffer);

141
  message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, -1);
142
  ASSERT_OBJECT_REFCOUNT (message, "message", 1);
143
144

  fail_unless (message != NULL);
145
  fail_unless (GST_MESSAGE_SRC (message) == GST_OBJECT (level));
146
  fail_unless (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT);
147
148
149
150
  structure = gst_message_get_structure (message);
  fail_if (structure == NULL);
  fail_unless_equals_string ((char *) gst_structure_get_name (structure),
      "level");
151
  fail_unless (gst_structure_get_clock_time (structure, "endtime", &endtime));
152
153
154
155
156
157
158
159

  /* block wave of half amplitude has -5.94 dB for rms, peak and decay */
  for (i = 0; i < 2; ++i) {
    gchar *fields[3] = { "rms", "peak", "decay" };
    for (j = 0; j < 3; ++j) {
      list = gst_structure_get_value (structure, fields[j]);
      value = gst_value_list_get_value (list, i);
      dB = g_value_get_double (value);
160
      GST_DEBUG ("%s is %lf", fields[j], dB);
161
162
163
164
      fail_if (dB < -6.0);
      fail_if (dB > -5.9);
    }
  }
165
166
167
168
169
170
171
172
173
174
  fail_unless_equals_int (g_list_length (buffers), 1);
  fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL);
  fail_unless (inbuffer == outbuffer);

  /* clean up */
  /* flush current messages,and future state change messages */
  gst_bus_set_flushing (bus, TRUE);

  /* message has a ref to the element */
  ASSERT_OBJECT_REFCOUNT (level, "level", 2);
175
  gst_message_unref (message);
176
177
178
179
180
181
182
183
184
  ASSERT_OBJECT_REFCOUNT (level, "level", 1);

  gst_element_set_bus (level, NULL);
  ASSERT_OBJECT_REFCOUNT (bus, "bus", 1);
  gst_object_unref (bus);
  gst_buffer_unref (outbuffer);
  fail_unless (gst_element_set_state (level,
          GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
  ASSERT_OBJECT_REFCOUNT (level, "level", 1);
185
  cleanup_level (level);
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
}

GST_END_TEST;


Suite *
level_suite (void)
{
  Suite *s = suite_create ("level");
  TCase *tc_chain = tcase_create ("general");

  suite_add_tcase (s, tc_chain);
  tcase_add_test (tc_chain, test_int16);

  return s;
}

int
main (int argc, char **argv)
{
  int nf;

  Suite *s = level_suite ();
  SRunner *sr = srunner_create (s);

  gst_check_init (&argc, &argv);

  srunner_run_all (sr, CK_NORMAL);
  nf = srunner_ntests_failed (sr);
  srunner_free (sr);

  return nf;
}