rtph265pay/depay: Sync against RFC 7798
[platform/upstream/gst-plugins-good.git] / tests / check / elements / rtp-payloading.c
1 /* GStreamer RTP payloader unit tests
2  * Copyright (C) 2008 Nokia Corporation and its subsidary(-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 #include <gst/check/gstcheck.h>
21 #include <gst/check/gstharness.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24
25 #define RELEASE_ELEMENT(x) if(x) {gst_object_unref(x); x = NULL;}
26
27 #define LOOP_COUNT 1
28
29 /*
30  * RTP pipeline structure to store the required elements.
31  */
32 typedef struct
33 {
34   GstElement *pipeline;
35   GstElement *appsrc;
36   GstElement *rtppay;
37   GstElement *rtpdepay;
38   GstElement *fakesink;
39   const guint8 *frame_data;
40   int frame_data_size;
41   int frame_count;
42   GstEvent *custom_event;
43 } rtp_pipeline;
44
45 /*
46  * Number of bytes received in the chain list function when using buffer lists
47  */
48 static guint chain_list_bytes_received;
49
50 /*
51  * Chain list function for testing buffer lists
52  */
53 static GstFlowReturn
54 rtp_pipeline_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list)
55 {
56   guint i, len;
57
58   fail_if (!list);
59   /*
60    * Count the size of the payload in the buffer list.
61    */
62   len = gst_buffer_list_length (list);
63   GST_LOG ("list length %u", len);
64
65   /* Loop through all groups */
66   for (i = 0; i < len; i++) {
67     GstBuffer *paybuf;
68     GstMemory *mem;
69     gint size;
70
71     paybuf = gst_buffer_list_get (list, i);
72     /* only count real data which is expected in last memory block */
73     GST_LOG ("n_memory %d", gst_buffer_n_memory (paybuf));
74     fail_unless (gst_buffer_n_memory (paybuf) > 1);
75     mem = gst_buffer_get_memory_range (paybuf, gst_buffer_n_memory (paybuf) - 1,
76         1);
77     size = gst_memory_get_sizes (mem, NULL, NULL);
78     gst_memory_unref (mem);
79     chain_list_bytes_received += size;
80     GST_LOG ("size %d, total %u", size, chain_list_bytes_received);
81   }
82   gst_buffer_list_unref (list);
83
84   return GST_FLOW_OK;
85 }
86
87 static GstFlowReturn
88 rtp_pipeline_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
89 {
90   GstBufferList *list;
91
92   list = gst_buffer_list_new_sized (1);
93   gst_buffer_list_add (list, buf);
94   return rtp_pipeline_chain_list (pad, parent, list);
95 }
96
97 /*
98  * RTP bus callback.
99  */
100 static gboolean
101 rtp_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
102 {
103   GMainLoop *mainloop = (GMainLoop *) data;
104
105   switch (GST_MESSAGE_TYPE (message)) {
106     case GST_MESSAGE_ERROR:
107     {
108       GError *err;
109
110       gchar *debug;
111
112       gchar *element_name;
113
114       element_name = (message->src) ? gst_object_get_name (message->src) : NULL;
115       gst_message_parse_error (message, &err, &debug);
116       g_print ("\nError from element %s: %s\n%s\n\n",
117           GST_STR_NULL (element_name), err->message, (debug) ? debug : "");
118       g_error_free (err);
119       g_free (debug);
120       g_free (element_name);
121
122       fail_if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR);
123
124       g_main_loop_quit (mainloop);
125     }
126       break;
127
128     case GST_MESSAGE_EOS:
129     {
130       g_main_loop_quit (mainloop);
131     }
132       break;
133       break;
134
135     default:
136     {
137     }
138       break;
139   }
140
141   return TRUE;
142 }
143
144 /*
145  * Creates a RTP pipeline for one test.
146  * @param frame_data Pointer to the frame data which is used to pass thru pay/depayloaders.
147  * @param frame_data_size Frame data size in bytes.
148  * @param frame_count Frame count.
149  * @param filtercaps Caps filters.
150  * @param pay Payloader name.
151  * @param depay Depayloader name.
152  * @return
153  * Returns pointer to the RTP pipeline.
154  * The user must free the RTP pipeline when it's not used anymore.
155  */
156 static rtp_pipeline *
157 rtp_pipeline_create (const guint8 * frame_data, int frame_data_size,
158     int frame_count, const char *filtercaps, const char *pay, const char *depay)
159 {
160   gchar *pipeline_name;
161   rtp_pipeline *p;
162   GstCaps *caps;
163
164   /* Check parameters. */
165   if (!frame_data || !pay || !depay) {
166     return NULL;
167   }
168
169   /* Allocate memory for the RTP pipeline. */
170   p = (rtp_pipeline *) malloc (sizeof (rtp_pipeline));
171
172   p->frame_data = frame_data;
173   p->frame_data_size = frame_data_size;
174   p->frame_count = frame_count;
175   p->custom_event = NULL;
176
177   /* Create elements. */
178   pipeline_name = g_strdup_printf ("%s-%s-pipeline", pay, depay);
179   p->pipeline = gst_pipeline_new (pipeline_name);
180   g_free (pipeline_name);
181   p->appsrc = gst_element_factory_make ("appsrc", NULL);
182   p->rtppay = gst_element_factory_make (pay, NULL);
183   p->rtpdepay = gst_element_factory_make (depay, NULL);
184   p->fakesink = gst_element_factory_make ("fakesink", NULL);
185
186   /* One or more elements are not created successfully or failed to create p? */
187   if (!p->pipeline || !p->appsrc || !p->rtppay || !p->rtpdepay || !p->fakesink) {
188     /* Release created elements. */
189     RELEASE_ELEMENT (p->pipeline);
190     RELEASE_ELEMENT (p->appsrc);
191     RELEASE_ELEMENT (p->rtppay);
192     RELEASE_ELEMENT (p->rtpdepay);
193     RELEASE_ELEMENT (p->fakesink);
194
195     /* Release allocated memory. */
196     free (p);
197
198     return NULL;
199   }
200
201   /* Set src properties. */
202   caps = gst_caps_from_string (filtercaps);
203   g_object_set (p->appsrc, "do-timestamp", TRUE, "caps", caps,
204       "format", GST_FORMAT_TIME, NULL);
205   gst_caps_unref (caps);
206
207   /* Add elements to the pipeline. */
208   gst_bin_add (GST_BIN (p->pipeline), p->appsrc);
209   gst_bin_add (GST_BIN (p->pipeline), p->rtppay);
210   gst_bin_add (GST_BIN (p->pipeline), p->rtpdepay);
211   gst_bin_add (GST_BIN (p->pipeline), p->fakesink);
212
213   /* Link elements. */
214   gst_element_link (p->appsrc, p->rtppay);
215   gst_element_link (p->rtppay, p->rtpdepay);
216   gst_element_link (p->rtpdepay, p->fakesink);
217
218   return p;
219 }
220
221 /*
222  * Destroys the RTP pipeline.
223  * @param p Pointer to the RTP pipeline.
224  */
225 static void
226 rtp_pipeline_destroy (rtp_pipeline * p)
227 {
228   /* Check parameters. */
229   if (p == NULL) {
230     return;
231   }
232
233   /* Release pipeline. */
234   RELEASE_ELEMENT (p->pipeline);
235
236   /* Release allocated memory. */
237   free (p);
238 }
239
240 static GstPadProbeReturn
241 pay_event_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
242 {
243   rtp_pipeline *p = (rtp_pipeline *) user_data;
244   GstEvent *event = GST_PAD_PROBE_INFO_DATA (info);
245
246   if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM) {
247     const GstStructure *s0 = gst_event_get_structure (p->custom_event);
248     const GstStructure *s1 = gst_event_get_structure (event);
249     if (gst_structure_is_equal (s0, s1)) {
250       return GST_PAD_PROBE_DROP;
251     }
252   }
253
254   return GST_PAD_PROBE_OK;
255 }
256
257 static GstPadProbeReturn
258 depay_event_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
259 {
260   rtp_pipeline *p = (rtp_pipeline *) user_data;
261   GstEvent *event = GST_PAD_PROBE_INFO_DATA (info);
262
263   if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM) {
264     const GstStructure *s0 = gst_event_get_structure (p->custom_event);
265     const GstStructure *s1 = gst_event_get_structure (event);
266     if (gst_structure_is_equal (s0, s1)) {
267       gst_event_unref (p->custom_event);
268       p->custom_event = NULL;
269     }
270   }
271
272   return GST_PAD_PROBE_OK;
273 }
274
275 /*
276  * Runs the RTP pipeline.
277  * @param p Pointer to the RTP pipeline.
278  */
279 static void
280 rtp_pipeline_run (rtp_pipeline * p)
281 {
282   GstFlowReturn flow_ret;
283   GMainLoop *mainloop = NULL;
284   GstBus *bus;
285   gint i, j;
286
287   /* Check parameters. */
288   if (p == NULL) {
289     return;
290   }
291
292   /* Create mainloop. */
293   mainloop = g_main_loop_new (NULL, FALSE);
294   if (!mainloop) {
295     return;
296   }
297
298   /* Add bus callback. */
299   bus = gst_pipeline_get_bus (GST_PIPELINE (p->pipeline));
300
301   gst_bus_add_watch (bus, rtp_bus_callback, (gpointer) mainloop);
302   gst_object_unref (bus);
303
304   /* Set pipeline to PLAYING. */
305   gst_element_set_state (p->pipeline, GST_STATE_PLAYING);
306
307   /* Push custom event into the pipeline */
308   if (p->custom_event) {
309     GstPad *srcpad;
310
311     /* Install a probe to drop the event after it being serialized */
312     srcpad = gst_element_get_static_pad (p->rtppay, "src");
313     gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
314         pay_event_probe_cb, p, NULL);
315     gst_object_unref (srcpad);
316
317     /* Install a probe to trace the deserialized event after depayloading */
318     srcpad = gst_element_get_static_pad (p->rtpdepay, "src");
319     gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
320         depay_event_probe_cb, p, NULL);
321     gst_object_unref (srcpad);
322     /* Send the event */
323     gst_element_send_event (p->appsrc, gst_event_ref (p->custom_event));
324   }
325
326   /* Push data into the pipeline */
327   for (i = 0; i < LOOP_COUNT; i++) {
328     const guint8 *data = p->frame_data;
329
330     for (j = 0; j < p->frame_count; j++) {
331       GstBuffer *buf;
332
333       buf =
334           gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
335           (guint8 *) data, p->frame_data_size, 0, p->frame_data_size, NULL,
336           NULL);
337
338       g_signal_emit_by_name (p->appsrc, "push-buffer", buf, &flow_ret);
339       fail_unless_equals_int (flow_ret, GST_FLOW_OK);
340       data += p->frame_data_size;
341
342       gst_buffer_unref (buf);
343     }
344   }
345
346   g_signal_emit_by_name (p->appsrc, "end-of-stream", &flow_ret);
347
348   /* Run mainloop. */
349   g_main_loop_run (mainloop);
350
351   /* Set pipeline to NULL. */
352   gst_element_set_state (p->pipeline, GST_STATE_NULL);
353
354   /* Release mainloop. */
355   g_main_loop_unref (mainloop);
356
357   fail_if (p->custom_event);
358 }
359
360 /*
361  * Enables buffer lists and adds a chain_list_function to the depayloader.
362  * @param p Pointer to the RTP pipeline.
363  */
364 static void
365 rtp_pipeline_enable_lists (rtp_pipeline * p)
366 {
367   GstPad *pad;
368
369   /* Add chain list function for the buffer list tests */
370   pad = gst_element_get_static_pad (p->rtpdepay, "sink");
371   gst_pad_set_chain_list_function (pad,
372       GST_DEBUG_FUNCPTR (rtp_pipeline_chain_list));
373   /* .. to satisfy this silly test code in case someone dares push a buffer */
374   gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (rtp_pipeline_chain));
375   gst_object_unref (pad);
376 }
377
378 /*
379  * Creates the RTP pipeline and runs the test using the pipeline.
380  * @param frame_data Pointer to the frame data which is used to pass thru pay/depayloaders.
381  * @param frame_data_size Frame data size in bytes.
382  * @param frame_count Frame count.
383  * @param filtercaps Caps filters.
384  * @param pay Payloader name.
385  * @param depay Depayloader name.
386  * @bytes_sent bytes that will be sent, used when testing buffer lists
387  * @mtu_size set mtu size when testing lists
388  * @use_lists enable buffer lists
389  */
390 static void
391 rtp_pipeline_test (const guint8 * frame_data, int frame_data_size,
392     int frame_count, const char *filtercaps, const char *pay, const char *depay,
393     guint bytes_sent, guint mtu_size, gboolean use_lists)
394 {
395   /* Create RTP pipeline. */
396   rtp_pipeline *p =
397       rtp_pipeline_create (frame_data, frame_data_size, frame_count, filtercaps,
398       pay, depay);
399
400   if (p == NULL) {
401     return;
402   }
403
404   /* set mtu size if needed */
405   if (mtu_size > 0) {
406     g_object_set (p->rtppay, "mtu", mtu_size, NULL);
407   }
408
409   if (use_lists) {
410     rtp_pipeline_enable_lists (p);
411     chain_list_bytes_received = 0;
412   }
413
414   /* Run RTP pipeline. */
415   rtp_pipeline_run (p);
416
417   /* Destroy RTP pipeline. */
418   rtp_pipeline_destroy (p);
419
420   if (use_lists) {
421     /* 'next NAL' indicator is 4 bytes */
422     fail_unless_equals_int (chain_list_bytes_received, bytes_sent * LOOP_COUNT);
423   }
424 }
425
426 static const guint8 rtp_ilbc_frame_data[] =
427     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
429 };
430
431 static int rtp_ilbc_frame_data_size = 20;
432
433 static int rtp_ilbc_frame_count = 1;
434
435 GST_START_TEST (rtp_ilbc)
436 {
437   rtp_pipeline_test (rtp_ilbc_frame_data, rtp_ilbc_frame_data_size,
438       rtp_ilbc_frame_count, "audio/x-iLBC,mode=20", "rtpilbcpay",
439       "rtpilbcdepay", 0, 0, FALSE);
440 }
441
442 GST_END_TEST;
443 static const guint8 rtp_gsm_frame_data[] =
444     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
446 };
447
448 static int rtp_gsm_frame_data_size = 20;
449
450 static int rtp_gsm_frame_count = 1;
451
452 GST_START_TEST (rtp_gsm)
453 {
454   rtp_pipeline_test (rtp_gsm_frame_data, rtp_gsm_frame_data_size,
455       rtp_gsm_frame_count, "audio/x-gsm,rate=8000,channels=1", "rtpgsmpay",
456       "rtpgsmdepay", 0, 0, FALSE);
457 }
458
459 GST_END_TEST;
460 static const guint8 rtp_amr_frame_data[] =
461     { 0x3c, 0x24, 0x03, 0xb3, 0x48, 0x10, 0x68, 0x46, 0x6c, 0xec, 0x03,
462   0x7a, 0x37, 0x16, 0x41, 0x41, 0xc0, 0x00, 0x0d, 0xcd, 0x12, 0xed,
463   0xad, 0x80, 0x00, 0x00, 0x11, 0x31, 0x00, 0x00, 0x0d, 0xa0
464 };
465
466 static int rtp_amr_frame_data_size = 32;
467
468 static int rtp_amr_frame_count = 1;
469
470 GST_START_TEST (rtp_amr)
471 {
472   rtp_pipeline_test (rtp_amr_frame_data, rtp_amr_frame_data_size,
473       rtp_amr_frame_count, "audio/AMR,channels=1,rate=8000", "rtpamrpay",
474       "rtpamrdepay", 0, 0, FALSE);
475 }
476
477 GST_END_TEST;
478 static const guint8 rtp_pcma_frame_data[] =
479     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
481 };
482
483 static int rtp_pcma_frame_data_size = 20;
484
485 static int rtp_pcma_frame_count = 1;
486
487 GST_START_TEST (rtp_pcma)
488 {
489   rtp_pipeline_test (rtp_pcma_frame_data, rtp_pcma_frame_data_size,
490       rtp_pcma_frame_count, "audio/x-alaw,channels=1,rate=8000", "rtppcmapay",
491       "rtppcmadepay", 0, 0, FALSE);
492 }
493
494 GST_END_TEST;
495 static const guint8 rtp_pcmu_frame_data[] =
496     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
497   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
498 };
499
500 static int rtp_pcmu_frame_data_size = 20;
501
502 static int rtp_pcmu_frame_count = 1;
503
504 GST_START_TEST (rtp_pcmu)
505 {
506   rtp_pipeline_test (rtp_pcmu_frame_data, rtp_pcmu_frame_data_size,
507       rtp_pcmu_frame_count, "audio/x-mulaw,channels=1,rate=8000", "rtppcmupay",
508       "rtppcmudepay", 0, 0, FALSE);
509 }
510
511 GST_END_TEST;
512 static const guint8 rtp_mpa_frame_data[] =
513     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
515 };
516
517 static int rtp_mpa_frame_data_size = 20;
518
519 static int rtp_mpa_frame_count = 1;
520
521 GST_START_TEST (rtp_mpa)
522 {
523   rtp_pipeline_test (rtp_mpa_frame_data, rtp_mpa_frame_data_size,
524       rtp_mpa_frame_count, "audio/mpeg,mpegversion=1", "rtpmpapay",
525       "rtpmpadepay", 0, 0, FALSE);
526 }
527
528 GST_END_TEST;
529
530 static const guint8 rtp_h261_frame_data[] = {
531   0x00, 0x01, 0x00, 0x06, 0x00, 0x01, 0x11, 0x00, 0x00, 0x4c, 0x40, 0x00,
532   0x15, 0x10,
533 };
534
535 static int rtp_h261_frame_data_size = 14;
536 static int rtp_h261_frame_count = 1;
537
538 GST_START_TEST (rtp_h261)
539 {
540   rtp_pipeline_test (rtp_h261_frame_data, rtp_h261_frame_data_size,
541       rtp_h261_frame_count, "video/x-h261", "rtph261pay", "rtph261depay",
542       0, 0, FALSE);
543 }
544
545 GST_END_TEST;
546
547 static const guint8 rtp_h263_frame_data[] =
548     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
550 };
551
552 static int rtp_h263_frame_data_size = 20;
553
554 static int rtp_h263_frame_count = 1;
555
556 GST_START_TEST (rtp_h263)
557 {
558   rtp_pipeline_test (rtp_h263_frame_data, rtp_h263_frame_data_size,
559       rtp_h263_frame_count,
560       "video/x-h263,variant=(string)itu,h263version=h263",
561       "rtph263pay", "rtph263depay", 0, 0, FALSE);
562   rtp_pipeline_test (rtp_h263_frame_data, rtp_h263_frame_data_size,
563       rtp_h263_frame_count,
564       "video/x-h263,variant=(string)itu,h263version=h263,width=10,height=20",
565       "rtph263pay", "rtph263depay", 0, 0, FALSE);
566 }
567
568 GST_END_TEST;
569 static const guint8 rtp_h263p_frame_data[] =
570     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
572 };
573
574 static int rtp_h263p_frame_data_size = 20;
575
576 static int rtp_h263p_frame_count = 1;
577
578 GST_START_TEST (rtp_h263p)
579 {
580   rtp_pipeline_test (rtp_h263p_frame_data, rtp_h263p_frame_data_size,
581       rtp_h263p_frame_count, "video/x-h263,variant=(string)itu,"
582       "h263version=(string)h263", "rtph263ppay", "rtph263pdepay", 0, 0, FALSE);
583
584   /* payloader should accept any input that matches the template caps
585    * if there's just a udpsink or fakesink downstream */
586   rtp_pipeline_test (rtp_h263p_frame_data, rtp_h263p_frame_data_size,
587       rtp_h263p_frame_count, "video/x-h263,variant=(string)itu,"
588       "h263version=(string)h263", "rtph263ppay", "identity", 0, 0, FALSE);
589
590   /* default output of avenc_h263p */
591   rtp_pipeline_test (rtp_h263p_frame_data, rtp_h263p_frame_data_size,
592       rtp_h263p_frame_count, "video/x-h263,variant=(string)itu,"
593       "h263version=(string)h263p, annex-f=(boolean)true, "
594       "annex-j=(boolean)true, annex-i=(boolean)true, annex-t=(boolean)true",
595       "rtph263ppay", "identity", 0, 0, FALSE);
596
597   /* pay ! depay should also work with any input */
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)h263p, annex-f=(boolean)true, "
601       "annex-j=(boolean)true, annex-i=(boolean)true, annex-t=(boolean)true",
602       "rtph263ppay", "rtph263pdepay", 0, 0, FALSE);
603 }
604
605 GST_END_TEST;
606 static const guint8 rtp_h264_frame_data[] =
607     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
608   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
609 };
610
611 static int rtp_h264_frame_data_size = 20;
612
613 static int rtp_h264_frame_count = 1;
614
615 GST_START_TEST (rtp_h264)
616 {
617   /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
618   rtp_pipeline_test (rtp_h264_frame_data, rtp_h264_frame_data_size,
619       rtp_h264_frame_count,
620       "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal",
621       "rtph264pay", "rtph264depay", 0, 0, FALSE);
622
623   /* config-interval property used to be of uint type, was changed to int,
624    * make sure old GValue stuff still works */
625   {
626     GValue val = G_VALUE_INIT;
627     GstElement *rtph264pay;
628     GParamSpec *pspec;
629
630
631     rtph264pay = gst_element_factory_make ("rtph264pay", NULL);
632     pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (rtph264pay),
633         "config-interval");
634     fail_unless (pspec->value_type == G_TYPE_INT);
635     g_value_init (&val, G_TYPE_UINT);
636     g_value_set_uint (&val, 10);
637     g_object_set_property (G_OBJECT (rtph264pay), "config-interval", &val);
638     g_value_set_uint (&val, 0);
639     g_object_get_property (G_OBJECT (rtph264pay), "config-interval", &val);
640     fail_unless_equals_int (10, g_value_get_uint (&val));
641     g_object_set (G_OBJECT (rtph264pay), "config-interval", -1, NULL);
642     g_object_get_property (G_OBJECT (rtph264pay), "config-interval", &val);
643     fail_unless (g_value_get_uint (&val) == G_MAXUINT);
644     g_value_unset (&val);
645     gst_object_unref (rtph264pay);
646   }
647 }
648
649 GST_END_TEST;
650 static const guint8 rtp_h264_list_lt_mtu_frame_data[] =
651     /* not packetized, next NAL starts with 0001 */
652 { 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
653   0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
654   0xad, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x10
655 };
656
657 static int rtp_h264_list_lt_mtu_frame_data_size = 16;
658
659 static int rtp_h264_list_lt_mtu_frame_count = 2;
660
661 /* NAL = 4 bytes */
662 /* also 2 bytes FU-A header each time */
663 static int rtp_h264_list_lt_mtu_bytes_sent = 2 * (16 - 4);
664
665 static int rtp_h264_list_lt_mtu_mtu_size = 1024;
666
667 GST_START_TEST (rtp_h264_list_lt_mtu)
668 {
669   /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
670   rtp_pipeline_test (rtp_h264_list_lt_mtu_frame_data,
671       rtp_h264_list_lt_mtu_frame_data_size, rtp_h264_list_lt_mtu_frame_count,
672       "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal",
673       "rtph264pay", "rtph264depay",
674       rtp_h264_list_lt_mtu_bytes_sent, rtp_h264_list_lt_mtu_mtu_size, TRUE);
675 }
676
677 GST_END_TEST;
678 static const guint8 rtp_h264_list_lt_mtu_frame_data_avc[] =
679     /* packetized data */
680 { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
681   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
682   0xad, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0d, 0x00
683 };
684
685 /* NAL = 4 bytes */
686 static int rtp_h264_list_lt_mtu_bytes_sent_avc = 2 * (16 - 2 * 4);
687
688 //static int rtp_h264_list_lt_mtu_mtu_size = 1024;
689
690 GST_START_TEST (rtp_h264_list_lt_mtu_avc)
691 {
692   /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
693   rtp_pipeline_test (rtp_h264_list_lt_mtu_frame_data_avc,
694       rtp_h264_list_lt_mtu_frame_data_size, rtp_h264_list_lt_mtu_frame_count,
695       "video/x-h264,stream-format=(string)avc,alignment=(string)au,"
696       "codec_data=(buffer)01640014ffe1001867640014acd94141fb0110000003001773594000f142996001000568ebecb22c",
697       "rtph264pay", "rtph264depay",
698       rtp_h264_list_lt_mtu_bytes_sent_avc, rtp_h264_list_lt_mtu_mtu_size, TRUE);
699 }
700
701 GST_END_TEST;
702 static const guint8 rtp_h264_list_gt_mtu_frame_data[] =
703     /* not packetized, next NAL starts with 0001 */
704 { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
707   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
708   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
710 };
711
712 static int rtp_h264_list_gt_mtu_frame_data_size = 64;
713
714 static int rtp_h264_list_gt_mtu_frame_count = 1;
715
716 /* NAL = 4 bytes. When data does not fit into 1 mtu, 1 byte will be skipped */
717 static int rtp_h264_list_gt_mtu_bytes_sent = 1 * (64 - 4) - 1;
718
719 static int rtp_h264_list_gt_mtu_mty_size = 28;
720
721 GST_START_TEST (rtp_h264_list_gt_mtu)
722 {
723   /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
724   rtp_pipeline_test (rtp_h264_list_gt_mtu_frame_data,
725       rtp_h264_list_gt_mtu_frame_data_size, rtp_h264_list_gt_mtu_frame_count,
726       "video/x-h264,stream-format=(string)byte-stream,alignment=(string)nal",
727       "rtph264pay", "rtph264depay",
728       rtp_h264_list_gt_mtu_bytes_sent, rtp_h264_list_gt_mtu_mty_size, TRUE);
729 }
730
731 GST_END_TEST;
732 static const guint8 rtp_h264_list_gt_mtu_frame_data_avc[] =
733     /* packetized data */
734 { 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
735   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
736   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
737   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
738   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
739   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
740 };
741
742 /* NAL = 4 bytes. When data does not fit into 1 mtu, 1 byte will be skipped */
743 static int rtp_h264_list_gt_mtu_bytes_sent_avc = 1 * (64 - 2 * 4 - 2 * 1);
744
745 GST_START_TEST (rtp_h264_list_gt_mtu_avc)
746 {
747   /* FIXME 0.11: fully specify h264 caps (and make payloader check) */
748   rtp_pipeline_test (rtp_h264_list_gt_mtu_frame_data_avc,
749       rtp_h264_list_gt_mtu_frame_data_size, rtp_h264_list_gt_mtu_frame_count,
750       "video/x-h264,stream-format=(string)avc,alignment=(string)au,"
751       "codec_data=(buffer)01640014ffe1001867640014acd94141fb0110000003001773594000f142996001000568ebecb22c",
752       "rtph264pay", "rtph264depay",
753       rtp_h264_list_gt_mtu_bytes_sent_avc, rtp_h264_list_gt_mtu_mty_size, TRUE);
754 }
755
756 GST_END_TEST;
757
758 static const guint8 rtp_h265_frame_data[] = {
759   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
760   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
761 };
762
763 static int rtp_h265_frame_data_size = 20;
764
765 static int rtp_h265_frame_count = 1;
766
767 GST_START_TEST (rtp_h265)
768 {
769   rtp_pipeline_test (rtp_h265_frame_data, rtp_h265_frame_data_size,
770       rtp_h265_frame_count,
771       "video/x-h265,stream-format=(string)byte-stream,alignment=(string)nal",
772       "rtph265pay", "rtph265depay", 0, 0, FALSE);
773
774   /* config-interval property used to be of uint type, was changed to int,
775    * make sure old GValue stuff still works */
776   {
777     GValue val = G_VALUE_INIT;
778     GstElement *rtph265pay;
779     GParamSpec *pspec;
780
781
782     rtph265pay = gst_element_factory_make ("rtph265pay", NULL);
783     pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (rtph265pay),
784         "config-interval");
785     fail_unless (pspec->value_type == G_TYPE_INT);
786     g_value_init (&val, G_TYPE_UINT);
787     g_value_set_uint (&val, 10);
788     g_object_set_property (G_OBJECT (rtph265pay), "config-interval", &val);
789     g_value_set_uint (&val, 0);
790     g_object_get_property (G_OBJECT (rtph265pay), "config-interval", &val);
791     fail_unless_equals_int (10, g_value_get_uint (&val));
792     g_object_set (G_OBJECT (rtph265pay), "config-interval", -1, NULL);
793     g_object_get_property (G_OBJECT (rtph265pay), "config-interval", &val);
794     fail_unless (g_value_get_uint (&val) == G_MAXUINT);
795     g_value_unset (&val);
796     gst_object_unref (rtph265pay);
797   }
798 }
799
800 GST_END_TEST;
801 static const guint8 rtp_h265_list_lt_mtu_frame_data[] = {
802   /* not packetized, next NALU starts with 0x00000001 */
803   0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
804   0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
805   0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806   0x00, 0x00, 0x00, 0x00, 0x00, 0x10
807 };
808
809 static int rtp_h265_list_lt_mtu_frame_data_size = 16;
810
811 static int rtp_h265_list_lt_mtu_frame_count = 2;
812
813 /* 3 bytes start code prefixed with one zero byte, NALU header is in payload */
814 static int rtp_h265_list_lt_mtu_bytes_sent = 2 * (16 - 3 - 1);
815
816 static int rtp_h265_list_lt_mtu_mtu_size = 1024;
817
818 GST_START_TEST (rtp_h265_list_lt_mtu)
819 {
820   rtp_pipeline_test (rtp_h265_list_lt_mtu_frame_data,
821       rtp_h265_list_lt_mtu_frame_data_size, rtp_h265_list_lt_mtu_frame_count,
822       "video/x-h265,stream-format=(string)byte-stream,alignment=(string)nal",
823       "rtph265pay", "rtph265depay", rtp_h265_list_lt_mtu_bytes_sent,
824       rtp_h265_list_lt_mtu_mtu_size, TRUE);
825 }
826
827 GST_END_TEST;
828 static const guint8 rtp_h265_list_lt_mtu_frame_data_hvc1[] = {
829   /* packetized data */
830   0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
831   0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832   0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
833   0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
834 };
835
836 /* length size is 3 bytes */
837 static int rtp_h265_list_lt_mtu_bytes_sent_hvc1 = 2 * (16 - 2 * 3);
838
839
840 GST_START_TEST (rtp_h265_list_lt_mtu_hvc1)
841 {
842   rtp_pipeline_test (rtp_h265_list_lt_mtu_frame_data_hvc1,
843       rtp_h265_list_lt_mtu_frame_data_size, rtp_h265_list_lt_mtu_frame_count,
844       "video/x-h265,stream-format=(string)hvc1,alignment=(string)au,"
845       "codec_data=(buffer)01640032ffe1002a67640032ac1b1a80a03dff016e02020280000"
846       "003008000000a74300018fff5de5c68600031ffebbcb85001000468ee3830",
847       "rtph265pay", "rtph265depay", rtp_h265_list_lt_mtu_bytes_sent_hvc1,
848       rtp_h265_list_lt_mtu_mtu_size, TRUE);
849 }
850
851 GST_END_TEST;
852 static const guint8 rtp_h265_list_gt_mtu_frame_data[] = {
853   /* not packetized, next NAL starts with 0x000001 */
854   0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
855   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
856   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
857   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
858   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
859   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
860   0x00, 0x10
861 };
862
863 static const int const rtp_h265_list_gt_mtu_frame_data_size = 62;
864
865 static const int rtp_h265_list_gt_mtu_frame_count = 1;
866
867 /* start code is 3 bytes, NALU header is 2 bytes */
868 static int rtp_h265_list_gt_mtu_bytes_sent = 1 * (62 - 3 - 2);
869
870 static int rtp_h265_list_gt_mtu_mtu_size = 28;
871
872 GST_START_TEST (rtp_h265_list_gt_mtu)
873 {
874   rtp_pipeline_test (rtp_h265_list_gt_mtu_frame_data,
875       rtp_h265_list_gt_mtu_frame_data_size, rtp_h265_list_gt_mtu_frame_count,
876       "video/x-h265,stream-format=(string)byte-stream,alignment=(string)nal",
877       "rtph265pay", "rtph265depay", rtp_h265_list_gt_mtu_bytes_sent,
878       rtp_h265_list_gt_mtu_mtu_size, TRUE);
879 }
880
881 GST_END_TEST;
882 static const guint8 rtp_h265_list_gt_mtu_frame_data_hvc1[] = {
883   /* packetized data */
884   0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
885   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
886   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
887   0x00, 0x00, 0x00, 0x00, 0x00,
888   0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
889   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
890   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
891 };
892
893 /* length size is 3 bytes, NALU header is 2 bytes */
894 static int rtp_h265_list_gt_mtu_bytes_sent_hvc1 = 1 * (62 - 2 * 3 - 2 * 2);
895
896 GST_START_TEST (rtp_h265_list_gt_mtu_hvc1)
897 {
898   rtp_pipeline_test (rtp_h265_list_gt_mtu_frame_data_hvc1,
899       rtp_h265_list_gt_mtu_frame_data_size, rtp_h265_list_gt_mtu_frame_count,
900       "video/x-h265,stream-format=(string)hvc1,alignment=(string)au,"
901       "codec_data=(buffer)01640032ffe1002a67640032ac1b1a80a03dff016e02020280000"
902       "003008000000a74300018fff5de5c68600031ffebbcb85001000468ee3830",
903       "rtph265pay", "rtph265depay", rtp_h265_list_gt_mtu_bytes_sent_hvc1,
904       rtp_h265_list_gt_mtu_mtu_size, TRUE);
905 }
906
907 GST_END_TEST;
908
909 /* KLV data from Day_Flight.mpg */
910 static const guint8 rtp_KLV_frame_data[] = {
911   0x06, 0x0e, 0x2b, 0x34, 0x02, 0x0b, 0x01, 0x01,
912   0x0e, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00,
913   0x81, 0x91, 0x02, 0x08, 0x00, 0x04, 0x6c, 0x8e,
914   0x20, 0x03, 0x83, 0x85, 0x41, 0x01, 0x01, 0x05,
915   0x02, 0x3d, 0x3b, 0x06, 0x02, 0x15, 0x80, 0x07,
916   0x02, 0x01, 0x52, 0x0b, 0x03, 0x45, 0x4f, 0x4e,
917   0x0c, 0x0e, 0x47, 0x65, 0x6f, 0x64, 0x65, 0x74,
918   0x69, 0x63, 0x20, 0x57, 0x47, 0x53, 0x38, 0x34,
919   0x0d, 0x04, 0x4d, 0xc4, 0xdc, 0xbb, 0x0e, 0x04,
920   0xb1, 0xa8, 0x6c, 0xfe, 0x0f, 0x02, 0x1f, 0x4a,
921   0x10, 0x02, 0x00, 0x85, 0x11, 0x02, 0x00, 0x4b,
922   0x12, 0x04, 0x20, 0xc8, 0xd2, 0x7d, 0x13, 0x04,
923   0xfc, 0xdd, 0x02, 0xd8, 0x14, 0x04, 0xfe, 0xb8,
924   0xcb, 0x61, 0x15, 0x04, 0x00, 0x8f, 0x3e, 0x61,
925   0x16, 0x04, 0x00, 0x00, 0x01, 0xc9, 0x17, 0x04,
926   0x4d, 0xdd, 0x8c, 0x2a, 0x18, 0x04, 0xb1, 0xbe,
927   0x9e, 0xf4, 0x19, 0x02, 0x0b, 0x85, 0x28, 0x04,
928   0x4d, 0xdd, 0x8c, 0x2a, 0x29, 0x04, 0xb1, 0xbe,
929   0x9e, 0xf4, 0x2a, 0x02, 0x0b, 0x85, 0x38, 0x01,
930   0x2e, 0x39, 0x04, 0x00, 0x8d, 0xd4, 0x29, 0x01,
931   0x02, 0x1c, 0x5f
932 };
933
934 GST_START_TEST (rtp_klv)
935 {
936   rtp_pipeline_test (rtp_KLV_frame_data, G_N_ELEMENTS (rtp_KLV_frame_data), 1,
937       "meta/x-klv, parsed=(bool)true", "rtpklvpay", "rtpklvdepay", 0, 0, FALSE);
938 }
939
940 GST_END_TEST;
941
942 GST_START_TEST (rtp_klv_fragmented)
943 {
944   /* force super-small mtu of 60 to fragment KLV unit */
945   rtp_pipeline_test (rtp_KLV_frame_data, sizeof (rtp_KLV_frame_data), 1,
946       "meta/x-klv, parsed=(bool)true", "rtpklvpay", "rtpklvdepay",
947       sizeof (rtp_KLV_frame_data), 60, FALSE);
948 }
949
950 GST_END_TEST;
951
952 static const guint8 rtp_L16_frame_data[] =
953     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
954   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
955 };
956
957 static int rtp_L16_frame_data_size = 20;
958
959 static int rtp_L16_frame_count = 1;
960
961 GST_START_TEST (rtp_L16)
962 {
963   rtp_pipeline_test (rtp_L16_frame_data, rtp_L16_frame_data_size,
964       rtp_L16_frame_count,
965       "audio/x-raw,format=S16BE,rate=1,channels=1,layout=(string)interleaved",
966       "rtpL16pay", "rtpL16depay", 0, 0, FALSE);
967 }
968
969 GST_END_TEST;
970
971 static const guint8 rtp_L24_frame_data[] =
972     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
973   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
974 };
975
976 static int rtp_L24_frame_data_size = 24;
977
978 static int rtp_L24_frame_count = 1;
979
980 GST_START_TEST (rtp_L24)
981 {
982   rtp_pipeline_test (rtp_L24_frame_data, rtp_L24_frame_data_size,
983       rtp_L24_frame_count,
984       "audio/x-raw,format=S24BE,rate=1,channels=1,layout=(string)interleaved",
985       "rtpL24pay", "rtpL24depay", 0, 0, FALSE);
986 }
987
988 GST_END_TEST;
989 static const guint8 rtp_mp2t_frame_data[] =
990     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
991   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
992 };
993
994 static int rtp_mp2t_frame_data_size = 20;
995
996 static int rtp_mp2t_frame_count = 1;
997
998 GST_START_TEST (rtp_mp2t)
999 {
1000   rtp_pipeline_test (rtp_mp2t_frame_data, rtp_mp2t_frame_data_size,
1001       rtp_mp2t_frame_count, "video/mpegts,packetsize=188,systemstream=true",
1002       "rtpmp2tpay", "rtpmp2tdepay", 0, 0, FALSE);
1003 }
1004
1005 GST_END_TEST;
1006 static const guint8 rtp_mp4v_frame_data[] =
1007     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1008   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1009 };
1010
1011 static int rtp_mp4v_frame_data_size = 20;
1012
1013 static int rtp_mp4v_frame_count = 1;
1014
1015 GST_START_TEST (rtp_mp4v)
1016 {
1017   rtp_pipeline_test (rtp_mp4v_frame_data, rtp_mp4v_frame_data_size,
1018       rtp_mp4v_frame_count, "video/mpeg,mpegversion=4,systemstream=false",
1019       "rtpmp4vpay", "rtpmp4vdepay", 0, 0, FALSE);
1020 }
1021
1022 GST_END_TEST;
1023 static const guint8 rtp_mp4v_list_frame_data[] =
1024     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1025   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1026 };
1027
1028 static int rtp_mp4v_list_frame_data_size = 20;
1029
1030 static int rtp_mp4v_list_frame_count = 1;
1031
1032 static int rtp_mp4v_list_bytes_sent = 1 * 20;
1033
1034 GST_START_TEST (rtp_mp4v_list)
1035 {
1036   rtp_pipeline_test (rtp_mp4v_list_frame_data, rtp_mp4v_list_frame_data_size,
1037       rtp_mp4v_list_frame_count,
1038       "video/mpeg,mpegversion=4,systemstream=false,codec_data=(buffer)000001b001",
1039       "rtpmp4vpay", "rtpmp4vdepay", rtp_mp4v_list_bytes_sent, 0, TRUE);
1040 }
1041
1042 GST_END_TEST;
1043 static const guint8 rtp_mp4g_frame_data[] =
1044     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1045   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1046 };
1047
1048 static int rtp_mp4g_frame_data_size = 20;
1049
1050 static int rtp_mp4g_frame_count = 1;
1051
1052 GST_START_TEST (rtp_mp4g)
1053 {
1054   rtp_pipeline_test (rtp_mp4g_frame_data, rtp_mp4g_frame_data_size,
1055       rtp_mp4g_frame_count,
1056       "video/mpeg,mpegversion=4,systemstream=false,codec_data=(buffer)000001b001",
1057       "rtpmp4gpay", "rtpmp4gdepay", 0, 0, FALSE);
1058 }
1059
1060 GST_END_TEST;
1061 static const guint8 rtp_theora_frame_data[] =
1062     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1063   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1064 };
1065
1066 static int rtp_theora_frame_data_size = 20;
1067
1068 static int rtp_theora_frame_count = 1;
1069
1070 GST_START_TEST (rtp_theora)
1071 {
1072   rtp_pipeline_test (rtp_theora_frame_data, rtp_theora_frame_data_size,
1073       rtp_theora_frame_count, "video/x-theora", "rtptheorapay",
1074       "rtptheoradepay", 0, 0, FALSE);
1075 }
1076
1077 GST_END_TEST;
1078 static const guint8 rtp_vorbis_frame_data[] =
1079     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1080   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1081 };
1082
1083 static int rtp_vorbis_frame_data_size = 20;
1084
1085 static int rtp_vorbis_frame_count = 1;
1086
1087 GST_START_TEST (rtp_vorbis)
1088 {
1089   rtp_pipeline_test (rtp_vorbis_frame_data, rtp_vorbis_frame_data_size,
1090       rtp_vorbis_frame_count, "audio/x-vorbis", "rtpvorbispay",
1091       "rtpvorbisdepay", 0, 0, FALSE);
1092 }
1093
1094 GST_END_TEST;
1095 static const guint8 rtp_jpeg_frame_data[] =
1096     { /* SOF */ 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x08, 0x00, 0x08,
1097   0x03, 0x00, 0x21, 0x08, 0x01, 0x11, 0x08, 0x02, 0x11, 0x08,
1098   /* DQT */ 0xFF, 0xDB, 0x00, 0x43, 0x08,
1099   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1101   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1102   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1103   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1104   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1105   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1106   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1107   /* DATA */ 0x00, 0x00, 0x00, 0x00, 0x00
1108 };
1109
1110 static int rtp_jpeg_frame_data_size = sizeof (rtp_jpeg_frame_data);
1111
1112 static int rtp_jpeg_frame_count = 1;
1113
1114 GST_START_TEST (rtp_jpeg)
1115 {
1116   rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
1117       rtp_jpeg_frame_count, "video/x-jpeg,height=640,width=480", "rtpjpegpay",
1118       "rtpjpegdepay", 0, 0, FALSE);
1119 }
1120
1121 GST_END_TEST;
1122
1123 GST_START_TEST (rtp_jpeg_width_greater_than_2040)
1124 {
1125   rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
1126       rtp_jpeg_frame_count, "video/x-jpeg,height=2048,width=480", "rtpjpegpay",
1127       "rtpjpegdepay", 0, 0, FALSE);
1128 }
1129
1130 GST_END_TEST;
1131
1132 GST_START_TEST (rtp_jpeg_height_greater_than_2040)
1133 {
1134   rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
1135       rtp_jpeg_frame_count, "video/x-jpeg,height=640,width=2048", "rtpjpegpay",
1136       "rtpjpegdepay", 0, 0, FALSE);
1137 }
1138
1139 GST_END_TEST;
1140
1141 GST_START_TEST (rtp_jpeg_width_and_height_greater_than_2040)
1142 {
1143   rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
1144       rtp_jpeg_frame_count, "video/x-jpeg,height=2048,width=2048", "rtpjpegpay",
1145       "rtpjpegdepay", 0, 0, FALSE);
1146 }
1147
1148 GST_END_TEST;
1149
1150 static const guint8 rtp_jpeg_list_frame_data[] =
1151     { /* SOF */ 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x08, 0x00, 0x08,
1152   0x03, 0x00, 0x21, 0x08, 0x01, 0x11, 0x08, 0x02, 0x11, 0x08,
1153   /* DQT */ 0xFF, 0xDB, 0x00, 0x43, 0x08,
1154   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1155   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1156   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1157   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1158   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1159   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1160   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1161   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1162   /* DATA */ 0x00, 0x00, 0x00, 0x00, 0x00
1163 };
1164
1165 static int rtp_jpeg_list_frame_data_size = sizeof (rtp_jpeg_list_frame_data);
1166
1167 static int rtp_jpeg_list_frame_count = 1;
1168
1169 static int rtp_jpeg_list_bytes_sent = 1 * sizeof (rtp_jpeg_list_frame_data);
1170
1171 GST_START_TEST (rtp_jpeg_list)
1172 {
1173   rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
1174       rtp_jpeg_list_frame_count, "video/x-jpeg,height=640,width=480",
1175       "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
1176 }
1177
1178 GST_END_TEST;
1179
1180 GST_START_TEST (rtp_jpeg_list_width_greater_than_2040)
1181 {
1182   rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
1183       rtp_jpeg_list_frame_count, "video/x-jpeg,height=2048,width=480",
1184       "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
1185 }
1186
1187 GST_END_TEST;
1188
1189 GST_START_TEST (rtp_jpeg_list_height_greater_than_2040)
1190 {
1191   rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
1192       rtp_jpeg_list_frame_count, "video/x-jpeg,height=640,width=2048",
1193       "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
1194 }
1195
1196 GST_END_TEST;
1197
1198 GST_START_TEST (rtp_jpeg_list_width_and_height_greater_than_2040)
1199 {
1200   rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
1201       rtp_jpeg_list_frame_count, "video/x-jpeg,height=2048,width=2048",
1202       "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
1203 }
1204
1205 GST_END_TEST;
1206
1207 static void
1208 rtp_jpeg_do_packet_loss (gdouble prob, gint num_expected)
1209 {
1210   GstHarness *h;
1211   gboolean eos = FALSE;
1212   gchar *s;
1213   guint i, buffer_count;
1214
1215   s = g_strdup_printf ("videotestsrc pattern=ball num-buffers=100 ! "
1216       "jpegenc quality=50 ! rtpjpegpay ! identity drop-probability=%g ! "
1217       "rtpjpegdepay", prob);
1218   GST_INFO ("running pipeline %s", s);
1219   h = gst_harness_new_parse (s);
1220   g_free (s);
1221
1222   gst_harness_play (h);
1223
1224   do {
1225     GstEvent *event;
1226
1227     event = gst_harness_pull_event (h);
1228     eos = (GST_EVENT_TYPE (event) == GST_EVENT_EOS);
1229     gst_event_unref (event);
1230   } while (!eos);
1231
1232   buffer_count = gst_harness_buffers_received (h);
1233   GST_INFO ("Got %u buffers", buffer_count);
1234
1235   if (num_expected >= 0) {
1236     fail_unless_equals_int (num_expected, buffer_count);
1237   }
1238
1239   for (i = 0; i < buffer_count; ++i) {
1240     GstBuffer *buf;
1241     GstMapInfo map;
1242     guint16 soi, eoi;
1243
1244     buf = gst_harness_pull (h);
1245     fail_unless (buf != NULL);
1246
1247     fail_unless (gst_buffer_map (buf, &map, GST_MAP_READ));
1248     GST_MEMDUMP ("jpeg frame", map.data, map.size);
1249     fail_unless (map.size > 4);
1250     soi = GST_READ_UINT16_BE (map.data);
1251     fail_unless (soi == 0xffd8, "expected JPEG frame start FFD8 not %02X", soi);
1252     eoi = GST_READ_UINT16_BE (map.data + map.size - 2);
1253     fail_unless (eoi == 0xffd9, "expected JPEG frame end FFD9 not %02X", eoi);
1254     gst_buffer_unmap (buf, &map);
1255     gst_buffer_unref (buf);
1256   }
1257
1258   gst_harness_teardown (h);
1259 }
1260
1261 GST_START_TEST (rtp_jpeg_packet_loss)
1262 {
1263   gdouble probabilities[] = { 0.0, 0.001, 0.01, 0.1, 0.2, 0.5, 1.0 };
1264   gint num_expected[] = { 100, -1, -1, -1, -1, -1, 0 };
1265
1266   GST_INFO ("Start iteration %d", __i__);
1267   fail_unless (__i__ < G_N_ELEMENTS (probabilities));
1268   rtp_jpeg_do_packet_loss (probabilities[__i__], num_expected[__i__]);
1269   GST_INFO ("Done with iteration %d", __i__);
1270 }
1271
1272 GST_END_TEST;
1273
1274 static const guint8 rtp_g729_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, 0x00, 0x00
1277 };
1278
1279 static int rtp_g729_frame_data_size = 22;
1280
1281 static int rtp_g729_frame_count = 1;
1282
1283 GST_START_TEST (rtp_g729)
1284 {
1285   rtp_pipeline_test (rtp_g729_frame_data, rtp_g729_frame_data_size,
1286       rtp_g729_frame_count, "audio/G729,rate=8000,channels=1", "rtpg729pay",
1287       "rtpg729depay", 0, 0, FALSE);
1288 }
1289
1290 GST_END_TEST;
1291
1292 static const guint8 rtp_gst_frame_data[] =
1293     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1294   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1295 };
1296
1297 static int rtp_gst_frame_data_size = 22;
1298
1299 static int rtp_gst_frame_count = 1;
1300
1301 GST_START_TEST (rtp_gst_custom_event)
1302 {
1303   /* Create RTP pipeline. */
1304   rtp_pipeline *p =
1305       rtp_pipeline_create (rtp_gst_frame_data, rtp_gst_frame_data_size,
1306       rtp_gst_frame_count, "application/x-test",
1307       "rtpgstpay", "rtpgstdepay");
1308
1309   if (p == NULL) {
1310     return;
1311   }
1312
1313   p->custom_event =
1314       gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
1315       gst_structure_new ("test", "foo", G_TYPE_INT, 1, NULL));
1316
1317   /* Run RTP pipeline. */
1318   rtp_pipeline_run (p);
1319
1320   /* Destroy RTP pipeline. */
1321   rtp_pipeline_destroy (p);
1322 }
1323
1324 GST_END_TEST;
1325
1326 /*
1327  * Creates the test suite.
1328  *
1329  * Returns: pointer to the test suite.
1330  */
1331 static Suite *
1332 rtp_payloading_suite (void)
1333 {
1334   GstRegistry *registry = gst_registry_get ();
1335   Suite *s = suite_create ("rtp_data_test");
1336
1337   TCase *tc_chain = tcase_create ("linear");
1338
1339   /* Set timeout to 60 seconds. */
1340   tcase_set_timeout (tc_chain, 60);
1341
1342   suite_add_tcase (s, tc_chain);
1343   tcase_add_test (tc_chain, rtp_ilbc);
1344   tcase_add_test (tc_chain, rtp_gsm);
1345   tcase_add_test (tc_chain, rtp_amr);
1346   tcase_add_test (tc_chain, rtp_pcma);
1347   tcase_add_test (tc_chain, rtp_pcmu);
1348   tcase_add_test (tc_chain, rtp_mpa);
1349   tcase_add_test (tc_chain, rtp_h261);
1350   tcase_add_test (tc_chain, rtp_h263);
1351   tcase_add_test (tc_chain, rtp_h263p);
1352   tcase_add_test (tc_chain, rtp_h264);
1353   tcase_add_test (tc_chain, rtp_h264_list_lt_mtu);
1354   tcase_add_test (tc_chain, rtp_h264_list_lt_mtu_avc);
1355   tcase_add_test (tc_chain, rtp_h264_list_gt_mtu);
1356   tcase_add_test (tc_chain, rtp_h264_list_gt_mtu_avc);
1357   tcase_add_test (tc_chain, rtp_h265);
1358   tcase_add_test (tc_chain, rtp_h265_list_lt_mtu);
1359   tcase_add_test (tc_chain, rtp_h265_list_lt_mtu_hvc1);
1360   tcase_add_test (tc_chain, rtp_h265_list_gt_mtu);
1361   tcase_add_test (tc_chain, rtp_h265_list_gt_mtu_hvc1);
1362   tcase_add_test (tc_chain, rtp_klv);
1363   tcase_add_test (tc_chain, rtp_klv_fragmented);
1364   tcase_add_test (tc_chain, rtp_L16);
1365   tcase_add_test (tc_chain, rtp_L24);
1366   tcase_add_test (tc_chain, rtp_mp2t);
1367   tcase_add_test (tc_chain, rtp_mp4v);
1368   tcase_add_test (tc_chain, rtp_mp4v_list);
1369   tcase_add_test (tc_chain, rtp_mp4g);
1370   tcase_add_test (tc_chain, rtp_theora);
1371   tcase_add_test (tc_chain, rtp_vorbis);
1372   tcase_add_test (tc_chain, rtp_jpeg);
1373   tcase_add_test (tc_chain, rtp_jpeg_width_greater_than_2040);
1374   tcase_add_test (tc_chain, rtp_jpeg_height_greater_than_2040);
1375   tcase_add_test (tc_chain, rtp_jpeg_width_and_height_greater_than_2040);
1376   tcase_add_test (tc_chain, rtp_jpeg_list);
1377   tcase_add_test (tc_chain, rtp_jpeg_list_width_greater_than_2040);
1378   tcase_add_test (tc_chain, rtp_jpeg_list_height_greater_than_2040);
1379   tcase_add_test (tc_chain, rtp_jpeg_list_width_and_height_greater_than_2040);
1380   if (gst_registry_check_feature_version (registry, "jpegenc", 1, 0, 0)
1381       && gst_registry_check_feature_version (registry, "videotestsrc", 1, 0, 0))
1382     tcase_add_loop_test (tc_chain, rtp_jpeg_packet_loss, 0, 7);
1383   tcase_add_test (tc_chain, rtp_g729);
1384   tcase_add_test (tc_chain, rtp_gst_custom_event);
1385   return s;
1386 }
1387
1388 GST_CHECK_MAIN (rtp_payloading)