rtpklvdepay: Recover after invalid fragmented KLV unit
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / tests / check / elements / rtp-payloading.c
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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 typedef struct
1166 {
1167   gint buffer_count;
1168   gint drop_index;
1169 } KlvDepayProbeData;
1170
1171 static GstPadProbeReturn
1172 rtp_klv_do_packet_loss_depay_probe_cb (GstPad * pad, GstPadProbeInfo * info,
1173     KlvDepayProbeData * data)
1174 {
1175   GstPadProbeReturn ret = GST_PAD_PROBE_OK;
1176
1177   if (info->type & GST_PAD_PROBE_TYPE_BUFFER_LIST) {
1178     GstBufferList *buffer_list = info->data;
1179     gint length = gst_buffer_list_length (buffer_list);
1180
1181     if (data->drop_index >= 0) {
1182       gint drop_offset = data->drop_index - data->buffer_count;
1183
1184       if (0 <= drop_offset && drop_offset < length)
1185         gst_buffer_list_remove (buffer_list, drop_offset, 1);
1186     }
1187
1188     data->buffer_count += length;
1189   } else {
1190     if (data->buffer_count == data->drop_index)
1191       ret = GST_PAD_PROBE_DROP;
1192     data->buffer_count++;
1193   }
1194
1195   return ret;
1196 }
1197
1198 GST_START_TEST (rtp_klv_fragmented_packet_loss)
1199 {
1200   /* Number of KLV frames to push through the pipeline */
1201   const guint FRAME_COUNT = 5;
1202
1203   /* Repeat frame data */
1204   int frame_data_size = sizeof (rtp_KLV_frame_data);
1205   guint8 *frame_data = malloc (FRAME_COUNT * sizeof (rtp_KLV_frame_data));
1206   for (guint i = 0; i < FRAME_COUNT; i++)
1207     memcpy (frame_data + i * frame_data_size, rtp_KLV_frame_data,
1208         frame_data_size);
1209
1210   /* Create RTP pipeline. */
1211   rtp_pipeline *p =
1212       rtp_pipeline_create (frame_data, frame_data_size, FRAME_COUNT,
1213       "meta/x-klv, parsed=(bool)true", "rtpklvpay", "rtpklvdepay");
1214
1215   if (p == NULL) {
1216     return;
1217   }
1218
1219   /* Force super-small mtu of 60 to fragment KLV unit (4 fragments per unit) */
1220   g_object_set (p->rtppay, "mtu", 60, NULL);
1221
1222   /* Drop the 7:th fragment on the depayloader's sink pad */
1223   KlvDepayProbeData sink_probe_data = {.buffer_count = 0,.drop_index = 7 };
1224   GstPad *depay_sink = gst_element_get_static_pad (p->rtpdepay, "sink");
1225   gst_pad_add_probe (depay_sink,
1226       GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BUFFER_LIST,
1227       (GstPadProbeCallback) rtp_klv_do_packet_loss_depay_probe_cb,
1228       &sink_probe_data, NULL);
1229   gst_object_unref (depay_sink);
1230
1231   /* Count buffers on the depayloader's source pad */
1232   KlvDepayProbeData src_probe_data = {.buffer_count = 0,.drop_index = -1 };
1233   GstPad *depay_src = gst_element_get_static_pad (p->rtpdepay, "src");
1234   gst_pad_add_probe (depay_src,
1235       GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BUFFER_LIST,
1236       (GstPadProbeCallback) rtp_klv_do_packet_loss_depay_probe_cb,
1237       &src_probe_data, NULL);
1238   gst_object_unref (depay_src);
1239
1240   /* Run RTP pipeline. */
1241   rtp_pipeline_run (p);
1242
1243   /* Destroy RTP pipeline. */
1244   rtp_pipeline_destroy (p);
1245
1246   free (frame_data);
1247
1248   /* We should be able to decode all RTP buffers except for the second one */
1249   g_assert_cmpuint (src_probe_data.buffer_count, ==, FRAME_COUNT - 1);
1250 }
1251
1252 GST_END_TEST;
1253
1254 static const guint8 rtp_L16_frame_data[] =
1255     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1256   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1257 };
1258
1259 static int rtp_L16_frame_data_size = 20;
1260
1261 static int rtp_L16_frame_count = 1;
1262
1263 GST_START_TEST (rtp_L16)
1264 {
1265   rtp_pipeline_test (rtp_L16_frame_data, rtp_L16_frame_data_size,
1266       rtp_L16_frame_count,
1267       "audio/x-raw,format=S16BE,rate=1,channels=1,layout=(string)interleaved",
1268       "rtpL16pay", "rtpL16depay", 0, 0, FALSE);
1269 }
1270
1271 GST_END_TEST;
1272
1273 static const guint8 rtp_L24_frame_data[] =
1274     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1275   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1276 };
1277
1278 static int rtp_L24_frame_data_size = 24;
1279
1280 static int rtp_L24_frame_count = 1;
1281
1282 GST_START_TEST (rtp_L24)
1283 {
1284   rtp_pipeline_test (rtp_L24_frame_data, rtp_L24_frame_data_size,
1285       rtp_L24_frame_count,
1286       "audio/x-raw,format=S24BE,rate=1,channels=1,layout=(string)interleaved",
1287       "rtpL24pay", "rtpL24depay", 0, 0, FALSE);
1288 }
1289
1290 GST_END_TEST;
1291 static const guint8 rtp_mp2t_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_mp2t_frame_data_size = 20;
1297
1298 static int rtp_mp2t_frame_count = 1;
1299
1300 GST_START_TEST (rtp_mp2t)
1301 {
1302   rtp_pipeline_test (rtp_mp2t_frame_data, rtp_mp2t_frame_data_size,
1303       rtp_mp2t_frame_count, "video/mpegts,packetsize=188,systemstream=true",
1304       "rtpmp2tpay", "rtpmp2tdepay", 0, 0, FALSE);
1305 }
1306
1307 GST_END_TEST;
1308 static const guint8 rtp_mp4v_frame_data[] =
1309     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1310   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1311 };
1312
1313 static int rtp_mp4v_frame_data_size = 20;
1314
1315 static int rtp_mp4v_frame_count = 1;
1316
1317 GST_START_TEST (rtp_mp4v)
1318 {
1319   rtp_pipeline_test (rtp_mp4v_frame_data, rtp_mp4v_frame_data_size,
1320       rtp_mp4v_frame_count, "video/mpeg,mpegversion=4,systemstream=false",
1321       "rtpmp4vpay", "rtpmp4vdepay", 0, 0, FALSE);
1322 }
1323
1324 GST_END_TEST;
1325 static const guint8 rtp_mp4v_list_frame_data[] =
1326     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1327   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1328 };
1329
1330 static int rtp_mp4v_list_frame_data_size = 20;
1331
1332 static int rtp_mp4v_list_frame_count = 1;
1333
1334 static int rtp_mp4v_list_bytes_sent = 1 * 20;
1335
1336 GST_START_TEST (rtp_mp4v_list)
1337 {
1338   rtp_pipeline_test (rtp_mp4v_list_frame_data, rtp_mp4v_list_frame_data_size,
1339       rtp_mp4v_list_frame_count,
1340       "video/mpeg,mpegversion=4,systemstream=false,codec_data=(buffer)000001b001",
1341       "rtpmp4vpay", "rtpmp4vdepay", rtp_mp4v_list_bytes_sent, 0, TRUE);
1342 }
1343
1344 GST_END_TEST;
1345 static const guint8 rtp_mp4g_frame_data[] =
1346     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1347   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1348 };
1349
1350 static int rtp_mp4g_frame_data_size = 20;
1351
1352 static int rtp_mp4g_frame_count = 1;
1353
1354 GST_START_TEST (rtp_mp4g)
1355 {
1356   rtp_pipeline_test (rtp_mp4g_frame_data, rtp_mp4g_frame_data_size,
1357       rtp_mp4g_frame_count,
1358       "video/mpeg,mpegversion=4,systemstream=false,codec_data=(buffer)000001b001",
1359       "rtpmp4gpay", "rtpmp4gdepay", 0, 0, FALSE);
1360 }
1361
1362 GST_END_TEST;
1363 static const guint8 rtp_theora_frame_data[] =
1364     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1365   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1366 };
1367
1368 static int rtp_theora_frame_data_size = 20;
1369
1370 static int rtp_theora_frame_count = 1;
1371
1372 GST_START_TEST (rtp_theora)
1373 {
1374   rtp_pipeline_test (rtp_theora_frame_data, rtp_theora_frame_data_size,
1375       rtp_theora_frame_count, "video/x-theora", "rtptheorapay",
1376       "rtptheoradepay", 0, 0, FALSE);
1377 }
1378
1379 GST_END_TEST;
1380 static const guint8 rtp_vorbis_frame_data[] =
1381     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1382   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1383 };
1384
1385 static int rtp_vorbis_frame_data_size = 20;
1386
1387 static int rtp_vorbis_frame_count = 1;
1388
1389 GST_START_TEST (rtp_vorbis)
1390 {
1391   rtp_pipeline_test (rtp_vorbis_frame_data, rtp_vorbis_frame_data_size,
1392       rtp_vorbis_frame_count, "audio/x-vorbis", "rtpvorbispay",
1393       "rtpvorbisdepay", 0, 0, FALSE);
1394 }
1395
1396 GST_END_TEST;
1397
1398 /* videotestsrc pattern=red  ! video/x-raw,width=160,height=120 ! vp8enc */
1399 #define VP8_CAPS "video/x-vp8, profile=(string)0, " \
1400     "streamheader=(buffer)4f5650383001010000a000780000010000010000001e00000001, " \
1401     "width=(int)160, height=(int)120, framerate=(fraction)30/1"
1402
1403 static const guint8 rtp_vp8_frame_data[] = {
1404   0x30, 0x07, 0x00, 0x9d, 0x01, 0x2a, 0xa0, 0x00,
1405   0x78, 0x00, 0x00, 0x47, 0x08, 0x85, 0x85, 0x88,
1406   0x85, 0x84, 0x88, 0x02, 0x02, 0x02, 0x75, 0xaa,
1407   0x03, 0xf8, 0x03, 0xfa, 0x02, 0x06, 0xc3, 0xef,
1408   0x05, 0x10, 0x9c, 0x52, 0xd2, 0xa1, 0x38, 0xa5,
1409   0xa5, 0x42, 0x71, 0x4b, 0x4a, 0x84, 0xe2, 0x96,
1410   0x95, 0x09, 0xc5, 0x2d, 0x2a, 0x13, 0x8a, 0x5a,
1411   0x54, 0x27, 0x14, 0xb4, 0xa8, 0x4e, 0x29, 0x69,
1412   0x50, 0x9b, 0x00, 0xfe, 0xfd, 0x6e, 0xf3, 0xff,
1413   0xe3, 0x99, 0x37, 0x30, 0xc4, 0xff, 0x8e, 0x6d,
1414   0xff, 0xf1, 0x61, 0x3c, 0x0e, 0x28, 0xc8, 0xff,
1415   0xf1, 0x51, 0x00
1416 };
1417
1418 GST_START_TEST (rtp_vp8)
1419 {
1420   rtp_pipeline_test (rtp_vp8_frame_data, sizeof (rtp_vp8_frame_data), 1,
1421       VP8_CAPS, "rtpvp8pay", "rtpvp8depay", 0, 0, FALSE);
1422 }
1423
1424 GST_END_TEST;
1425
1426 /* videotestsrc pattern=red  ! video/x-raw,width=160,height=120 ! vp9enc */
1427 #define VP9_CAPS "video/x-vp9, profile=(string)0, " \
1428     "width=(int)160, height=(int)120, framerate=(fraction)30/1"
1429
1430 static const guint8 rtp_vp9_frame_data[] = {
1431   0x82, 0x49, 0x83, 0x42, 0x00, 0x09, 0xf0, 0x07,
1432   0x76, 0x00, 0x38, 0x24, 0x1c, 0x18, 0x42, 0x00,
1433   0x00, 0x30, 0x60, 0x00, 0x00, 0x67, 0x3f, 0xff,
1434   0xfe, 0x69, 0x95, 0xff, 0xff, 0xff, 0xfe, 0x99,
1435   0x6b, 0xff, 0xff, 0xff, 0xff, 0x62, 0x98, 0x1d,
1436   0x45, 0x4c, 0x90, 0xc4, 0x70
1437 };
1438
1439 GST_START_TEST (rtp_vp9)
1440 {
1441   rtp_pipeline_test (rtp_vp9_frame_data, sizeof (rtp_vp9_frame_data), 1,
1442       VP9_CAPS, "rtpvp9pay", "rtpvp9depay", 0, 0, FALSE);
1443 }
1444
1445 GST_END_TEST;
1446
1447 static const guint8 rtp_jpeg_frame_data[] =
1448     { /* SOF */ 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x08, 0x00, 0x08,
1449   0x03, 0x00, 0x21, 0x08, 0x01, 0x11, 0x08, 0x02, 0x11, 0x08,
1450   /* DQT */ 0xFF, 0xDB, 0x00, 0x43, 0x08,
1451   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1452   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1453   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1454   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1455   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1456   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1457   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1458   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1459   /* DATA */ 0x00, 0x00, 0x00, 0x00, 0x00
1460 };
1461
1462 static int rtp_jpeg_frame_data_size = sizeof (rtp_jpeg_frame_data);
1463
1464 static int rtp_jpeg_frame_count = 1;
1465
1466 GST_START_TEST (rtp_jpeg)
1467 {
1468   rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
1469       rtp_jpeg_frame_count, "video/x-jpeg,height=640,width=480", "rtpjpegpay",
1470       "rtpjpegdepay", 0, 0, FALSE);
1471 }
1472
1473 GST_END_TEST;
1474
1475 GST_START_TEST (rtp_jpeg_width_greater_than_2040)
1476 {
1477   rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
1478       rtp_jpeg_frame_count, "video/x-jpeg,height=2048,width=480", "rtpjpegpay",
1479       "rtpjpegdepay", 0, 0, FALSE);
1480 }
1481
1482 GST_END_TEST;
1483
1484 GST_START_TEST (rtp_jpeg_height_greater_than_2040)
1485 {
1486   rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
1487       rtp_jpeg_frame_count, "video/x-jpeg,height=640,width=2048", "rtpjpegpay",
1488       "rtpjpegdepay", 0, 0, FALSE);
1489 }
1490
1491 GST_END_TEST;
1492
1493 GST_START_TEST (rtp_jpeg_width_and_height_greater_than_2040)
1494 {
1495   rtp_pipeline_test (rtp_jpeg_frame_data, rtp_jpeg_frame_data_size,
1496       rtp_jpeg_frame_count, "video/x-jpeg,height=2048,width=2048", "rtpjpegpay",
1497       "rtpjpegdepay", 0, 0, FALSE);
1498 }
1499
1500 GST_END_TEST;
1501
1502 static const guint8 rtp_jpeg_list_frame_data[] =
1503     { /* SOF */ 0xFF, 0xC0, 0x00, 0x11, 0x08, 0x00, 0x08, 0x00, 0x08,
1504   0x03, 0x00, 0x21, 0x08, 0x01, 0x11, 0x08, 0x02, 0x11, 0x08,
1505   /* DQT */ 0xFF, 0xDB, 0x00, 0x43, 0x08,
1506   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1507   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1508   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1509   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1510   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1511   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1512   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1513   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1514   /* DATA */ 0x00, 0x00, 0x00, 0x00, 0x00
1515 };
1516
1517 static int rtp_jpeg_list_frame_data_size = sizeof (rtp_jpeg_list_frame_data);
1518
1519 static int rtp_jpeg_list_frame_count = 1;
1520
1521 static int rtp_jpeg_list_bytes_sent = 1 * sizeof (rtp_jpeg_list_frame_data);
1522
1523 GST_START_TEST (rtp_jpeg_list)
1524 {
1525   rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
1526       rtp_jpeg_list_frame_count, "video/x-jpeg,height=640,width=480",
1527       "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
1528 }
1529
1530 GST_END_TEST;
1531
1532 GST_START_TEST (rtp_jpeg_list_width_greater_than_2040)
1533 {
1534   rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
1535       rtp_jpeg_list_frame_count, "video/x-jpeg,height=2048,width=480",
1536       "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
1537 }
1538
1539 GST_END_TEST;
1540
1541 GST_START_TEST (rtp_jpeg_list_height_greater_than_2040)
1542 {
1543   rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
1544       rtp_jpeg_list_frame_count, "video/x-jpeg,height=640,width=2048",
1545       "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
1546 }
1547
1548 GST_END_TEST;
1549
1550 GST_START_TEST (rtp_jpeg_list_width_and_height_greater_than_2040)
1551 {
1552   rtp_pipeline_test (rtp_jpeg_list_frame_data, rtp_jpeg_list_frame_data_size,
1553       rtp_jpeg_list_frame_count, "video/x-jpeg,height=2048,width=2048",
1554       "rtpjpegpay", "rtpjpegdepay", rtp_jpeg_list_bytes_sent, 0, TRUE);
1555 }
1556
1557 GST_END_TEST;
1558
1559 static void
1560 rtp_jpeg_do_packet_loss (gdouble prob, gint num_expected)
1561 {
1562   GstHarness *h;
1563   gboolean eos = FALSE;
1564   gchar *s;
1565   guint i, buffer_count;
1566
1567   s = g_strdup_printf ("videotestsrc pattern=ball num-buffers=100 ! "
1568       "jpegenc quality=50 ! rtpjpegpay ! identity drop-probability=%g ! "
1569       "rtpjpegdepay", prob);
1570   GST_INFO ("running pipeline %s", s);
1571   h = gst_harness_new_parse (s);
1572   g_free (s);
1573
1574   gst_harness_play (h);
1575
1576   do {
1577     GstEvent *event;
1578
1579     event = gst_harness_pull_event (h);
1580     eos = (GST_EVENT_TYPE (event) == GST_EVENT_EOS);
1581     gst_event_unref (event);
1582   } while (!eos);
1583
1584   buffer_count = gst_harness_buffers_received (h);
1585   GST_INFO ("Got %u buffers", buffer_count);
1586
1587   if (num_expected >= 0) {
1588     fail_unless_equals_int (num_expected, buffer_count);
1589   }
1590
1591   for (i = 0; i < buffer_count; ++i) {
1592     GstBuffer *buf;
1593     GstMapInfo map;
1594     guint16 soi, eoi;
1595
1596     buf = gst_harness_pull (h);
1597     fail_unless (buf != NULL);
1598
1599     fail_unless (gst_buffer_map (buf, &map, GST_MAP_READ));
1600     GST_MEMDUMP ("jpeg frame", map.data, map.size);
1601     fail_unless (map.size > 4);
1602     soi = GST_READ_UINT16_BE (map.data);
1603     fail_unless (soi == 0xffd8, "expected JPEG frame start FFD8 not %02X", soi);
1604     eoi = GST_READ_UINT16_BE (map.data + map.size - 2);
1605     fail_unless (eoi == 0xffd9, "expected JPEG frame end FFD9 not %02X", eoi);
1606     gst_buffer_unmap (buf, &map);
1607     gst_buffer_unref (buf);
1608   }
1609
1610   gst_harness_teardown (h);
1611 }
1612
1613 GST_START_TEST (rtp_jpeg_packet_loss)
1614 {
1615   gdouble probabilities[] = { 0.0, 0.001, 0.01, 0.1, 0.2, 0.5, 1.0 };
1616   gint num_expected[] = { 100, -1, -1, -1, -1, -1, 0 };
1617
1618   GST_INFO ("Start iteration %d", __i__);
1619   fail_unless (__i__ < G_N_ELEMENTS (probabilities));
1620   rtp_jpeg_do_packet_loss (probabilities[__i__], num_expected[__i__]);
1621   GST_INFO ("Done with iteration %d", __i__);
1622 }
1623
1624 GST_END_TEST;
1625
1626 static const guint8 rtp_g729_frame_data[] =
1627     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1628   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1629 };
1630
1631 static int rtp_g729_frame_data_size = 22;
1632
1633 static int rtp_g729_frame_count = 1;
1634
1635 GST_START_TEST (rtp_g729)
1636 {
1637   rtp_pipeline_test (rtp_g729_frame_data, rtp_g729_frame_data_size,
1638       rtp_g729_frame_count, "audio/G729,rate=8000,channels=1", "rtpg729pay",
1639       "rtpg729depay", 0, 0, FALSE);
1640 }
1641
1642 GST_END_TEST;
1643
1644 static const guint8 rtp_gst_frame_data[] =
1645     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1646   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1647 };
1648
1649 static int rtp_gst_frame_data_size = 22;
1650
1651 static int rtp_gst_frame_count = 1;
1652
1653 GST_START_TEST (rtp_gst_custom_event)
1654 {
1655   /* Create RTP pipeline. */
1656   rtp_pipeline *p =
1657       rtp_pipeline_create (rtp_gst_frame_data, rtp_gst_frame_data_size,
1658       rtp_gst_frame_count, "application/x-test",
1659       "rtpgstpay", "rtpgstdepay");
1660
1661   if (p == NULL) {
1662     return;
1663   }
1664
1665   p->custom_event =
1666       gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
1667       gst_structure_new ("test", "foo", G_TYPE_INT, 1, NULL));
1668
1669   /* Run RTP pipeline. */
1670   rtp_pipeline_run (p);
1671
1672   /* Destroy RTP pipeline. */
1673   rtp_pipeline_destroy (p);
1674 }
1675
1676 GST_END_TEST;
1677
1678 GST_START_TEST (rtp_vorbis_renegotiate)
1679 {
1680   GstElement *pipeline;
1681   GstElement *enc, *pay, *depay, *dec, *sink;
1682   GstPad *sinkpad, *srcpad;
1683   GstCaps *templcaps, *caps, *filter, *srccaps;
1684   GstSegment segment;
1685   GstBuffer *buffer;
1686   GstMapInfo map;
1687   GstAudioInfo info;
1688
1689   pipeline = gst_pipeline_new (NULL);
1690   enc = gst_element_factory_make ("vorbisenc", NULL);
1691   pay = gst_element_factory_make ("rtpvorbispay", NULL);
1692   depay = gst_element_factory_make ("rtpvorbisdepay", NULL);
1693   dec = gst_element_factory_make ("vorbisdec", NULL);
1694   sink = gst_element_factory_make ("fakesink", NULL);
1695   g_object_set (sink, "async", FALSE, NULL);
1696   gst_bin_add_many (GST_BIN (pipeline), enc, pay, depay, dec, sink, NULL);
1697   fail_unless (gst_element_link_many (enc, pay, depay, dec, sink, NULL));
1698   fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING),
1699       GST_STATE_CHANGE_SUCCESS);
1700
1701   sinkpad = gst_element_get_static_pad (enc, "sink");
1702   srcpad = gst_element_get_static_pad (dec, "src");
1703
1704   templcaps = gst_pad_get_pad_template_caps (sinkpad);
1705   filter =
1706       gst_caps_new_simple ("audio/x-raw", "channels", G_TYPE_INT, 2, "rate",
1707       G_TYPE_INT, 44100, NULL);
1708   caps = gst_caps_intersect (templcaps, filter);
1709   caps = gst_caps_fixate (caps);
1710
1711   gst_segment_init (&segment, GST_FORMAT_TIME);
1712   fail_unless (gst_pad_send_event (sinkpad,
1713           gst_event_new_stream_start ("test")));
1714   fail_unless (gst_pad_send_event (sinkpad, gst_event_new_caps (caps)));
1715   fail_unless (gst_pad_send_event (sinkpad, gst_event_new_segment (&segment)));
1716
1717   gst_audio_info_from_caps (&info, caps);
1718   buffer = gst_buffer_new_and_alloc (44100 * info.bpf);
1719   gst_buffer_map (buffer, &map, GST_MAP_WRITE);
1720   gst_audio_format_info_fill_silence (info.finfo, map.data, map.size);
1721   gst_buffer_unmap (buffer, &map);
1722   GST_BUFFER_PTS (buffer) = 0;
1723   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
1724
1725   fail_unless_equals_int (gst_pad_chain (sinkpad, buffer), GST_FLOW_OK);
1726
1727   srccaps = gst_pad_get_current_caps (srcpad);
1728   fail_unless (gst_caps_can_intersect (srccaps, caps));
1729   gst_caps_unref (srccaps);
1730
1731   gst_caps_unref (caps);
1732   gst_caps_unref (filter);
1733   filter =
1734       gst_caps_new_simple ("audio/x-raw", "channels", G_TYPE_INT, 2, "rate",
1735       G_TYPE_INT, 48000, NULL);
1736   caps = gst_caps_intersect (templcaps, filter);
1737   caps = gst_caps_fixate (caps);
1738
1739   fail_unless (gst_pad_send_event (sinkpad, gst_event_new_caps (caps)));
1740
1741   gst_audio_info_from_caps (&info, caps);
1742   buffer = gst_buffer_new_and_alloc (48000 * info.bpf);
1743   gst_buffer_map (buffer, &map, GST_MAP_WRITE);
1744   gst_audio_format_info_fill_silence (info.finfo, map.data, map.size);
1745   gst_buffer_unmap (buffer, &map);
1746   GST_BUFFER_PTS (buffer) = 0;
1747   GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND;
1748   GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
1749
1750   fail_unless_equals_int (gst_pad_chain (sinkpad, buffer), GST_FLOW_OK);
1751
1752   srccaps = gst_pad_get_current_caps (srcpad);
1753   fail_unless (gst_caps_can_intersect (srccaps, caps));
1754   gst_caps_unref (srccaps);
1755
1756   gst_caps_unref (caps);
1757   gst_caps_unref (filter);
1758   gst_caps_unref (templcaps);
1759   gst_object_unref (sinkpad);
1760   gst_object_unref (srcpad);
1761   gst_element_set_state (pipeline, GST_STATE_NULL);
1762   gst_object_unref (pipeline);
1763 }
1764
1765 GST_END_TEST;
1766
1767 static guint16
1768 pull_rtp_buffer (GstHarness * h, gboolean has_marker)
1769 {
1770   gint16 seq;
1771   GstBuffer *buf;
1772   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
1773
1774   buf = gst_harness_try_pull (h);
1775   fail_unless (buf);
1776
1777   fail_unless (gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp));
1778   seq = gst_rtp_buffer_get_seq (&rtp);
1779   gst_rtp_buffer_unmap (&rtp);
1780
1781   if (has_marker)
1782     fail_unless (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_MARKER));
1783   else
1784     fail_if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_MARKER));
1785
1786   gst_buffer_unref (buf);
1787   return seq;
1788 }
1789
1790 static void
1791 test_rtp_opus_dtx (gboolean dtx)
1792 {
1793   GstHarness *h;
1794   GstBuffer *buf;
1795   /* generated with a muted mic using:
1796    * gst-launch-1.0 pulsesrc ! opusenc dtx=true bitrate-type=vbr ! fakesink silent=false dump=true -v
1797    */
1798   static const guint8 opus_empty[] = { 0xf8 };
1799   static const guint8 opus_frame[] = { 0xf8, 0xff, 0xfe };
1800   guint16 seq, expected_seq;
1801
1802   h = gst_harness_new_parse ("rtpopuspay");
1803   fail_unless (h);
1804
1805   gst_harness_set (h, "rtpopuspay", "dtx", dtx, NULL);
1806
1807   gst_harness_set_caps_str (h,
1808       "audio/x-opus, rate=48000, channels=1, channel-mapping-family=0",
1809       "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");
1810
1811   /* push first opus frame */
1812   buf = gst_buffer_new_memdup (opus_frame, sizeof (opus_frame));
1813   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1814   seq = pull_rtp_buffer (h, TRUE);
1815   expected_seq = seq + 1;
1816
1817   /* push empty frame */
1818   buf = gst_buffer_new_memdup (opus_empty, sizeof (opus_empty));
1819   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1820   if (dtx) {
1821     /* buffer is not transmitted if dtx is enabled */
1822     buf = gst_harness_try_pull (h);
1823     fail_if (buf);
1824   } else {
1825     seq = pull_rtp_buffer (h, FALSE);
1826     fail_unless_equals_int (seq, expected_seq);
1827     expected_seq++;
1828   }
1829
1830   /* push second opus frame */
1831   buf = gst_buffer_new_memdup (opus_frame, sizeof (opus_frame));
1832   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
1833   seq = pull_rtp_buffer (h, dtx);
1834   fail_unless_equals_int (seq, expected_seq);
1835
1836   gst_harness_teardown (h);
1837 }
1838
1839 GST_START_TEST (rtp_opus_dtx_disabled)
1840 {
1841   test_rtp_opus_dtx (FALSE);
1842 }
1843
1844 GST_END_TEST;
1845
1846 GST_START_TEST (rtp_opus_dtx_enabled)
1847 {
1848   test_rtp_opus_dtx (TRUE);
1849 }
1850
1851 GST_END_TEST;
1852
1853 /*
1854  * Creates the test suite.
1855  *
1856  * Returns: pointer to the test suite.
1857  */
1858 static Suite *
1859 rtp_payloading_suite (void)
1860 {
1861   GstRegistry *registry = gst_registry_get ();
1862   Suite *s = suite_create ("rtp_data_test");
1863
1864   TCase *tc_chain = tcase_create ("linear");
1865
1866   /* Set timeout to 60 seconds. */
1867   tcase_set_timeout (tc_chain, 60);
1868
1869   suite_add_tcase (s, tc_chain);
1870   tcase_add_test (tc_chain, rtp_ilbc);
1871   tcase_add_test (tc_chain, rtp_gsm);
1872   tcase_add_test (tc_chain, rtp_amr);
1873   tcase_add_test (tc_chain, rtp_pcma);
1874   tcase_add_test (tc_chain, rtp_pcmu);
1875   tcase_add_test (tc_chain, rtp_mpa);
1876   tcase_add_test (tc_chain, rtp_h261);
1877   tcase_add_test (tc_chain, rtp_h263);
1878   tcase_add_test (tc_chain, rtp_h263p);
1879   tcase_add_test (tc_chain, rtp_h264);
1880   tcase_add_test (tc_chain, rtp_h264depay_avc);
1881   tcase_add_test (tc_chain, rtp_h264depay_bytestream);
1882   tcase_add_test (tc_chain, rtp_h264_list_lt_mtu);
1883   tcase_add_test (tc_chain, rtp_h264_list_lt_mtu_avc);
1884   tcase_add_test (tc_chain, rtp_h264_list_gt_mtu);
1885   tcase_add_test (tc_chain, rtp_h264_list_gt_mtu_avc);
1886   tcase_add_test (tc_chain, rtp_h265);
1887   tcase_add_test (tc_chain, rtp_h265_list_lt_mtu);
1888   tcase_add_test (tc_chain, rtp_h265_list_lt_mtu_hvc1);
1889   tcase_add_test (tc_chain, rtp_h265_list_gt_mtu);
1890   tcase_add_test (tc_chain, rtp_h265_list_gt_mtu_hvc1);
1891   tcase_add_test (tc_chain, rtp_klv);
1892   tcase_add_test (tc_chain, rtp_klv_fragmented);
1893   tcase_add_test (tc_chain, rtp_klv_fragmented_packet_loss);
1894   tcase_add_test (tc_chain, rtp_L16);
1895   tcase_add_test (tc_chain, rtp_L24);
1896   tcase_add_test (tc_chain, rtp_mp2t);
1897   tcase_add_test (tc_chain, rtp_mp4v);
1898   tcase_add_test (tc_chain, rtp_mp4v_list);
1899   tcase_add_test (tc_chain, rtp_mp4g);
1900   tcase_add_test (tc_chain, rtp_theora);
1901   tcase_add_test (tc_chain, rtp_vorbis);
1902   tcase_add_test (tc_chain, rtp_vp8);
1903   tcase_add_test (tc_chain, rtp_vp9);
1904   tcase_add_test (tc_chain, rtp_jpeg);
1905   tcase_add_test (tc_chain, rtp_jpeg_width_greater_than_2040);
1906   tcase_add_test (tc_chain, rtp_jpeg_height_greater_than_2040);
1907   tcase_add_test (tc_chain, rtp_jpeg_width_and_height_greater_than_2040);
1908   tcase_add_test (tc_chain, rtp_jpeg_list);
1909   tcase_add_test (tc_chain, rtp_jpeg_list_width_greater_than_2040);
1910   tcase_add_test (tc_chain, rtp_jpeg_list_height_greater_than_2040);
1911   tcase_add_test (tc_chain, rtp_jpeg_list_width_and_height_greater_than_2040);
1912   if (gst_registry_check_feature_version (registry, "jpegenc", 1, 0, 0)
1913       && gst_registry_check_feature_version (registry, "videotestsrc", 1, 0, 0))
1914     tcase_add_loop_test (tc_chain, rtp_jpeg_packet_loss, 0, 7);
1915   tcase_add_test (tc_chain, rtp_g729);
1916   tcase_add_test (tc_chain, rtp_gst_custom_event);
1917   tcase_add_test (tc_chain, rtp_vorbis_renegotiate);
1918   tcase_add_test (tc_chain, rtp_opus_dtx_disabled);
1919   tcase_add_test (tc_chain, rtp_opus_dtx_enabled);
1920   return s;
1921 }
1922
1923 GST_CHECK_MAIN (rtp_payloading)