• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 0xAABBCCDDEEFF0001
30 
31 /* Simple codec data, with only the NAL size len, no SPS/PPS. */
32 static GstCaps *
generate_caps(guint8 nal_size_len)33 generate_caps (guint8 nal_size_len)
34 {
35   GstBuffer *codec_data;
36   GstMapInfo map;
37   GstCaps *caps;
38 
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);
42 
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 */
47 
48   gst_buffer_unmap (codec_data, &map);
49 
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);
55 
56   return caps;
57 }
58 
59 static void
fill(guint8 * buf,gsize size)60 fill (guint8 * buf, gsize size)
61 {
62   guint8 i = 0;
63 
64   while (size--)
65     *buf++ = i++;
66 }
67 
68 static gboolean
check_nal_filling(GstBuffer * buffer,guint8 first)69 check_nal_filling (GstBuffer * buffer, guint8 first)
70 {
71   GstMapInfo map;
72   gint i;
73   gsize offset = AVTP_CVF_H264_HEADER_SIZE + 1;
74   gboolean result = TRUE;
75 
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 */
79 
80   for (i = offset; i < map.size; i++) {
81     if (map.data[i] != first++) {
82       result = FALSE;
83       break;
84     }
85   }
86 
87   gst_buffer_unmap (buffer, &map);
88 
89   return result;
90 }
91 
92 static void
add_nal(GstBuffer * buffer,gsize size,guint type,gsize offset)93 add_nal (GstBuffer * buffer, gsize size, guint type, gsize offset)
94 {
95   GstMapInfo map;
96 
97   gst_buffer_map (buffer, &map, GST_MAP_READWRITE);
98 
99   map.data[offset] = map.data[offset + 1] = 0;
100   map.data[offset + 2] = size >> 8;
101   map.data[offset + 3] = size & 0xff;
102   map.data[offset + 4] = type & 0x1f;
103   fill (&map.data[offset + 5], size - 1);
104 
105   gst_buffer_unmap (buffer, &map);
106 }
107 
108 /* This function assumes that NAL size len is 2 */
109 static void
add_nal_2(GstBuffer * buffer,gsize size,guint type,gsize offset)110 add_nal_2 (GstBuffer * buffer, gsize size, guint type, gsize offset)
111 {
112   GstMapInfo map;
113 
114   gst_buffer_map (buffer, &map, GST_MAP_READWRITE);
115 
116   map.data[offset] = size >> 8;
117   map.data[offset + 1] = size & 0xff;
118   map.data[offset + 2] = type & 0x1f;
119   fill (&map.data[offset + 3], size - 1);
120 
121   gst_buffer_unmap (buffer, &map);
122 }
123 
124 static gboolean
compare_h264_avtpdu(struct avtp_stream_pdu * pdu,GstBuffer * buffer)125 compare_h264_avtpdu (struct avtp_stream_pdu *pdu, GstBuffer * buffer)
126 {
127   GstMapInfo map;
128   gboolean result;
129 
130   gst_buffer_map (buffer, &map, GST_MAP_READ);
131   /* buffer must have at least the header size */
132   if (map.size < AVTP_CVF_H264_HEADER_SIZE)
133     return FALSE;
134 
135   result = memcmp (map.data, pdu, AVTP_CVF_H264_HEADER_SIZE) == 0;
136 
137   gst_buffer_unmap (buffer, &map);
138 
139   return result;
140 }
141 
GST_START_TEST(test_payloader_spread_ts)142 GST_START_TEST (test_payloader_spread_ts)
143 {
144   GstHarness *h;
145   GstBuffer *in, *out;
146   gint i, total_fragments, max_interval_frames;
147   guint64 first_tx_time, final_dts, measurement_interval = 250000;
148 
149   /* Create the harness for the avtpcvfpay */
150   h = gst_harness_new_parse
151       ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=2000000 tu=125000 processing-deadline=0 mtu=128 measurement-interval=250000 max-interval-frames=3");
152   gst_harness_set_src_caps (h, generate_caps (4));
153 
154   /* A 980 bytes NAL with mtu=128 should generate 10 fragments */
155   in = gst_harness_create_buffer (h, 980 + 4);
156   add_nal (in, 980, 7, 0);
157   GST_BUFFER_DTS (in) = final_dts = 1000000;
158   GST_BUFFER_PTS (in) = 2000000;
159 
160   /* We now push the buffer, and check if we got ten from the avtpcvfpay */
161   gst_harness_push (h, in);
162   fail_unless_equals_int (gst_harness_buffers_received (h), 10);
163 
164   /* Using max-interval-frames=3, we'll need 4 measurement intervals to send
165    * all fragments, with last one just about current DTS, and others
166    * progressively before that.
167    *
168    * So we should have something like:
169    *
170    * |  1st  |  2nd  |  3rd  |  4th |  Intervals
171    * | 1 2 3 | 4 5 6 | 7 8 9 |  10  |  AVTPDUs in each interval (sharing same DTS/PTS)
172    *
173    * And PTS/DTS should increment by a
174    * measurement-interval / max-interval-frames for each AVTPDU.
175    */
176   i = 0;
177   total_fragments = 10;
178   max_interval_frames = 3;
179   first_tx_time =
180       final_dts -
181       (measurement_interval / max_interval_frames) * (total_fragments - 1);
182   for (i = 0; i < 10; i++) {
183     out = gst_harness_pull (h);
184     fail_unless_equals_uint64 (GST_BUFFER_DTS (out), first_tx_time);
185     gst_buffer_unref (out);
186 
187     first_tx_time += measurement_interval / max_interval_frames;
188   }
189 
190 
191   gst_harness_teardown (h);
192 }
193 
194 GST_END_TEST;
195 
GST_START_TEST(test_payloader_downstream_eos)196 GST_START_TEST (test_payloader_downstream_eos)
197 {
198   GstHarness *h;
199   GstBuffer *in;
200 
201   /* Create the harness for the avtpcvfpay */
202   h = gst_harness_new_parse
203       ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0 ! fakesink num-buffers=1");
204   gst_harness_set_src_caps (h, generate_caps (4));
205 
206   /* Buffer must have the nal len (4 bytes) and the nal (4 bytes) */
207   in = gst_harness_create_buffer (h, 8);
208   add_nal (in, 4, 1, 0);
209   GST_BUFFER_DTS (in) = 1000000;
210   GST_BUFFER_PTS (in) = 2000000;
211 
212   fail_unless_equals_int (gst_harness_push (h, in), GST_FLOW_EOS);
213 
214   gst_harness_teardown (h);
215 }
216 
217 GST_END_TEST;
218 
GST_START_TEST(test_payloader_zero_sized_nal)219 GST_START_TEST (test_payloader_zero_sized_nal)
220 {
221   GstHarness *h;
222   GstBuffer *in;
223   GstMapInfo map;
224 
225   /* Create the harness for the avtpcvfpay */
226   h = gst_harness_new_parse
227       ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
228   gst_harness_set_src_caps (h, generate_caps (4));
229 
230   /* We have the buffer with the nal size (4 bytes) and the nal (4 bytes), but
231    * nal size will be zero */
232   in = gst_harness_create_buffer (h, 8);
233   GST_BUFFER_DTS (in) = 1000000;
234   GST_BUFFER_PTS (in) = 2000000;
235 
236   gst_buffer_map (in, &map, GST_MAP_READWRITE);
237   map.data[0] = map.data[1] = map.data[2] = map.data[3] = 0;    /* Set NAL size to 0 */
238   map.data[4] = 1;              /* Some dummy vcl NAL type */
239   gst_buffer_unmap (in, &map);
240 
241   gst_harness_push (h, in);
242 
243   /* No buffer shuld come out */
244   fail_unless_equals_int (gst_harness_buffers_received (h), 0);
245 
246   gst_harness_teardown (h);
247 }
248 
249 GST_END_TEST;
250 
GST_START_TEST(test_payloader_no_codec_data)251 GST_START_TEST (test_payloader_no_codec_data)
252 {
253   GstHarness *h;
254   GstCaps *caps;
255   GstBuffer *in;
256 
257   /* Caps without codec_data */
258   caps = gst_caps_new_simple ("video/x-h264",
259       "stream-format", G_TYPE_STRING, "avc",
260       "alignment", G_TYPE_STRING, "au", NULL);
261 
262   /* Create the harness for the avtpcvfpay */
263   h = gst_harness_new_parse
264       ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
265   gst_harness_set_src_caps (h, caps);
266 
267   /* No buffer should come out when we send input */
268   in = gst_harness_create_buffer (h, 8);
269   add_nal (in, 4, 1, 0);
270   GST_BUFFER_DTS (in) = 1000000;
271   GST_BUFFER_PTS (in) = 2000000;
272 
273   gst_harness_push (h, in);
274   fail_unless_equals_int (gst_harness_buffers_received (h), 0);
275 
276   gst_harness_teardown (h);
277 }
278 
279 GST_END_TEST;
280 
GST_START_TEST(test_payloader_invalid_caps)281 GST_START_TEST (test_payloader_invalid_caps)
282 {
283   GstBuffer *codec_data;
284   GstElement *element;
285   GstPad *sinkpad;
286   GstMapInfo map;
287   GstCaps *caps;
288   GstHarness *h;
289 
290   /* 7 is the minimal codec_data size, when no SPS/PPS is sent */
291   codec_data = gst_buffer_new_allocate (NULL, 7, NULL);
292   gst_buffer_map (codec_data, &map, GST_MAP_READWRITE);
293 
294   memset (map.data, 0, map.size);
295   map.data[0] = 0;              /* version */
296   map.data[4] = 0x03 | 0xfc;    /* Other 6 bits are 1 */
297   map.data[5] = 0xe0;           /* first 3 bits are 1 */
298 
299   gst_buffer_unmap (codec_data, &map);
300 
301   caps = gst_caps_new_simple ("video/x-h264",
302       "stream-format", G_TYPE_STRING, "avc",
303       "alignment", G_TYPE_STRING, "au",
304       "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
305   gst_buffer_unref (codec_data);
306 
307   /* Create the harness for the avtpcvfpay */
308   h = gst_harness_new_parse
309       ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000");
310   element = gst_harness_find_element (h, "avtpcvfpay");
311   sinkpad = gst_element_get_static_pad (element, "sink");
312 
313   /* 'codec_data' caps has invalid version */
314   gst_harness_push_event (h, gst_event_new_caps (caps));
315   fail_unless (gst_pad_get_current_caps (sinkpad) == NULL);
316   gst_caps_unref (caps);
317 
318   /* Send a 'codec_data' too small */
319   codec_data = gst_buffer_new_allocate (NULL, 6, NULL);
320   caps = gst_caps_new_simple ("video/x-h264",
321       "stream-format", G_TYPE_STRING, "avc",
322       "alignment", G_TYPE_STRING, "au",
323       "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
324   gst_buffer_unref (codec_data);
325 
326   gst_harness_push_event (h, gst_event_new_caps (caps));
327   fail_unless (gst_pad_get_current_caps (sinkpad) == NULL);
328   gst_caps_unref (caps);
329 
330   gst_object_unref (sinkpad);
331   gst_object_unref (element);
332   gst_harness_teardown (h);
333 }
334 
335 GST_END_TEST;
336 
GST_START_TEST(test_payloader_incomplete_nal)337 GST_START_TEST (test_payloader_incomplete_nal)
338 {
339   GstHarness *h;
340   GstBuffer *in, *out;
341   GstMapInfo map;
342   struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
343   const gint DATA_LEN = sizeof (guint32) + 3;
344 
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_M, 1);
350   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
351   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
352   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
353   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
354 
355   /* Create the harness for the avtpcvfpay */
356   h = gst_harness_new_parse
357       ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
358   gst_harness_set_src_caps (h, generate_caps (4));
359 
360   /* Buffer must have the nal len (4 bytes) and the nal (3 bytes) */
361   in = gst_harness_create_buffer (h, 7);
362   GST_BUFFER_DTS (in) = 1000000;
363   GST_BUFFER_PTS (in) = 2000000;
364 
365   gst_buffer_map (in, &map, GST_MAP_READWRITE);
366   map.data[0] = map.data[1] = map.data[2] = 0;
367   map.data[3] = 8;              /* Lie that NAL size is 8, when buffer is only 7 (so NAL is 3) */
368   map.data[4] = 1;              /* Some dummy vcl NAL type */
369   map.data[5] = 0x0;
370   map.data[6] = 0x1;
371   gst_buffer_unmap (in, &map);
372 
373   out = gst_harness_push_and_pull (h, in);
374 
375   /* avtpcvfpay will happily payload the three byte nal. Now, we check it */
376   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
377   fail_unless (check_nal_filling (out, 0) == TRUE);
378 
379   gst_buffer_unref (out);
380   gst_harness_teardown (h);
381 }
382 
383 GST_END_TEST;
384 
GST_START_TEST(test_payloader_properties)385 GST_START_TEST (test_payloader_properties)
386 {
387   GstHarness *h;
388   GstElement *element;
389   guint mtu, mtt, tu, max_interval_frames;
390   guint64 streamid, processing_deadline, measurement_interval;
391 
392   /* Create the harness for the avtpcvfpay */
393   h = gst_harness_new_parse
394       ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=2000000 mtu=100 processing-deadline=5000 measurement-interval=125000 max-interval-frames=3");
395 
396   /* Check if all properties were properly set up */
397   element = gst_harness_find_element (h, "avtpcvfpay");
398   g_object_get (G_OBJECT (element), "mtt", &mtt, NULL);
399   fail_unless_equals_uint64 (mtt, 1000000);
400 
401   g_object_get (G_OBJECT (element), "mtu", &mtu, NULL);
402   fail_unless_equals_uint64 (mtu, 100);
403 
404   g_object_get (G_OBJECT (element), "tu", &tu, NULL);
405   fail_unless_equals_uint64 (tu, 2000000);
406 
407   g_object_get (G_OBJECT (element), "streamid", &streamid, NULL);
408   fail_unless_equals_uint64 (streamid, 0xAABBCCDDEEFF0001);
409 
410   g_object_get (G_OBJECT (element), "processing-deadline", &processing_deadline,
411       NULL);
412   fail_unless_equals_uint64 (processing_deadline, 5000);
413 
414   g_object_get (G_OBJECT (element), "measurement-interval",
415       &measurement_interval, NULL);
416   fail_unless_equals_uint64 (measurement_interval, 125000);
417 
418   g_object_get (G_OBJECT (element), "max-interval-frames",
419       &max_interval_frames, NULL);
420   fail_unless_equals_uint64 (max_interval_frames, 3);
421 
422   gst_object_unref (element);
423   gst_harness_teardown (h);
424 }
425 
426 GST_END_TEST;
GST_START_TEST(test_payloader_single_and_fragment_edge)427 GST_START_TEST (test_payloader_single_and_fragment_edge)
428 {
429   GstHarness *h;
430   GstBuffer *in, *out;
431   struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
432   const gint DATA_LEN_1 = sizeof (guint32) + 100;
433   const gint DATA_LEN_2 = sizeof (guint32) + 100;
434   const gint DATA_LEN_3 = sizeof (guint32) + 4;
435 
436   /* Create the 'expected' header */
437   avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
438   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
439   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
440   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
441   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
442   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
443 
444   /* Create the harness for the avtpcvfpay. Setting mtu=128 ensures that
445    * NAL units will be broken roughly at 100 bytes. More details below. */
446   h = gst_harness_new_parse
447       ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 mtu=128 processing-deadline=0");
448   gst_harness_set_src_caps (h, generate_caps (4));
449 
450   /* Create a buffer to contain the multiple NAL units. This buffer
451    * will hold two NAL units, with 100 and 101 bytes, each preceded
452    * by a 4 bytes header */
453   in = gst_harness_create_buffer (h, 100 + 101 + 2 * 4);
454   add_nal (in, 100, 7, 0);
455   add_nal (in, 101, 1, 104);
456   GST_BUFFER_DTS (in) = 1000000;
457   GST_BUFFER_PTS (in) = 2000000;
458 
459   /* We now push the buffer, and check if we get three from the avtpcvfpay */
460   gst_harness_push (h, in);
461   fail_unless (gst_harness_buffers_received (h) == 3);
462 
463   out = gst_harness_pull (h);
464   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_1);
465   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
466   gst_buffer_unref (out);
467 
468   out = gst_harness_pull (h);
469   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_2);
470   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
471   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
472   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
473   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
474   gst_buffer_unref (out);
475 
476   /* DATA_LEN_3 is 4 because only 98 bytes from the original NAL unit are
477    * sent on the first buffer (due 2 bytes header), and the two remaining
478    * bytes are preceded by the 2 bytes header. Note that the first byte of
479    * the NAL is stripped before the fragmentation (see comment on
480    * test_payloader_single_and_fragment below for more details). */
481   out = gst_harness_pull (h);
482   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_3);
483   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
484   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
485   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
486   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
487   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
488   gst_buffer_unref (out);
489   gst_harness_teardown (h);
490 }
491 
492 GST_END_TEST;
493 
GST_START_TEST(test_payloader_single_and_fragment)494 GST_START_TEST (test_payloader_single_and_fragment)
495 {
496   GstHarness *h;
497   GstBuffer *in, *out;
498   struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
499   const gint DATA_LEN_1 = sizeof (guint32) + 4;
500   const gint DATA_LEN_2 = sizeof (guint32) + 100;
501   const gint DATA_LEN_3 = sizeof (guint32) + 100;
502   const gint DATA_LEN_4 = sizeof (guint32) + 55;
503 
504   /* Create the 'expected' header */
505   avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
506   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
507   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
508   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 4000000);
509   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
510   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 5000000);
511 
512   /* Create the harness for the avtpcvfpay. Setting mtu=128 ensures that
513    * NAL units will be broken roughly at 100 bytes. More details below. */
514   h = gst_harness_new_parse
515       ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=1000000 mtu=128");
516   gst_harness_set_src_caps (h, generate_caps (4));
517 
518   /* Create a buffer to contain the multiple NAL units. This buffer
519    * will hold two NAL units, with 4 and 250 bytes, each preceded
520    * by a 4 bytes header */
521   in = gst_harness_create_buffer (h, 4 + 250 + 2 * 4);
522   add_nal (in, 4, 7, 0);
523   add_nal (in, 250, 1, 8);
524   GST_BUFFER_DTS (in) = 1000000;
525   GST_BUFFER_PTS (in) = 2000000;
526 
527   /* We now push the buffer, and check if we get four from the avtpcvfpay */
528   gst_harness_push (h, in);
529   fail_unless (gst_harness_buffers_received (h) == 4);
530 
531   out = gst_harness_pull (h);
532   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_1);
533   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
534   fail_unless (check_nal_filling (out, 0) == TRUE);
535   gst_buffer_unref (out);
536 
537   out = gst_harness_pull (h);
538   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_2);
539   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
540   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
541   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
542   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
543   fail_unless (check_nal_filling (out, 0) == TRUE);
544   gst_buffer_unref (out);
545 
546   out = gst_harness_pull (h);
547   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_3);
548   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
549   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 0);
550   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 0);
551   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
552   fail_unless (check_nal_filling (out, 98) == TRUE);
553   gst_buffer_unref (out);
554 
555   /* For those wondering why DATA_LEN_4 is 55 and not 50 - or why
556    * comment above states that NAL units are broken "roughly" at 100 bytes:
557    * With mtu=128, there are only 100 bytes left for NAL units, so anything
558    * bigger will be broken. But AVTP NAL units fragments have a header with
559    * two bytes, so NAL units will use only 98 bytes. This leaves the last
560    * fragment with 54 bytes. However, instead of being 56 (54 bytes plus
561    * 2 bytes header), it is 55 (53 bytes plus 2 bytes header) due to the
562    * fact that the first byte of the NAL unit (the NAL unit header) is
563    * in fact stripped from the NAL unit before the fragmentation. */
564   out = gst_harness_pull (h);
565   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_4);
566   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 3);
567   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
568   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
569   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 4000000);
570   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
571   fail_unless (check_nal_filling (out, 196) == TRUE);
572   gst_buffer_unref (out);
573   gst_harness_teardown (h);
574 }
575 
576 GST_END_TEST;
577 
GST_START_TEST(test_payloader_multiple_single_2)578 GST_START_TEST (test_payloader_multiple_single_2)
579 {
580   GstHarness *h;
581   GstBuffer *in, *out;
582   struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
583   const gint DATA_LEN_1 = sizeof (guint32) + 32;
584   const gint DATA_LEN_2 = sizeof (guint32) + 16;
585   const gint DATA_LEN_3 = sizeof (guint32) + 8;
586 
587   /* Create the 'expected' header */
588   avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
589   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
590   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
591   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
592   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
593   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
594 
595   /* Create the harness for the avtpcvfpay */
596   h = gst_harness_new_parse
597       ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
598   gst_harness_set_src_caps (h, generate_caps (2));
599 
600   /* Create a buffer to contain the multiple NAL units. This buffer
601    * will hold three NAL units, with 32, 16 and 8 bytes, each preceded
602    * by a 2 bytes header */
603   in = gst_harness_create_buffer (h, 32 + 16 + 8 + 4 * 2);
604   add_nal_2 (in, 32, 7, 0);
605   add_nal_2 (in, 16, 7, 34);
606   add_nal_2 (in, 8, 1, 52);
607   GST_BUFFER_DTS (in) = 1000000;
608   GST_BUFFER_PTS (in) = 2000000;
609 
610   /* We now push the buffer, and check if we get three from the avtpcvfpay */
611   gst_harness_push (h, in);
612   fail_unless (gst_harness_buffers_received (h) == 3);
613 
614   out = gst_harness_pull (h);
615   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_1);
616   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
617   fail_unless (check_nal_filling (out, 0) == TRUE);
618   gst_buffer_unref (out);
619 
620   out = gst_harness_pull (h);
621   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_2);
622   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
623   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
624   fail_unless (check_nal_filling (out, 0) == TRUE);
625   gst_buffer_unref (out);
626 
627   out = gst_harness_pull (h);
628   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_3);
629   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
630   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
631   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
632   fail_unless (check_nal_filling (out, 0) == TRUE);
633   gst_buffer_unref (out);
634   gst_harness_teardown (h);
635 }
636 
637 GST_END_TEST;
638 
GST_START_TEST(test_payloader_multiple_single)639 GST_START_TEST (test_payloader_multiple_single)
640 {
641   GstHarness *h;
642   GstBuffer *in, *out;
643   struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
644   const gint DATA_LEN_1 = sizeof (guint32) + 32;
645   const gint DATA_LEN_2 = sizeof (guint32) + 16;
646   const gint DATA_LEN_3 = sizeof (guint32) + 8;
647 
648   /* Create the 'expected' header */
649   avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
650   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
651   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
652   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
653   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
654   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
655 
656   /* Create the harness for the avtpcvfpay */
657   h = gst_harness_new_parse
658       ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
659   gst_harness_set_src_caps (h, generate_caps (4));
660 
661   /* Create a buffer to contain the multiple NAL units. This buffer
662    * will hold three NAL units, with 32, 16 and 8 bytes, each preceded
663    * by a 4 bytes header */
664   in = gst_harness_create_buffer (h, 32 + 16 + 8 + 4 * 4);
665   add_nal (in, 32, 7, 0);
666   add_nal (in, 16, 7, 36);
667   add_nal (in, 8, 1, 56);
668   GST_BUFFER_DTS (in) = 1000000;
669   GST_BUFFER_PTS (in) = 2000000;
670 
671   /* We now push the buffer, and check if we get three from the avtpcvfpay */
672   gst_harness_push (h, in);
673   fail_unless (gst_harness_buffers_received (h) == 3);
674 
675   out = gst_harness_pull (h);
676   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_1);
677   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
678   fail_unless (check_nal_filling (out, 0) == TRUE);
679   gst_buffer_unref (out);
680 
681   out = gst_harness_pull (h);
682   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_2);
683   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
684   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
685   fail_unless (check_nal_filling (out, 0) == TRUE);
686   gst_buffer_unref (out);
687 
688   out = gst_harness_pull (h);
689   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN_3);
690   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 2);
691   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
692   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
693   fail_unless (check_nal_filling (out, 0) == TRUE);
694   gst_buffer_unref (out);
695   gst_harness_teardown (h);
696 }
697 
698 GST_END_TEST;
699 
GST_START_TEST(test_payloader_single)700 GST_START_TEST (test_payloader_single)
701 {
702   GstHarness *h;
703   GstBuffer *in, *out;
704   struct avtp_stream_pdu *pdu = alloca (AVTP_CVF_H264_HEADER_SIZE);
705   const gint DATA_LEN = sizeof (guint32) + 4;
706 
707   /* Create the 'expected' header */
708   avtp_cvf_pdu_init (pdu, AVTP_CVF_FORMAT_SUBTYPE_H264);
709   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_ID, STREAM_ID);
710   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TV, 1);
711   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 1);
712   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_TIMESTAMP, 3000000);
713   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_PTV, 1);
714   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_H264_TIMESTAMP, 4000000);
715   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_STREAM_DATA_LEN, DATA_LEN);
716 
717   /* Create the harness for the avtpcvfpay */
718   h = gst_harness_new_parse
719       ("avtpcvfpay streamid=0xAABBCCDDEEFF0001 mtt=1000000 tu=1000000 processing-deadline=0");
720   gst_harness_set_src_caps (h, generate_caps (4));
721 
722   /* Buffer must have the nal len (4 bytes) and the nal (4 bytes) */
723   in = gst_harness_create_buffer (h, 8);
724   add_nal (in, 4, 1, 0);
725   GST_BUFFER_DTS (in) = 1000000;
726   GST_BUFFER_PTS (in) = 2000000;
727 
728   out = gst_harness_push_and_pull (h, in);
729   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
730   gst_buffer_unref (out);
731 
732   /* Now test if, when nal_type is not vcl (not between 1 and 5), M is not set.
733    * Also, as we're using the same element, seqnum should increase by one */
734   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_M, 0);
735   avtp_cvf_pdu_set (pdu, AVTP_CVF_FIELD_SEQ_NUM, 1);
736 
737   in = gst_harness_create_buffer (h, 8);
738   add_nal (in, 4, 6, 0);
739   GST_BUFFER_DTS (in) = 1000000;
740   GST_BUFFER_PTS (in) = 2000000;
741 
742   out = gst_harness_push_and_pull (h, in);
743   fail_unless (compare_h264_avtpdu (pdu, out) == TRUE);
744   fail_unless (check_nal_filling (out, 0) == TRUE);
745   gst_buffer_unref (out);
746   gst_harness_teardown (h);
747 }
748 
749 GST_END_TEST;
750 
751 static Suite *
avtpcvfpay_suite(void)752 avtpcvfpay_suite (void)
753 {
754   Suite *s = suite_create ("avtpcvfpay");
755   TCase *tc_chain = tcase_create ("general");
756 
757   suite_add_tcase (s, tc_chain);
758   tcase_add_test (tc_chain, test_payloader_single);
759   tcase_add_test (tc_chain, test_payloader_multiple_single);
760   tcase_add_test (tc_chain, test_payloader_multiple_single_2);
761   tcase_add_test (tc_chain, test_payloader_single_and_fragment);
762   tcase_add_test (tc_chain, test_payloader_single_and_fragment_edge);
763   tcase_add_test (tc_chain, test_payloader_incomplete_nal);
764   tcase_add_test (tc_chain, test_payloader_invalid_caps);
765   tcase_add_test (tc_chain, test_payloader_properties);
766   tcase_add_test (tc_chain, test_payloader_no_codec_data);
767   tcase_add_test (tc_chain, test_payloader_zero_sized_nal);
768   tcase_add_test (tc_chain, test_payloader_downstream_eos);
769   tcase_add_test (tc_chain, test_payloader_spread_ts);
770 
771   return s;
772 }
773 
774 GST_CHECK_MAIN (avtpcvfpay);
775