1 /*
2 * GStreamer AVTP Plugin
3 * Copyright (C) 2019 Intel Corporation
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later
9 * version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
20 */
21
22 #include <avtp.h>
23 #include <avtp_aaf.h>
24 #include <gst/check/gstcheck.h>
25 #include <gst/check/gstharness.h>
26
27 const guint8 audio_data[] = { 0xAA, 0xBB, 0xCC, 0xDD };
28
29 static GstHarness *
setup_harness(void)30 setup_harness (void)
31 {
32 GstHarness *h;
33
34 h = gst_harness_new_parse ("avtpaafdepay streamid=0xDEADC0DEDEADC0DE");
35 gst_harness_set_src_caps_str (h, "application/x-avtp");
36
37 return h;
38 }
39
40 static GstBuffer *
create_input_buffer(GstHarness * h)41 create_input_buffer (GstHarness * h)
42 {
43 GstBuffer *buf;
44 GstMapInfo info;
45 struct avtp_stream_pdu *pdu;
46
47 buf = gst_harness_create_buffer (h, sizeof (struct avtp_stream_pdu) +
48 sizeof (audio_data));
49 gst_buffer_map (buf, &info, GST_MAP_WRITE);
50 pdu = (struct avtp_stream_pdu *) info.data;
51 avtp_aaf_pdu_init (pdu);
52 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_TV, 1);
53 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_STREAM_ID, 0xDEADC0DEDEADC0DE);
54 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_FORMAT, AVTP_AAF_FORMAT_INT_16BIT);
55 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_NSR, AVTP_AAF_PCM_NSR_48KHZ);
56 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_CHAN_PER_FRAME, 2);
57 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_BIT_DEPTH, 16);
58 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_TIMESTAMP, 3000);
59 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_STREAM_DATA_LEN, sizeof (audio_data));
60 memcpy (pdu->avtp_payload, audio_data, sizeof (audio_data));
61 gst_buffer_unmap (buf, &info);
62
63 return buf;
64 }
65
GST_START_TEST(test_invalid_audio_features)66 GST_START_TEST (test_invalid_audio_features)
67 {
68 GstHarness *h;
69 GstMapInfo map;
70 GstBuffer *buf;
71 struct avtp_stream_pdu *pdu;
72
73 h = setup_harness ();
74 buf = create_input_buffer (h);
75
76 gst_harness_push (h, gst_buffer_copy (buf));
77 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 1);
78
79 /* Don't care about the first buffer - it only sets what should
80 * be accepted from now on */
81 gst_buffer_unref (gst_harness_pull (h));
82
83 /* Invalid rate */
84 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
85 pdu = (struct avtp_stream_pdu *) map.data;
86 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_NSR, AVTP_AAF_PCM_NSR_16KHZ);
87 gst_buffer_unmap (buf, &map);
88
89 gst_harness_push (h, gst_buffer_copy (buf));
90 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 1);
91
92 /* Invalid depth */
93 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
94 pdu = (struct avtp_stream_pdu *) map.data;
95 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_NSR, AVTP_AAF_PCM_NSR_48KHZ);
96 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_BIT_DEPTH, 32);
97 gst_buffer_unmap (buf, &map);
98
99 gst_harness_push (h, gst_buffer_copy (buf));
100 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 1);
101
102 /* Invalid format */
103 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
104 pdu = (struct avtp_stream_pdu *) map.data;
105 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_BIT_DEPTH, 16);
106 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_FORMAT, AVTP_AAF_FORMAT_INT_32BIT);
107 gst_buffer_unmap (buf, &map);
108
109 gst_harness_push (h, gst_buffer_copy (buf));
110 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 1);
111
112 /* Invalid channels */
113 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
114 pdu = (struct avtp_stream_pdu *) map.data;
115 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_FORMAT, AVTP_AAF_FORMAT_INT_16BIT);
116 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_CHAN_PER_FRAME, 4);
117 gst_buffer_unmap (buf, &map);
118
119 gst_harness_push (h, gst_buffer_copy (buf));
120 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 1);
121
122 gst_buffer_unref (buf);
123 gst_harness_teardown (h);
124 }
125
126 GST_END_TEST;
127
GST_START_TEST(test_invalid_avtpdu)128 GST_START_TEST (test_invalid_avtpdu)
129 {
130 GstHarness *h;
131 GstMapInfo map;
132 GstBuffer *buf, *small;
133 struct avtp_stream_pdu *pdu;
134
135 h = setup_harness ();
136 buf = create_input_buffer (h);
137
138 /* Invalid subtype */
139 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
140 pdu = (struct avtp_stream_pdu *) map.data;
141 avtp_pdu_set ((struct avtp_common_pdu *) pdu, AVTP_FIELD_SUBTYPE,
142 AVTP_SUBTYPE_CRF);
143 gst_buffer_unmap (buf, &map);
144
145 gst_harness_push (h, gst_buffer_copy (buf));
146 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
147
148 /* Invalid AVTP version */
149 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
150 pdu = (struct avtp_stream_pdu *) map.data;
151 avtp_pdu_set ((struct avtp_common_pdu *) pdu, AVTP_FIELD_SUBTYPE,
152 AVTP_SUBTYPE_AAF);
153 avtp_pdu_set ((struct avtp_common_pdu *) pdu, AVTP_FIELD_VERSION, 3);
154 gst_buffer_unmap (buf, &map);
155
156 gst_harness_push (h, gst_buffer_copy (buf));
157 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
158
159 /* Invalid SV */
160 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
161 pdu = (struct avtp_stream_pdu *) map.data;
162 avtp_pdu_set ((struct avtp_common_pdu *) pdu, AVTP_FIELD_VERSION, 0);
163 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_SV, 0);
164 gst_buffer_unmap (buf, &map);
165
166 gst_harness_push (h, gst_buffer_copy (buf));
167 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
168
169 /* Invalid stream id */
170 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
171 pdu = (struct avtp_stream_pdu *) map.data;
172 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_SV, 0);
173 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_STREAM_ID, 0xAABBCCDDEEFF0001);
174 gst_buffer_unmap (buf, &map);
175
176 gst_harness_push (h, gst_buffer_copy (buf));
177 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
178
179 /* Invalid stream data len */
180 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
181 pdu = (struct avtp_stream_pdu *) map.data;
182 avtp_aaf_pdu_set (pdu, AVTP_AAF_FIELD_STREAM_ID, 0xDEADC0DEDEADC0DE);
183 gst_buffer_unmap (buf, &map);
184
185 gst_harness_push (h, gst_buffer_copy (buf));
186 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
187
188 /* Invalid buffer size (too small to fit an AVTP header) */
189 small = gst_harness_create_buffer (h, sizeof (struct avtp_stream_pdu) / 2);
190 gst_harness_push (h, small);
191 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
192
193 gst_buffer_unref (buf);
194 gst_harness_teardown (h);
195 }
196
197 GST_END_TEST;
198
GST_START_TEST(test_events)199 GST_START_TEST (test_events)
200 {
201 gchar *str;
202 GstHarness *h;
203 GstBuffer *buf;
204 GstEvent *event;
205 guint event_count;
206 GstCaps *caps;
207 const GstSegment *segment;
208
209 h = setup_harness ();
210 buf = create_input_buffer (h);
211 gst_harness_push (h, buf);
212
213 event_count = gst_harness_events_in_queue (h);
214 fail_unless (event_count == 3);
215
216 event = gst_harness_pull_event (h);
217 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
218 gst_event_unref (event);
219
220 event = gst_harness_pull_event (h);
221 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_CAPS);
222 gst_event_parse_caps (event, &caps);
223 str = gst_caps_to_string (caps);
224 fail_unless (strcmp (str,
225 "audio/x-raw, format=(string)S16BE, rate=(int)48000, channels=(int)2, layout=(string)interleaved")
226 == 0);
227 g_free (str);
228 gst_event_unref (event);
229
230 event = gst_harness_pull_event (h);
231 fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT);
232 gst_event_parse_segment (event, &segment);
233 fail_unless (segment->format == GST_FORMAT_TIME);
234 fail_unless (segment->base == 3000);
235 fail_unless (segment->start == 3000);
236 fail_unless (segment->stop == -1);
237 gst_event_unref (event);
238
239 gst_harness_teardown (h);
240 }
241
242 GST_END_TEST;
243
GST_START_TEST(test_buffer)244 GST_START_TEST (test_buffer)
245 {
246 GstHarness *h;
247 GstMapInfo info;
248 GstBuffer *in, *out;
249
250 h = setup_harness ();
251 in = create_input_buffer (h);
252 out = gst_harness_push_and_pull (h, in);
253
254 fail_unless (gst_buffer_get_size (out) == sizeof (audio_data));
255
256 gst_buffer_map (out, &info, GST_MAP_READ);
257 fail_unless (memcmp (info.data, audio_data, info.size) == 0);
258 gst_buffer_unmap (out, &info);
259
260 gst_buffer_unref (out);
261 gst_harness_teardown (h);
262 }
263
264 GST_END_TEST;
265
GST_START_TEST(test_property)266 GST_START_TEST (test_property)
267 {
268 guint64 val;
269 GstHarness *h;
270 GstElement *element;
271 const guint64 streamid = 0xAABBCCDDEEFF0001;
272
273 h = setup_harness ();
274 element = gst_harness_find_element (h, "avtpaafdepay");
275
276 g_object_set (G_OBJECT (element), "streamid", streamid, NULL);
277 g_object_get (G_OBJECT (element), "streamid", &val, NULL);
278 fail_unless (val == streamid);
279
280 gst_object_unref (element);
281 gst_harness_teardown (h);
282 }
283
284 GST_END_TEST;
285
286 static Suite *
avtpaafdepay_suite(void)287 avtpaafdepay_suite (void)
288 {
289 Suite *s = suite_create ("avtpaafdepay");
290 TCase *tc_chain = tcase_create ("general");
291
292 suite_add_tcase (s, tc_chain);
293 tcase_add_test (tc_chain, test_buffer);
294 tcase_add_test (tc_chain, test_events);
295 tcase_add_test (tc_chain, test_property);
296 tcase_add_test (tc_chain, test_invalid_avtpdu);
297 tcase_add_test (tc_chain, test_invalid_audio_features);
298
299 return s;
300 }
301
302 GST_CHECK_MAIN (avtpaafdepay);
303