• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer RTP payloader unit tests
2  * Copyright (C) 2008 Nokia Corporation and its subsidiary(-ies)
3  *               contact: <stefan.kost@nokia.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include <gst/check/gstcheck.h>
25 #include <gst/check/gstharness.h>
26 #include <gst/audio/audio.h>
27 #include <gst/base/base.h>
28 #include <gst/rtp/gstrtpbuffer.h>
29 #include <stdlib.h>
30 
31 #define RELEASE_ELEMENT(x) if(x) {gst_object_unref(x); x = NULL;}
32 
33 #define LOOP_COUNT 1
34 
35 /*
36  * RTP pipeline structure to store the required elements.
37  */
38 typedef struct
39 {
40   GstElement *pipeline;
41   GstElement *appsrc;
42   GstElement *rtppay;
43   GstElement *rtpdepay;
44   GstElement *fakesink;
45   const guint8 *frame_data;
46   int frame_data_size;
47   int frame_count;
48   GstEvent *custom_event;
49 } rtp_pipeline;
50 
51 /*
52  * Number of bytes received in the chain list function when using buffer lists
53  */
54 static guint chain_list_bytes_received;
55 
56 /*
57  * Chain list function for testing buffer lists
58  */
59 static GstFlowReturn
rtp_pipeline_chain_list(GstPad * pad,GstObject * parent,GstBufferList * list)60 rtp_pipeline_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list)
61 {
62   guint i, len;
63 
64   fail_if (!list);
65   /*
66    * Count the size of the payload in the buffer list.
67    */
68   len = gst_buffer_list_length (list);
69   GST_LOG ("list length %u", len);
70 
71   /* Loop through all buffers */
72   for (i = 0; i < len; i++) {
73     GstBuffer *paybuf;
74     GstMemory *mem;
75     gint size;
76 
77     paybuf = gst_buffer_list_get (list, i);
78     /* only count real data which is expected in last memory block */
79     GST_LOG ("n_memory %d", gst_buffer_n_memory (paybuf));
80     fail_unless (gst_buffer_n_memory (paybuf) > 1);
81     mem = gst_buffer_get_memory_range (paybuf, gst_buffer_n_memory (paybuf) - 1,
82         1);
83     size = gst_memory_get_sizes (mem, NULL, NULL);
84     gst_memory_unref (mem);
85     chain_list_bytes_received += size;
86     GST_LOG ("size %d, total %u", size, chain_list_bytes_received);
87   }
88   gst_buffer_list_unref (list);
89 
90   return GST_FLOW_OK;
91 }
92 
93 static GstFlowReturn
rtp_pipeline_chain(GstPad * pad,GstObject * parent,GstBuffer * buf)94 rtp_pipeline_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
95 {
96   GstBufferList *list;
97 
98   list = gst_buffer_list_new_sized (1);
99   gst_buffer_list_add (list, buf);
100   return rtp_pipeline_chain_list (pad, parent, list);
101 }
102 
103 /*
104  * RTP bus callback.
105  */
106 static gboolean
rtp_bus_callback(GstBus * bus,GstMessage * message,gpointer data)107 rtp_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
108 {
109   GMainLoop *mainloop = (GMainLoop *) data;
110 
111   switch (GST_MESSAGE_TYPE (message)) {
112     case GST_MESSAGE_ERROR:
113     {
114       GError *err;
115 
116       gchar *debug;
117 
118       gchar *element_name;
119 
120       element_name = (message->src) ? gst_object_get_name (message->src) : NULL;
121       gst_message_parse_error (message, &err, &debug);
122       g_print ("\nError from element %s: %s\n%s\n\n",
123           GST_STR_NULL (element_name), err->message, (debug) ? debug : "");
124       g_error_free (err);
125       g_free (debug);
126       g_free (element_name);
127 
128       fail_if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR);
129 
130       g_main_loop_quit (mainloop);
131     }
132       break;
133 
134     case GST_MESSAGE_EOS:
135     {
136       g_main_loop_quit (mainloop);
137     }
138       break;
139       break;
140 
141     default:
142     {
143     }
144       break;
145   }
146 
147   return TRUE;
148 }
149 
150 /*
151  * Creates a RTP pipeline for one test.
152  * @param frame_data Pointer to the frame data which is used to pass through pay/depayloaders.
153  * @param frame_data_size Frame data size in bytes.
154  * @param frame_count Frame count.
155  * @param filtercaps Caps filters.
156  * @param pay Payloader name.
157  * @param depay Depayloader name.
158  * @return
159  * Returns pointer to the RTP pipeline.
160  * The user must free the RTP pipeline when it's not used anymore.
161  */
162 static rtp_pipeline *
rtp_pipeline_create(const guint8 * frame_data,int frame_data_size,int frame_count,const char * filtercaps,const char * pay,const char * depay)163 rtp_pipeline_create (const guint8 * frame_data, int frame_data_size,
164     int frame_count, const char *filtercaps, const char *pay, const char *depay)
165 {
166   gchar *pipeline_name;
167   rtp_pipeline *p;
168   GstCaps *caps;
169 
170   /* Check parameters. */
171   if (!frame_data || !pay || !depay) {
172     return NULL;
173   }
174 
175   /* Allocate memory for the RTP pipeline. */
176   p = (rtp_pipeline *) malloc (sizeof (rtp_pipeline));
177 
178   p->frame_data = frame_data;
179   p->frame_data_size = frame_data_size;
180   p->frame_count = frame_count;
181   p->custom_event = NULL;
182 
183   /* Create elements. */
184   pipeline_name = g_strdup_printf ("%s-%s-pipeline", pay, depay);
185   p->pipeline = gst_pipeline_new (pipeline_name);
186   g_free (pipeline_name);
187   p->appsrc = gst_element_factory_make ("appsrc", NULL);
188   p->rtppay =
189       gst_parse_bin_from_description_full (pay, TRUE, NULL,
190       GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS, NULL);
191   p->rtpdepay =
192       gst_parse_bin_from_description_full (depay, TRUE, NULL,
193       GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS, NULL);
194   p->fakesink = gst_element_factory_make ("fakesink", NULL);
195 
196   /* One or more elements are not created successfully or failed to create p? */
197   if (!p->pipeline || !p->appsrc || !p->rtppay || !p->rtpdepay || !p->fakesink) {
198     /* Release created elements. */
199     RELEASE_ELEMENT (p->pipeline);
200     RELEASE_ELEMENT (p->appsrc);
201     RELEASE_ELEMENT (p->rtppay);
202     RELEASE_ELEMENT (p->rtpdepay);
203     RELEASE_ELEMENT (p->fakesink);
204 
205     /* Release allocated memory. */
206     free (p);
207 
208     return NULL;
209   }
210 
211   /* Set src properties. */
212   caps = gst_caps_from_string (filtercaps);
213   g_object_set (p->appsrc, "do-timestamp", TRUE, "caps", caps,
214       "format", GST_FORMAT_TIME, NULL);
215   gst_caps_unref (caps);
216 
217   /* Add elements to the pipeline. */
218   gst_bin_add (GST_BIN (p->pipeline), p->appsrc);
219   gst_bin_add (GST_BIN (p->pipeline), p->rtppay);
220   gst_bin_add (GST_BIN (p->pipeline), p->rtpdepay);
221   gst_bin_add (GST_BIN (p->pipeline), p->fakesink);
222 
223   /* Link elements. */
224   gst_element_link (p->appsrc, p->rtppay);
225   gst_element_link (p->rtppay, p->rtpdepay);
226   gst_element_link (p->rtpdepay, p->fakesink);
227 
228   return p;
229 }
230 
231 /*
232  * Destroys the RTP pipeline.
233  * @param p Pointer to the RTP pipeline.
234  */
235 static void
rtp_pipeline_destroy(rtp_pipeline * p)236 rtp_pipeline_destroy (rtp_pipeline * p)
237 {
238   /* Check parameters. */
239   if (p == NULL) {
240     return;
241   }
242 
243   /* Release pipeline. */
244   RELEASE_ELEMENT (p->pipeline);
245 
246   /* Release allocated memory. */
247   free (p);
248 }
249 
250 static GstPadProbeReturn
pay_event_probe_cb(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)251 pay_event_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
252 {
253   rtp_pipeline *p = (rtp_pipeline *) user_data;
254   GstEvent *event = GST_PAD_PROBE_INFO_DATA (info);
255 
256   if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM) {
257     const GstStructure *s0 = gst_event_get_structure (p->custom_event);
258     const GstStructure *s1 = gst_event_get_structure (event);
259     if (gst_structure_is_equal (s0, s1)) {
260       return GST_PAD_PROBE_DROP;
261     }
262   }
263 
264   return GST_PAD_PROBE_OK;
265 }
266 
267 static GstPadProbeReturn
depay_event_probe_cb(GstPad * pad,GstPadProbeInfo * info,gpointer user_data)268 depay_event_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
269 {
270   rtp_pipeline *p = (rtp_pipeline *) user_data;
271   GstEvent *event = GST_PAD_PROBE_INFO_DATA (info);
272 
273   if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM) {
274     const GstStructure *s0 = gst_event_get_structure (p->custom_event);
275     const GstStructure *s1 = gst_event_get_structure (event);
276     if (gst_structure_is_equal (s0, s1)) {
277       gst_event_unref (p->custom_event);
278       p->custom_event = NULL;
279     }
280   }
281 
282   return GST_PAD_PROBE_OK;
283 }
284 
285 /*
286  * Runs the RTP pipeline.
287  * @param p Pointer to the RTP pipeline.
288  */
289 static void
rtp_pipeline_run(rtp_pipeline * p)290 rtp_pipeline_run (rtp_pipeline * p)
291 {
292   GstFlowReturn flow_ret;
293   GMainLoop *mainloop = NULL;
294   GstBus *bus;
295   gint i, j;
296 
297   /* Check parameters. */
298   if (p == NULL) {
299     return;
300   }
301 
302   /* Create mainloop. */
303   mainloop = g_main_loop_new (NULL, FALSE);
304   if (!mainloop) {
305     return;
306   }
307 
308   /* Add bus callback. */
309   bus = gst_pipeline_get_bus (GST_PIPELINE (p->pipeline));
310 
311   gst_bus_add_watch (bus, rtp_bus_callback, (gpointer) mainloop);
312 
313   /* Set pipeline to PLAYING. */
314   gst_element_set_state (p->pipeline, GST_STATE_PLAYING);
315 
316   /* Push custom event into the pipeline */
317   if (p->custom_event) {
318     GstPad *srcpad;
319 
320     /* Install a probe to drop the event after it being serialized */
321     srcpad = gst_element_get_static_pad (p->rtppay, "src");
322     gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
323         pay_event_probe_cb, p, NULL);
324     gst_object_unref (srcpad);
325 
326     /* Install a probe to trace the deserialized event after depayloading */
327     srcpad = gst_element_get_static_pad (p->rtpdepay, "src");
328     gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
329         depay_event_probe_cb, p, NULL);
330     gst_object_unref (srcpad);
331     /* Send the event */
332     gst_element_send_event (p->appsrc, gst_event_ref (p->custom_event));
333   }
334 
335   /* Push data into the pipeline */
336   for (i = 0; i < LOOP_COUNT; i++) {
337     const guint8 *data = p->frame_data;
338 
339     for (j = 0; j < p->frame_count; j++) {
340       GstBuffer *buf;
341 
342       buf =
343           gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
344           (guint8 *) data, p->frame_data_size, 0, p->frame_data_size, NULL,
345           NULL);
346 
347       g_signal_emit_by_name (p->appsrc, "push-buffer", buf, &flow_ret);
348       fail_unless_equals_int (flow_ret, GST_FLOW_OK);
349       data += p->frame_data_size;
350 
351       gst_buffer_unref (buf);
352     }
353   }
354 
355   g_signal_emit_by_name (p->appsrc, "end-of-stream", &flow_ret);
356 
357   /* Run mainloop. */
358   g_main_loop_run (mainloop);
359 
360   /* Set pipeline to NULL. */
361   gst_element_set_state (p->pipeline, GST_STATE_NULL);
362 
363   /* Release mainloop. */
364   g_main_loop_unref (mainloop);
365 
366   gst_bus_remove_watch (bus);
367   gst_object_unref (bus);
368 
369   fail_if (p->custom_event);
370 }
371 
372 /*
373  * Enables buffer lists and adds a chain_list_function to the depayloader.
374  * @param p Pointer to the RTP pipeline.
375  */
376 static void
rtp_pipeline_enable_lists(rtp_pipeline * p)377 rtp_pipeline_enable_lists (rtp_pipeline * p)
378 {
379   GstPad *pad;
380 
381   /* Add chain list function for the buffer list tests */
382   pad = gst_element_get_static_pad (p->rtpdepay, "sink");
383   gst_pad_set_chain_list_function (pad,
384       GST_DEBUG_FUNCPTR (rtp_pipeline_chain_list));
385   /* .. to satisfy this silly test code in case someone dares push a buffer */
386   gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (rtp_pipeline_chain));
387   gst_object_unref (pad);
388 }
389 
390 /*
391  * Creates the RTP pipeline and runs the test using the pipeline.
392  * @param frame_data Pointer to the frame data which is used to pass through pay/depayloaders.
393  * @param frame_data_size Frame data size in bytes.
394  * @param frame_count Frame count.
395  * @param filtercaps Caps filters.
396  * @param pay Payloader name.
397  * @param depay Depayloader name.
398  * @bytes_sent bytes that will be sent, used when testing buffer lists
399  * @mtu_size set mtu size when testing lists
400  * @use_lists enable buffer lists
401  */
402 static void
rtp_pipeline_test(const guint8 * frame_data,int frame_data_size,int frame_count,const char * filtercaps,const char * pay,const char * depay,guint bytes_sent,guint mtu_size,gboolean use_lists)403 rtp_pipeline_test (const guint8 * frame_data, int frame_data_size,
404     int frame_count, const char *filtercaps, const char *pay, const char *depay,
405     guint bytes_sent, guint mtu_size, gboolean use_lists)
406 {
407   /* Create RTP pipeline. */
408   rtp_pipeline *p =
409       rtp_pipeline_create (frame_data, frame_data_size, frame_count, filtercaps,
410       pay, depay);
411 
412   if (p == NULL) {
413     return;
414   }
415 
416   /* set mtu size if needed */
417   if (mtu_size > 0) {
418     g_object_set (p->rtppay, "mtu", mtu_size, NULL);
419   }
420 
421   if (use_lists) {
422     rtp_pipeline_enable_lists (p);
423     chain_list_bytes_received = 0;
424   }
425 
426   /* Run RTP pipeline. */
427   rtp_pipeline_run (p);
428 
429   /* Destroy RTP pipeline. */
430   rtp_pipeline_destroy (p);
431 
432   if (use_lists) {
433     /* 'next NAL' indicator is 4 bytes */
434     fail_unless_equals_int (chain_list_bytes_received, bytes_sent * LOOP_COUNT);
435   }
436 }
437 
438 static const guint8 rtp_ilbc_frame_data[] =
439     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
441 };
442 
443 static int rtp_ilbc_frame_data_size = 20;
444 
445 static int rtp_ilbc_frame_count = 1;
446 
GST_START_TEST(rtp_ilbc)447 GST_START_TEST (rtp_ilbc)
448 {
449   rtp_pipeline_test (rtp_ilbc_frame_data, rtp_ilbc_frame_data_size,
450       rtp_ilbc_frame_count, "audio/x-iLBC,mode=20", "rtpilbcpay",
451       "rtpilbcdepay", 0, 0, FALSE);
452 }
453 
454 GST_END_TEST;
455 static const guint8 rtp_gsm_frame_data[] =
456     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
458 };
459 
460 static int rtp_gsm_frame_data_size = 20;
461 
462 static int rtp_gsm_frame_count = 1;
463 
GST_START_TEST(rtp_gsm)464 GST_START_TEST (rtp_gsm)
465 {
466   rtp_pipeline_test (rtp_gsm_frame_data, rtp_gsm_frame_data_size,
467       rtp_gsm_frame_count, "audio/x-gsm,rate=8000,channels=1", "rtpgsmpay",
468       "rtpgsmdepay", 0, 0, FALSE);
469 }
470 
471 GST_END_TEST;
472 static const guint8 rtp_amr_frame_data[] =
473     { 0x3c, 0x24, 0x03, 0xb3, 0x48, 0x10, 0x68, 0x46, 0x6c, 0xec, 0x03,
474   0x7a, 0x37, 0x16, 0x41, 0x41, 0xc0, 0x00, 0x0d, 0xcd, 0x12, 0xed,
475   0xad, 0x80, 0x00, 0x00, 0x11, 0x31, 0x00, 0x00, 0x0d, 0xa0
476 };
477 
478 static int rtp_amr_frame_data_size = 32;
479 
480 static int rtp_amr_frame_count = 1;
481 
GST_START_TEST(rtp_amr)482 GST_START_TEST (rtp_amr)
483 {
484   rtp_pipeline_test (rtp_amr_frame_data, rtp_amr_frame_data_size,
485       rtp_amr_frame_count, "audio/AMR,channels=1,rate=8000", "rtpamrpay",
486       "rtpamrdepay", 0, 0, FALSE);
487 }
488 
489 GST_END_TEST;
490 static const guint8 rtp_pcma_frame_data[] =
491     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
493 };
494 
495 static int rtp_pcma_frame_data_size = 20;
496 
497 static int rtp_pcma_frame_count = 1;
498 
GST_START_TEST(rtp_pcma)499 GST_START_TEST (rtp_pcma)
500 {
501   rtp_pipeline_test (rtp_pcma_frame_data, rtp_pcma_frame_data_size,
502       rtp_pcma_frame_count, "audio/x-alaw,channels=1,rate=8000", "rtppcmapay",
503       "rtppcmadepay", 0, 0, FALSE);
504 }
505 
506 GST_END_TEST;
507 static const guint8 rtp_pcmu_frame_data[] =
508     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
509   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
510 };
511 
512 static int rtp_pcmu_frame_data_size = 20;
513 
514 static int rtp_pcmu_frame_count = 1;
515 
GST_START_TEST(rtp_pcmu)516 GST_START_TEST (rtp_pcmu)
517 {
518   rtp_pipeline_test (rtp_pcmu_frame_data, rtp_pcmu_frame_data_size,
519       rtp_pcmu_frame_count, "audio/x-mulaw,channels=1,rate=8000", "rtppcmupay",
520       "rtppcmudepay", 0, 0, FALSE);
521 }
522 
523 GST_END_TEST;
524 static const guint8 rtp_mpa_frame_data[] =
525     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
527 };
528 
529 static int rtp_mpa_frame_data_size = 20;
530 
531 static int rtp_mpa_frame_count = 1;
532 
GST_START_TEST(rtp_mpa)533 GST_START_TEST (rtp_mpa)
534 {
535   rtp_pipeline_test (rtp_mpa_frame_data, rtp_mpa_frame_data_size,
536       rtp_mpa_frame_count, "audio/mpeg,mpegversion=1", "rtpmpapay",
537       "rtpmpadepay", 0, 0, FALSE);
538 }
539 
540 GST_END_TEST;
541 
542 static const guint8 rtp_h261_frame_data[] = {
543   0x00, 0x01, 0x00, 0x06, 0x00, 0x01, 0x11, 0x00, 0x00, 0x4c, 0x40, 0x00,
544   0x15, 0x10,
545 };
546 
547 static int rtp_h261_frame_data_size = 14;
548 static int rtp_h261_frame_count = 1;
549 
GST_START_TEST(rtp_h261)550 GST_START_TEST (rtp_h261)
551 {
552   rtp_pipeline_test (rtp_h261_frame_data, rtp_h261_frame_data_size,
553       rtp_h261_frame_count, "video/x-h261", "rtph261pay", "rtph261depay",
554       0, 0, FALSE);
555 }
556 
557 GST_END_TEST;
558 
559 static const guint8 rtp_h263_frame_data[] =
560     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
561   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
562 };
563 
564 static int rtp_h263_frame_data_size = 20;
565 
566 static int rtp_h263_frame_count = 1;
567 
GST_START_TEST(rtp_h263)568 GST_START_TEST (rtp_h263)
569 {
570   rtp_pipeline_test (rtp_h263_frame_data, rtp_h263_frame_data_size,
571       rtp_h263_frame_count,
572       "video/x-h263,variant=(string)itu,h263version=h263",
573       "rtph263pay", "rtph263depay", 0, 0, FALSE);
574   rtp_pipeline_test (rtp_h263_frame_data, rtp_h263_frame_data_size,
575       rtp_h263_frame_count,
576       "video/x-h263,variant=(string)itu,h263version=h263,width=10,height=20",
577       "rtph263pay", "rtph263depay", 0, 0, FALSE);
578 }
579 
580 GST_END_TEST;
581 static const guint8 rtp_h263p_frame_data[] =
582     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
584 };
585 
586 static int rtp_h263p_frame_data_size = 20;
587 
588 static int rtp_h263p_frame_count = 1;
589 
GST_START_TEST(rtp_h263p)590 GST_START_TEST (rtp_h263p)
591 {
592   rtp_pipeline_test (rtp_h263p_frame_data, rtp_h263p_frame_data_size,
593       rtp_h263p_frame_count, "video/x-h263,variant=(string)itu,"
594       "h263version=(string)h263", "rtph263ppay", "rtph263pdepay", 0, 0, FALSE);
595 
596   /* payloader should accept any input that matches the template caps
597    * if there's just a udpsink or fakesink downstream */
598   rtp_pipeline_test (rtp_h263p_frame_data, rtp_h263p_frame_data_size,
599       rtp_h263p_frame_count, "video/x-h263,variant=(string)itu,"
600       "h263version=(string)h263", "rtph263ppay", "identity", 0, 0, FALSE);
601 
602   /* default output of avenc_h263p */
603   rtp_pipeline_test (rtp_h263p_frame_data, rtp_h263p_frame_data_size,
604       rtp_h263p_frame_count, "video/x-h263,variant=(string)itu,"
605       "h263version=(string)h263p, annex-f=(boolean)true, "
606       "annex-j=(boolean)true, annex-i=(boolean)true, annex-t=(boolean)true",
607       "rtph263ppay", "identity", 0, 0, FALSE);
608 
609   /* pay ! depay should also work with any input */
610   rtp_pipeline_test (rtp_h263p_frame_data, rtp_h263p_frame_data_size,
611       rtp_h263p_frame_count, "video/x-h263,variant=(string)itu,"
612       "h263version=(string)h263p, annex-f=(boolean)true, "
613       "annex-j=(boolean)true, annex-i=(boolean)true, annex-t=(boolean)true",
614       "rtph263ppay", "rtph263pdepay", 0, 0, FALSE);
615 }
616 
617 GST_END_TEST;
618 static const guint8 rtp_h264_frame_data[] =
619     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
621 };
622 
623 static int rtp_h264_frame_data_size = 20;
624 
625 static int rtp_h264_frame_count = 1;
626 
GST_START_TEST(rtp_h264)627 GST_START_TEST (rtp_h264)
628 {
629   /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
630   rtp_pipeline_test (rtp_h264_frame_data, rtp_h264_frame_data_size,
631       rtp_h264_frame_count,
632       "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal",
633       "rtph264pay", "rtph264depay", 0, 0, FALSE);
634 
635   /* config-interval property used to be of uint type, was changed to int,
636    * make sure old GValue stuff still works */
637   {
638     GValue val = G_VALUE_INIT;
639     GstElement *rtph264pay;
640     GParamSpec *pspec;
641 
642 
643     rtph264pay = gst_element_factory_make ("rtph264pay", NULL);
644     pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (rtph264pay),
645         "config-interval");
646     fail_unless (pspec->value_type == G_TYPE_INT);
647     g_value_init (&val, G_TYPE_UINT);
648     g_value_set_uint (&val, 10);
649     g_object_set_property (G_OBJECT (rtph264pay), "config-interval", &val);
650     g_value_set_uint (&val, 0);
651     g_object_get_property (G_OBJECT (rtph264pay), "config-interval", &val);
652     fail_unless_equals_int (10, g_value_get_uint (&val));
653     g_object_set (G_OBJECT (rtph264pay), "config-interval", -1, NULL);
654     g_object_get_property (G_OBJECT (rtph264pay), "config-interval", &val);
655     fail_unless (g_value_get_uint (&val) == G_MAXUINT);
656     g_value_unset (&val);
657     gst_object_unref (rtph264pay);
658   }
659 }
660 
661 GST_END_TEST;
662 
663 /* H264 data generated with:
664  * videotestsrc pattern=black ! video/x-raw,width=16,height=16 ! openh264enc */
665 static const guint8 h264_16x16_black_bs[] = {
666   0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xd0, 0x0b,
667   0x8c, 0x8d, 0x4e, 0x40, 0x3c, 0x22, 0x11, 0xa8,
668   0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x3c, 0x80,
669   0x00, 0x00, 0x00, 0x01, 0x65, 0xb8, 0x00, 0x04,
670   0x00, 0x00, 0x09, 0xe4, 0xc5, 0x00, 0x01, 0x19,
671   0xfc
672 };
673 
674 static GstSample *
rtp_h264depay_run(const gchar * stream_format)675 rtp_h264depay_run (const gchar * stream_format)
676 {
677   GstHarness *h;
678   GstSample *sample;
679   GstBuffer *buf;
680   GstEvent *e;
681   GstCaps *out_caps;
682   GstCaps *in_caps;
683   gboolean seen_caps = FALSE;
684   gsize size;
685 
686   h = gst_harness_new_parse ("rtph264pay ! rtph264depay");
687 
688   /* Our input data is in byte-stream format (not that it matters) */
689   in_caps = gst_caps_new_simple ("video/x-h264",
690       "stream-format", G_TYPE_STRING, "byte-stream",
691       "alignment", G_TYPE_STRING, "au",
692       "profile", G_TYPE_STRING, "baseline",
693       "width", G_TYPE_INT, 16,
694       "height", G_TYPE_INT, 16, "framerate", GST_TYPE_FRACTION, 30, 1, NULL);
695 
696   /* Force rtph264depay to output format as requested */
697   out_caps = gst_caps_new_simple ("video/x-h264",
698       "stream-format", G_TYPE_STRING, stream_format,
699       "alignment", G_TYPE_STRING, "au", NULL);
700 
701   gst_harness_set_caps (h, in_caps, out_caps);
702   in_caps = NULL;
703   out_caps = NULL;
704 
705   gst_harness_play (h);
706 
707   size = sizeof (h264_16x16_black_bs);
708   buf = gst_buffer_new_memdup (h264_16x16_black_bs, size);
709   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
710   fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
711 
712   while ((e = gst_harness_try_pull_event (h))) {
713     if (GST_EVENT_TYPE (e) == GST_EVENT_CAPS) {
714       GstCaps *caps = NULL;
715 
716       gst_event_parse_caps (e, &caps);
717       gst_caps_replace (&out_caps, caps);
718       seen_caps = TRUE;
719     }
720     gst_event_unref (e);
721   }
722   fail_unless (seen_caps);
723 
724   buf = gst_harness_pull (h);
725   sample = gst_sample_new (buf, out_caps, NULL, NULL);
726   gst_buffer_unref (buf);
727   gst_caps_replace (&out_caps, NULL);
728 
729   gst_harness_teardown (h);
730   return sample;
731 }
732 
GST_START_TEST(rtp_h264depay_avc)733 GST_START_TEST (rtp_h264depay_avc)
734 {
735   const GValue *val;
736   GstStructure *st;
737   GstMapInfo map = GST_MAP_INFO_INIT;
738   GstBuffer *buf;
739   GstSample *s;
740   GstCaps *caps;
741 
742   s = rtp_h264depay_run ("avc");
743 
744   /* must have codec_data in output caps */
745   caps = gst_sample_get_caps (s);
746   st = gst_caps_get_structure (caps, 0);
747   GST_LOG ("caps: %" GST_PTR_FORMAT, caps);
748   fail_unless (gst_structure_has_field (st, "stream-format"));
749   fail_unless (gst_structure_has_field (st, "alignment"));
750   fail_unless (gst_structure_has_field (st, "level"));
751   fail_unless (gst_structure_has_field (st, "profile"));
752   val = gst_structure_get_value (st, "codec_data");
753   fail_unless (val != NULL);
754   fail_unless (GST_VALUE_HOLDS_BUFFER (val));
755   /* check codec_data, shouldn't contain trailing zeros */
756   buf = gst_value_get_buffer (val);
757   fail_unless (gst_buffer_map (buf, &map, GST_MAP_READ));
758   {
759     guint num_sps, num_pps, len;
760     guint8 *data;
761 
762     GST_MEMDUMP ("H.264 codec_data", map.data, map.size);
763     fail_unless_equals_int (map.data[0], 1);
764     num_sps = map.data[5] & 0x1f;
765     data = map.data + 6;
766     fail_unless_equals_int (num_sps, 1);
767     len = GST_READ_UINT16_BE (data);
768     data += 2;
769     /* make sure there are no trailing zeros in the SPS */
770     fail_unless (data[len - 1] != 0);
771     data += len;
772     num_pps = *data++;
773     fail_unless_equals_int (num_pps, 1);
774     len = GST_READ_UINT16_BE (data);
775     data += 2;
776     /* make sure there are no trailing zeros in the PPS */
777     fail_unless (data[len - 1] != 0);
778   }
779   gst_buffer_unmap (buf, &map);
780 
781   buf = gst_sample_get_buffer (s);
782   fail_unless (gst_buffer_map (buf, &map, GST_MAP_READ));
783   GST_MEMDUMP ("H.264 AVC frame", map.data, map.size);
784   fail_unless (map.size >= 4 + 13);
785   /* Want IDR slice as very first thing.
786    * We assume nal size markers are 4 bytes here. */
787   fail_unless_equals_int (map.data[4] & 0x1f, 5);
788   gst_buffer_unmap (buf, &map);
789 
790   gst_sample_unref (s);
791 }
792 
793 GST_END_TEST;
794 
GST_START_TEST(rtp_h264depay_bytestream)795 GST_START_TEST (rtp_h264depay_bytestream)
796 {
797   GstByteReader br;
798   GstStructure *st;
799   GstMapInfo map = GST_MAP_INFO_INIT;
800   GstBuffer *buf;
801   GstSample *s;
802   GstCaps *caps;
803   guint32 dw = 0;
804   guint8 b = 0;
805   guint off, left;
806 
807   s = rtp_h264depay_run ("byte-stream");
808 
809   /* must not have codec_data in output caps */
810   caps = gst_sample_get_caps (s);
811   st = gst_caps_get_structure (caps, 0);
812   GST_LOG ("caps: %" GST_PTR_FORMAT, caps);
813   fail_if (gst_structure_has_field (st, "codec_data"));
814 
815   buf = gst_sample_get_buffer (s);
816   fail_unless (gst_buffer_map (buf, &map, GST_MAP_READ));
817   GST_MEMDUMP ("H.264 byte-stream frame", map.data, map.size);
818   fail_unless (map.size > 40);
819   gst_byte_reader_init (&br, map.data, map.size);
820   /* We assume nal sync markers are 4 bytes... */
821   fail_unless (gst_byte_reader_get_uint32_be (&br, &dw));
822   fail_unless_equals_int (dw, 0x00000001);
823   /* Want SPS as very first thing */
824   fail_unless (gst_byte_reader_get_uint8 (&br, &b));
825   fail_unless_equals_int (b & 0x1f, 7);
826   /* Then, we want the PPS */
827   left = gst_byte_reader_get_remaining (&br);
828   off = gst_byte_reader_masked_scan_uint32 (&br, 0xffffffff, 1, 0, left);
829   fail_if (off == (guint) - 1);
830   gst_byte_reader_skip (&br, off + 4);
831   fail_unless (gst_byte_reader_get_uint8 (&br, &b));
832   fail_unless_equals_int (b & 0x1f, 8);
833   /* FIXME: looks like we get two sets of SPS/PPS ?! */
834   left = gst_byte_reader_get_remaining (&br);
835   off = gst_byte_reader_masked_scan_uint32 (&br, 0xffffffff, 1, 0, left);
836   fail_if (off == (guint) - 1);
837   gst_byte_reader_skip (&br, off + 4);
838   left = gst_byte_reader_get_remaining (&br);
839   off = gst_byte_reader_masked_scan_uint32 (&br, 0xffffffff, 1, 0, left);
840   fail_if (off == (guint) - 1);
841   gst_byte_reader_skip (&br, off + 4);
842   /* Finally, we want an IDR slice */
843   left = gst_byte_reader_get_remaining (&br);
844   off = gst_byte_reader_masked_scan_uint32 (&br, 0xffffffff, 1, 0, left);
845   fail_if (off == (guint) - 1);
846   gst_byte_reader_skip (&br, off + 4);
847   fail_unless (gst_byte_reader_get_uint8 (&br, &b));
848   fail_unless_equals_int (b & 0x1f, 5);
849   gst_buffer_unmap (buf, &map);
850 
851   gst_sample_unref (s);
852 }
853 
854 GST_END_TEST;
855 
856 static const guint8 rtp_h264_list_lt_mtu_frame_data[] =
857     /* not packetized, next NAL starts with 0001 */
858 { 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
859   0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
860   0xad, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x10
861 };
862 
863 static int rtp_h264_list_lt_mtu_frame_data_size = 16;
864 
865 static int rtp_h264_list_lt_mtu_frame_count = 2;
866 
867 /* NAL = 4 bytes */
868 /* also 2 bytes FU-A header each time */
869 static int rtp_h264_list_lt_mtu_bytes_sent = (16 - 4);
870 
871 static int rtp_h264_list_lt_mtu_mtu_size = 1024;
872 
GST_START_TEST(rtp_h264_list_lt_mtu)873 GST_START_TEST (rtp_h264_list_lt_mtu)
874 {
875   /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
876   rtp_pipeline_test (rtp_h264_list_lt_mtu_frame_data,
877       rtp_h264_list_lt_mtu_frame_data_size, rtp_h264_list_lt_mtu_frame_count,
878       "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal",
879       "rtph264pay aggregate-mode=zero-latency", "rtph264depay",
880       rtp_h264_list_lt_mtu_bytes_sent, rtp_h264_list_lt_mtu_mtu_size, TRUE);
881 }
882 
883 GST_END_TEST;
884 static const guint8 rtp_h264_list_lt_mtu_frame_data_avc[] =
885     /* packetized data */
886 { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
887   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
888   0xad, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0d, 0x00
889 };
890 
891 /* Only the last NAL of each packet is computed by the strange algorithm in
892  * rtp_pipeline_chain_list()
893  */
894 static int rtp_h264_list_lt_mtu_bytes_sent_avc = 7 + 3;
895 
896 //static int rtp_h264_list_lt_mtu_mtu_size = 1024;
897 
GST_START_TEST(rtp_h264_list_lt_mtu_avc)898 GST_START_TEST (rtp_h264_list_lt_mtu_avc)
899 {
900   /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
901   rtp_pipeline_test (rtp_h264_list_lt_mtu_frame_data_avc,
902       rtp_h264_list_lt_mtu_frame_data_size, rtp_h264_list_lt_mtu_frame_count,
903       "video/x-h264,stream-format=(string)avc,alignment=(string)au,"
904       "codec_data=(buffer)01640014ffe1001867640014acd94141fb0110000003001773594000f142996001000568ebecb22c",
905       "rtph264pay aggregate-mode=zero-latency", "rtph264depay",
906       rtp_h264_list_lt_mtu_bytes_sent_avc, rtp_h264_list_lt_mtu_mtu_size, TRUE);
907 }
908 
909 GST_END_TEST;
910 static const guint8 rtp_h264_list_gt_mtu_frame_data[] =
911     /* not packetized, next NAL starts with 0001 */
912 { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
913   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
914   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
915   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
916   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
917   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
918 };
919 
920 static int rtp_h264_list_gt_mtu_frame_data_size = 64;
921 
922 static int rtp_h264_list_gt_mtu_frame_count = 1;
923 
924 /* NAL = 4 bytes. When data does not fit into 1 mtu, 1 byte will be skipped */
925 static int rtp_h264_list_gt_mtu_bytes_sent = 1 * (64 - 4) - 1;
926 
927 static int rtp_h264_list_gt_mtu_mty_size = 28;
928 
GST_START_TEST(rtp_h264_list_gt_mtu)929 GST_START_TEST (rtp_h264_list_gt_mtu)
930 {
931   /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
932   rtp_pipeline_test (rtp_h264_list_gt_mtu_frame_data,
933       rtp_h264_list_gt_mtu_frame_data_size, rtp_h264_list_gt_mtu_frame_count,
934       "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal",
935       "rtph264pay", "rtph264depay",
936       rtp_h264_list_gt_mtu_bytes_sent, rtp_h264_list_gt_mtu_mty_size, TRUE);
937 }
938 
939 GST_END_TEST;
940 static const guint8 rtp_h264_list_gt_mtu_frame_data_avc[] =
941     /* packetized data */
942 { 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
943   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
944   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
945   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
946   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
947   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
948 };
949 
950 /* NAL = 4 bytes. When data does not fit into 1 mtu, 1 byte will be skipped */
951 static int rtp_h264_list_gt_mtu_bytes_sent_avc = 1 * (64 - 2 * 4 - 2 * 1);
952 
GST_START_TEST(rtp_h264_list_gt_mtu_avc)953 GST_START_TEST (rtp_h264_list_gt_mtu_avc)
954 {
955   /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
956   rtp_pipeline_test (rtp_h264_list_gt_mtu_frame_data_avc,
957       rtp_h264_list_gt_mtu_frame_data_size, rtp_h264_list_gt_mtu_frame_count,
958       "video/x-h264,stream-format=(string)avc,alignment=(string)au,"
959       "codec_data=(buffer)01640014ffe1001867640014acd94141fb0110000003001773594000f142996001000568ebecb22c",
960       "rtph264pay", "rtph264depay",
961       rtp_h264_list_gt_mtu_bytes_sent_avc, rtp_h264_list_gt_mtu_mty_size, TRUE);
962 }
963 
964 GST_END_TEST;
965 
966 static const guint8 rtp_h265_frame_data[] = {
967   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
968   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
969 };
970 
971 static int rtp_h265_frame_data_size = 20;
972 
973 static int rtp_h265_frame_count = 1;
974 
GST_START_TEST(rtp_h265)975 GST_START_TEST (rtp_h265)
976 {
977   rtp_pipeline_test (rtp_h265_frame_data, rtp_h265_frame_data_size,
978       rtp_h265_frame_count,
979       "video/x-h265,stream-format=(string)byte-stream,alignment=(string)nal",
980       "rtph265pay", "rtph265depay", 0, 0, FALSE);
981 
982   /* config-interval property used to be of uint type, was changed to int,
983    * make sure old GValue stuff still works */
984   {
985     GValue val = G_VALUE_INIT;
986     GstElement *rtph265pay;
987     GParamSpec *pspec;
988 
989 
990     rtph265pay = gst_element_factory_make ("rtph265pay", NULL);
991     pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (rtph265pay),
992         "config-interval");
993     fail_unless (pspec->value_type == G_TYPE_INT);
994     g_value_init (&val, G_TYPE_UINT);
995     g_value_set_uint (&val, 10);
996     g_object_set_property (G_OBJECT (rtph265pay), "config-interval", &val);
997     g_value_set_uint (&val, 0);
998     g_object_get_property (G_OBJECT (rtph265pay), "config-interval", &val);
999     fail_unless_equals_int (10, g_value_get_uint (&val));
1000     g_object_set (G_OBJECT (rtph265pay), "config-interval", -1, NULL);
1001     g_object_get_property (G_OBJECT (rtph265pay), "config-interval", &val);
1002     fail_unless (g_value_get_uint (&val) == G_MAXUINT);
1003     g_value_unset (&val);
1004     gst_object_unref (rtph265pay);
1005   }
1006 }
1007 
1008 GST_END_TEST;
1009 static const guint8 rtp_h265_list_lt_mtu_frame_data[] = {
1010   /* not packetized, next NALU starts with 0x00000001 */
1011   0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1012   0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
1013   0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1014   0x00, 0x00, 0x00, 0x00, 0x00, 0x10
1015 };
1016 
1017 static int rtp_h265_list_lt_mtu_frame_data_size = 16;
1018 
1019 static int rtp_h265_list_lt_mtu_frame_count = 2;
1020 
1021 /* 3 bytes start code prefixed with one zero byte, NALU header is in payload */
1022 static int rtp_h265_list_lt_mtu_bytes_sent = 2 * (16 - 3 - 1);
1023 
1024 static int rtp_h265_list_lt_mtu_mtu_size = 1024;
1025 
GST_START_TEST(rtp_h265_list_lt_mtu)1026 GST_START_TEST (rtp_h265_list_lt_mtu)
1027 {
1028   rtp_pipeline_test (rtp_h265_list_lt_mtu_frame_data,
1029       rtp_h265_list_lt_mtu_frame_data_size, rtp_h265_list_lt_mtu_frame_count,
1030       "video/x-h265,stream-format=(string)byte-stream,alignment=(string)nal",
1031       "rtph265pay", "rtph265depay", rtp_h265_list_lt_mtu_bytes_sent,
1032       rtp_h265_list_lt_mtu_mtu_size, TRUE);
1033 }
1034 
1035 GST_END_TEST;
1036 static const guint8 rtp_h265_list_lt_mtu_frame_data_hvc1[] = {
1037   /* packetized data */
1038   0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1039   0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1040   0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1041   0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
1042 };
1043 
1044 /* length size is 3 bytes */
1045 static int rtp_h265_list_lt_mtu_bytes_sent_hvc1 = 4 + 9;
1046 
1047 
GST_START_TEST(rtp_h265_list_lt_mtu_hvc1)1048 GST_START_TEST (rtp_h265_list_lt_mtu_hvc1)
1049 {
1050   rtp_pipeline_test (rtp_h265_list_lt_mtu_frame_data_hvc1,
1051       rtp_h265_list_lt_mtu_frame_data_size, rtp_h265_list_lt_mtu_frame_count,
1052       "video/x-h265,stream-format=(string)hvc1,alignment=(string)au,"
1053       "codec_data=(buffer)0101c000000080000000000099f000fcfdf8f800000203a000010"
1054       "01840010c01ffff01c000000300800000030000030099ac0900a10001003042010101c00"
1055       "0000300800000030000030099a00a080f1fe36bbb5377725d602dc040404100000300010"
1056       "00003000a0800a2000100074401c172b02240",
1057       "rtph265pay aggregate-mode=zero-latency", "rtph265depay",
1058       rtp_h265_list_lt_mtu_bytes_sent_hvc1, rtp_h265_list_lt_mtu_mtu_size,
1059       TRUE);
1060 }
1061 
1062 GST_END_TEST;
1063 static const guint8 rtp_h265_list_gt_mtu_frame_data[] = {
1064   /* not packetized, next NAL starts with 0x000001 */
1065   0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1066   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1067   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1068   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1069   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1070   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1071   0x00, 0x10
1072 };
1073 
1074 static const int rtp_h265_list_gt_mtu_frame_data_size = 62;
1075 
1076 static const int rtp_h265_list_gt_mtu_frame_count = 1;
1077 
1078 /* start code is 3 bytes, NALU header is 2 bytes */
1079 static int rtp_h265_list_gt_mtu_bytes_sent = 1 * (62 - 3 - 2);
1080 
1081 static int rtp_h265_list_gt_mtu_mtu_size = 28;
1082 
GST_START_TEST(rtp_h265_list_gt_mtu)1083 GST_START_TEST (rtp_h265_list_gt_mtu)
1084 {
1085   rtp_pipeline_test (rtp_h265_list_gt_mtu_frame_data,
1086       rtp_h265_list_gt_mtu_frame_data_size, rtp_h265_list_gt_mtu_frame_count,
1087       "video/x-h265,stream-format=(string)byte-stream,alignment=(string)nal",
1088       "rtph265pay", "rtph265depay", rtp_h265_list_gt_mtu_bytes_sent,
1089       rtp_h265_list_gt_mtu_mtu_size, TRUE);
1090 }
1091 
1092 GST_END_TEST;
1093 static const guint8 rtp_h265_list_gt_mtu_frame_data_hvc1[] = {
1094   /* packetized data */
1095   0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1097   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1098   0x00, 0x00, 0x00, 0x00, 0x00,
1099   0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1101   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1102 };
1103 
1104 /* length size is 3 bytes, NALU header is 2 bytes */
1105 static int rtp_h265_list_gt_mtu_bytes_sent_hvc1 = 1 * (62 - 2 * 3 - 2 * 2);
1106 
GST_START_TEST(rtp_h265_list_gt_mtu_hvc1)1107 GST_START_TEST (rtp_h265_list_gt_mtu_hvc1)
1108 {
1109   rtp_pipeline_test (rtp_h265_list_gt_mtu_frame_data_hvc1,
1110       rtp_h265_list_gt_mtu_frame_data_size, rtp_h265_list_gt_mtu_frame_count,
1111       "video/x-h265,stream-format=(string)hvc1,alignment=(string)au,"
1112       "codec_data=(buffer)0101c000000080000000000099f000fcfdf8f800000203a000010"
1113       "01840010c01ffff01c000000300800000030000030099ac0900a10001003042010101c00"
1114       "0000300800000030000030099a00a080f1fe36bbb5377725d602dc040404100000300010"
1115       "00003000a0800a2000100074401c172b02240",
1116       "rtph265pay", "rtph265depay", rtp_h265_list_gt_mtu_bytes_sent_hvc1,
1117       rtp_h265_list_gt_mtu_mtu_size, TRUE);
1118 }
1119 
1120 GST_END_TEST;
1121 
1122 /* KLV data from Day_Flight.mpg */
1123 static const guint8 rtp_KLV_frame_data[] = {
1124   0x06, 0x0e, 0x2b, 0x34, 0x02, 0x0b, 0x01, 0x01,
1125   0x0e, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00,
1126   0x81, 0x91, 0x02, 0x08, 0x00, 0x04, 0x6c, 0x8e,
1127   0x20, 0x03, 0x83, 0x85, 0x41, 0x01, 0x01, 0x05,
1128   0x02, 0x3d, 0x3b, 0x06, 0x02, 0x15, 0x80, 0x07,
1129   0x02, 0x01, 0x52, 0x0b, 0x03, 0x45, 0x4f, 0x4e,
1130   0x0c, 0x0e, 0x47, 0x65, 0x6f, 0x64, 0x65, 0x74,
1131   0x69, 0x63, 0x20, 0x57, 0x47, 0x53, 0x38, 0x34,
1132   0x0d, 0x04, 0x4d, 0xc4, 0xdc, 0xbb, 0x0e, 0x04,
1133   0xb1, 0xa8, 0x6c, 0xfe, 0x0f, 0x02, 0x1f, 0x4a,
1134   0x10, 0x02, 0x00, 0x85, 0x11, 0x02, 0x00, 0x4b,
1135   0x12, 0x04, 0x20, 0xc8, 0xd2, 0x7d, 0x13, 0x04,
1136   0xfc, 0xdd, 0x02, 0xd8, 0x14, 0x04, 0xfe, 0xb8,
1137   0xcb, 0x61, 0x15, 0x04, 0x00, 0x8f, 0x3e, 0x61,
1138   0x16, 0x04, 0x00, 0x00, 0x01, 0xc9, 0x17, 0x04,
1139   0x4d, 0xdd, 0x8c, 0x2a, 0x18, 0x04, 0xb1, 0xbe,
1140   0x9e, 0xf4, 0x19, 0x02, 0x0b, 0x85, 0x28, 0x04,
1141   0x4d, 0xdd, 0x8c, 0x2a, 0x29, 0x04, 0xb1, 0xbe,
1142   0x9e, 0xf4, 0x2a, 0x02, 0x0b, 0x85, 0x38, 0x01,
1143   0x2e, 0x39, 0x04, 0x00, 0x8d, 0xd4, 0x29, 0x01,
1144   0x02, 0x1c, 0x5f
1145 };
1146 
GST_START_TEST(rtp_klv)1147 GST_START_TEST (rtp_klv)
1148 {
1149   rtp_pipeline_test (rtp_KLV_frame_data, G_N_ELEMENTS (rtp_KLV_frame_data), 1,
1150       "meta/x-klv, parsed=(bool)true", "rtpklvpay", "rtpklvdepay", 0, 0, FALSE);
1151 }
1152 
1153 GST_END_TEST;
1154 
GST_START_TEST(rtp_klv_fragmented)1155 GST_START_TEST (rtp_klv_fragmented)
1156 {
1157   /* force super-small mtu of 60 to fragment KLV unit */
1158   rtp_pipeline_test (rtp_KLV_frame_data, sizeof (rtp_KLV_frame_data), 1,
1159       "meta/x-klv, parsed=(bool)true", "rtpklvpay", "rtpklvdepay",
1160       sizeof (rtp_KLV_frame_data), 60, FALSE);
1161 }
1162 
1163 GST_END_TEST;
1164 
1165 static const guint8 rtp_L16_frame_data[] =
1166     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1167   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1168 };
1169 
1170 static int rtp_L16_frame_data_size = 20;
1171 
1172 static int rtp_L16_frame_count = 1;
1173 
GST_START_TEST(rtp_L16)1174 GST_START_TEST (rtp_L16)
1175 {
1176   rtp_pipeline_test (rtp_L16_frame_data, rtp_L16_frame_data_size,
1177       rtp_L16_frame_count,
1178       "audio/x-raw,format=S16BE,rate=1,channels=1,layout=(string)interleaved",
1179       "rtpL16pay", "rtpL16depay", 0, 0, FALSE);
1180 }
1181 
1182 GST_END_TEST;
1183 
1184 static const guint8 rtp_L24_frame_data[] =
1185     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1186   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1187 };
1188 
1189 static int rtp_L24_frame_data_size = 24;
1190 
1191 static int rtp_L24_frame_count = 1;
1192 
GST_START_TEST(rtp_L24)1193 GST_START_TEST (rtp_L24)
1194 {
1195   rtp_pipeline_test (rtp_L24_frame_data, rtp_L24_frame_data_size,
1196       rtp_L24_frame_count,
1197       "audio/x-raw,format=S24BE,rate=1,channels=1,layout=(string)interleaved",
1198       "rtpL24pay", "rtpL24depay", 0, 0, FALSE);
1199 }
1200 
1201 GST_END_TEST;
1202 static const guint8 rtp_mp2t_frame_data[] =
1203     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1204   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1205 };
1206 
1207 static int rtp_mp2t_frame_data_size = 20;
1208 
1209 static int rtp_mp2t_frame_count = 1;
1210 
GST_START_TEST(rtp_mp2t)1211 GST_START_TEST (rtp_mp2t)
1212 {
1213   rtp_pipeline_test (rtp_mp2t_frame_data, rtp_mp2t_frame_data_size,
1214       rtp_mp2t_frame_count, "video/mpegts,packetsize=188,systemstream=true",
1215       "rtpmp2tpay", "rtpmp2tdepay", 0, 0, FALSE);
1216 }
1217 
1218 GST_END_TEST;
1219 static const guint8 rtp_mp4v_frame_data[] =
1220     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1221   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1222 };
1223 
1224 static int rtp_mp4v_frame_data_size = 20;
1225 
1226 static int rtp_mp4v_frame_count = 1;
1227 
GST_START_TEST(rtp_mp4v)1228 GST_START_TEST (rtp_mp4v)
1229 {
1230   rtp_pipeline_test (rtp_mp4v_frame_data, rtp_mp4v_frame_data_size,
1231       rtp_mp4v_frame_count, "video/mpeg,mpegversion=4,systemstream=false",
1232       "rtpmp4vpay", "rtpmp4vdepay", 0, 0, FALSE);
1233 }
1234 
1235 GST_END_TEST;
1236 static const guint8 rtp_mp4v_list_frame_data[] =
1237     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1238   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1239 };
1240 
1241 static int rtp_mp4v_list_frame_data_size = 20;
1242 
1243 static int rtp_mp4v_list_frame_count = 1;
1244 
1245 static int rtp_mp4v_list_bytes_sent = 1 * 20;
1246 
GST_START_TEST(rtp_mp4v_list)1247 GST_START_TEST (rtp_mp4v_list)
1248 {
1249   rtp_pipeline_test (rtp_mp4v_list_frame_data, rtp_mp4v_list_frame_data_size,
1250       rtp_mp4v_list_frame_count,
1251       "video/mpeg,mpegversion=4,systemstream=false,codec_data=(buffer)000001b001",
1252       "rtpmp4vpay", "rtpmp4vdepay", rtp_mp4v_list_bytes_sent, 0, TRUE);
1253 }
1254 
1255 GST_END_TEST;
1256 static const guint8 rtp_mp4g_frame_data[] =
1257     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1258   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1259 };
1260 
1261 static int rtp_mp4g_frame_data_size = 20;
1262 
1263 static int rtp_mp4g_frame_count = 1;
1264 
GST_START_TEST(rtp_mp4g)1265 GST_START_TEST (rtp_mp4g)
1266 {
1267   rtp_pipeline_test (rtp_mp4g_frame_data, rtp_mp4g_frame_data_size,
1268       rtp_mp4g_frame_count,
1269       "video/mpeg,mpegversion=4,systemstream=false,codec_data=(buffer)000001b001",
1270       "rtpmp4gpay", "rtpmp4gdepay", 0, 0, FALSE);
1271 }
1272 
1273 GST_END_TEST;
1274 static const guint8 rtp_theora_frame_data[] =
1275     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1276   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1277 };
1278 
1279 static int rtp_theora_frame_data_size = 20;
1280 
1281 static int rtp_theora_frame_count = 1;
1282 
GST_START_TEST(rtp_theora)1283 GST_START_TEST (rtp_theora)
1284 {
1285   rtp_pipeline_test (rtp_theora_frame_data, rtp_theora_frame_data_size,
1286       rtp_theora_frame_count, "video/x-theora", "rtptheorapay",
1287       "rtptheoradepay", 0, 0, FALSE);
1288 }
1289 
1290 GST_END_TEST;
1291 static const guint8 rtp_vorbis_frame_data[] =
1292     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1293   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1294 };
1295 
1296 static int rtp_vorbis_frame_data_size = 20;
1297 
1298 static int rtp_vorbis_frame_count = 1;
1299 
GST_START_TEST(rtp_vorbis)1300 GST_START_TEST (rtp_vorbis)
1301 {
1302   rtp_pipeline_test (rtp_vorbis_frame_data, rtp_vorbis_frame_data_size,
1303       rtp_vorbis_frame_count, "audio/x-vorbis", "rtpvorbispay",
1304       "rtpvorbisdepay", 0, 0, FALSE);
1305 }
1306 
1307 GST_END_TEST;
1308 
1309 /* videotestsrc pattern=red  ! video/x-raw,width=160,height=120 ! vp8enc */
1310 #define VP8_CAPS "video/x-vp8, profile=(string)0, " \
1311     "streamheader=(buffer)4f5650383001010000a000780000010000010000001e00000001, " \
1312     "width=(int)160, height=(int)120, framerate=(fraction)30/1"
1313 
1314 static const guint8 rtp_vp8_frame_data[] = {
1315   0x30, 0x07, 0x00, 0x9d, 0x01, 0x2a, 0xa0, 0x00,
1316   0x78, 0x00, 0x00, 0x47, 0x08, 0x85, 0x85, 0x88,
1317   0x85, 0x84, 0x88, 0x02, 0x02, 0x02, 0x75, 0xaa,
1318   0x03, 0xf8, 0x03, 0xfa, 0x02, 0x06, 0xc3, 0xef,
1319   0x05, 0x10, 0x9c, 0x52, 0xd2, 0xa1, 0x38, 0xa5,
1320   0xa5, 0x42, 0x71, 0x4b, 0x4a, 0x84, 0xe2, 0x96,
1321   0x95, 0x09, 0xc5, 0x2d, 0x2a, 0x13, 0x8a, 0x5a,
1322   0x54, 0x27, 0x14, 0xb4, 0xa8, 0x4e, 0x29, 0x69,
1323   0x50, 0x9b, 0x00, 0xfe, 0xfd, 0x6e, 0xf3, 0xff,
1324   0xe3, 0x99, 0x37, 0x30, 0xc4, 0xff, 0x8e, 0x6d,
1325   0xff, 0xf1, 0x61, 0x3c, 0x0e, 0x28, 0xc8, 0xff,
1326   0xf1, 0x51, 0x00
1327 };
1328 
GST_START_TEST(rtp_vp8)1329 GST_START_TEST (rtp_vp8)
1330 {
1331   rtp_pipeline_test (rtp_vp8_frame_data, sizeof (rtp_vp8_frame_data), 1,
1332       VP8_CAPS, "rtpvp8pay", "rtpvp8depay", 0, 0, FALSE);
1333 }
1334 
1335 GST_END_TEST;
1336 
1337 /* videotestsrc pattern=red  ! video/x-raw,width=160,height=120 ! vp9enc */
1338 #define VP9_CAPS "video/x-vp9, profile=(string)0, " \
1339     "width=(int)160, height=(int)120, framerate=(fraction)30/1"
1340 
1341 static const guint8 rtp_vp9_frame_data[] = {
1342   0x82, 0x49, 0x83, 0x42, 0x00, 0x09, 0xf0, 0x07,
1343   0x76, 0x00, 0x38, 0x24, 0x1c, 0x18, 0x42, 0x00,
1344   0x00, 0x30, 0x60, 0x00, 0x00, 0x67, 0x3f, 0xff,
1345   0xfe, 0x69, 0x95, 0xff, 0xff, 0xff, 0xfe, 0x99,
1346   0x6b, 0xff, 0xff, 0xff, 0xff, 0x62, 0x98, 0x1d,
1347   0x45, 0x4c, 0x90, 0xc4, 0x70
1348 };
1349 
GST_START_TEST(rtp_vp9)1350 GST_START_TEST (rtp_vp9)
1351 {
1352   rtp_pipeline_test (rtp_vp9_frame_data, sizeof (rtp_vp9_frame_data), 1,
1353       VP9_CAPS, "rtpvp9pay", "rtpvp9depay", 0, 0, FALSE);
1354 }
1355 
1356 GST_END_TEST;
1357 
1358 static const guint8 rtp_jpeg_frame_data[] =
1359     { /* SOF */ 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x08, 0x00, 0x08,
1360   0x03, 0x00, 0x21, 0x08, 0x01, 0x11, 0x08, 0x02, 0x11, 0x08,
1361   /* DQT */ 0xFF, 0xDB, 0x00, 0x43, 0x08,
1362   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1363   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1364   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1365   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1366   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1367   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1368   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1369   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1370   /* DATA */ 0x00, 0x00, 0x00, 0x00, 0x00
1371 };
1372 
1373 static int rtp_jpeg_frame_data_size = sizeof (rtp_jpeg_frame_data);
1374 
1375 static int rtp_jpeg_frame_count = 1;
1376 
GST_START_TEST(rtp_jpeg)1377 GST_START_TEST (rtp_jpeg)
1378 {
1379   rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
1380       rtp_jpeg_frame_count, "video/x-jpeg,height=640,width=480", "rtpjpegpay",
1381       "rtpjpegdepay", 0, 0, FALSE);
1382 }
1383 
1384 GST_END_TEST;
1385 
GST_START_TEST(rtp_jpeg_width_greater_than_2040)1386 GST_START_TEST (rtp_jpeg_width_greater_than_2040)
1387 {
1388   rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
1389       rtp_jpeg_frame_count, "video/x-jpeg,height=2048,width=480", "rtpjpegpay",
1390       "rtpjpegdepay", 0, 0, FALSE);
1391 }
1392 
1393 GST_END_TEST;
1394 
GST_START_TEST(rtp_jpeg_height_greater_than_2040)1395 GST_START_TEST (rtp_jpeg_height_greater_than_2040)
1396 {
1397   rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
1398       rtp_jpeg_frame_count, "video/x-jpeg,height=640,width=2048", "rtpjpegpay",
1399       "rtpjpegdepay", 0, 0, FALSE);
1400 }
1401 
1402 GST_END_TEST;
1403 
GST_START_TEST(rtp_jpeg_width_and_height_greater_than_2040)1404 GST_START_TEST (rtp_jpeg_width_and_height_greater_than_2040)
1405 {
1406   rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
1407       rtp_jpeg_frame_count, "video/x-jpeg,height=2048,width=2048", "rtpjpegpay",
1408       "rtpjpegdepay", 0, 0, FALSE);
1409 }
1410 
1411 GST_END_TEST;
1412 
1413 static const guint8 rtp_jpeg_list_frame_data[] =
1414     { /* SOF */ 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x08, 0x00, 0x08,
1415   0x03, 0x00, 0x21, 0x08, 0x01, 0x11, 0x08, 0x02, 0x11, 0x08,
1416   /* DQT */ 0xFF, 0xDB, 0x00, 0x43, 0x08,
1417   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1418   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1419   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1420   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1421   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1422   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1423   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1424   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1425   /* DATA */ 0x00, 0x00, 0x00, 0x00, 0x00
1426 };
1427 
1428 static int rtp_jpeg_list_frame_data_size = sizeof (rtp_jpeg_list_frame_data);
1429 
1430 static int rtp_jpeg_list_frame_count = 1;
1431 
1432 static int rtp_jpeg_list_bytes_sent = 1 * sizeof (rtp_jpeg_list_frame_data);
1433 
GST_START_TEST(rtp_jpeg_list)1434 GST_START_TEST (rtp_jpeg_list)
1435 {
1436   rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
1437       rtp_jpeg_list_frame_count, "video/x-jpeg,height=640,width=480",
1438       "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
1439 }
1440 
1441 GST_END_TEST;
1442 
GST_START_TEST(rtp_jpeg_list_width_greater_than_2040)1443 GST_START_TEST (rtp_jpeg_list_width_greater_than_2040)
1444 {
1445   rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
1446       rtp_jpeg_list_frame_count, "video/x-jpeg,height=2048,width=480",
1447       "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
1448 }
1449 
1450 GST_END_TEST;
1451 
GST_START_TEST(rtp_jpeg_list_height_greater_than_2040)1452 GST_START_TEST (rtp_jpeg_list_height_greater_than_2040)
1453 {
1454   rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
1455       rtp_jpeg_list_frame_count, "video/x-jpeg,height=640,width=2048",
1456       "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
1457 }
1458 
1459 GST_END_TEST;
1460 
GST_START_TEST(rtp_jpeg_list_width_and_height_greater_than_2040)1461 GST_START_TEST (rtp_jpeg_list_width_and_height_greater_than_2040)
1462 {
1463   rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
1464       rtp_jpeg_list_frame_count, "video/x-jpeg,height=2048,width=2048",
1465       "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
1466 }
1467 
1468 GST_END_TEST;
1469 
1470 static void
rtp_jpeg_do_packet_loss(gdouble prob,gint num_expected)1471 rtp_jpeg_do_packet_loss (gdouble prob, gint num_expected)
1472 {
1473   GstHarness *h;
1474   gboolean eos = FALSE;
1475   gchar *s;
1476   guint i, buffer_count;
1477 
1478   s = g_strdup_printf ("videotestsrc pattern=ball num-buffers=100 ! "
1479       "jpegenc quality=50 ! rtpjpegpay ! identity drop-probability=%g ! "
1480       "rtpjpegdepay", prob);
1481   GST_INFO ("running pipeline %s", s);
1482   h = gst_harness_new_parse (s);
1483   g_free (s);
1484 
1485   gst_harness_play (h);
1486 
1487   do {
1488     GstEvent *event;
1489 
1490     event = gst_harness_pull_event (h);
1491     eos = (GST_EVENT_TYPE (event) == GST_EVENT_EOS);
1492     gst_event_unref (event);
1493   } while (!eos);
1494 
1495   buffer_count = gst_harness_buffers_received (h);
1496   GST_INFO ("Got %u buffers", buffer_count);
1497 
1498   if (num_expected >= 0) {
1499     fail_unless_equals_int (num_expected, buffer_count);
1500   }
1501 
1502   for (i = 0; i < buffer_count; ++i) {
1503     GstBuffer *buf;
1504     GstMapInfo map;
1505     guint16 soi, eoi;
1506 
1507     buf = gst_harness_pull (h);
1508     fail_unless (buf != NULL);
1509 
1510     fail_unless (gst_buffer_map (buf, &map, GST_MAP_READ));
1511     GST_MEMDUMP ("jpeg frame", map.data, map.size);
1512     fail_unless (map.size > 4);
1513     soi = GST_READ_UINT16_BE (map.data);
1514     fail_unless (soi == 0xffd8, "expected JPEG frame start FFD8 not %02X", soi);
1515     eoi = GST_READ_UINT16_BE (map.data + map.size - 2);
1516     fail_unless (eoi == 0xffd9, "expected JPEG frame end FFD9 not %02X", eoi);
1517     gst_buffer_unmap (buf, &map);
1518     gst_buffer_unref (buf);
1519   }
1520 
1521   gst_harness_teardown (h);
1522 }
1523 
GST_START_TEST(rtp_jpeg_packet_loss)1524 GST_START_TEST (rtp_jpeg_packet_loss)
1525 {
1526   gdouble probabilities[] = { 0.0, 0.001, 0.01, 0.1, 0.2, 0.5, 1.0 };
1527   gint num_expected[] = { 100, -1, -1, -1, -1, -1, 0 };
1528 
1529   GST_INFO ("Start iteration %d", __i__);
1530   fail_unless (__i__ < G_N_ELEMENTS (probabilities));
1531   rtp_jpeg_do_packet_loss (probabilities[__i__], num_expected[__i__]);
1532   GST_INFO ("Done with iteration %d", __i__);
1533 }
1534 
1535 GST_END_TEST;
1536 
1537 static const guint8 rtp_g729_frame_data[] =
1538     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1539   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1540 };
1541 
1542 static int rtp_g729_frame_data_size = 22;
1543 
1544 static int rtp_g729_frame_count = 1;
1545 
GST_START_TEST(rtp_g729)1546 GST_START_TEST (rtp_g729)
1547 {
1548   rtp_pipeline_test (rtp_g729_frame_data, rtp_g729_frame_data_size,
1549       rtp_g729_frame_count, "audio/G729,rate=8000,channels=1", "rtpg729pay",
1550       "rtpg729depay", 0, 0, FALSE);
1551 }
1552 
1553 GST_END_TEST;
1554 
1555 static const guint8 rtp_gst_frame_data[] =
1556     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1557   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1558 };
1559 
1560 static int rtp_gst_frame_data_size = 22;
1561 
1562 static int rtp_gst_frame_count = 1;
1563 
GST_START_TEST(rtp_gst_custom_event)1564 GST_START_TEST (rtp_gst_custom_event)
1565 {
1566   /* Create RTP pipeline. */
1567   rtp_pipeline *p =
1568       rtp_pipeline_create (rtp_gst_frame_data, rtp_gst_frame_data_size,
1569       rtp_gst_frame_count, "application/x-test",
1570       "rtpgstpay", "rtpgstdepay");
1571 
1572   if (p == NULL) {
1573     return;
1574   }
1575 
1576   p->custom_event =
1577       gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
1578       gst_structure_new ("test", "foo", G_TYPE_INT, 1, NULL));
1579 
1580   /* Run RTP pipeline. */
1581   rtp_pipeline_run (p);
1582 
1583   /* Destroy RTP pipeline. */
1584   rtp_pipeline_destroy (p);
1585 }
1586 
1587 GST_END_TEST;
1588 
GST_START_TEST(rtp_vorbis_renegotiate)1589 GST_START_TEST (rtp_vorbis_renegotiate)
1590 {
1591   GstElement *pipeline;
1592   GstElement *enc, *pay, *depay, *dec, *sink;
1593   GstPad *sinkpad, *srcpad;
1594   GstCaps *templcaps, *caps, *filter, *srccaps;
1595   GstSegment segment;
1596   GstBuffer *buffer;
1597   GstMapInfo map;
1598   GstAudioInfo info;
1599 
1600   pipeline = gst_pipeline_new (NULL);
1601   enc = gst_element_factory_make ("vorbisenc", NULL);
1602   pay = gst_element_factory_make ("rtpvorbispay", NULL);
1603   depay = gst_element_factory_make ("rtpvorbisdepay", NULL);
1604   dec = gst_element_factory_make ("vorbisdec", NULL);
1605   sink = gst_element_factory_make ("fakesink", NULL);
1606   g_object_set (sink, "async", FALSE, NULL);
1607   gst_bin_add_many (GST_BIN (pipeline), enc, pay, depay, dec, sink, NULL);
1608   fail_unless (gst_element_link_many (enc, pay, depay, dec, sink, NULL));
1609   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
1610       GST_STATE_CHANGE_SUCCESS);
1611 
1612   sinkpad = gst_element_get_static_pad (enc, "sink");
1613   srcpad = gst_element_get_static_pad (dec, "src");
1614 
1615   templcaps = gst_pad_get_pad_template_caps (sinkpad);
1616   filter =
1617       gst_caps_new_simple ("audio/x-raw", "channels", G_TYPE_INT, 2, "rate",
1618       G_TYPE_INT, 44100, NULL);
1619   caps = gst_caps_intersect (templcaps, filter);
1620   caps = gst_caps_fixate (caps);
1621 
1622   gst_segment_init (&segment, GST_FORMAT_TIME);
1623   fail_unless (gst_pad_send_event (sinkpad,
1624           gst_event_new_stream_start ("test")));
1625   fail_unless (gst_pad_send_event (sinkpad, gst_event_new_caps (caps)));
1626   fail_unless (gst_pad_send_event (sinkpad, gst_event_new_segment (&segment)));
1627 
1628   gst_audio_info_from_caps (&info, caps);
1629   buffer = gst_buffer_new_and_alloc (44100 * info.bpf);
1630   gst_buffer_map (buffer, &map, GST_MAP_WRITE);
1631   gst_audio_format_info_fill_silence (info.finfo, map.data, map.size);
1632   gst_buffer_unmap (buffer, &map);
1633   GST_BUFFER_PTS (buffer) = 0;
1634   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
1635 
1636   fail_unless_equals_int (gst_pad_chain (sinkpad, buffer), GST_FLOW_OK);
1637 
1638   srccaps = gst_pad_get_current_caps (srcpad);
1639   fail_unless (gst_caps_can_intersect (srccaps, caps));
1640   gst_caps_unref (srccaps);
1641 
1642   gst_caps_unref (caps);
1643   gst_caps_unref (filter);
1644   filter =
1645       gst_caps_new_simple ("audio/x-raw", "channels", G_TYPE_INT, 2, "rate",
1646       G_TYPE_INT, 48000, NULL);
1647   caps = gst_caps_intersect (templcaps, filter);
1648   caps = gst_caps_fixate (caps);
1649 
1650   fail_unless (gst_pad_send_event (sinkpad, gst_event_new_caps (caps)));
1651 
1652   gst_audio_info_from_caps (&info, caps);
1653   buffer = gst_buffer_new_and_alloc (48000 * info.bpf);
1654   gst_buffer_map (buffer, &map, GST_MAP_WRITE);
1655   gst_audio_format_info_fill_silence (info.finfo, map.data, map.size);
1656   gst_buffer_unmap (buffer, &map);
1657   GST_BUFFER_PTS (buffer) = 0;
1658   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
1659   GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
1660 
1661   fail_unless_equals_int (gst_pad_chain (sinkpad, buffer), GST_FLOW_OK);
1662 
1663   srccaps = gst_pad_get_current_caps (srcpad);
1664   fail_unless (gst_caps_can_intersect (srccaps, caps));
1665   gst_caps_unref (srccaps);
1666 
1667   gst_caps_unref (caps);
1668   gst_caps_unref (filter);
1669   gst_caps_unref (templcaps);
1670   gst_object_unref (sinkpad);
1671   gst_object_unref (srcpad);
1672   gst_element_set_state (pipeline, GST_STATE_NULL);
1673   gst_object_unref (pipeline);
1674 }
1675 
1676 GST_END_TEST;
1677 
1678 static guint16
pull_rtp_buffer(GstHarness * h,gboolean has_marker)1679 pull_rtp_buffer (GstHarness * h, gboolean has_marker)
1680 {
1681   gint16 seq;
1682   GstBuffer *buf;
1683   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
1684 
1685   buf = gst_harness_try_pull (h);
1686   fail_unless (buf);
1687 
1688   fail_unless (gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp));
1689   seq = gst_rtp_buffer_get_seq (&rtp);
1690   gst_rtp_buffer_unmap (&rtp);
1691 
1692   if (has_marker)
1693     fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_MARKER));
1694   else
1695     fail_if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_MARKER));
1696 
1697   gst_buffer_unref (buf);
1698   return seq;
1699 }
1700 
1701 static void
test_rtp_opus_dtx(gboolean dtx)1702 test_rtp_opus_dtx (gboolean dtx)
1703 {
1704   GstHarness *h;
1705   GstBuffer *buf;
1706   /* generated with a muted mic using:
1707    * gst-launch-1.0 pulsesrc ! opusenc dtx=true bitrate-type=vbr ! fakesink silent=false dump=true -v
1708    */
1709   static const guint8 opus_empty[] = { 0xf8 };
1710   static const guint8 opus_frame[] = { 0xf8, 0xff, 0xfe };
1711   guint16 seq, expected_seq;
1712 
1713   h = gst_harness_new_parse ("rtpopuspay");
1714   fail_unless (h);
1715 
1716   gst_harness_set (h, "rtpopuspay", "dtx", dtx, NULL);
1717 
1718   gst_harness_set_caps_str (h,
1719       "audio/x-opus, rate=48000, channels=1, channel-mapping-family=0",
1720       "application/x-rtp, media=audio, clock-rate=48000, encoding-name=OPUS, sprop-stereo=(string)0, encoding-params=(string)2, sprop-maxcapturerate=(string)48000, payload=96");
1721 
1722   /* push first opus frame */
1723   buf = gst_buffer_new_memdup (opus_frame, sizeof (opus_frame));
1724   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1725   seq = pull_rtp_buffer (h, TRUE);
1726   expected_seq = seq + 1;
1727 
1728   /* push empty frame */
1729   buf = gst_buffer_new_memdup (opus_empty, sizeof (opus_empty));
1730   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1731   if (dtx) {
1732     /* buffer is not transmitted if dtx is enabled */
1733     buf = gst_harness_try_pull (h);
1734     fail_if (buf);
1735   } else {
1736     seq = pull_rtp_buffer (h, FALSE);
1737     fail_unless_equals_int (seq, expected_seq);
1738     expected_seq++;
1739   }
1740 
1741   /* push second opus frame */
1742   buf = gst_buffer_new_memdup (opus_frame, sizeof (opus_frame));
1743   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1744   seq = pull_rtp_buffer (h, dtx);
1745   fail_unless_equals_int (seq, expected_seq);
1746 
1747   gst_harness_teardown (h);
1748 }
1749 
GST_START_TEST(rtp_opus_dtx_disabled)1750 GST_START_TEST (rtp_opus_dtx_disabled)
1751 {
1752   test_rtp_opus_dtx (FALSE);
1753 }
1754 
1755 GST_END_TEST;
1756 
GST_START_TEST(rtp_opus_dtx_enabled)1757 GST_START_TEST (rtp_opus_dtx_enabled)
1758 {
1759   test_rtp_opus_dtx (TRUE);
1760 }
1761 
1762 GST_END_TEST;
1763 
1764 /*
1765  * Creates the test suite.
1766  *
1767  * Returns: pointer to the test suite.
1768  */
1769 static Suite *
rtp_payloading_suite(void)1770 rtp_payloading_suite (void)
1771 {
1772   GstRegistry *registry = gst_registry_get ();
1773   Suite *s = suite_create ("rtp_data_test");
1774 
1775   TCase *tc_chain = tcase_create ("linear");
1776 
1777   /* Set timeout to 60 seconds. */
1778   tcase_set_timeout (tc_chain, 60);
1779 
1780   suite_add_tcase (s, tc_chain);
1781   tcase_add_test (tc_chain, rtp_ilbc);
1782   tcase_add_test (tc_chain, rtp_gsm);
1783   tcase_add_test (tc_chain, rtp_amr);
1784   tcase_add_test (tc_chain, rtp_pcma);
1785   tcase_add_test (tc_chain, rtp_pcmu);
1786   tcase_add_test (tc_chain, rtp_mpa);
1787   tcase_add_test (tc_chain, rtp_h261);
1788   tcase_add_test (tc_chain, rtp_h263);
1789   tcase_add_test (tc_chain, rtp_h263p);
1790   tcase_add_test (tc_chain, rtp_h264);
1791   tcase_add_test (tc_chain, rtp_h264depay_avc);
1792   tcase_add_test (tc_chain, rtp_h264depay_bytestream);
1793   tcase_add_test (tc_chain, rtp_h264_list_lt_mtu);
1794   tcase_add_test (tc_chain, rtp_h264_list_lt_mtu_avc);
1795   tcase_add_test (tc_chain, rtp_h264_list_gt_mtu);
1796   tcase_add_test (tc_chain, rtp_h264_list_gt_mtu_avc);
1797   tcase_add_test (tc_chain, rtp_h265);
1798   tcase_add_test (tc_chain, rtp_h265_list_lt_mtu);
1799   tcase_add_test (tc_chain, rtp_h265_list_lt_mtu_hvc1);
1800   tcase_add_test (tc_chain, rtp_h265_list_gt_mtu);
1801   tcase_add_test (tc_chain, rtp_h265_list_gt_mtu_hvc1);
1802   tcase_add_test (tc_chain, rtp_klv);
1803   tcase_add_test (tc_chain, rtp_klv_fragmented);
1804   tcase_add_test (tc_chain, rtp_L16);
1805   tcase_add_test (tc_chain, rtp_L24);
1806   tcase_add_test (tc_chain, rtp_mp2t);
1807   tcase_add_test (tc_chain, rtp_mp4v);
1808   tcase_add_test (tc_chain, rtp_mp4v_list);
1809   tcase_add_test (tc_chain, rtp_mp4g);
1810   tcase_add_test (tc_chain, rtp_theora);
1811   tcase_add_test (tc_chain, rtp_vorbis);
1812   tcase_add_test (tc_chain, rtp_vp8);
1813   tcase_add_test (tc_chain, rtp_vp9);
1814   tcase_add_test (tc_chain, rtp_jpeg);
1815   tcase_add_test (tc_chain, rtp_jpeg_width_greater_than_2040);
1816   tcase_add_test (tc_chain, rtp_jpeg_height_greater_than_2040);
1817   tcase_add_test (tc_chain, rtp_jpeg_width_and_height_greater_than_2040);
1818   tcase_add_test (tc_chain, rtp_jpeg_list);
1819   tcase_add_test (tc_chain, rtp_jpeg_list_width_greater_than_2040);
1820   tcase_add_test (tc_chain, rtp_jpeg_list_height_greater_than_2040);
1821   tcase_add_test (tc_chain, rtp_jpeg_list_width_and_height_greater_than_2040);
1822   if (gst_registry_check_feature_version (registry, "jpegenc", 1, 0, 0)
1823       && gst_registry_check_feature_version (registry, "videotestsrc", 1, 0, 0))
1824     tcase_add_loop_test (tc_chain, rtp_jpeg_packet_loss, 0, 7);
1825   tcase_add_test (tc_chain, rtp_g729);
1826   tcase_add_test (tc_chain, rtp_gst_custom_event);
1827   tcase_add_test (tc_chain, rtp_vorbis_renegotiate);
1828   tcase_add_test (tc_chain, rtp_opus_dtx_disabled);
1829   tcase_add_test (tc_chain, rtp_opus_dtx_enabled);
1830   return s;
1831 }
1832 
1833 GST_CHECK_MAIN (rtp_payloading)
1834