1 /* GStreamer RTP H.265 unit test
2  *
3  * Copyright (C) 2017 Centricular Ltd
4  *   @author: Tim-Philipp Müller <tim@centricular.com>
5  * Copyright (C) 2018 Collabora Ltd
6  *   @author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #include <gst/check/check.h>
25 #include <gst/app/app.h>
26 #include <gst/rtp/gstrtpbuffer.h>
27 
28 #define ALLOCATOR_CUSTOM_SYSMEM "CustomSysMem"
29 
30 static GstAllocator *custom_sysmem_allocator;   /* NULL */
31 
32 /* Custom memory */
33 
34 typedef struct
35 {
36   GstMemory mem;
37   guint8 *data;
38   guint8 *allocdata;
39 } CustomSysmem;
40 
41 static CustomSysmem *
custom_sysmem_new(GstMemoryFlags flags,gsize maxsize,gsize align,gsize offset,gsize size)42 custom_sysmem_new (GstMemoryFlags flags, gsize maxsize, gsize align,
43     gsize offset, gsize size)
44 {
45   gsize aoffset, padding;
46   CustomSysmem *mem;
47 
48   /* ensure configured alignment */
49   align |= gst_memory_alignment;
50   /* allocate more to compensate for alignment */
51   maxsize += align;
52 
53   mem = g_new0 (CustomSysmem, 1);
54 
55   mem->allocdata = g_malloc (maxsize);
56 
57   mem->data = mem->allocdata;
58 
59   /* do alignment */
60   if ((aoffset = ((guintptr) mem->data & align))) {
61     aoffset = (align + 1) - aoffset;
62     mem->data += aoffset;
63     maxsize -= aoffset;
64   }
65 
66   if (offset && (flags & GST_MEMORY_FLAG_ZERO_PREFIXED))
67     memset (mem->data, 0, offset);
68 
69   padding = maxsize - (offset + size);
70   if (padding && (flags & GST_MEMORY_FLAG_ZERO_PADDED))
71     memset (mem->data + offset + size, 0, padding);
72 
73   gst_memory_init (GST_MEMORY_CAST (mem), flags, custom_sysmem_allocator,
74       NULL, maxsize, align, offset, size);
75 
76   return mem;
77 }
78 
79 static gpointer
custom_sysmem_map(CustomSysmem * mem,gsize maxsize,GstMapFlags flags)80 custom_sysmem_map (CustomSysmem * mem, gsize maxsize, GstMapFlags flags)
81 {
82   return mem->data;
83 }
84 
85 static gboolean
custom_sysmem_unmap(CustomSysmem * mem)86 custom_sysmem_unmap (CustomSysmem * mem)
87 {
88   return TRUE;
89 }
90 
91 static CustomSysmem *
custom_sysmem_copy(CustomSysmem * mem,gssize offset,gsize size)92 custom_sysmem_copy (CustomSysmem * mem, gssize offset, gsize size)
93 {
94   g_return_val_if_reached (NULL);
95 }
96 
97 static CustomSysmem *
custom_sysmem_share(CustomSysmem * mem,gssize offset,gsize size)98 custom_sysmem_share (CustomSysmem * mem, gssize offset, gsize size)
99 {
100   g_return_val_if_reached (NULL);
101 }
102 
103 static gboolean
custom_sysmem_is_span(CustomSysmem * mem1,CustomSysmem * mem2,gsize * offset)104 custom_sysmem_is_span (CustomSysmem * mem1, CustomSysmem * mem2, gsize * offset)
105 {
106   g_return_val_if_reached (FALSE);
107 }
108 
109 /* Custom allocator */
110 
111 typedef struct
112 {
113   GstAllocator allocator;
114 } CustomSysmemAllocator;
115 
116 typedef struct
117 {
118   GstAllocatorClass allocator_class;
119 } CustomSysmemAllocatorClass;
120 
121 GType custom_sysmem_allocator_get_type (void);
122 G_DEFINE_TYPE (CustomSysmemAllocator, custom_sysmem_allocator,
123     GST_TYPE_ALLOCATOR);
124 
125 static GstMemory *
custom_sysmem_allocator_alloc(GstAllocator * allocator,gsize size,GstAllocationParams * params)126 custom_sysmem_allocator_alloc (GstAllocator * allocator, gsize size,
127     GstAllocationParams * params)
128 {
129   gsize maxsize = size + params->prefix + params->padding;
130 
131   return (GstMemory *) custom_sysmem_new (params->flags,
132       maxsize, params->align, params->prefix, size);
133 }
134 
135 static void
custom_sysmem_allocator_free(GstAllocator * allocator,GstMemory * mem)136 custom_sysmem_allocator_free (GstAllocator * allocator, GstMemory * mem)
137 {
138   CustomSysmem *csmem = (CustomSysmem *) mem;
139 
140   g_free (csmem->allocdata);
141   g_free (csmem);
142 }
143 
144 static void
custom_sysmem_allocator_class_init(CustomSysmemAllocatorClass * klass)145 custom_sysmem_allocator_class_init (CustomSysmemAllocatorClass * klass)
146 {
147   GstAllocatorClass *allocator_class = (GstAllocatorClass *) klass;
148 
149   allocator_class->alloc = custom_sysmem_allocator_alloc;
150   allocator_class->free = custom_sysmem_allocator_free;
151 }
152 
153 static void
custom_sysmem_allocator_init(CustomSysmemAllocator * allocator)154 custom_sysmem_allocator_init (CustomSysmemAllocator * allocator)
155 {
156   GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
157 
158   alloc->mem_type = ALLOCATOR_CUSTOM_SYSMEM;
159   alloc->mem_map = (GstMemoryMapFunction) custom_sysmem_map;
160   alloc->mem_unmap = (GstMemoryUnmapFunction) custom_sysmem_unmap;
161   alloc->mem_copy = (GstMemoryCopyFunction) custom_sysmem_copy;
162   alloc->mem_share = (GstMemoryShareFunction) custom_sysmem_share;
163   alloc->mem_is_span = (GstMemoryIsSpanFunction) custom_sysmem_is_span;
164 }
165 
166 /* AppSink subclass proposing our custom allocator to upstream */
167 
168 typedef struct
169 {
170   GstAppSink appsink;
171 } CMemAppSink;
172 
173 typedef struct
174 {
175   GstAppSinkClass appsink;
176 } CMemAppSinkClass;
177 
178 GType c_mem_app_sink_get_type (void);
179 
180 G_DEFINE_TYPE (CMemAppSink, c_mem_app_sink, GST_TYPE_APP_SINK);
181 
182 static void
c_mem_app_sink_init(CMemAppSink * cmemsink)183 c_mem_app_sink_init (CMemAppSink * cmemsink)
184 {
185 }
186 
187 static gboolean
c_mem_app_sink_propose_allocation(GstBaseSink * sink,GstQuery * query)188 c_mem_app_sink_propose_allocation (GstBaseSink * sink, GstQuery * query)
189 {
190   gst_query_add_allocation_param (query, custom_sysmem_allocator, NULL);
191   return TRUE;
192 }
193 
194 static void
c_mem_app_sink_class_init(CMemAppSinkClass * klass)195 c_mem_app_sink_class_init (CMemAppSinkClass * klass)
196 {
197   GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass;
198 
199   basesink_class->propose_allocation = c_mem_app_sink_propose_allocation;
200 }
201 
202 #define RTP_H265_FILE GST_TEST_FILES_PATH G_DIR_SEPARATOR_S "h265.rtp"
203 
GST_START_TEST(test_rtph265depay_with_downstream_allocator)204 GST_START_TEST (test_rtph265depay_with_downstream_allocator)
205 {
206   GstElement *pipeline, *src, *depay, *sink;
207   GstMemory *mem;
208   GstSample *sample;
209   GstBuffer *buf;
210   GstCaps *caps;
211 
212   custom_sysmem_allocator =
213       g_object_new (custom_sysmem_allocator_get_type (), NULL);
214 
215   pipeline = gst_pipeline_new ("pipeline");
216 
217   src = gst_element_factory_make ("appsrc", NULL);
218 
219   caps = gst_caps_new_simple ("application/x-rtp",
220       "media", G_TYPE_STRING, "video",
221       "payload", G_TYPE_INT, 96,
222       "clock-rate", G_TYPE_INT, 90000,
223       "encoding-name", G_TYPE_STRING, "H265",
224       "ssrc", G_TYPE_UINT, 1990683810,
225       "timestamp-offset", G_TYPE_UINT, 3697583446UL,
226       "seqnum-offset", G_TYPE_UINT, 15568,
227       "a-framerate", G_TYPE_STRING, "30", NULL);
228   g_object_set (src, "format", GST_FORMAT_TIME, "caps", caps, NULL);
229   gst_bin_add (GST_BIN (pipeline), src);
230   gst_caps_unref (caps);
231 
232   depay = gst_element_factory_make ("rtph265depay", NULL);
233   gst_bin_add (GST_BIN (pipeline), depay);
234 
235   sink = g_object_new (c_mem_app_sink_get_type (), NULL);
236   gst_bin_add (GST_BIN (pipeline), sink);
237 
238   gst_element_link_many (src, depay, sink, NULL);
239 
240   gst_element_set_state (pipeline, GST_STATE_PAUSED);
241 
242   {
243     gchar *data, *pdata;
244     gsize len;
245 
246     fail_unless (g_file_get_contents (RTP_H265_FILE, &data, &len, NULL));
247     fail_unless (len > 2);
248 
249     pdata = data;
250     while (len > 2) {
251       GstFlowReturn flow;
252       guint16 packet_len;
253 
254       packet_len = GST_READ_UINT16_BE (pdata);
255       GST_INFO ("rtp packet length: %u (bytes left: %u)", packet_len,
256           (guint) len);
257       fail_unless (len >= 2 + packet_len);
258 
259       flow = gst_app_src_push_buffer (GST_APP_SRC (src),
260           gst_buffer_new_wrapped (g_memdup (pdata + 2, packet_len),
261               packet_len));
262 
263       fail_unless_equals_int (flow, GST_FLOW_OK);
264 
265       pdata += 2 + packet_len;
266       len -= 2 + packet_len;
267     }
268 
269     g_free (data);
270   }
271 
272   gst_app_src_end_of_stream (GST_APP_SRC (src));
273 
274   sample = gst_app_sink_pull_preroll (GST_APP_SINK (sink));
275   fail_unless (sample != NULL);
276 
277   buf = gst_sample_get_buffer (sample);
278 
279   GST_LOG ("buffer has %u memories", gst_buffer_n_memory (buf));
280   GST_LOG ("buffer size: %u", (guint) gst_buffer_get_size (buf));
281 
282   fail_unless (gst_buffer_n_memory (buf) > 0);
283   mem = gst_buffer_peek_memory (buf, 0);
284   fail_unless (mem != NULL);
285 
286   GST_LOG ("buffer memory type: %s", mem->allocator->mem_type);
287   fail_unless (gst_memory_is_type (mem, ALLOCATOR_CUSTOM_SYSMEM));
288 
289   gst_sample_unref (sample);
290 
291   gst_element_set_state (pipeline, GST_STATE_NULL);
292 
293   gst_object_unref (pipeline);
294 
295   g_object_unref (custom_sysmem_allocator);
296   custom_sysmem_allocator = NULL;
297 }
298 
299 GST_END_TEST;
300 
301 
302 static GstBuffer *
wrap_static_buffer_with_pts(guint8 * buf,gsize size,GstClockTime pts)303 wrap_static_buffer_with_pts (guint8 * buf, gsize size, GstClockTime pts)
304 {
305   GstBuffer *buffer;
306 
307   buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
308       buf, size, 0, size, NULL, NULL);
309   GST_BUFFER_PTS (buffer) = pts;
310 
311   return buffer;
312 }
313 
314 static GstBuffer *
wrap_static_buffer(guint8 * buf,gsize size)315 wrap_static_buffer (guint8 * buf, gsize size)
316 {
317   return wrap_static_buffer_with_pts (buf, size, GST_CLOCK_TIME_NONE);
318 }
319 
320 /* This was generated using pipeline:
321  * gst-launch-1.0 videotestsrc num-buffers=1 pattern=green \
322  *     ! video/x-raw,width=64,height=64 ! x265enc ! h265parse \
323  *     ! rtph265pay ! fakesink dump=1
324  */
325 /* RTP h265_idr + marker */
326 static guint8 rtp_h265_idr[] = {
327   0x80, 0xe0, 0x2c, 0x6a, 0xab, 0x7f, 0x71, 0xc0,
328   0x8d, 0x11, 0x33, 0x07, 0x28, 0x01, 0xaf, 0x05,
329   0x38, 0x4a, 0x03, 0x06, 0x7c, 0x7a, 0xb1, 0x8b,
330   0xff, 0xfe, 0xfd, 0xb7, 0xff, 0xff, 0xd1, 0xff,
331   0x40, 0x06, 0xd8, 0xd3, 0xb2, 0xf8
332 };
333 
GST_START_TEST(test_rtph265depay_eos)334 GST_START_TEST (test_rtph265depay_eos)
335 {
336   GstHarness *h = gst_harness_new ("rtph265depay");
337   GstBuffer *buffer;
338   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
339   GstFlowReturn ret;
340 
341   gst_harness_set_caps_str (h,
342       "application/x-rtp,media=video,clock-rate=90000,encoding-name=H265",
343       "video/x-h265,alignment=au,stream-format=byte-stream");
344 
345   buffer = wrap_static_buffer (rtp_h265_idr, sizeof (rtp_h265_idr));
346   fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_WRITE, &rtp));
347   gst_rtp_buffer_set_marker (&rtp, FALSE);
348   gst_rtp_buffer_unmap (&rtp);
349 
350   ret = gst_harness_push (h, buffer);
351   fail_unless_equals_int (ret, GST_FLOW_OK);
352   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
353 
354   fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
355   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
356 
357   gst_harness_teardown (h);
358 }
359 
360 GST_END_TEST;
361 
362 
GST_START_TEST(test_rtph265depay_marker_to_flag)363 GST_START_TEST (test_rtph265depay_marker_to_flag)
364 {
365   GstHarness *h = gst_harness_new ("rtph265depay");
366   GstBuffer *buffer;
367   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
368   GstFlowReturn ret;
369   guint16 seq;
370 
371   gst_harness_set_caps_str (h,
372       "application/x-rtp,media=video,clock-rate=90000,encoding-name=H265",
373       "video/x-h265,alignment=au,stream-format=byte-stream");
374 
375   buffer = wrap_static_buffer (rtp_h265_idr, sizeof (rtp_h265_idr));
376   fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
377   fail_unless (gst_rtp_buffer_get_marker (&rtp));
378   seq = gst_rtp_buffer_get_seq (&rtp);
379   gst_rtp_buffer_unmap (&rtp);
380 
381   ret = gst_harness_push (h, buffer);
382   fail_unless_equals_int (ret, GST_FLOW_OK);
383   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
384 
385   buffer = wrap_static_buffer (rtp_h265_idr, sizeof (rtp_h265_idr));
386   fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_WRITE, &rtp));
387   gst_rtp_buffer_set_marker (&rtp, FALSE);
388   gst_rtp_buffer_set_seq (&rtp, ++seq);
389   gst_rtp_buffer_unmap (&rtp);
390 
391   ret = gst_harness_push (h, buffer);
392   fail_unless_equals_int (ret, GST_FLOW_OK);
393 
394   /* the second NAL is blocked as there is no marker to let the payloader
395    * know it's a complete AU, we'll use an EOS to unblock it */
396   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
397   fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
398   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
399 
400   buffer = gst_harness_pull (h);
401   fail_unless (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_MARKER));
402   gst_buffer_unref (buffer);
403 
404   buffer = gst_harness_pull (h);
405   fail_if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_MARKER));
406   gst_buffer_unref (buffer);
407 
408   gst_harness_teardown (h);
409 }
410 
411 GST_END_TEST;
412 
413 /* These were generated using pipeline:
414  * gst-launch-1.0 videotestsrc num-buffers=1 pattern=green \
415  *     ! video/x-raw,width=256,height=256 \
416  *     ! x265enc option-string="slices=2" \
417  *     ! fakesink dump=1
418  */
419 
420 /* IDR Slice 1 */
421 static guint8 h265_idr_slice_1[] = {
422   0x00, 0x00, 0x00, 0x01, 0x28, 0x01, 0xaf, 0x08,
423   0xa2, 0xe6, 0xa3, 0xc6, 0x53, 0x90, 0xea, 0xc8,
424   0x3f, 0xfe, 0xfa, 0xf9, 0x3f, 0xf2, 0x61, 0x98,
425   0xef, 0xf4, 0xe9, 0x97, 0xe7, 0xc2, 0x74, 0x78,
426   0x98, 0x10, 0x01, 0x21, 0xa4, 0x3c, 0x4c, 0x08,
427   0x00, 0x3e, 0x40, 0x92, 0x0c, 0x78
428 };
429 
430 /* IDR Slice 2 */
431 static guint8 h265_idr_slice_2[] = {
432   0x00, 0x00, 0x01, 0x28, 0x01, 0x30, 0xf0, 0x8a,
433   0x2e, 0x60, 0xa3, 0xc6, 0x53, 0x90, 0xea, 0xc8,
434   0x3f, 0xfe, 0xfa, 0xf9, 0x3f, 0xf2, 0x61, 0x98,
435   0xef, 0xf4, 0xe9, 0x97, 0xe7, 0xc2, 0x74, 0x78,
436   0x98, 0x10, 0x01, 0x21, 0xa4, 0x3c, 0x4c, 0x08,
437   0x00, 0x3e, 0x40, 0x92, 0x0c, 0x78
438 };
439 
GST_START_TEST(test_rtph265pay_two_slices_timestamp)440 GST_START_TEST (test_rtph265pay_two_slices_timestamp)
441 {
442   GstHarness *h = gst_harness_new_parse ("rtph265pay timestamp-offset=123");
443   GstFlowReturn ret;
444   GstBuffer *buffer;
445   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
446 
447   gst_harness_set_src_caps_str (h,
448       "video/x-h265,alignment=nal,stream-format=byte-stream");
449 
450   ret = gst_harness_push (h, wrap_static_buffer_with_pts (h265_idr_slice_1,
451           sizeof (h265_idr_slice_1), 0));
452   fail_unless_equals_int (ret, GST_FLOW_OK);
453 
454   ret = gst_harness_push (h, wrap_static_buffer_with_pts (h265_idr_slice_2,
455           sizeof (h265_idr_slice_2), 0));
456   fail_unless_equals_int (ret, GST_FLOW_OK);
457 
458   ret = gst_harness_push (h, wrap_static_buffer_with_pts (h265_idr_slice_1,
459           sizeof (h265_idr_slice_1), GST_SECOND));
460   fail_unless_equals_int (ret, GST_FLOW_OK);
461 
462   ret = gst_harness_push (h, wrap_static_buffer_with_pts (h265_idr_slice_2,
463           sizeof (h265_idr_slice_2), GST_SECOND));
464   fail_unless_equals_int (ret, GST_FLOW_OK);
465 
466   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4);
467 
468   buffer = gst_harness_pull (h);
469   fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
470   fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), 0);
471   fail_unless_equals_uint64 (gst_rtp_buffer_get_timestamp (&rtp), 123);
472   gst_rtp_buffer_unmap (&rtp);
473   gst_buffer_unref (buffer);
474 
475   buffer = gst_harness_pull (h);
476   fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
477   fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), 0);
478   fail_unless_equals_uint64 (gst_rtp_buffer_get_timestamp (&rtp), 123);
479   gst_rtp_buffer_unmap (&rtp);
480   gst_buffer_unref (buffer);
481 
482   buffer = gst_harness_pull (h);
483   fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
484   fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), GST_SECOND);
485   fail_unless_equals_uint64 (gst_rtp_buffer_get_timestamp (&rtp), 123 + 90000);
486   gst_rtp_buffer_unmap (&rtp);
487   gst_buffer_unref (buffer);
488 
489   buffer = gst_harness_pull (h);
490   fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
491   fail_unless_equals_uint64 (GST_BUFFER_PTS (buffer), GST_SECOND);
492   fail_unless_equals_uint64 (gst_rtp_buffer_get_timestamp (&rtp), 123 + 90000);
493   gst_rtp_buffer_unmap (&rtp);
494   gst_buffer_unref (buffer);
495 
496   gst_harness_teardown (h);
497 }
498 
499 GST_END_TEST;
500 
GST_START_TEST(test_rtph265pay_marker_for_flag)501 GST_START_TEST (test_rtph265pay_marker_for_flag)
502 {
503   GstHarness *h = gst_harness_new_parse ("rtph265pay timestamp-offset=123");
504   GstFlowReturn ret;
505   GstBuffer *buffer;
506   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
507 
508   gst_harness_set_src_caps_str (h,
509       "video/x-h265,alignment=nal,stream-format=byte-stream");
510 
511   ret = gst_harness_push (h, wrap_static_buffer (h265_idr_slice_1,
512           sizeof (h265_idr_slice_1)));
513   fail_unless_equals_int (ret, GST_FLOW_OK);
514 
515   buffer = wrap_static_buffer (h265_idr_slice_2, sizeof (h265_idr_slice_2));
516   GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_MARKER);
517   ret = gst_harness_push (h, buffer);
518   fail_unless_equals_int (ret, GST_FLOW_OK);
519 
520   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
521 
522   buffer = gst_harness_pull (h);
523   fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
524   fail_if (gst_rtp_buffer_get_marker (&rtp));
525   gst_rtp_buffer_unmap (&rtp);
526   gst_buffer_unref (buffer);
527 
528   buffer = gst_harness_pull (h);
529   fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
530   fail_unless (gst_rtp_buffer_get_marker (&rtp));
531   gst_rtp_buffer_unmap (&rtp);
532   gst_buffer_unref (buffer);
533 
534   gst_harness_teardown (h);
535 }
536 
537 GST_END_TEST;
538 
539 
GST_START_TEST(test_rtph265pay_marker_for_au)540 GST_START_TEST (test_rtph265pay_marker_for_au)
541 {
542   GstHarness *h = gst_harness_new_parse ("rtph265pay timestamp-offset=123");
543   GstFlowReturn ret;
544   GstBuffer *slice1, *slice2, *buffer;
545   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
546 
547   gst_harness_set_src_caps_str (h,
548       "video/x-h265,alignment=au,stream-format=byte-stream");
549 
550   slice1 = wrap_static_buffer (h265_idr_slice_1, sizeof (h265_idr_slice_1));
551   slice2 = wrap_static_buffer (h265_idr_slice_2, sizeof (h265_idr_slice_2));
552   buffer = gst_buffer_append (slice1, slice2);
553 
554   ret = gst_harness_push (h, buffer);
555   fail_unless_equals_int (ret, GST_FLOW_OK);
556 
557   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
558 
559   buffer = gst_harness_pull (h);
560   fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
561   fail_if (gst_rtp_buffer_get_marker (&rtp));
562   gst_rtp_buffer_unmap (&rtp);
563   gst_buffer_unref (buffer);
564 
565   buffer = gst_harness_pull (h);
566   fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
567   fail_unless (gst_rtp_buffer_get_marker (&rtp));
568   gst_rtp_buffer_unmap (&rtp);
569   gst_buffer_unref (buffer);
570 
571   gst_harness_teardown (h);
572 }
573 
574 GST_END_TEST;
575 
576 
GST_START_TEST(test_rtph265pay_marker_for_fragmented_au)577 GST_START_TEST (test_rtph265pay_marker_for_fragmented_au)
578 {
579   GstHarness *h =
580       gst_harness_new_parse ("rtph265pay timestamp-offset=123 mtu=40");
581   GstFlowReturn ret;
582   GstBuffer *slice1, *slice2, *buffer;
583   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
584   gint i;
585 
586   gst_harness_set_src_caps_str (h,
587       "video/x-h265,alignment=au,stream-format=byte-stream");
588 
589   slice1 = wrap_static_buffer (h265_idr_slice_1, sizeof (h265_idr_slice_1));
590   slice2 = wrap_static_buffer (h265_idr_slice_2, sizeof (h265_idr_slice_2));
591   buffer = gst_buffer_append (slice1, slice2);
592 
593   ret = gst_harness_push (h, buffer);
594   fail_unless_equals_int (ret, GST_FLOW_OK);
595 
596   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4);
597 
598   for (i = 0; i < 3; i++) {
599     buffer = gst_harness_pull (h);
600     fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
601     fail_if (gst_rtp_buffer_get_marker (&rtp));
602     gst_rtp_buffer_unmap (&rtp);
603     gst_buffer_unref (buffer);
604   }
605 
606   buffer = gst_harness_pull (h);
607   fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp));
608   fail_unless (gst_rtp_buffer_get_marker (&rtp));
609   gst_rtp_buffer_unmap (&rtp);
610   gst_buffer_unref (buffer);
611 
612   gst_harness_teardown (h);
613 }
614 
615 GST_END_TEST;
616 
617 
618 static Suite *
rtph265_suite(void)619 rtph265_suite (void)
620 {
621   Suite *s = suite_create ("rtph265");
622   TCase *tc_chain;
623 
624   tc_chain = tcase_create ("rtph265depay");
625   suite_add_tcase (s, tc_chain);
626   tcase_add_test (tc_chain, test_rtph265depay_with_downstream_allocator);
627   tcase_add_test (tc_chain, test_rtph265depay_eos);
628   tcase_add_test (tc_chain, test_rtph265depay_marker_to_flag);
629   /* TODO We need a sample to test with */
630   /* tcase_add_test (tc_chain, test_rtph265depay_aggregate_marker); */
631 
632   tc_chain = tcase_create ("rtph265pay");
633   suite_add_tcase (s, tc_chain);
634   tcase_add_test (tc_chain, test_rtph265pay_two_slices_timestamp);
635   tcase_add_test (tc_chain, test_rtph265pay_marker_for_flag);
636   tcase_add_test (tc_chain, test_rtph265pay_marker_for_au);
637   tcase_add_test (tc_chain, test_rtph265pay_marker_for_fragmented_au);
638 
639   return s;
640 }
641 
642 GST_CHECK_MAIN (rtph265);
643