2 * GStreamer AVTP Plugin
3 * Copyright (C) 2019 Intel Corporation
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
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.
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
22 #include <gst/check/gstcheck.h>
23 #include <gst/check/gstharness.h>
28 #define AVTP_CVF_H264_HEADER_SIZE (sizeof(struct avtp_stream_pdu) + sizeof(guint32))
29 #define STREAM_ID 0xAABBCCDDEEFF0001
31 /* Simple codec data, with only the NAL size len, no SPS/PPS. */
33 generate_caps (guint8 nal_size_len)
35 GstBuffer *codec_data;
39 /* 7 is the minimal codec_data size, when no SPS/PPS is sent */
40 codec_data = gst_buffer_new_allocate (NULL, 7, NULL);
41 gst_buffer_map (codec_data, &map, GST_MAP_READWRITE);
43 memset (map.data, 0, map.size);
44 map.data[0] = 1; /* version */
45 map.data[4] = (nal_size_len - 1) | 0xfc; /* Other 6 bits are 1 */
46 map.data[5] = 0xe0; /* first 3 bits are 1 */
48 gst_buffer_unmap (codec_data, &map);
50 caps = gst_caps_new_simple ("video/x-h264",
51 "stream-format", G_TYPE_STRING, "avc",
52 "alignment", G_TYPE_STRING, "au",
53 "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
54 gst_buffer_unref (codec_data);
60 fill (guint8 * buf, gsize size)
69 check_nal_filling (GstBuffer * buffer, guint8 first)
73 gsize offset = AVTP_CVF_H264_HEADER_SIZE + 1;
74 gboolean result = TRUE;
76 gst_buffer_map (buffer, &map, GST_MAP_READ);
77 if ((map.data[AVTP_CVF_H264_HEADER_SIZE] & 0x1f) == 28)
78 offset++; /* Fragmented NALs have 2 bytes header */
80 for (i = offset; i < map.size; i++) {
81 if (map.data[i] != first++) {
91 add_nal (GstBuffer * buffer, gsize size, guint type, gsize offset)
95 gst_buffer_map (buffer, &map, GST_MAP_READWRITE);
97 map.data[offset] = map.data[offset + 1] = 0;
98 map.data[offset + 2] = size >> 8;
99 map.data[offset + 3] = size & 0xff;
100 map.data[offset + 4] = type & 0x1f;
101 fill (&map.data[offset + 5], size - 1);
103 gst_buffer_unmap (buffer, &map);
106 /* This function assumes that NAL size len is 2 */
108 add_nal_2 (GstBuffer * buffer, gsize size, guint type, gsize offset)
112 gst_buffer_map (buffer, &map, GST_MAP_READWRITE);
114 map.data[offset] = size >> 8;
115 map.data[offset + 1] = size & 0xff;
116 map.data[offset + 2] = type & 0x1f;
117 fill (&map.data[offset + 3], size - 1);
119 gst_buffer_unmap (buffer, &map);
123 compare_h264_avtpdu (struct avtp_stream_pdu *pdu, GstBuffer * buffer)
128 gst_buffer_map (buffer, &map, GST_MAP_READ);
129 /* buffer must have at least the header size */
130 if (map.size < AVTP_CVF_H264_HEADER_SIZE)
133 result = memcmp (map.data, pdu, AVTP_CVF_H264_HEADER_SIZE) == 0;
135 gst_buffer_unmap (buffer, &map);
140 GST_START_TEST (test_payloader_zero_sized_nal)
146 /* Create the harness for the avtpcvfpay */
147 h = gst_harness_new_parse
148 ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
149 gst_harness_set_src_caps (h, generate_caps (4));
151 /* We have the buffer with the nal size (4 bytes) and the nal (4 bytes), but
152 * nal size will be zero */
153 in = gst_harness_create_buffer (h, 8);
154 GST_BUFFER_DTS (in) = 1000000;
155 GST_BUFFER_PTS (in) = 2000000;
157 gst_buffer_map (in, &map, GST_MAP_READWRITE);
158 map.data[0] = map.data[1] = map.data[2] = map.data[3] = 0; /* Set NAL size to 0 */
159 map.data[4] = 1; /* Some dummy vcl NAL type */
160 gst_buffer_unmap (in, &map);
162 gst_harness_push (h, in);
164 /* No buffer shuld come out */
165 fail_unless_equals_int (gst_harness_buffers_received (h), 0);
167 gst_harness_teardown (h);
172 GST_START_TEST (test_payloader_no_codec_data)
178 /* Caps without codec_data */
179 caps = gst_caps_new_simple ("video/x-h264",
180 "stream-format", G_TYPE_STRING, "avc",
181 "alignment", G_TYPE_STRING, "au", NULL);
183 /* Create the harness for the avtpcvfpay */
184 h = gst_harness_new_parse
185 ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
186 gst_harness_set_src_caps (h, caps);
188 /* No buffer should come out when we send input */
189 in = gst_harness_create_buffer (h, 8);
190 add_nal (in, 4, 1, 0);
191 GST_BUFFER_DTS (in) = 1000000;
192 GST_BUFFER_PTS (in) = 2000000;
194 gst_harness_push (h, in);
195 fail_unless_equals_int (gst_harness_buffers_received (h), 0);
197 gst_harness_teardown (h);
202 GST_START_TEST (test_payloader_invalid_caps)
204 GstBuffer *codec_data;
211 /* 7 is the minimal codec_data size, when no SPS/PPS is sent */
212 codec_data = gst_buffer_new_allocate (NULL, 7, NULL);
213 gst_buffer_map (codec_data, &map, GST_MAP_READWRITE);
215 memset (map.data, 0, map.size);
216 map.data[0] = 0; /* version */
217 map.data[4] = 0x03 | 0xfc; /* Other 6 bits are 1 */
218 map.data[5] = 0xe0; /* first 3 bits are 1 */
220 gst_buffer_unmap (codec_data, &map);
222 caps = gst_caps_new_simple ("video/x-h264",
223 "stream-format", G_TYPE_STRING, "avc",
224 "alignment", G_TYPE_STRING, "au",
225 "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
226 gst_buffer_unref (codec_data);
228 /* Create the harness for the avtpcvfpay */
229 h = gst_harness_new_parse
230 ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000");
231 element = gst_harness_find_element (h, "avtpcvfpay");
232 sinkpad = gst_element_get_static_pad (element, "sink");
234 /* 'codec_data' caps has invalid version */
235 gst_harness_push_event (h, gst_event_new_caps (caps));
236 fail_unless (gst_pad_get_current_caps (sinkpad) == NULL);
237 gst_caps_unref (caps);
239 /* Send a 'codec_data' too small */
240 codec_data = gst_buffer_new_allocate (NULL, 6, NULL);
241 caps = gst_caps_new_simple ("video/x-h264",
242 "stream-format", G_TYPE_STRING, "avc",
243 "alignment", G_TYPE_STRING, "au",
244 "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
245 gst_buffer_unref (codec_data);
247 gst_harness_push_event (h, gst_event_new_caps (caps));
248 fail_unless (gst_pad_get_current_caps (sinkpad) == NULL);
249 gst_caps_unref (caps);
251 gst_harness_teardown (h);
256 GST_START_TEST (test_payloader_incomplete_nal)
261 struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
262 const gint DATA_LEN = sizeof (guint32) + 3;
264 /* Create the 'expected' header */
265 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
266 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
267 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
268 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
269 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
270 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
271 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
272 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
274 /* Create the harness for the avtpcvfpay */
275 h = gst_harness_new_parse
276 ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
277 gst_harness_set_src_caps (h, generate_caps (4));
279 /* Buffer must have the nal len (4 bytes) and the nal (3 bytes) */
280 in = gst_harness_create_buffer (h, 7);
281 GST_BUFFER_DTS (in) = 1000000;
282 GST_BUFFER_PTS (in) = 2000000;
284 gst_buffer_map (in, &map, GST_MAP_READWRITE);
285 map.data[0] = map.data[1] = map.data[2] = 0;
286 map.data[3] = 8; /* Lie that NAL size is 8, when buffer is only 7 (so NAL is 3) */
287 map.data[4] = 1; /* Some dummy vcl NAL type */
291 out = gst_harness_push_and_pull (h, in);
293 /* avtpcvfpay will happily payload the three byte nal. Now, we check it */
294 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
295 fail_unless (check_nal_filling (out, 0) == TRUE);
297 gst_buffer_unref (out);
298 gst_harness_teardown (h);
303 GST_START_TEST (test_payloader_properties)
308 guint64 streamid, processing_deadline;
310 /* Create the harness for the avtpcvfpay */
311 h = gst_harness_new_parse
312 ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=2000000 mtu=100 processing-deadline=5000");
314 /* Check if all properties were properly set up */
315 element = gst_harness_find_element (h, "avtpcvfpay");
316 g_object_get (G_OBJECT (element), "mtt", &mtt, NULL);
317 fail_unless_equals_uint64 (mtt, 1000000);
319 g_object_get (G_OBJECT (element), "mtu", &mtu, NULL);
320 fail_unless_equals_uint64 (mtu, 100);
322 g_object_get (G_OBJECT (element), "tu", &tu, NULL);
323 fail_unless_equals_uint64 (tu, 2000000);
325 g_object_get (G_OBJECT (element), "streamid", &streamid, NULL);
326 fail_unless_equals_uint64 (streamid, 0xAABBCCDDEEFF0001);
328 g_object_get (G_OBJECT (element), "processing-deadline", &processing_deadline,
330 fail_unless_equals_uint64 (processing_deadline, 5000);
332 gst_harness_teardown (h);
336 GST_START_TEST (test_payloader_single_and_fragment_edge)
340 struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
341 const gint DATA_LEN_1 = sizeof (guint32) + 100;
342 const gint DATA_LEN_2 = sizeof (guint32) + 100;
343 const gint DATA_LEN_3 = sizeof (guint32) + 4;
345 /* Create the 'expected' header */
346 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
347 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
348 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
349 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
350 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
351 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
353 /* Create the harness for the avtpcvfpay. Setting mtu=128 ensures that
354 * NAL units will be broken roughly at 100 bytes. More details below. */
355 h = gst_harness_new_parse
356 ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 mtu=128 processing-deadline=0");
357 gst_harness_set_src_caps (h, generate_caps (4));
359 /* Create a buffer to contain the multiple NAL units. This buffer
360 * will hold two NAL units, with 100 and 101 bytes, each preceded
361 * by a 4 bytes header */
362 in = gst_harness_create_buffer (h, 100 + 101 + 2 * 4);
363 add_nal (in, 100, 7, 0);
364 add_nal (in, 101, 1, 104);
365 GST_BUFFER_DTS (in) = 1000000;
366 GST_BUFFER_PTS (in) = 2000000;
368 /* We now push the buffer, and check if we get three from the avtpcvfpay */
369 gst_harness_push (h, in);
370 fail_unless (gst_harness_buffers_received (h) == 3);
372 out = gst_harness_pull (h);
373 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_1);
374 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
375 gst_buffer_unref (out);
377 out = gst_harness_pull (h);
378 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_2);
379 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
380 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
381 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
382 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
383 gst_buffer_unref (out);
385 /* DATA_LEN_3 is 4 because only 98 bytes from the original NAL unit are
386 * sent on the first buffer (due 2 bytes header), and the two remaining
387 * bytes are preceded by the 2 bytes header. Note that the first byte of
388 * the NAL is stripped before the fragmentation (see comment on
389 * test_payloader_single_and_fragment below for more details). */
390 out = gst_harness_pull (h);
391 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_3);
392 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
393 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
394 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
395 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
396 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
397 gst_buffer_unref (out);
398 gst_harness_teardown (h);
403 GST_START_TEST (test_payloader_single_and_fragment)
407 struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
408 const gint DATA_LEN_1 = sizeof (guint32) + 4;
409 const gint DATA_LEN_2 = sizeof (guint32) + 100;
410 const gint DATA_LEN_3 = sizeof (guint32) + 100;
411 const gint DATA_LEN_4 = sizeof (guint32) + 55;
413 /* Create the 'expected' header */
414 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
415 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
416 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
417 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 4000000);
418 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
419 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 5000000);
421 /* Create the harness for the avtpcvfpay. Setting mtu=128 ensures that
422 * NAL units will be broken roughly at 100 bytes. More details below. */
423 h = gst_harness_new_parse
424 ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=1000000 mtu=128");
425 gst_harness_set_src_caps (h, generate_caps (4));
427 /* Create a buffer to contain the multiple NAL units. This buffer
428 * will hold two NAL units, with 4 and 250 bytes, each preceded
429 * by a 4 bytes header */
430 in = gst_harness_create_buffer (h, 4 + 250 + 2 * 4);
431 add_nal (in, 4, 7, 0);
432 add_nal (in, 250, 1, 8);
433 GST_BUFFER_DTS (in) = 1000000;
434 GST_BUFFER_PTS (in) = 2000000;
436 /* We now push the buffer, and check if we get four from the avtpcvfpay */
437 gst_harness_push (h, in);
438 fail_unless (gst_harness_buffers_received (h) == 4);
440 out = gst_harness_pull (h);
441 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_1);
442 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
443 fail_unless (check_nal_filling (out, 0) == TRUE);
444 gst_buffer_unref (out);
446 out = gst_harness_pull (h);
447 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_2);
448 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
449 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
450 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
451 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
452 fail_unless (check_nal_filling (out, 0) == TRUE);
453 gst_buffer_unref (out);
455 out = gst_harness_pull (h);
456 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_3);
457 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
458 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
459 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
460 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
461 fail_unless (check_nal_filling (out, 98) == TRUE);
462 gst_buffer_unref (out);
464 /* For those wondering why DATA_LEN_4 is 55 and not 50 - or why
465 * comment above states that NAL units are broken "rougly" at 100 bytes:
466 * With mtu=128, there are only 100 bytes left for NAL units, so anything
467 * bigger will be broken. But AVTP NAL units fragments have a header with
468 * two bytes, so NAL units will use only 98 bytes. This leaves the last
469 * fragment with 54 bytes. However, instead of being 56 (54 bytes plus
470 * 2 bytes header), it is 55 (53 bytes plus 2 bytes header) due to the
471 * fact that the first byte of the NAL unit (the NAL unit header) is
472 * in fact stripped from the NAL unit before the fragmentation. */
473 out = gst_harness_pull (h);
474 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_4);
475 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 3);
476 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
477 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
478 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 4000000);
479 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
480 fail_unless (check_nal_filling (out, 196) == TRUE);
481 gst_buffer_unref (out);
482 gst_harness_teardown (h);
487 GST_START_TEST (test_payloader_multiple_single_2)
491 struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
492 const gint DATA_LEN_1 = sizeof (guint32) + 32;
493 const gint DATA_LEN_2 = sizeof (guint32) + 16;
494 const gint DATA_LEN_3 = sizeof (guint32) + 8;
496 /* Create the 'expected' header */
497 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
498 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
499 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
500 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
501 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
502 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
504 /* Create the harness for the avtpcvfpay */
505 h = gst_harness_new_parse
506 ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
507 gst_harness_set_src_caps (h, generate_caps (2));
509 /* Create a buffer to contain the multiple NAL units. This buffer
510 * will hold three NAL units, with 32, 16 and 8 bytes, each preceded
511 * by a 2 bytes header */
512 in = gst_harness_create_buffer (h, 32 + 16 + 8 + 4 * 2);
513 add_nal_2 (in, 32, 7, 0);
514 add_nal_2 (in, 16, 7, 34);
515 add_nal_2 (in, 8, 1, 52);
516 GST_BUFFER_DTS (in) = 1000000;
517 GST_BUFFER_PTS (in) = 2000000;
519 /* We now push the buffer, and check if we get three from the avtpcvfpay */
520 gst_harness_push (h, in);
521 fail_unless (gst_harness_buffers_received (h) == 3);
523 out = gst_harness_pull (h);
524 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_1);
525 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
526 fail_unless (check_nal_filling (out, 0) == TRUE);
527 gst_buffer_unref (out);
529 out = gst_harness_pull (h);
530 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_2);
531 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
532 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
533 fail_unless (check_nal_filling (out, 0) == TRUE);
534 gst_buffer_unref (out);
536 out = gst_harness_pull (h);
537 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_3);
538 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
539 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
540 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
541 fail_unless (check_nal_filling (out, 0) == TRUE);
542 gst_buffer_unref (out);
543 gst_harness_teardown (h);
548 GST_START_TEST (test_payloader_multiple_single)
552 struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
553 const gint DATA_LEN_1 = sizeof (guint32) + 32;
554 const gint DATA_LEN_2 = sizeof (guint32) + 16;
555 const gint DATA_LEN_3 = sizeof (guint32) + 8;
557 /* Create the 'expected' header */
558 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
559 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
560 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
561 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
562 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
563 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
565 /* Create the harness for the avtpcvfpay */
566 h = gst_harness_new_parse
567 ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
568 gst_harness_set_src_caps (h, generate_caps (4));
570 /* Create a buffer to contain the multiple NAL units. This buffer
571 * will hold three NAL units, with 32, 16 and 8 bytes, each preceded
572 * by a 4 bytes header */
573 in = gst_harness_create_buffer (h, 32 + 16 + 8 + 4 * 4);
574 add_nal (in, 32, 7, 0);
575 add_nal (in, 16, 7, 36);
576 add_nal (in, 8, 1, 56);
577 GST_BUFFER_DTS (in) = 1000000;
578 GST_BUFFER_PTS (in) = 2000000;
580 /* We now push the buffer, and check if we get three from the avtpcvfpay */
581 gst_harness_push (h, in);
582 fail_unless (gst_harness_buffers_received (h) == 3);
584 out = gst_harness_pull (h);
585 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_1);
586 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
587 fail_unless (check_nal_filling (out, 0) == TRUE);
588 gst_buffer_unref (out);
590 out = gst_harness_pull (h);
591 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_2);
592 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
593 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
594 fail_unless (check_nal_filling (out, 0) == TRUE);
595 gst_buffer_unref (out);
597 out = gst_harness_pull (h);
598 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_3);
599 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
600 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
601 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
602 fail_unless (check_nal_filling (out, 0) == TRUE);
603 gst_buffer_unref (out);
604 gst_harness_teardown (h);
609 GST_START_TEST (test_payloader_single)
613 struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
614 const gint DATA_LEN = sizeof (guint32) + 4;
616 /* Create the 'expected' header */
617 avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
618 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
619 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
620 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
621 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
622 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
623 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
624 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
626 /* Create the harness for the avtpcvfpay */
627 h = gst_harness_new_parse
628 ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
629 gst_harness_set_src_caps (h, generate_caps (4));
631 /* Buffer must have the nal len (4 bytes) and the nal (4 bytes) */
632 in = gst_harness_create_buffer (h, 8);
633 add_nal (in, 4, 1, 0);
634 GST_BUFFER_DTS (in) = 1000000;
635 GST_BUFFER_PTS (in) = 2000000;
637 out = gst_harness_push_and_pull (h, in);
638 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
639 gst_buffer_unref (out);
641 /* Now test if, when nal_type is not vcl (not between 1 and 5), M is not set.
642 * Also, as we're using the same element, seqnum should increase by one */
643 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
644 avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
646 in = gst_harness_create_buffer (h, 8);
647 add_nal (in, 4, 6, 0);
648 GST_BUFFER_DTS (in) = 1000000;
649 GST_BUFFER_PTS (in) = 2000000;
651 out = gst_harness_push_and_pull (h, in);
652 fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
653 fail_unless (check_nal_filling (out, 0) == TRUE);
654 gst_buffer_unref (out);
655 gst_harness_teardown (h);
661 avtpcvfpay_suite (void)
663 Suite *s = suite_create ("avtpcvfpay");
664 TCase *tc_chain = tcase_create ("general");
666 suite_add_tcase (s, tc_chain);
667 tcase_add_test (tc_chain, test_payloader_single);
668 tcase_add_test (tc_chain, test_payloader_multiple_single);
669 tcase_add_test (tc_chain, test_payloader_multiple_single_2);
670 tcase_add_test (tc_chain, test_payloader_single_and_fragment);
671 tcase_add_test (tc_chain, test_payloader_single_and_fragment_edge);
672 tcase_add_test (tc_chain, test_payloader_incomplete_nal);
673 tcase_add_test (tc_chain, test_payloader_invalid_caps);
674 tcase_add_test (tc_chain, test_payloader_properties);
675 tcase_add_test (tc_chain, test_payloader_no_codec_data);
676 tcase_add_test (tc_chain, test_payloader_zero_sized_nal);
681 GST_CHECK_MAIN (avtpcvfpay);