1 /* GStreamer RTP H.264 unit test
3 * Copyright (C) 2017 Centricular Ltd
4 * @author: Tim-Philipp Müller <tim@centricular.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
22 #include <gst/check/check.h>
23 #include <gst/app/app.h>
24 #include <gst/rtp/gstrtpbuffer.h>
26 #define ALLOCATOR_CUSTOM_SYSMEM "CustomSysMem"
28 static GstAllocator *custom_sysmem_allocator; /* NULL */
40 custom_sysmem_new (GstMemoryFlags flags, gsize maxsize, gsize align,
41 gsize offset, gsize size)
43 gsize aoffset, padding;
46 /* ensure configured alignment */
47 align |= gst_memory_alignment;
48 /* allocate more to compensate for alignment */
51 mem = g_new0 (CustomSysmem, 1);
53 mem->allocdata = g_malloc (maxsize);
55 mem->data = mem->allocdata;
58 if ((aoffset = ((guintptr) mem->data & align))) {
59 aoffset = (align + 1) - aoffset;
64 if (offset && (flags & GST_MEMORY_FLAG_ZERO_PREFIXED))
65 memset (mem->data, 0, offset);
67 padding = maxsize - (offset + size);
68 if (padding && (flags & GST_MEMORY_FLAG_ZERO_PADDED))
69 memset (mem->data + offset + size, 0, padding);
71 gst_memory_init (GST_MEMORY_CAST (mem), flags, custom_sysmem_allocator,
72 NULL, maxsize, align, offset, size);
78 custom_sysmem_map (CustomSysmem * mem, gsize maxsize, GstMapFlags flags)
84 custom_sysmem_unmap (CustomSysmem * mem)
90 custom_sysmem_copy (CustomSysmem * mem, gssize offset, gsize size)
92 g_return_val_if_reached (NULL);
96 custom_sysmem_share (CustomSysmem * mem, gssize offset, gsize size)
98 g_return_val_if_reached (NULL);
102 custom_sysmem_is_span (CustomSysmem * mem1, CustomSysmem * mem2, gsize * offset)
104 g_return_val_if_reached (FALSE);
107 /* Custom allocator */
111 GstAllocator allocator;
112 } CustomSysmemAllocator;
116 GstAllocatorClass allocator_class;
117 } CustomSysmemAllocatorClass;
119 GType custom_sysmem_allocator_get_type (void);
120 G_DEFINE_TYPE (CustomSysmemAllocator, custom_sysmem_allocator,
124 custom_sysmem_allocator_alloc (GstAllocator * allocator, gsize size,
125 GstAllocationParams * params)
127 gsize maxsize = size + params->prefix + params->padding;
129 return (GstMemory *) custom_sysmem_new (params->flags,
130 maxsize, params->align, params->prefix, size);
134 custom_sysmem_allocator_free (GstAllocator * allocator, GstMemory * mem)
136 CustomSysmem *csmem = (CustomSysmem *) mem;
138 g_free (csmem->allocdata);
143 custom_sysmem_allocator_class_init (CustomSysmemAllocatorClass * klass)
145 GstAllocatorClass *allocator_class = (GstAllocatorClass *) klass;
147 allocator_class->alloc = custom_sysmem_allocator_alloc;
148 allocator_class->free = custom_sysmem_allocator_free;
152 custom_sysmem_allocator_init (CustomSysmemAllocator * allocator)
154 GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
156 alloc->mem_type = ALLOCATOR_CUSTOM_SYSMEM;
157 alloc->mem_map = (GstMemoryMapFunction) custom_sysmem_map;
158 alloc->mem_unmap = (GstMemoryUnmapFunction) custom_sysmem_unmap;
159 alloc->mem_copy = (GstMemoryCopyFunction) custom_sysmem_copy;
160 alloc->mem_share = (GstMemoryShareFunction) custom_sysmem_share;
161 alloc->mem_is_span = (GstMemoryIsSpanFunction) custom_sysmem_is_span;
164 /* AppSink subclass proposing our custom allocator to upstream */
173 GstAppSinkClass appsink;
176 GType c_mem_app_sink_get_type (void);
178 G_DEFINE_TYPE (CMemAppSink, c_mem_app_sink, GST_TYPE_APP_SINK);
181 c_mem_app_sink_init (CMemAppSink * cmemsink)
186 c_mem_app_sink_propose_allocation (GstBaseSink * sink, GstQuery * query)
188 gst_query_add_allocation_param (query, custom_sysmem_allocator, NULL);
193 c_mem_app_sink_class_init (CMemAppSinkClass * klass)
195 GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass;
197 basesink_class->propose_allocation = c_mem_app_sink_propose_allocation;
200 #define RTP_H264_FILE GST_TEST_FILES_PATH G_DIR_SEPARATOR_S "h264.rtp"
202 GST_START_TEST (test_rtph264depay_with_downstream_allocator)
204 GstElement *pipeline, *src, *depay, *sink;
210 custom_sysmem_allocator =
211 g_object_new (custom_sysmem_allocator_get_type (), NULL);
213 pipeline = gst_pipeline_new ("pipeline");
215 src = gst_element_factory_make ("appsrc", NULL);
217 caps = gst_caps_new_simple ("application/x-rtp",
218 "media", G_TYPE_STRING, "video",
219 "payload", G_TYPE_INT, 96,
220 "clock-rate", G_TYPE_INT, 90000,
221 "encoding-name", G_TYPE_STRING, "H264",
222 "ssrc", G_TYPE_UINT, 1990683810,
223 "timestamp-offset", G_TYPE_UINT, 3697583446UL,
224 "seqnum-offset", G_TYPE_UINT, 15568,
225 "a-framerate", G_TYPE_STRING, "30", NULL);
226 g_object_set (src, "format", GST_FORMAT_TIME, "caps", caps, NULL);
227 gst_bin_add (GST_BIN (pipeline), src);
228 gst_caps_unref (caps);
230 depay = gst_element_factory_make ("rtph264depay", NULL);
231 gst_bin_add (GST_BIN (pipeline), depay);
233 sink = g_object_new (c_mem_app_sink_get_type (), NULL);
234 gst_bin_add (GST_BIN (pipeline), sink);
236 gst_element_link_many (src, depay, sink, NULL);
238 gst_element_set_state (pipeline, GST_STATE_PAUSED);
244 fail_unless (g_file_get_contents (RTP_H264_FILE, &data, &len, NULL));
245 fail_unless (len > 2);
252 packet_len = GST_READ_UINT16_BE (pdata);
253 GST_INFO ("rtp packet length: %u (bytes left: %u)", packet_len,
255 fail_unless (len >= 2 + packet_len);
257 flow = gst_app_src_push_buffer (GST_APP_SRC (src),
258 gst_buffer_new_wrapped (g_memdup (pdata + 2, packet_len),
261 fail_unless_equals_int (flow, GST_FLOW_OK);
263 pdata += 2 + packet_len;
264 len -= 2 + packet_len;
270 gst_app_src_end_of_stream (GST_APP_SRC (src));
272 sample = gst_app_sink_pull_preroll (GST_APP_SINK (sink));
273 fail_unless (sample != NULL);
275 buf = gst_sample_get_buffer (sample);
277 GST_LOG ("buffer has %u memories", gst_buffer_n_memory (buf));
278 GST_LOG ("buffer size: %u", (guint) gst_buffer_get_size (buf));
280 fail_unless (gst_buffer_n_memory (buf) > 0);
281 mem = gst_buffer_peek_memory (buf, 0);
282 fail_unless (mem != NULL);
284 GST_LOG ("buffer memory type: %s", mem->allocator->mem_type);
285 fail_unless (gst_memory_is_type (mem, ALLOCATOR_CUSTOM_SYSMEM));
287 gst_sample_unref (sample);
289 gst_element_set_state (pipeline, GST_STATE_NULL);
291 gst_object_unref (pipeline);
293 g_object_unref (custom_sysmem_allocator);
294 custom_sysmem_allocator = NULL;
301 wrap_static_buffer_with_pts (guint8 * buf, gsize size, GstClockTime pts)
305 buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
306 buf, size, 0, size, NULL, NULL);
307 GST_BUFFER_PTS (buffer) = pts;
313 wrap_static_buffer (guint8 * buf, gsize size)
315 return wrap_static_buffer_with_pts (buf, size, GST_CLOCK_TIME_NONE);
318 /* This was generated using pipeline:
319 * gst-launch-1.0 videotestsrc num-buffers=1 pattern=green \
320 * ! video/x-raw,width=16,height=16 \
321 * ! openh264enc ! rtph264pay ! fakesink dump=1
323 /* RTP h264_idr + marker */
324 static guint8 rtp_h264_idr[] = {
325 0x80, 0xe0, 0x3e, 0xf0, 0xd9, 0xbe, 0x80, 0x28,
326 0xf4, 0x2d, 0xe1, 0x70, 0x65, 0xb8, 0x00, 0x04,
327 0x00, 0x00, 0x09, 0xff, 0xff, 0xf8, 0x22, 0x8a,
328 0x00, 0x1f, 0x1c, 0x00, 0x04, 0x1c, 0xe3, 0x80,
332 GST_START_TEST (test_rtph264depay_eos)
334 GstHarness *h = gst_harness_new ("rtph264depay");
336 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
339 gst_harness_set_caps_str (h,
340 "application/x-rtp,media=video,clock-rate=90000,encoding-name=H264",
341 "video/x-h264,alignment=au,stream-format=byte-stream");
343 buffer = wrap_static_buffer (rtp_h264_idr, sizeof (rtp_h264_idr));
344 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_WRITE, &rtp));
345 gst_rtp_buffer_set_marker (&rtp, FALSE);
346 gst_rtp_buffer_unmap (&rtp);
348 ret = gst_harness_push (h, buffer);
349 fail_unless_equals_int (ret, GST_FLOW_OK);
350 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
352 fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
353 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
355 gst_harness_teardown (h);
361 GST_START_TEST (test_rtph264depay_marker_to_flag)
363 GstHarness *h = gst_harness_new ("rtph264depay");
365 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
369 gst_harness_set_caps_str (h,
370 "application/x-rtp,media=video,clock-rate=90000,encoding-name=H264",
371 "video/x-h264,alignment=au,stream-format=byte-stream");
373 buffer = wrap_static_buffer (rtp_h264_idr, sizeof (rtp_h264_idr));
374 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
375 fail_unless (gst_rtp_buffer_get_marker (&rtp));
376 seq = gst_rtp_buffer_get_seq (&rtp);
377 gst_rtp_buffer_unmap (&rtp);
379 ret = gst_harness_push (h, buffer);
380 fail_unless_equals_int (ret, GST_FLOW_OK);
381 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
383 buffer = wrap_static_buffer (rtp_h264_idr, sizeof (rtp_h264_idr));
384 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_WRITE, &rtp));
385 gst_rtp_buffer_set_marker (&rtp, FALSE);
386 gst_rtp_buffer_set_seq (&rtp, ++seq);
387 gst_rtp_buffer_unmap (&rtp);
389 ret = gst_harness_push (h, buffer);
390 fail_unless_equals_int (ret, GST_FLOW_OK);
392 /* the second NAL is blocked as there is no marker to let the payloader
393 * know it's a complete AU, we'll use an EOS to unblock it */
394 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
395 fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
396 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
398 buffer = gst_harness_pull (h);
399 fail_unless (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_MARKER));
400 gst_buffer_unref (buffer);
402 buffer = gst_harness_pull (h);
403 fail_if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_MARKER));
404 gst_buffer_unref (buffer);
406 gst_harness_teardown (h);
412 /* As GStreamer does not have STAP-A yet, this was extracted from
413 * issue #557 provided sample */
414 static guint8 rtp_stapa_pps_sps[] = {
415 0x80, 0x60, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
416 0xd8, 0xd9, 0x06, 0x7f, 0x38, 0x00, 0x1c, 0x27,
417 0x64, 0x00, 0x29, 0xac, 0x13, 0x16, 0x50, 0x28,
418 0x0f, 0x6c, 0x00, 0x30, 0x30, 0x00, 0x5d, 0xc0,
419 0x00, 0x17, 0x70, 0x5e, 0xf7, 0xc1, 0xda, 0x08,
420 0x84, 0x65, 0x80, 0x00, 0x04, 0x28, 0xef, 0x1f,
424 static guint8 rtp_stapa_slices_marker[] = {
425 0x80, 0xe0, 0x00, 0x0c, 0x00, 0x00, 0x57, 0xe4,
426 0xd8, 0xd9, 0x06, 0x7f, 0x38, 0x00, 0x28, 0x21,
427 0xe0, 0x02, 0x00, 0x10, 0x73, 0x84, 0x12, 0xff,
428 0x00, 0x1f, 0x0c, 0xbf, 0x0c, 0xb7, 0xb8, 0x73,
429 0xd3, 0xf2, 0xfc, 0xba, 0x7b, 0xce, 0x3c, 0xaf,
430 0x90, 0x11, 0xb3, 0x15, 0xa2, 0x53, 0x96, 0xc1,
431 0xa8, 0x27, 0x01, 0xdb, 0xde, 0xc8, 0x80, 0x00,
432 0x35, 0x21, 0x00, 0xa0, 0xe0, 0x02, 0x00, 0x10,
433 0x73, 0x84, 0x12, 0xff, 0x79, 0x9d, 0x3b, 0x38,
434 0xc6, 0x26, 0x47, 0x01, 0x02, 0x6b, 0xd6, 0x40,
435 0x17, 0x06, 0x0b, 0x8c, 0x22, 0xd0, 0x04, 0xe4,
436 0xea, 0x5e, 0x3f, 0xb8, 0x6a, 0x03, 0x4e, 0x15,
437 0x1f, 0x74, 0x62, 0x51, 0x78, 0xef, 0x5a, 0xd1,
438 0xf0, 0x3e, 0xb8, 0x56, 0xbb, 0x08, 0x00, 0x2e,
439 0x21, 0x00, 0x50, 0x38, 0x00, 0x80, 0x04, 0x1c,
440 0xe1, 0x04, 0xbf, 0x00, 0xa8, 0x40, 0x67, 0x09,
441 0xa8, 0x4d, 0x95, 0x5b, 0x0e, 0x2b, 0xba, 0x34,
442 0xc7, 0xa6, 0x78, 0x27, 0xe4, 0x5c, 0x74, 0xa0,
443 0xa2, 0xce, 0x30, 0x51, 0x78, 0x30, 0x56, 0xd0,
444 0x7a, 0xcd, 0x12, 0xbc, 0xba, 0xe0, 0x00, 0x1e,
445 0x21, 0x00, 0x78, 0x38, 0x00, 0x80, 0x04, 0x1c,
446 0xe1, 0x04, 0xbf, 0x67, 0x37, 0xc0, 0x86, 0x26,
447 0x7d, 0x4c, 0x52, 0x4b, 0x80, 0x9a, 0x3c, 0xa3,
448 0x02, 0xcd, 0x8d, 0xcd, 0x18, 0xd8
451 GST_START_TEST (test_rtph264depay_stap_a_marker)
453 GstHarness *h = gst_harness_new ("rtph264depay");
455 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
458 gst_harness_set_caps_str (h,
459 "application/x-rtp,media=video,clock-rate=90000,encoding-name=H264",
460 "video/x-h264,alignment=au,stream-format=byte-stream");
462 ret = gst_harness_push (h,
463 wrap_static_buffer (rtp_stapa_pps_sps, sizeof (rtp_stapa_pps_sps)));
464 fail_unless_equals_int (ret, GST_FLOW_OK);
465 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
467 buffer = wrap_static_buffer (rtp_stapa_slices_marker,
468 sizeof (rtp_stapa_slices_marker));
469 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_WRITE, &rtp));
470 gst_rtp_buffer_set_seq (&rtp, 2);
471 gst_rtp_buffer_unmap (&rtp);
472 ret = gst_harness_push (h, buffer);
473 fail_unless_equals_int (ret, GST_FLOW_OK);
475 /* Only one AU should have been pushed */
476 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
478 gst_harness_teardown (h);
485 static guint8 h264_aud[] = {
486 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0
489 /* These were generated using pipeline:
490 * gst-launch-1.0 videotestsrc num-buffers=1 pattern=green \
491 * ! video/x-raw,width=128,height=128 \
492 * ! openh264enc num-slices=2 \
497 static guint8 h264_sps[] = {
498 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x29,
499 0x8c, 0x8d, 0x41, 0x02, 0x24, 0x03, 0xc2, 0x21,
504 static guint8 h264_pps[] = {
505 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x3c, 0x80
509 static guint8 h264_idr_slice_1[] = {
510 0x00, 0x00, 0x00, 0x01, 0x65, 0xb8, 0x00, 0x04,
511 0x00, 0x00, 0x11, 0xff, 0xff, 0xf8, 0x22, 0x8a,
512 0x1f, 0x1c, 0x00, 0x04, 0x0a, 0x63, 0x80, 0x00,
513 0x81, 0xec, 0x9a, 0x93, 0x93, 0x93, 0x93, 0x93,
514 0x93, 0xad, 0x57, 0x5d, 0x75, 0xd7, 0x5d, 0x75,
515 0xd7, 0x5d, 0x75, 0xd7, 0x5d, 0x75, 0xd7, 0x5d,
516 0x75, 0xd7, 0x5d, 0x78
520 static guint8 h264_idr_slice_2[] = {
521 0x00, 0x00, 0x00, 0x01, 0x65, 0x04, 0x2e, 0x00,
522 0x01, 0x00, 0x00, 0x04, 0x7f, 0xff, 0xfe, 0x08,
523 0xa2, 0x87, 0xc7, 0x00, 0x01, 0x02, 0x98, 0xe0,
524 0x00, 0x20, 0x7b, 0x26, 0xa4, 0xe4, 0xe4, 0xe4,
525 0xe4, 0xe4, 0xeb, 0x55, 0xd7, 0x5d, 0x75, 0xd7,
526 0x5d, 0x75, 0xd7, 0x5d, 0x75, 0xd7, 0x5d, 0x75,
527 0xd7, 0x5d, 0x75, 0xd7, 0x5e
530 /* The RFC makes special use of NAL type 24 to 27, this test makes sure that
531 * such a NAL from the outside gets ignored properly. */
532 GST_START_TEST (test_rtph264pay_reserved_nals)
534 GstHarness *h = gst_harness_new ("rtph264pay");
535 /* we simply hack an AUD with the reserved nal types */
536 guint8 nal_24[sizeof (h264_aud)];
537 guint8 nal_25[sizeof (h264_aud)];
538 guint8 nal_26[sizeof (h264_aud)];
539 guint8 nal_27[sizeof (h264_aud)];
542 gst_harness_set_src_caps_str (h,
543 "video/x-h264,alignment=nal,stream-format=byte-stream");
545 ret = gst_harness_push (h, wrap_static_buffer (h264_sps, sizeof (h264_sps)));
546 fail_unless_equals_int (ret, GST_FLOW_OK);
548 ret = gst_harness_push (h, wrap_static_buffer (h264_pps, sizeof (h264_pps)));
549 fail_unless_equals_int (ret, GST_FLOW_OK);
551 memcpy (nal_24, h264_aud, sizeof (h264_aud));
553 ret = gst_harness_push (h, wrap_static_buffer (nal_24, sizeof (nal_24)));
554 fail_unless_equals_int (ret, GST_FLOW_OK);
556 memcpy (nal_25, h264_aud, sizeof (h264_aud));
558 ret = gst_harness_push (h, wrap_static_buffer (nal_25, sizeof (nal_25)));
559 fail_unless_equals_int (ret, GST_FLOW_OK);
562 memcpy (nal_26, h264_aud, sizeof (h264_aud));
564 ret = gst_harness_push (h, wrap_static_buffer (nal_26, sizeof (nal_26)));
565 fail_unless_equals_int (ret, GST_FLOW_OK);
568 memcpy (nal_27, h264_aud, sizeof (h264_aud));
570 ret = gst_harness_push (h, wrap_static_buffer (nal_27, sizeof (nal_27)));
571 fail_unless_equals_int (ret, GST_FLOW_OK);
573 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
574 gst_harness_teardown (h);
580 GST_START_TEST (test_rtph264pay_two_slices_timestamp)
582 GstHarness *h = gst_harness_new_parse ("rtph264pay timestamp-offset=123");
585 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
587 gst_harness_set_src_caps_str (h,
588 "video/x-h264,alignment=nal,stream-format=byte-stream");
590 ret = gst_harness_push (h, wrap_static_buffer_with_pts (h264_idr_slice_1,
591 sizeof (h264_idr_slice_1), 0));
592 fail_unless_equals_int (ret, GST_FLOW_OK);
594 ret = gst_harness_push (h, wrap_static_buffer_with_pts (h264_idr_slice_2,
595 sizeof (h264_idr_slice_2), 0));
596 fail_unless_equals_int (ret, GST_FLOW_OK);
598 ret = gst_harness_push (h, wrap_static_buffer_with_pts (h264_idr_slice_1,
599 sizeof (h264_idr_slice_1), GST_SECOND));
600 fail_unless_equals_int (ret, GST_FLOW_OK);
602 ret = gst_harness_push (h, wrap_static_buffer_with_pts (h264_idr_slice_2,
603 sizeof (h264_idr_slice_2), GST_SECOND));
604 fail_unless_equals_int (ret, GST_FLOW_OK);
607 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4);
609 buffer = gst_harness_pull (h);
610 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
611 fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), 0);
612 fail_unless_equals_uint64 (gst_rtp_buffer_get_timestamp (&rtp), 123);
613 gst_rtp_buffer_unmap (&rtp);
614 gst_buffer_unref (buffer);
616 buffer = gst_harness_pull (h);
617 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
618 fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), 0);
619 fail_unless_equals_uint64 (gst_rtp_buffer_get_timestamp (&rtp), 123);
620 gst_rtp_buffer_unmap (&rtp);
621 gst_buffer_unref (buffer);
623 buffer = gst_harness_pull (h);
624 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
625 fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), GST_SECOND);
626 fail_unless_equals_uint64 (gst_rtp_buffer_get_timestamp (&rtp), 123 + 90000);
627 gst_rtp_buffer_unmap (&rtp);
628 gst_buffer_unref (buffer);
630 buffer = gst_harness_pull (h);
631 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
632 fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), GST_SECOND);
633 fail_unless_equals_uint64 (gst_rtp_buffer_get_timestamp (&rtp), 123 + 90000);
634 gst_rtp_buffer_unmap (&rtp);
635 gst_buffer_unref (buffer);
637 gst_harness_teardown (h);
642 GST_START_TEST (test_rtph264pay_marker_for_flag)
644 GstHarness *h = gst_harness_new_parse ("rtph264pay timestamp-offset=123");
647 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
649 gst_harness_set_src_caps_str (h,
650 "video/x-h264,alignment=nal,stream-format=byte-stream");
652 ret = gst_harness_push (h, wrap_static_buffer (h264_idr_slice_1,
653 sizeof (h264_idr_slice_1)));
654 fail_unless_equals_int (ret, GST_FLOW_OK);
656 buffer = wrap_static_buffer (h264_idr_slice_2, sizeof (h264_idr_slice_2));
657 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_MARKER);
658 ret = gst_harness_push (h, buffer);
659 fail_unless_equals_int (ret, GST_FLOW_OK);
661 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
663 buffer = gst_harness_pull (h);
664 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
665 fail_if (gst_rtp_buffer_get_marker (&rtp));
666 gst_rtp_buffer_unmap (&rtp);
667 gst_buffer_unref (buffer);
669 buffer = gst_harness_pull (h);
670 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
671 fail_unless (gst_rtp_buffer_get_marker (&rtp));
672 gst_rtp_buffer_unmap (&rtp);
673 gst_buffer_unref (buffer);
675 gst_harness_teardown (h);
681 GST_START_TEST (test_rtph264pay_marker_for_au)
683 GstHarness *h = gst_harness_new_parse ("rtph264pay timestamp-offset=123");
685 GstBuffer *slice1, *slice2, *buffer;
686 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
688 gst_harness_set_src_caps_str (h,
689 "video/x-h264,alignment=au,stream-format=byte-stream");
691 slice1 = wrap_static_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1));
692 slice2 = wrap_static_buffer (h264_idr_slice_2, sizeof (h264_idr_slice_2));
693 buffer = gst_buffer_append (slice1, slice2);
695 ret = gst_harness_push (h, buffer);
696 fail_unless_equals_int (ret, GST_FLOW_OK);
698 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
700 buffer = gst_harness_pull (h);
701 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
702 fail_if (gst_rtp_buffer_get_marker (&rtp));
703 gst_rtp_buffer_unmap (&rtp);
704 gst_buffer_unref (buffer);
706 buffer = gst_harness_pull (h);
707 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
708 fail_unless (gst_rtp_buffer_get_marker (&rtp));
709 gst_rtp_buffer_unmap (&rtp);
710 gst_buffer_unref (buffer);
712 gst_harness_teardown (h);
718 GST_START_TEST (test_rtph264pay_marker_for_fragmented_au)
721 gst_harness_new_parse ("rtph264pay timestamp-offset=123 mtu=40");
723 GstBuffer *slice1, *slice2, *buffer;
724 GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
727 gst_harness_set_src_caps_str (h,
728 "video/x-h264,alignment=au,stream-format=byte-stream");
730 slice1 = wrap_static_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1));
731 slice2 = wrap_static_buffer (h264_idr_slice_2, sizeof (h264_idr_slice_2));
732 buffer = gst_buffer_append (slice1, slice2);
734 ret = gst_harness_push (h, buffer);
735 fail_unless_equals_int (ret, GST_FLOW_OK);
737 fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4);
739 for (i = 0; i < 3; i++) {
740 buffer = gst_harness_pull (h);
741 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
742 fail_if (gst_rtp_buffer_get_marker (&rtp));
743 gst_rtp_buffer_unmap (&rtp);
744 gst_buffer_unref (buffer);
747 buffer = gst_harness_pull (h);
748 fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
749 fail_unless (gst_rtp_buffer_get_marker (&rtp));
750 gst_rtp_buffer_unmap (&rtp);
751 gst_buffer_unref (buffer);
753 gst_harness_teardown (h);
762 Suite *s = suite_create ("rtph264");
765 tc_chain = tcase_create ("rtph264depay");
766 suite_add_tcase (s, tc_chain);
767 tcase_add_test (tc_chain, test_rtph264depay_with_downstream_allocator);
768 tcase_add_test (tc_chain, test_rtph264depay_eos);
769 tcase_add_test (tc_chain, test_rtph264depay_marker_to_flag);
770 tcase_add_test (tc_chain, test_rtph264depay_stap_a_marker);
772 tc_chain = tcase_create ("rtph264pay");
773 suite_add_tcase (s, tc_chain);
774 tcase_add_test (tc_chain, test_rtph264pay_reserved_nals);
775 tcase_add_test (tc_chain, test_rtph264pay_two_slices_timestamp);
776 tcase_add_test (tc_chain, test_rtph264pay_marker_for_flag);
777 tcase_add_test (tc_chain, test_rtph264pay_marker_for_au);
778 tcase_add_test (tc_chain, test_rtph264pay_marker_for_fragmented_au);
783 GST_CHECK_MAIN (rtph264);