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