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