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 <gst/check/gstcheck.h>
23 #include <gst/check/gstharness.h>
24
25 #include <avtp.h>
26 #include <avtp_cvf.h>
27
28 #define AVTP_CVF_H264_HEADER_SIZE (sizeof(struct avtp_stream_pdu) + sizeof(guint32))
29 #define STREAM_ID 0xAABBCCDDEEFF0000
30
31 static gboolean
check_nal_filling(GstBuffer * buffer,guint8 first)32 check_nal_filling (GstBuffer * buffer, guint8 first)
33 {
34 GstMapInfo map;
35 gboolean result = TRUE;
36 gsize offset = 5; /* 4 bytes for the nal size and one with nal type */
37 int i;
38
39 gst_buffer_map (buffer, &map, GST_MAP_READ);
40
41 for (i = offset; i < map.size; i++) {
42 if (map.data[i] != first++) {
43 result = FALSE;
44 break;
45 }
46 }
47
48 gst_buffer_unmap (buffer, &map);
49
50 return result;
51 }
52
53 static void
fill_nal(guint8 * buf,gsize size,guint8 first)54 fill_nal (guint8 * buf, gsize size, guint8 first)
55 {
56 while (size--) {
57 *buf++ = first++;
58 }
59 }
60
61 static gsize
nal_size(GstBuffer * buffer)62 nal_size (GstBuffer * buffer)
63 {
64 guint8 nal_size[4];
65
66 gst_buffer_extract (buffer, 0, nal_size, 4);
67 return GST_READ_UINT32_BE (nal_size);
68 }
69
70 static gsize
nal_type(GstBuffer * buffer)71 nal_type (GstBuffer * buffer)
72 {
73 guint8 nal_type;
74
75 gst_buffer_extract (buffer, 4, &nal_type, 1);
76 return nal_type & 0x1f;
77 }
78
79 static GstBuffer *
fetch_nal(GstBuffer * buffer,gsize * offset)80 fetch_nal (GstBuffer * buffer, gsize * offset)
81 {
82 gsize nal_size;
83 GstBuffer *ret;
84 guint8 buf[4];
85
86 if (*offset >= (gst_buffer_get_size (buffer) - 4))
87 return NULL;
88
89 gst_buffer_extract (buffer, *offset, buf, 4);
90 nal_size = GST_READ_UINT32_BE (buf);
91
92 ret =
93 gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY, *offset,
94 nal_size + 4);
95 *offset += nal_size + 4;
96
97 return ret;
98 }
99
GST_START_TEST(test_depayloader_fragment_and_single)100 GST_START_TEST (test_depayloader_fragment_and_single)
101 {
102 GstHarness *h;
103 GstBuffer *in;
104 const gint DATA_LEN = sizeof (guint32) + 10;
105 struct avtp_stream_pdu *pdu;
106 GstMapInfo map;
107
108 /* Create the harness for the avtpcvfpay */
109 h = gst_harness_new_parse ("avtpcvfdepay ! fakesink num-buffers=1");
110 gst_harness_set_src_caps_str (h, "application/x-avtp");
111
112 /* Create the input AVTPDU */
113 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 10);
114 gst_buffer_map (in, &map, GST_MAP_READWRITE);
115 pdu = (struct avtp_stream_pdu *) map.data;
116
117 /* Start with a single NAL */
118 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
119 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
120 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
121 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
122 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
123 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
124 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
125 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
126 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x1;
127 gst_buffer_unmap (in, &map);
128
129 /* We push a copy so that we can change only what is necessary on our buffer */
130 fail_unless_equals_int (gst_harness_push (h, gst_buffer_copy (in)),
131 GST_FLOW_OK);
132 fail_unless (gst_harness_try_pull (h) == NULL);
133
134 /* Then a fragment */
135 gst_buffer_map (in, &map, GST_MAP_READWRITE);
136 pdu = (struct avtp_stream_pdu *) map.data;
137 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
138 map.data[AVTP_CVF_H264_HEADER_SIZE] = 3 << 5 | 28; /* NAL type FU-A, NRI 3 */
139 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 7) | 4; /* S = 1, type 4 */
140 gst_buffer_unmap (in, &map);
141
142 fail_unless_equals_int (gst_harness_push (h, gst_buffer_copy (in)),
143 GST_FLOW_OK);
144
145 /* Third and last AVTPDU, again a single NAL */
146 gst_buffer_map (in, &map, GST_MAP_READWRITE);
147 pdu = (struct avtp_stream_pdu *) map.data;
148 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
149 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
150 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
151 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
152 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x1;
153 gst_buffer_unmap (in, &map);
154
155 fail_unless_equals_int (gst_harness_push (h, gst_buffer_copy (in)),
156 GST_FLOW_EOS);
157
158 gst_buffer_unref (in);
159 gst_harness_teardown (h);
160 }
161
162 GST_END_TEST;
163
GST_START_TEST(test_depayloader_fragmented_two_start_eos)164 GST_START_TEST (test_depayloader_fragmented_two_start_eos)
165 {
166 GstHarness *h;
167 GstBuffer *in;
168 const gint DATA_LEN = sizeof (guint32) + 10;
169 struct avtp_stream_pdu *pdu;
170 GstMapInfo map;
171
172 /* Create the harness for the avtpcvfpay */
173 h = gst_harness_new_parse ("avtpcvfdepay ! fakesink num-buffers=1");
174 gst_harness_set_src_caps_str (h, "application/x-avtp");
175
176 /* Create the input AVTPDU */
177 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 10);
178 gst_buffer_map (in, &map, GST_MAP_READWRITE);
179 pdu = (struct avtp_stream_pdu *) map.data;
180
181 /* Start with a single NAL */
182 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
183 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
184 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
185 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
186 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
187 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
188 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
189 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
190 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x1;
191 gst_buffer_unmap (in, &map);
192
193 /* We push a copy so that we can change only what is necessary on our buffer */
194 fail_unless_equals_int (gst_harness_push (h, gst_buffer_copy (in)),
195 GST_FLOW_OK);
196 fail_unless (gst_harness_try_pull (h) == NULL);
197
198 /* Then a fragment */
199 gst_buffer_map (in, &map, GST_MAP_READWRITE);
200 pdu = (struct avtp_stream_pdu *) map.data;
201 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
202 map.data[AVTP_CVF_H264_HEADER_SIZE] = 3 << 5 | 28; /* NAL type FU-A, NRI 3 */
203 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 7) | 4; /* S = 1, type 4 */
204 gst_buffer_unmap (in, &map);
205
206 fail_unless_equals_int (gst_harness_push (h, gst_buffer_copy (in)),
207 GST_FLOW_OK);
208
209 /* Third and last AVTPDU, another fragment with start bit set */
210 gst_buffer_map (in, &map, GST_MAP_READWRITE);
211 pdu = (struct avtp_stream_pdu *) map.data;
212 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
213 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
214 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
215 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
216 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 7) | 4; /* S = 1, type 4 */
217 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 16);
218 gst_buffer_unmap (in, &map);
219
220 fail_unless_equals_int (gst_harness_push (h, gst_buffer_copy (in)),
221 GST_FLOW_EOS);
222
223 gst_buffer_unref (in);
224 gst_harness_teardown (h);
225 }
226
227 GST_END_TEST;
228
GST_START_TEST(test_depayloader_multiple_lost_eos)229 GST_START_TEST (test_depayloader_multiple_lost_eos)
230 {
231 GstHarness *h;
232 GstBuffer *in;
233 const gint DATA_LEN = sizeof (guint32) + 4;
234 struct avtp_stream_pdu *pdu;
235 GstMapInfo map;
236
237 /* Create the harness for the avtpcvfpay */
238 h = gst_harness_new_parse ("avtpcvfdepay ! fakesink num-buffers=1");
239 gst_harness_set_src_caps_str (h, "application/x-avtp");
240
241 /* Create the input AVTPDU header */
242 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 4);
243 gst_buffer_map (in, &map, GST_MAP_READWRITE);
244 pdu = (struct avtp_stream_pdu *) map.data;
245
246 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
247 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
248 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
249 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
250 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
251 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
252 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
253 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
254 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x7; /* Add NAL type */
255 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
256 gst_buffer_unmap (in, &map);
257
258 /* We push a copy so that we can change only what is necessary on our buffer */
259 gst_harness_push (h, gst_buffer_copy (in));
260 fail_unless (gst_harness_try_pull (h) == NULL);
261
262 /* Send second AVTPDU, but skipping one seqnum */
263 gst_buffer_map (in, &map, GST_MAP_READWRITE);
264 pdu = (struct avtp_stream_pdu *) map.data;
265 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
266 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x1; /* Add NAL type */
267 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
268 gst_buffer_unmap (in, &map);
269
270 fail_unless_equals_int (gst_harness_push (h, gst_buffer_copy (in)),
271 GST_FLOW_EOS);
272
273 gst_buffer_unref (in);
274 gst_harness_teardown (h);
275 }
276
277 GST_END_TEST;
278
GST_START_TEST(test_depayloader_fragmented_eos)279 GST_START_TEST (test_depayloader_fragmented_eos)
280 {
281 GstHarness *h;
282 GstBuffer *in;
283 const gint DATA_LEN = sizeof (guint32) + 10;
284 struct avtp_stream_pdu *pdu;
285 GstMapInfo map;
286
287 /* Create the harness for the avtpcvfpay */
288 h = gst_harness_new_parse ("avtpcvfdepay ! fakesink num-buffers=1");
289 gst_harness_set_src_caps_str (h, "application/x-avtp");
290
291 /* Create the input AVTPDU */
292 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 10);
293 gst_buffer_map (in, &map, GST_MAP_READWRITE);
294 pdu = (struct avtp_stream_pdu *) map.data;
295
296 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
297 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
298 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
299 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
300 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
301 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
302 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
303 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
304 map.data[AVTP_CVF_H264_HEADER_SIZE] = 3 << 5 | 28; /* NAL type FU-A, NRI 3 */
305 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 7) | 4; /* S = 1, type 4 */
306 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 0);
307 gst_buffer_unmap (in, &map);
308
309 /* We push a copy so that we can change only what is necessary on our buffer */
310 fail_unless_equals_int (gst_harness_push (h, gst_buffer_copy (in)),
311 GST_FLOW_OK);
312 fail_unless (gst_harness_try_pull (h) == NULL);
313
314 /* Send second and last AVTPDU */
315 gst_buffer_map (in, &map, GST_MAP_READWRITE);
316 pdu = (struct avtp_stream_pdu *) map.data;
317 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
318 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
319 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
320 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
321 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 6) | 4; /* E = 1, type 4 */
322 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 16);
323 gst_buffer_unmap (in, &map);
324
325 fail_unless_equals_int (gst_harness_push (h, gst_buffer_copy (in)),
326 GST_FLOW_EOS);
327
328 gst_buffer_unref (in);
329 gst_harness_teardown (h);
330 }
331
332 GST_END_TEST;
333
334 /* Tests a big fragmented NAL scenario */
GST_START_TEST(test_depayloader_single_eos)335 GST_START_TEST (test_depayloader_single_eos)
336 {
337 GstHarness *h;
338 GstBuffer *in;
339 const gint DATA_LEN = sizeof (guint32) + 4;
340 struct avtp_stream_pdu *pdu;
341 GstMapInfo map;
342
343 /* Create the harness for the avtpcvfpay */
344 h = gst_harness_new_parse ("avtpcvfdepay ! fakesink num-buffers=1");
345 gst_harness_set_src_caps_str (h, "application/x-avtp");
346
347 /* Create the input AVTPDU header */
348 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 4);
349 gst_buffer_map (in, &map, GST_MAP_READWRITE);
350 pdu = (struct avtp_stream_pdu *) map.data;
351
352 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
353 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
354 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
355 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
356 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
357 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
358 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
359 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
360 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x1; /* Add NAL type */
361 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
362 gst_buffer_unmap (in, &map);
363
364 fail_unless_equals_int (gst_harness_push (h, in), GST_FLOW_EOS);
365
366 gst_harness_teardown (h);
367 }
368
369 GST_END_TEST;
370
GST_START_TEST(test_depayloader_invalid_avtpdu)371 GST_START_TEST (test_depayloader_invalid_avtpdu)
372 {
373 GstHarness *h;
374 GstBuffer *in, *small;
375 const gint DATA_LEN = sizeof (guint32) + 4;
376 struct avtp_stream_pdu *pdu;
377 GstMapInfo map;
378
379 /* Create the harness for the avtpcvfpay */
380 h = gst_harness_new ("avtpcvfdepay");
381 gst_harness_set_src_caps_str (h, "application/x-avtp");
382
383 /* Create the input AVTPDU header */
384 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 4);
385 gst_buffer_map (in, &map, GST_MAP_READWRITE);
386 pdu = (struct avtp_stream_pdu *) map.data;
387
388 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_MJPEG);
389 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
390 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
391 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
392 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
393 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
394 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
395 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
396 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x1; /* Add NAL type */
397 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
398 gst_buffer_unmap (in, &map);
399
400 /* Invalid CVF subtype */
401 gst_harness_push (h, gst_buffer_copy (in));
402 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
403
404 /* Invalid subtype */
405 gst_buffer_map (in, &map, GST_MAP_READWRITE);
406 pdu = (struct avtp_stream_pdu *) map.data;
407 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_FORMAT_SUBTYPE,
408 AVTP_CVF_FORMAT_SUBTYPE_H264);
409 avtp_pdu_set ((struct avtp_common_pdu *) pdu, AVTP_FIELD_SUBTYPE,
410 AVTP_SUBTYPE_CRF);
411 gst_buffer_unmap (in, &map);
412
413 gst_harness_push (h, gst_buffer_copy (in));
414 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
415
416 /* Invalid CVF type */
417 gst_buffer_map (in, &map, GST_MAP_READWRITE);
418 pdu = (struct avtp_stream_pdu *) map.data;
419 avtp_pdu_set ((struct avtp_common_pdu *) pdu, AVTP_FIELD_SUBTYPE,
420 AVTP_SUBTYPE_CVF);
421 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_FORMAT, 0);
422 gst_buffer_unmap (in, &map);
423
424 gst_harness_push (h, gst_buffer_copy (in));
425 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
426
427 /* Invalid AVTP version */
428 gst_buffer_map (in, &map, GST_MAP_READWRITE);
429 pdu = (struct avtp_stream_pdu *) map.data;
430 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_FORMAT, AVTP_CVF_FORMAT_RFC);
431 avtp_pdu_set ((struct avtp_common_pdu *) pdu, AVTP_FIELD_VERSION, 3);
432 gst_buffer_unmap (in, &map);
433
434 gst_harness_push (h, gst_buffer_copy (in));
435 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
436
437 /* Invalid SV */
438 gst_buffer_map (in, &map, GST_MAP_READWRITE);
439 pdu = (struct avtp_stream_pdu *) map.data;
440 avtp_pdu_set ((struct avtp_common_pdu *) pdu, AVTP_FIELD_VERSION, 0);
441 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SV, 0);
442 gst_buffer_unmap (in, &map);
443
444 gst_harness_push (h, gst_buffer_copy (in));
445 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
446
447 /* Invalid stream id */
448 gst_buffer_map (in, &map, GST_MAP_READWRITE);
449 pdu = (struct avtp_stream_pdu *) map.data;
450 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SV, 1);
451 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, 0xAABBCCDDEEFF0001);
452 gst_buffer_unmap (in, &map);
453
454 gst_harness_push (h, gst_buffer_copy (in));
455 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
456
457 /* Invalid stream data len */
458 gst_buffer_map (in, &map, GST_MAP_READWRITE);
459 pdu = (struct avtp_stream_pdu *) map.data;
460 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
461 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, 100);
462 gst_buffer_unmap (in, &map);
463
464 gst_harness_push (h, gst_buffer_copy (in));
465 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
466
467 /* Invalid NAL type (STAP-A) */
468 gst_buffer_map (in, &map, GST_MAP_READWRITE);
469 pdu = (struct avtp_stream_pdu *) map.data;
470 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
471 map.data[AVTP_CVF_H264_HEADER_SIZE] = 24;
472 gst_buffer_unmap (in, &map);
473
474 gst_harness_push (h, gst_buffer_copy (in));
475 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
476
477 /* Invalid NAL type (STAP-B) */
478 gst_buffer_map (in, &map, GST_MAP_READWRITE);
479 pdu = (struct avtp_stream_pdu *) map.data;
480 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
481 map.data[AVTP_CVF_H264_HEADER_SIZE] = 25;
482 gst_buffer_unmap (in, &map);
483
484 gst_harness_push (h, gst_buffer_copy (in));
485 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
486
487 /* Invalid NAL type (MTAP16) */
488 gst_buffer_map (in, &map, GST_MAP_READWRITE);
489 pdu = (struct avtp_stream_pdu *) map.data;
490 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
491 map.data[AVTP_CVF_H264_HEADER_SIZE] = 26;
492 gst_buffer_unmap (in, &map);
493
494 gst_harness_push (h, gst_buffer_copy (in));
495 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
496
497 /* Invalid NAL type (MTAP24) */
498 gst_buffer_map (in, &map, GST_MAP_READWRITE);
499 pdu = (struct avtp_stream_pdu *) map.data;
500 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
501 map.data[AVTP_CVF_H264_HEADER_SIZE] = 27;
502 gst_buffer_unmap (in, &map);
503
504 gst_harness_push (h, gst_buffer_copy (in));
505 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
506
507 /* Invalid NAL type (FU-B) */
508 gst_buffer_map (in, &map, GST_MAP_READWRITE);
509 pdu = (struct avtp_stream_pdu *) map.data;
510 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
511 map.data[AVTP_CVF_H264_HEADER_SIZE] = 29;
512 gst_buffer_unmap (in, &map);
513
514 gst_harness_push (h, gst_buffer_copy (in));
515 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
516
517 /* Invalid NAL type (STAP-A) */
518 gst_buffer_map (in, &map, GST_MAP_READWRITE);
519 pdu = (struct avtp_stream_pdu *) map.data;
520 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
521 map.data[AVTP_CVF_H264_HEADER_SIZE] = 24;
522 gst_buffer_unmap (in, &map);
523
524 gst_harness_push (h, gst_buffer_copy (in));
525 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
526
527 /* Invalid buffer size (too small to fit an AVTP header) */
528 small = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE / 2);
529 gst_harness_push (h, small);
530 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
531
532 /* Invalid buffer size (too small to fit a fragment header) */
533 small = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 1);
534 gst_buffer_map (small, &map, GST_MAP_READWRITE);
535 pdu = (struct avtp_stream_pdu *) map.data;
536 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
537 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
538 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
539 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
540 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
541 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
542 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
543 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, sizeof (guint32) + 1);
544 map.data[AVTP_CVF_H264_HEADER_SIZE] = 28;
545 gst_buffer_unmap (small, &map);
546
547 gst_harness_push (h, small);
548 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 0);
549
550 gst_buffer_unref (in);
551 gst_harness_teardown (h);
552 }
553
554 GST_END_TEST;
555
556 /*
557 * This test will send some invalid fragments, but with valid seqnum
558 * (misbehaving payloader).*/
GST_START_TEST(test_depayloader_lost_fragments)559 GST_START_TEST (test_depayloader_lost_fragments)
560 {
561 GstHarness *h;
562 GstBuffer *in, *out, *nal;
563 const gint DATA_LEN = sizeof (guint32) + 10;
564 struct avtp_stream_pdu *pdu;
565 GstMapInfo map;
566 gsize offset;
567
568 /* Create the harness for the avtpcvfpay */
569 h = gst_harness_new ("avtpcvfdepay");
570 gst_harness_set_src_caps_str (h, "application/x-avtp");
571
572 /* Create the input AVTPDU */
573 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 10);
574 gst_buffer_map (in, &map, GST_MAP_READWRITE);
575 pdu = (struct avtp_stream_pdu *) map.data;
576
577 /* First fragment doesn't have start bit set, so it should be ignored */
578 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
579 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
580 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
581 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
582 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
583 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
584 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
585 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
586 map.data[AVTP_CVF_H264_HEADER_SIZE] = 3 << 5 | 28; /* NAL type FU-A, NRI 3 */
587 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = 4; /* S = 0, type 4 */
588 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 0);
589 gst_buffer_unmap (in, &map);
590
591 /* We push a copy so that we can change only what is necessary on our buffer */
592 gst_harness_push (h, gst_buffer_copy (in));
593 fail_unless (gst_harness_try_pull (h) == NULL);
594
595 /* Send second AVTPDU - but this should be also ignored as it doesn't have the
596 * start bit set */
597 gst_buffer_map (in, &map, GST_MAP_READWRITE);
598 pdu = (struct avtp_stream_pdu *) map.data;
599 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
600 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = 4; /* type 4 */
601 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 8);
602 gst_buffer_unmap (in, &map);
603
604 gst_harness_push (h, gst_buffer_copy (in));
605 fail_unless (gst_harness_try_pull (h) == NULL);
606
607 /* Send third AVTPDU, with end bit set, but it should be discarded as there
608 * was no start fragment */
609 gst_buffer_map (in, &map, GST_MAP_READWRITE);
610 pdu = (struct avtp_stream_pdu *) map.data;
611 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
612 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
613 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
614 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
615 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 6) | 4; /* E = 1, type 4 */
616 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 16);
617 gst_buffer_unmap (in, &map);
618
619 /* Ensure no buffer came out */
620 gst_harness_push (h, gst_buffer_copy (in));
621 fail_unless (gst_harness_try_pull (h) == NULL);
622
623 /* Now, let's send an invalid one, with both start and end bits set */
624 gst_buffer_map (in, &map, GST_MAP_READWRITE);
625 pdu = (struct avtp_stream_pdu *) map.data;
626 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 3);
627 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (3 << 6) | 4; /* S = E = 1, type 4 */
628 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 24);
629 gst_buffer_unmap (in, &map);
630
631 gst_harness_push (h, gst_buffer_copy (in));
632 fail_unless (gst_harness_try_pull (h) == NULL);
633
634 /* Send a fragment with proper start */
635 gst_buffer_map (in, &map, GST_MAP_READWRITE);
636 pdu = (struct avtp_stream_pdu *) map.data;
637 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 4);
638 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 7) | 4; /* S = 1, type 4 */
639 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 32);
640 gst_buffer_unmap (in, &map);
641
642 gst_harness_push (h, gst_buffer_copy (in));
643 fail_unless (gst_harness_try_pull (h) == NULL);
644
645 /* But send start again. Previous one should be dropped */
646 gst_buffer_map (in, &map, GST_MAP_READWRITE);
647 pdu = (struct avtp_stream_pdu *) map.data;
648 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 5);
649 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 7) | 4; /* S = 1, type 4 */
650 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 40);
651 gst_buffer_unmap (in, &map);
652
653 gst_harness_push (h, gst_buffer_copy (in));
654 fail_unless (gst_harness_try_pull (h) == NULL);
655
656 /* Finally, send ending fragment. It should come out a buffer
657 * whose content starts on 40 (starting of start fragment) */
658 gst_buffer_map (in, &map, GST_MAP_READWRITE);
659 pdu = (struct avtp_stream_pdu *) map.data;
660 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 6);
661 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 6) | 4; /* E = 1, type 4 */
662 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 48);
663 gst_buffer_unmap (in, &map);
664
665 gst_harness_push (h, gst_buffer_copy (in));
666
667 out = gst_harness_pull (h);
668 fail_unless_equals_uint64 (GST_BUFFER_DTS (out), 1000000);
669 fail_unless_equals_uint64 (GST_BUFFER_PTS (out), 2000000);
670
671 /* NAL is composed of 8 bytes fragment + reconstructed NAL header, so 17 bytes */
672 offset = 0;
673 nal = fetch_nal (out, &offset);
674 fail_unless_equals_uint64 (nal_size (nal), 17);
675 fail_unless (check_nal_filling (nal, 40) == TRUE);
676 fail_unless_equals_uint64 (nal_type (nal), 4);
677 gst_buffer_unref (nal);
678
679 /* Ensure no other NAL units are present */
680 nal = fetch_nal (out, &offset);
681 fail_unless (nal == NULL);
682
683 gst_buffer_unref (out);
684 gst_buffer_unref (in);
685 gst_harness_teardown (h);
686 }
687
688 GST_END_TEST;
689
690 /* This test jumps one seq_num, thus simulating a lost packet */
GST_START_TEST(test_depayloader_lost_packet)691 GST_START_TEST (test_depayloader_lost_packet)
692 {
693 GstHarness *h;
694 GstBuffer *in, *out, *nal;
695 const gint DATA_LEN = sizeof (guint32) + 4;
696 struct avtp_stream_pdu *pdu;
697 GstMapInfo map;
698 gsize offset;
699
700 /* Create the harness for the avtpcvfpay */
701 h = gst_harness_new ("avtpcvfdepay");
702 gst_harness_set_src_caps_str (h, "application/x-avtp");
703
704 /* Create the input AVTPDU header */
705 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 4);
706 gst_buffer_map (in, &map, GST_MAP_READWRITE);
707 pdu = (struct avtp_stream_pdu *) map.data;
708
709 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
710 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
711 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
712 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
713 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
714 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
715 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
716 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
717 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x7; /* Add NAL type */
718 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
719 gst_buffer_unmap (in, &map);
720
721 /* We push a copy so that we can change only what is necessary on our buffer */
722 gst_harness_push (h, gst_buffer_copy (in));
723 fail_unless (gst_harness_try_pull (h) == NULL);
724
725 /* Send second AVTPDU */
726 gst_buffer_map (in, &map, GST_MAP_READWRITE);
727 pdu = (struct avtp_stream_pdu *) map.data;
728 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
729 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
730 gst_buffer_unmap (in, &map);
731
732 gst_harness_push (h, gst_buffer_copy (in));
733 fail_unless (gst_harness_try_pull (h) == NULL);
734
735 /* Send third and last AVTPDU, but jumping one SEQ_NUM.
736 * This should make the first two NAL units to be flushed,
737 * despite M not being set on this third packet.
738 * Also, this NAL is not filled from 0, so if it somehow
739 * leaks - it's not supposed to go outside of the avtpcvdepay
740 * as it doesn't have M bit set - we can catch on checks below */
741 gst_buffer_map (in, &map, GST_MAP_READWRITE);
742 pdu = (struct avtp_stream_pdu *) map.data;
743 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
744 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 3);
745 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x1; /* Add NAL type */
746 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 5);
747 gst_buffer_unmap (in, &map);
748
749 gst_harness_push (h, gst_buffer_copy (in));
750 fail_unless_equals_int (gst_harness_buffers_received (h), 1);
751
752 out = gst_harness_pull (h);
753 fail_unless_equals_uint64 (GST_BUFFER_DTS (out), 1000000);
754 fail_unless_equals_uint64 (GST_BUFFER_PTS (out), 2000000);
755
756 /* Validate each NAL unit size and content */
757 offset = 0;
758 nal = fetch_nal (out, &offset);
759 fail_unless_equals_uint64 (nal_size (nal), 4);
760 fail_unless (check_nal_filling (nal, 0) == TRUE);
761 fail_unless_equals_uint64 (nal_type (nal), 7);
762 gst_buffer_unref (nal);
763
764 nal = fetch_nal (out, &offset);
765 fail_unless_equals_uint64 (nal_size (nal), 4);
766 fail_unless (check_nal_filling (nal, 0) == TRUE);
767 fail_unless_equals_uint64 (nal_type (nal), 7);
768 gst_buffer_unref (nal);
769
770 /* Ensure no other NAL units are present */
771 nal = fetch_nal (out, &offset);
772 fail_unless (nal == NULL);
773
774 gst_buffer_unref (out);
775 gst_buffer_unref (in);
776 gst_harness_teardown (h);
777 }
778
779 GST_END_TEST;
780
781 /* This test simulates a scenario in which one single NAL unit is sent,
782 * followed by a fragment without start bit set, so fragment is discarded
783 * and previous single NAL is sent to the pipeline, as avtpcvfdepay is not
784 * sure about the sanity of the data anymore - but hopes h264decoder knows
785 * what to do. This scenario emerges from misbehaving payloaders. */
GST_START_TEST(test_depayloader_single_and_messed_fragments)786 GST_START_TEST (test_depayloader_single_and_messed_fragments)
787 {
788 GstHarness *h;
789 GstBuffer *in, *out, *nal;
790 const gint DATA_LEN = sizeof (guint32) + 4;
791 struct avtp_stream_pdu *pdu;
792 GstMapInfo map;
793 gsize offset;
794
795 /* Create the harness for the avtpcvfpay */
796 h = gst_harness_new ("avtpcvfdepay");
797 gst_harness_set_src_caps_str (h, "application/x-avtp");
798
799 /* Create the input AVTPDU header */
800 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 4);
801 gst_buffer_map (in, &map, GST_MAP_READWRITE);
802 pdu = (struct avtp_stream_pdu *) map.data;
803
804 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
805 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
806 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
807 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
808 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
809 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
810 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
811 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
812 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x1; /* Add NAL type */
813 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
814 gst_buffer_unmap (in, &map);
815
816 /* First, we send a single NAL with M = 0, so nothing should come out */
817 gst_harness_push (h, gst_buffer_copy (in));
818 fail_unless (gst_harness_try_pull (h) == NULL);
819
820 /* Then, we send invalid fragment */
821 gst_buffer_map (in, &map, GST_MAP_READWRITE);
822 pdu = (struct avtp_stream_pdu *) map.data;
823 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
824 map.data[AVTP_CVF_H264_HEADER_SIZE] = 3 << 5 | 28; /* NAL type FU-A, NRI 3 */
825 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = 4; /* S = 0, type 4 */
826 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 2, 0);
827 gst_buffer_unmap (in, &map);
828
829 /* When we push it, it should be discarded, but previous single NAL
830 * should come out */
831 out = gst_harness_push_and_pull (h, gst_buffer_copy (in));
832
833 /* Check that we got the right one */
834 fail_unless_equals_uint64 (GST_BUFFER_DTS (out), 1000000);
835 fail_unless_equals_uint64 (GST_BUFFER_PTS (out), 2000000);
836
837 offset = 0;
838 nal = fetch_nal (out, &offset);
839 fail_unless_equals_uint64 (nal_size (nal), 4);
840 fail_unless_equals_uint64 (nal_type (nal), 1);
841 fail_unless (check_nal_filling (nal, 0) == TRUE);
842 gst_buffer_unref (nal);
843
844 /* Ensure no other NAL units are present */
845 nal = fetch_nal (out, &offset);
846 fail_unless (nal == NULL);
847
848 gst_buffer_unref (out);
849 gst_buffer_unref (in);
850 gst_harness_teardown (h);
851 }
852
853 GST_END_TEST;
854
855 /* This test explores the case in which a fragment is followed by
856 * a single NAL - and not by an ending fragment. Fragments stored
857 * so far are dropped, and things shall flow normally for the single NAL.
858 * This can be created by a misbehaving payloader */
GST_START_TEST(test_depayloader_single_and_messed_fragments_2)859 GST_START_TEST (test_depayloader_single_and_messed_fragments_2)
860 {
861 GstHarness *h;
862 GstBuffer *in, *out, *nal;
863 const gint DATA_LEN = sizeof (guint32) + 4;
864 struct avtp_stream_pdu *pdu;
865 GstMapInfo map;
866 gsize offset;
867
868 /* Create the harness for the avtpcvfpay */
869 h = gst_harness_new ("avtpcvfdepay");
870 gst_harness_set_src_caps_str (h, "application/x-avtp");
871
872 /* Create the input AVTPDU header */
873 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 4);
874 gst_buffer_map (in, &map, GST_MAP_READWRITE);
875 pdu = (struct avtp_stream_pdu *) map.data;
876
877 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
878 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
879 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
880 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
881 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
882 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
883 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
884 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
885 map.data[AVTP_CVF_H264_HEADER_SIZE] = 3 << 5 | 28; /* NAL type FU-A, NRI 3 */
886 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 7) | 4; /* S = 1, type 4 */
887 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 2, 0);
888 gst_buffer_unmap (in, &map);
889
890 /* Send a perfectly valid start fragment */
891 gst_harness_push (h, gst_buffer_copy (in));
892 fail_unless (gst_harness_try_pull (h) == NULL);
893
894 /* Then, we send a single NAL. Previous fragment should be dropped */
895 gst_buffer_map (in, &map, GST_MAP_READWRITE);
896 pdu = (struct avtp_stream_pdu *) map.data;
897 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
898 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
899 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x2; /* Add NAL type */
900 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 5);
901 gst_buffer_unmap (in, &map);
902
903 /* When we push it, it should come out as it has M = 1 */
904 out = gst_harness_push_and_pull (h, gst_buffer_copy (in));
905
906 /* Check that we got the right one - its NAL filling should start with 5 */
907 fail_unless_equals_uint64 (GST_BUFFER_DTS (out), 1000000);
908 fail_unless_equals_uint64 (GST_BUFFER_PTS (out), 2000000);
909
910 offset = 0;
911 nal = fetch_nal (out, &offset);
912 fail_unless_equals_uint64 (nal_size (nal), 4);
913 fail_unless_equals_uint64 (nal_type (nal), 2);
914 fail_unless (check_nal_filling (nal, 5) == TRUE);
915 gst_buffer_unref (nal);
916
917 /* Ensure no other NAL units are present */
918 nal = fetch_nal (out, &offset);
919 fail_unless (nal == NULL);
920
921 /* To be really sure, send an ending fragment. It should be dropped,
922 * as there should not be any previous fragment on the wait */
923 gst_buffer_map (in, &map, GST_MAP_READWRITE);
924 pdu = (struct avtp_stream_pdu *) map.data;
925 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
926 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
927 map.data[AVTP_CVF_H264_HEADER_SIZE] = 3 << 5 | 28; /* NAL type FU-A, NRI 3 */
928 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 6) | 4; /* E = 1, type 4 */
929 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 2, 2);
930 gst_buffer_unmap (in, &map);
931
932 gst_harness_push (h, gst_buffer_copy (in));
933 fail_unless (gst_harness_try_pull (h) == NULL);
934
935 gst_buffer_unref (out);
936 gst_buffer_unref (in);
937 gst_harness_teardown (h);
938 }
939
940 GST_END_TEST;
941
942 /* This test ensures that, if a fragment is dropped due arrival of a single
943 * NAL (and fragment was never completed), any previous single NAL waiting
944 * for M set NAL are flushed to the pipeline. avtpcvfdepay never sents known
945 * incomplete NAL units to the pipeline, but should not hold forever NALs
946 * waiting for an M set NAL - specially after something wrong already happened */
GST_START_TEST(test_depayloader_single_and_messed_fragments_3)947 GST_START_TEST (test_depayloader_single_and_messed_fragments_3)
948 {
949 GstHarness *h;
950 GstBuffer *in, *out, *nal;
951 const gint DATA_LEN = sizeof (guint32) + 4;
952 struct avtp_stream_pdu *pdu;
953 GstMapInfo map;
954 gsize offset;
955
956 /* Create the harness for the avtpcvfpay */
957 h = gst_harness_new ("avtpcvfdepay");
958 gst_harness_set_src_caps_str (h, "application/x-avtp");
959
960 /* Create the input AVTPDU header */
961 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 4);
962 gst_buffer_map (in, &map, GST_MAP_READWRITE);
963 pdu = (struct avtp_stream_pdu *) map.data;
964
965 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
966 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
967 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
968 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
969 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
970 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
971 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
972 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
973 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x2; /* Add NAL type */
974 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
975 gst_buffer_unmap (in, &map);
976
977 /* Send a single NAL with M = 0, so nothing will come out */
978 gst_harness_push (h, gst_buffer_copy (in));
979 fail_unless (gst_harness_try_pull (h) == NULL);
980
981 /* Send a valid start fragment */
982 gst_buffer_map (in, &map, GST_MAP_READWRITE);
983 pdu = (struct avtp_stream_pdu *) map.data;
984 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
985 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
986 map.data[AVTP_CVF_H264_HEADER_SIZE] = 3 << 5 | 28; /* NAL type FU-A, NRI 3 */
987 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 7) | 4; /* S = 1, type 4 */
988 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 2, 0);
989 gst_buffer_unmap (in, &map);
990
991 gst_harness_push (h, gst_buffer_copy (in));
992 fail_unless (gst_harness_try_pull (h) == NULL);
993
994 /* Send a single NAL without ending fragment. So, both first NAL and second should
995 * come out, on two different buffers. Fragment should be gone. */
996 gst_buffer_map (in, &map, GST_MAP_READWRITE);
997 pdu = (struct avtp_stream_pdu *) map.data;
998 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
999 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
1000 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x3; /* Add NAL type */
1001 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 7);
1002 gst_buffer_unmap (in, &map);
1003
1004 gst_harness_push (h, gst_buffer_copy (in));
1005 fail_unless_equals_uint64 (gst_harness_buffers_received (h), 2);
1006
1007 /* Check that we got the right ones. First has nal_type 2, and second 3.
1008 * Second also has its nal filling starting from 7 */
1009 out = gst_harness_pull (h);
1010 fail_unless_equals_uint64 (GST_BUFFER_DTS (out), 1000000);
1011 fail_unless_equals_uint64 (GST_BUFFER_PTS (out), 2000000);
1012
1013 offset = 0;
1014 nal = fetch_nal (out, &offset);
1015 fail_unless_equals_uint64 (nal_size (nal), 4);
1016 fail_unless_equals_uint64 (nal_type (nal), 2);
1017 fail_unless (check_nal_filling (nal, 0) == TRUE);
1018 gst_buffer_unref (nal);
1019
1020 /* Ensure no other NAL units are present */
1021 nal = fetch_nal (out, &offset);
1022 fail_unless (nal == NULL);
1023 gst_buffer_unref (out);
1024
1025 out = gst_harness_pull (h);
1026 fail_unless_equals_uint64 (GST_BUFFER_DTS (out), 1000000);
1027 fail_unless_equals_uint64 (GST_BUFFER_PTS (out), 2000000);
1028
1029 offset = 0;
1030 nal = fetch_nal (out, &offset);
1031 fail_unless_equals_uint64 (nal_size (nal), 4);
1032 fail_unless_equals_uint64 (nal_type (nal), 3);
1033 fail_unless (check_nal_filling (nal, 7) == TRUE);
1034 gst_buffer_unref (nal);
1035
1036 /* Ensure no other NAL units are present */
1037 nal = fetch_nal (out, &offset);
1038 fail_unless (nal == NULL);
1039 gst_buffer_unref (out);
1040
1041 /* To be really sure, send an ending fragment. It should be dropped,
1042 * as there should not be any previous fragment on the wait */
1043 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1044 pdu = (struct avtp_stream_pdu *) map.data;
1045 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 3);
1046 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
1047 map.data[AVTP_CVF_H264_HEADER_SIZE] = 3 << 5 | 28; /* NAL type FU-A, NRI 3 */
1048 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 6) | 4; /* E = 1, type 4 */
1049 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 2, 2);
1050 gst_buffer_unmap (in, &map);
1051
1052 gst_harness_push (h, gst_buffer_copy (in));
1053 fail_unless (gst_harness_try_pull (h) == NULL);
1054
1055 gst_buffer_unref (in);
1056 gst_harness_teardown (h);
1057 }
1058
1059 GST_END_TEST;
1060
GST_START_TEST(test_depayloader_property)1061 GST_START_TEST (test_depayloader_property)
1062 {
1063 GstHarness *h;
1064 GstElement *element;
1065 guint64 streamid;
1066
1067 /* Create the harness for the avtpcvfpay */
1068 h = gst_harness_new_parse ("avtpcvfdepay streamid=0xAABBCCDDEEFF0001");
1069
1070 /* Check if property was properly set up */
1071 element = gst_harness_find_element (h, "avtpcvfdepay");
1072 g_object_get (G_OBJECT (element), "streamid", &streamid, NULL);
1073 fail_unless_equals_uint64 (streamid, 0xAABBCCDDEEFF0001);
1074
1075 gst_object_unref (element);
1076 gst_harness_teardown (h);
1077 }
1078
1079 GST_END_TEST;
1080
1081 /* Tests if everything goes right when a single NAL unit without M bit is
1082 * followed by fragments that, when merged, have the M bit set */
GST_START_TEST(test_depayloader_single_and_fragmented)1083 GST_START_TEST (test_depayloader_single_and_fragmented)
1084 {
1085 GstHarness *h;
1086 GstBuffer *in, *out, *nal;
1087 const gint DATA_LEN = sizeof (guint32) + 4;
1088 struct avtp_stream_pdu *pdu;
1089 GstMapInfo map;
1090 gsize offset;
1091
1092 /* Create the harness for the avtpcvfpay */
1093 h = gst_harness_new ("avtpcvfdepay");
1094 gst_harness_set_src_caps_str (h, "application/x-avtp");
1095
1096 /* Create the input AVTPDU header */
1097 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 4);
1098 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1099 pdu = (struct avtp_stream_pdu *) map.data;
1100
1101 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
1102 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
1103 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
1104 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
1105 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
1106 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
1107 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
1108 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
1109 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x1; /* Add NAL type */
1110 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
1111 gst_buffer_unmap (in, &map);
1112
1113 /* First, we send a single NAL with M = 0, so nothing should come out */
1114 gst_harness_push (h, gst_buffer_copy (in));
1115 fail_unless (gst_harness_try_pull (h) == NULL);
1116
1117 /* Then, we send first fragment */
1118 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1119 pdu = (struct avtp_stream_pdu *) map.data;
1120 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
1121 map.data[AVTP_CVF_H264_HEADER_SIZE] = 3 << 5 | 28; /* NAL type FU-A, NRI 3 */
1122 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 7) | 4; /* S = 1, type 4 */
1123 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 2, 0);
1124 gst_buffer_unmap (in, &map);
1125
1126 gst_harness_push (h, gst_buffer_copy (in));
1127 fail_unless (gst_harness_try_pull (h) == NULL);
1128
1129 /* And last */
1130 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1131 pdu = (struct avtp_stream_pdu *) map.data;
1132 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
1133 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
1134 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 6) | 4; /* E = 1, type 4 */
1135 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 2, 2);
1136 gst_buffer_unmap (in, &map);
1137
1138 gst_harness_push (h, gst_buffer_copy (in));
1139 fail_unless_equals_int (gst_harness_buffers_received (h), 1);
1140
1141 out = gst_harness_pull (h);
1142 fail_unless_equals_uint64 (GST_BUFFER_DTS (out), 1000000);
1143 fail_unless_equals_uint64 (GST_BUFFER_PTS (out), 2000000);
1144
1145 /* Validate each NAL unit size and content */
1146 offset = 0;
1147 nal = fetch_nal (out, &offset);
1148 fail_unless_equals_uint64 (nal_size (nal), 4);
1149 fail_unless (check_nal_filling (nal, 0) == TRUE);
1150 fail_unless_equals_uint64 (nal_type (nal), 1);
1151 gst_buffer_unref (nal);
1152 nal = fetch_nal (out, &offset);
1153 fail_unless_equals_uint64 (nal_size (nal), 5);
1154 fail_unless (check_nal_filling (nal, 0) == TRUE);
1155 fail_unless_equals_uint64 (nal_type (nal), 4);
1156 gst_buffer_unref (nal);
1157
1158 /* Ensure no other NAL units are present */
1159 nal = fetch_nal (out, &offset);
1160 fail_unless (nal == NULL);
1161
1162 gst_buffer_unref (out);
1163 gst_buffer_unref (in);
1164 gst_harness_teardown (h);
1165 }
1166
1167 GST_END_TEST;
1168
1169 /* Tests a simple fragmented NAL scenario */
GST_START_TEST(test_depayloader_fragmented)1170 GST_START_TEST (test_depayloader_fragmented)
1171 {
1172 GstHarness *h;
1173 GstBuffer *in, *out, *nal;
1174 const gint DATA_LEN = sizeof (guint32) + 10;
1175 struct avtp_stream_pdu *pdu;
1176 GstMapInfo map;
1177 gsize offset;
1178
1179 /* Create the harness for the avtpcvfpay */
1180 h = gst_harness_new ("avtpcvfdepay");
1181 gst_harness_set_src_caps_str (h, "application/x-avtp");
1182
1183 /* Create the input AVTPDU */
1184 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 10);
1185 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1186 pdu = (struct avtp_stream_pdu *) map.data;
1187
1188 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
1189 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
1190 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
1191 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
1192 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
1193 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
1194 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
1195 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
1196 map.data[AVTP_CVF_H264_HEADER_SIZE] = 3 << 5 | 28; /* NAL type FU-A, NRI 3 */
1197 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 7) | 4; /* S = 1, type 4 */
1198 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 0);
1199 gst_buffer_unmap (in, &map);
1200
1201 /* We push a copy so that we can change only what is necessary on our buffer */
1202 gst_harness_push (h, gst_buffer_copy (in));
1203 fail_unless (gst_harness_try_pull (h) == NULL);
1204
1205 /* Send second AVTPDU */
1206 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1207 pdu = (struct avtp_stream_pdu *) map.data;
1208 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
1209 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = 4; /* type 4 */
1210 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 8);
1211 gst_buffer_unmap (in, &map);
1212
1213 gst_harness_push (h, gst_buffer_copy (in));
1214 fail_unless (gst_harness_try_pull (h) == NULL);
1215
1216 /* Send third and last AVTPDU */
1217 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1218 pdu = (struct avtp_stream_pdu *) map.data;
1219 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
1220 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
1221 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
1222 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
1223 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 6) | 4; /* E = 1, type 4 */
1224 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], 8, 16);
1225 gst_buffer_unmap (in, &map);
1226
1227 gst_harness_push (h, gst_buffer_copy (in));
1228 fail_unless_equals_int (gst_harness_buffers_received (h), 1);
1229
1230 out = gst_harness_pull (h);
1231 fail_unless_equals_uint64 (GST_BUFFER_DTS (out), 1000000);
1232 fail_unless_equals_uint64 (GST_BUFFER_PTS (out), 2000000);
1233
1234 offset = 0;
1235 nal = fetch_nal (out, &offset);
1236 fail_unless_equals_uint64 (nal_size (nal), 25);
1237 fail_unless (check_nal_filling (nal, 0) == TRUE);
1238 fail_unless_equals_uint64 (nal_type (nal), 4);
1239 gst_buffer_unref (nal);
1240
1241 gst_buffer_unref (out);
1242 gst_buffer_unref (in);
1243 gst_harness_teardown (h);
1244 }
1245
1246 GST_END_TEST;
1247
1248 /* Tests a big fragmented NAL scenario */
GST_START_TEST(test_depayloader_fragmented_big)1249 GST_START_TEST (test_depayloader_fragmented_big)
1250 {
1251 GstHarness *h;
1252 GstBuffer *in, *out, *nal;
1253 const gint DATA_LEN = 1470;
1254 struct avtp_stream_pdu *pdu;
1255 /* 12000 * 1468 > 2^24 - so we can check if nal size is retrieved correctly */
1256 const gint nal_count = 12000;
1257 guint8 seq_num = 0;
1258 GstMapInfo map;
1259 gsize offset;
1260 gint i;
1261
1262 /* Create the harness for the avtpcvfpay */
1263 h = gst_harness_new ("avtpcvfdepay");
1264 gst_harness_set_src_caps_str (h, "application/x-avtp");
1265
1266 /* Create the input AVTPDU */
1267 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + DATA_LEN);
1268 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1269 pdu = (struct avtp_stream_pdu *) map.data;
1270
1271 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
1272 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
1273 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
1274 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
1275 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
1276 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
1277 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
1278 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN,
1279 DATA_LEN + sizeof (guint32));
1280 map.data[AVTP_CVF_H264_HEADER_SIZE] = 3 << 5 | 28; /* NAL type FU-A, NRI 3 */
1281 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 7) | 4; /* S = 1, type 4 */
1282 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], DATA_LEN - 2, 0);
1283 gst_buffer_unmap (in, &map);
1284
1285 /* We push a copy so that we can change only what is necessary on our buffer */
1286 gst_harness_push (h, gst_buffer_copy (in));
1287 fail_unless (gst_harness_try_pull (h) == NULL);
1288
1289 /* Loop sending fragments. The idea is to create a NAL unit big enough
1290 * to use the 4 bytes of nal_length_size */
1291 for (i = 0; i < nal_count - 1; i++) {
1292
1293 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1294 pdu = (struct avtp_stream_pdu *) map.data;
1295 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, ++seq_num);
1296 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = 4; /* type 4 */
1297 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 2], DATA_LEN - 2,
1298 (guint8) ((DATA_LEN - 2) * seq_num));
1299
1300 /* Last one is special - need to set M and TV, etc */
1301 if (i == nal_count - 2) {
1302 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
1303 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
1304 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
1305 map.data[AVTP_CVF_H264_HEADER_SIZE + 1] = (1 << 6) | 4; /* E = 1, type 4 */
1306 }
1307
1308 gst_buffer_unmap (in, &map);
1309
1310 gst_harness_push (h, gst_buffer_copy (in));
1311 if (i < nal_count - 2)
1312 fail_unless (gst_harness_try_pull (h) == NULL);
1313 }
1314
1315 /* After last one was sent, we check everything */
1316 fail_unless_equals_int (gst_harness_buffers_received (h), 1);
1317
1318 out = gst_harness_pull (h);
1319 fail_unless_equals_uint64 (GST_BUFFER_DTS (out), 1000000);
1320 fail_unless_equals_uint64 (GST_BUFFER_PTS (out), 2000000);
1321
1322 offset = 0;
1323 nal = fetch_nal (out, &offset);
1324 fail_unless_equals_uint64 (nal_size (nal), (DATA_LEN - 2) * nal_count + 1);
1325 fail_unless (check_nal_filling (nal, 0) == TRUE);
1326 fail_unless_equals_uint64 (nal_type (nal), 4);
1327 gst_buffer_unref (nal);
1328
1329 gst_buffer_unref (out);
1330 gst_buffer_unref (in);
1331 gst_harness_teardown (h);
1332 }
1333
1334 GST_END_TEST;
1335
1336 /* Tests several single NAL units. They should be grouped and delivered
1337 * to the pipeline only when one NAL unit with M bit set arrives */
GST_START_TEST(test_depayloader_multiple_single)1338 GST_START_TEST (test_depayloader_multiple_single)
1339 {
1340 GstHarness *h;
1341 GstBuffer *in, *out, *nal;
1342 const gint DATA_LEN = sizeof (guint32) + 4;
1343 struct avtp_stream_pdu *pdu;
1344 GstMapInfo map;
1345 gsize offset;
1346
1347 /* Create the harness for the avtpcvfpay */
1348 h = gst_harness_new ("avtpcvfdepay");
1349 gst_harness_set_src_caps_str (h, "application/x-avtp");
1350
1351 /* Create the input AVTPDU header */
1352 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 4);
1353 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1354 pdu = (struct avtp_stream_pdu *) map.data;
1355
1356 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
1357 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
1358 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
1359 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
1360 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
1361 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
1362 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
1363 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
1364 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x7; /* Add NAL type */
1365 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
1366 gst_buffer_unmap (in, &map);
1367
1368 /* We push a copy so that we can change only what is necessary on our buffer */
1369 gst_harness_push (h, gst_buffer_copy (in));
1370 fail_unless (gst_harness_try_pull (h) == NULL);
1371
1372 /* Send second AVTPDU */
1373 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1374 pdu = (struct avtp_stream_pdu *) map.data;
1375 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
1376 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
1377 gst_buffer_unmap (in, &map);
1378
1379 gst_harness_push (h, gst_buffer_copy (in));
1380 fail_unless (gst_harness_try_pull (h) == NULL);
1381
1382 /* Send third and last AVTPDU */
1383 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1384 pdu = (struct avtp_stream_pdu *) map.data;
1385 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
1386 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
1387 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x1; /* Add NAL type */
1388 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
1389 gst_buffer_unmap (in, &map);
1390
1391 gst_harness_push (h, gst_buffer_copy (in));
1392 fail_unless_equals_int (gst_harness_buffers_received (h), 1);
1393
1394 out = gst_harness_pull (h);
1395 fail_unless_equals_uint64 (GST_BUFFER_DTS (out), 1000000);
1396 fail_unless_equals_uint64 (GST_BUFFER_PTS (out), 2000000);
1397
1398 /* Validate each NAL unit size and content */
1399 offset = 0;
1400 nal = fetch_nal (out, &offset);
1401 fail_unless_equals_uint64 (nal_size (nal), 4);
1402 fail_unless (check_nal_filling (nal, 0) == TRUE);
1403 fail_unless_equals_uint64 (nal_type (nal), 7);
1404 gst_buffer_unref (nal);
1405 nal = fetch_nal (out, &offset);
1406 fail_unless_equals_uint64 (nal_size (nal), 4);
1407 fail_unless (check_nal_filling (nal, 0) == TRUE);
1408 fail_unless_equals_uint64 (nal_type (nal), 7);
1409 gst_buffer_unref (nal);
1410 nal = fetch_nal (out, &offset);
1411 fail_unless_equals_uint64 (nal_size (nal), 4);
1412 fail_unless (check_nal_filling (nal, 0) == TRUE);
1413 fail_unless_equals_uint64 (nal_type (nal), 1);
1414 gst_buffer_unref (nal);
1415
1416 /* Ensure no other NAL units are present */
1417 nal = fetch_nal (out, &offset);
1418 fail_unless (nal == NULL);
1419
1420 gst_buffer_unref (out);
1421 gst_buffer_unref (in);
1422 gst_harness_teardown (h);
1423 }
1424
1425 GST_END_TEST;
1426
GST_START_TEST(test_depayloader_single)1427 GST_START_TEST (test_depayloader_single)
1428 {
1429 GstHarness *h;
1430 GstBuffer *in, *out;
1431 const gint DATA_LEN = sizeof (guint32) + 4;
1432 struct avtp_stream_pdu *pdu;
1433 GstMapInfo map;
1434
1435 /* Create the harness for the avtpcvfpay */
1436 h = gst_harness_new ("avtpcvfdepay");
1437 gst_harness_set_src_caps_str (h, "application/x-avtp");
1438
1439 /* Create the input AVTPDU header */
1440 in = gst_harness_create_buffer (h, AVTP_CVF_H264_HEADER_SIZE + 4);
1441 gst_buffer_map (in, &map, GST_MAP_READWRITE);
1442 pdu = (struct avtp_stream_pdu *) map.data;
1443
1444 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
1445 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
1446 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
1447 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
1448 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 1000000);
1449 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
1450 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 2000000);
1451 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
1452 map.data[AVTP_CVF_H264_HEADER_SIZE] = 0x1; /* Add NAL type */
1453 fill_nal (&map.data[AVTP_CVF_H264_HEADER_SIZE + 1], 3, 0);
1454 gst_buffer_unmap (in, &map);
1455
1456 out = gst_harness_push_and_pull (h, in);
1457
1458 fail_unless_equals_uint64 (GST_BUFFER_DTS (out), 1000000);
1459 fail_unless_equals_uint64 (GST_BUFFER_PTS (out), 2000000);
1460 fail_unless_equals_uint64 (nal_size (out), 4);
1461 fail_unless_equals_uint64 (nal_type (out), 1);
1462 fail_unless (check_nal_filling (out, 0) == TRUE);
1463 gst_buffer_unref (out);
1464 gst_harness_teardown (h);
1465 }
1466
1467 GST_END_TEST;
1468
1469 static Suite *
avtpcvfdepay_suite(void)1470 avtpcvfdepay_suite (void)
1471 {
1472 Suite *s = suite_create ("avtpcvfdepay");
1473 TCase *tc_chain = tcase_create ("general");
1474 TCase *tc_slow = tcase_create ("slow");
1475
1476 suite_add_tcase (s, tc_chain);
1477 tcase_add_test (tc_chain, test_depayloader_single);
1478 tcase_add_test (tc_chain, test_depayloader_multiple_single);
1479 tcase_add_test (tc_chain, test_depayloader_fragmented);
1480 tcase_add_test (tc_chain, test_depayloader_single_and_fragmented);
1481 tcase_add_test (tc_chain, test_depayloader_property);
1482 tcase_add_test (tc_chain, test_depayloader_lost_packet);
1483 tcase_add_test (tc_chain, test_depayloader_lost_fragments);
1484 tcase_add_test (tc_chain, test_depayloader_single_and_messed_fragments);
1485 tcase_add_test (tc_chain, test_depayloader_single_and_messed_fragments_2);
1486 tcase_add_test (tc_chain, test_depayloader_single_and_messed_fragments_3);
1487 tcase_add_test (tc_chain, test_depayloader_invalid_avtpdu);
1488 tcase_add_test (tc_chain, test_depayloader_single_eos);
1489 tcase_add_test (tc_chain, test_depayloader_fragmented_eos);
1490 tcase_add_test (tc_chain, test_depayloader_fragmented_two_start_eos);
1491 tcase_add_test (tc_chain, test_depayloader_multiple_lost_eos);
1492 tcase_add_test (tc_chain, test_depayloader_fragment_and_single);
1493
1494 suite_add_tcase (s, tc_slow);
1495 /* 'fragmented_big' may take some time to run, so give it a bit more time */
1496 tcase_set_timeout (tc_slow, 20);
1497 tcase_add_test (tc_slow, test_depayloader_fragmented_big);
1498
1499 return s;
1500 }
1501
1502 GST_CHECK_MAIN (avtpcvfdepay);
1503