misc: Fix warnings on Cerbero's mingw (gcc 4.7)
[platform/upstream/gst-plugins-good.git] / tests / check / elements / rtph264.c
1 /* GStreamer RTP H.264 unit test
2  *
3  * Copyright (C) 2017 Centricular Ltd
4  *   @author: Tim-Philipp Müller <tim@centricular.com>
5  *
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.
10  *
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.
15  *
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.
20  */
21
22 #include <gst/check/check.h>
23 #include <gst/app/app.h>
24 #include <gst/rtp/gstrtpbuffer.h>
25
26 #define ALLOCATOR_CUSTOM_SYSMEM "CustomSysMem"
27
28 static GstAllocator *custom_sysmem_allocator;   /* NULL */
29
30 /* Custom memory */
31
32 typedef struct
33 {
34   GstMemory mem;
35   guint8 *data;
36   guint8 *allocdata;
37 } CustomSysmem;
38
39 static CustomSysmem *
40 custom_sysmem_new (GstMemoryFlags flags, gsize maxsize, gsize align,
41     gsize offset, gsize size)
42 {
43   gsize aoffset, padding;
44   CustomSysmem *mem;
45
46   /* ensure configured alignment */
47   align |= gst_memory_alignment;
48   /* allocate more to compensate for alignment */
49   maxsize += align;
50
51   mem = g_new0 (CustomSysmem, 1);
52
53   mem->allocdata = g_malloc (maxsize);
54
55   mem->data = mem->allocdata;
56
57   /* do alignment */
58   if ((aoffset = ((guintptr) mem->data & align))) {
59     aoffset = (align + 1) - aoffset;
60     mem->data += aoffset;
61     maxsize -= aoffset;
62   }
63
64   if (offset && (flags & GST_MEMORY_FLAG_ZERO_PREFIXED))
65     memset (mem->data, 0, offset);
66
67   padding = maxsize - (offset + size);
68   if (padding && (flags & GST_MEMORY_FLAG_ZERO_PADDED))
69     memset (mem->data + offset + size, 0, padding);
70
71   gst_memory_init (GST_MEMORY_CAST (mem), flags, custom_sysmem_allocator,
72       NULL, maxsize, align, offset, size);
73
74   return mem;
75 }
76
77 static gpointer
78 custom_sysmem_map (CustomSysmem * mem, gsize maxsize, GstMapFlags flags)
79 {
80   return mem->data;
81 }
82
83 static gboolean
84 custom_sysmem_unmap (CustomSysmem * mem)
85 {
86   return TRUE;
87 }
88
89 static CustomSysmem *
90 custom_sysmem_copy (CustomSysmem * mem, gssize offset, gsize size)
91 {
92   g_return_val_if_reached (NULL);
93 }
94
95 static CustomSysmem *
96 custom_sysmem_share (CustomSysmem * mem, gssize offset, gsize size)
97 {
98   g_return_val_if_reached (NULL);
99 }
100
101 static gboolean
102 custom_sysmem_is_span (CustomSysmem * mem1, CustomSysmem * mem2, gsize * offset)
103 {
104   g_return_val_if_reached (FALSE);
105 }
106
107 /* Custom allocator */
108
109 typedef struct
110 {
111   GstAllocator allocator;
112 } CustomSysmemAllocator;
113
114 typedef struct
115 {
116   GstAllocatorClass allocator_class;
117 } CustomSysmemAllocatorClass;
118
119 GType custom_sysmem_allocator_get_type (void);
120 G_DEFINE_TYPE (CustomSysmemAllocator, custom_sysmem_allocator,
121     GST_TYPE_ALLOCATOR);
122
123 static GstMemory *
124 custom_sysmem_allocator_alloc (GstAllocator * allocator, gsize size,
125     GstAllocationParams * params)
126 {
127   gsize maxsize = size + params->prefix + params->padding;
128
129   return (GstMemory *) custom_sysmem_new (params->flags,
130       maxsize, params->align, params->prefix, size);
131 }
132
133 static void
134 custom_sysmem_allocator_free (GstAllocator * allocator, GstMemory * mem)
135 {
136   CustomSysmem *csmem = (CustomSysmem *) mem;
137
138   g_free (csmem->allocdata);
139   g_free (csmem);
140 }
141
142 static void
143 custom_sysmem_allocator_class_init (CustomSysmemAllocatorClass * klass)
144 {
145   GstAllocatorClass *allocator_class = (GstAllocatorClass *) klass;
146
147   allocator_class->alloc = custom_sysmem_allocator_alloc;
148   allocator_class->free = custom_sysmem_allocator_free;
149 }
150
151 static void
152 custom_sysmem_allocator_init (CustomSysmemAllocator * allocator)
153 {
154   GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
155
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;
162 }
163
164 /* AppSink subclass proposing our custom allocator to upstream */
165
166 typedef struct
167 {
168   GstAppSink appsink;
169 } CMemAppSink;
170
171 typedef struct
172 {
173   GstAppSinkClass appsink;
174 } CMemAppSinkClass;
175
176 GType c_mem_app_sink_get_type (void);
177
178 G_DEFINE_TYPE (CMemAppSink, c_mem_app_sink, GST_TYPE_APP_SINK);
179
180 static void
181 c_mem_app_sink_init (CMemAppSink * cmemsink)
182 {
183 }
184
185 static gboolean
186 c_mem_app_sink_propose_allocation (GstBaseSink * sink, GstQuery * query)
187 {
188   gst_query_add_allocation_param (query, custom_sysmem_allocator, NULL);
189   return TRUE;
190 }
191
192 static void
193 c_mem_app_sink_class_init (CMemAppSinkClass * klass)
194 {
195   GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass;
196
197   basesink_class->propose_allocation = c_mem_app_sink_propose_allocation;
198 }
199
200 #define RTP_H264_FILE GST_TEST_FILES_PATH G_DIR_SEPARATOR_S "h264.rtp"
201
202 GST_START_TEST (test_rtph264depay_with_downstream_allocator)
203 {
204   GstElement *pipeline, *src, *depay, *sink;
205   GstMemory *mem;
206   GstSample *sample;
207   GstBuffer *buf;
208   GstCaps *caps;
209
210   custom_sysmem_allocator =
211       g_object_new (custom_sysmem_allocator_get_type (), NULL);
212
213   pipeline = gst_pipeline_new ("pipeline");
214
215   src = gst_element_factory_make ("appsrc", NULL);
216
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);
229
230   depay = gst_element_factory_make ("rtph264depay", NULL);
231   gst_bin_add (GST_BIN (pipeline), depay);
232
233   sink = g_object_new (c_mem_app_sink_get_type (), NULL);
234   gst_bin_add (GST_BIN (pipeline), sink);
235
236   gst_element_link_many (src, depay, sink, NULL);
237
238   gst_element_set_state (pipeline, GST_STATE_PAUSED);
239
240   {
241     gchar *data, *pdata;
242     gsize len;
243
244     fail_unless (g_file_get_contents (RTP_H264_FILE, &data, &len, NULL));
245     fail_unless (len > 2);
246
247     pdata = data;
248     while (len > 2) {
249       GstFlowReturn flow;
250       guint16 packet_len;
251
252       packet_len = GST_READ_UINT16_BE (pdata);
253       GST_INFO ("rtp packet length: %u (bytes left: %u)", packet_len,
254           (guint) len);
255       fail_unless (len >= 2 + packet_len);
256
257       flow = gst_app_src_push_buffer (GST_APP_SRC (src),
258           gst_buffer_new_wrapped (g_memdup (pdata + 2, packet_len),
259               packet_len));
260
261       fail_unless_equals_int (flow, GST_FLOW_OK);
262
263       pdata += 2 + packet_len;
264       len -= 2 + packet_len;
265     }
266
267     g_free (data);
268   }
269
270   gst_app_src_end_of_stream (GST_APP_SRC (src));
271
272   sample = gst_app_sink_pull_preroll (GST_APP_SINK (sink));
273   fail_unless (sample != NULL);
274
275   buf = gst_sample_get_buffer (sample);
276
277   GST_LOG ("buffer has %u memories", gst_buffer_n_memory (buf));
278   GST_LOG ("buffer size: %u", (guint) gst_buffer_get_size (buf));
279
280   fail_unless (gst_buffer_n_memory (buf) > 0);
281   mem = gst_buffer_peek_memory (buf, 0);
282   fail_unless (mem != NULL);
283
284   GST_LOG ("buffer memory type: %s", mem->allocator->mem_type);
285   fail_unless (gst_memory_is_type (mem, ALLOCATOR_CUSTOM_SYSMEM));
286
287   gst_sample_unref (sample);
288
289   gst_element_set_state (pipeline, GST_STATE_NULL);
290
291   gst_object_unref (pipeline);
292
293   g_object_unref (custom_sysmem_allocator);
294   custom_sysmem_allocator = NULL;
295 }
296
297 GST_END_TEST;
298
299
300 static GstBuffer *
301 wrap_static_buffer_with_pts (guint8 * buf, gsize size, GstClockTime pts)
302 {
303   GstBuffer *buffer;
304
305   buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
306       buf, size, 0, size, NULL, NULL);
307   GST_BUFFER_PTS (buffer) = pts;
308
309   return buffer;
310 }
311
312 static GstBuffer *
313 wrap_static_buffer (guint8 * buf, gsize size)
314 {
315   return wrap_static_buffer_with_pts (buf, size, GST_CLOCK_TIME_NONE);
316 }
317
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
322  */
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,
329   0x00, 0x84, 0xde
330 };
331
332 GST_START_TEST (test_rtph264depay_eos)
333 {
334   GstHarness *h = gst_harness_new ("rtph264depay");
335   GstBuffer *buffer;
336   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
337   GstFlowReturn ret;
338
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");
342
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);
347
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);
351
352   fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
353   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
354
355   gst_harness_teardown (h);
356 }
357
358 GST_END_TEST;
359
360
361 GST_START_TEST (test_rtph264depay_marker_to_flag)
362 {
363   GstHarness *h = gst_harness_new ("rtph264depay");
364   GstBuffer *buffer;
365   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
366   GstFlowReturn ret;
367   guint16 seq;
368
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");
372
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);
378
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);
382
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);
388
389   ret = gst_harness_push (h, buffer);
390   fail_unless_equals_int (ret, GST_FLOW_OK);
391
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);
397
398   buffer = gst_harness_pull (h);
399   fail_unless (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_MARKER));
400   gst_buffer_unref (buffer);
401
402   buffer = gst_harness_pull (h);
403   fail_if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_MARKER));
404   gst_buffer_unref (buffer);
405
406   gst_harness_teardown (h);
407 }
408
409 GST_END_TEST;
410
411
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,
421   0x2c
422 };
423
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
449 };
450
451 GST_START_TEST (test_rtph264depay_stap_a_marker)
452 {
453   GstHarness *h = gst_harness_new ("rtph264depay");
454   GstBuffer *buffer;
455   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
456   GstFlowReturn ret;
457
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");
461
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);
466
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);
474
475   /* Only one AU should have been pushed */
476   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
477
478   gst_harness_teardown (h);
479 }
480
481 GST_END_TEST;
482
483
484 /* AUD */
485 static guint8 h264_aud[] = {
486   0x00, 0x00, 0x00, 0x01, 0x09, 0xf0
487 };
488
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 \
493  *     ! fakesink dump=1
494  */
495
496 /* SPS */
497 static guint8 h264_sps[] = {
498   0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x29,
499   0x8c, 0x8d, 0x41, 0x02, 0x24, 0x03, 0xc2, 0x21,
500   0x1a, 0x80
501 };
502
503 /* PPS */
504 static guint8 h264_pps[] = {
505   0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x3c, 0x80
506 };
507
508 /* IDR Slice 1 */
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
517 };
518
519 /* IDR Slice 2 */
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
528 };
529
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)
533 {
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)];
540   GstFlowReturn ret;
541
542   gst_harness_set_src_caps_str (h,
543       "video/x-h264,alignment=nal,stream-format=byte-stream");
544
545   ret = gst_harness_push (h, wrap_static_buffer (h264_sps, sizeof (h264_sps)));
546   fail_unless_equals_int (ret, GST_FLOW_OK);
547
548   ret = gst_harness_push (h, wrap_static_buffer (h264_pps, sizeof (h264_pps)));
549   fail_unless_equals_int (ret, GST_FLOW_OK);
550
551   memcpy (nal_24, h264_aud, sizeof (h264_aud));
552   nal_24[4] = 24;
553   ret = gst_harness_push (h, wrap_static_buffer (nal_24, sizeof (nal_24)));
554   fail_unless_equals_int (ret, GST_FLOW_OK);
555
556   memcpy (nal_25, h264_aud, sizeof (h264_aud));
557   nal_25[4] = 25;
558   ret = gst_harness_push (h, wrap_static_buffer (nal_25, sizeof (nal_25)));
559   fail_unless_equals_int (ret, GST_FLOW_OK);
560
561
562   memcpy (nal_26, h264_aud, sizeof (h264_aud));
563   nal_26[4] = 26;
564   ret = gst_harness_push (h, wrap_static_buffer (nal_26, sizeof (nal_26)));
565   fail_unless_equals_int (ret, GST_FLOW_OK);
566
567
568   memcpy (nal_27, h264_aud, sizeof (h264_aud));
569   nal_27[4] = 27;
570   ret = gst_harness_push (h, wrap_static_buffer (nal_27, sizeof (nal_27)));
571   fail_unless_equals_int (ret, GST_FLOW_OK);
572
573   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
574   gst_harness_teardown (h);
575 }
576
577 GST_END_TEST;
578
579
580 GST_START_TEST (test_rtph264pay_two_slices_timestamp)
581 {
582   GstHarness *h = gst_harness_new_parse ("rtph264pay timestamp-offset=123");
583   GstFlowReturn ret;
584   GstBuffer *buffer;
585   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
586
587   gst_harness_set_src_caps_str (h,
588       "video/x-h264,alignment=nal,stream-format=byte-stream");
589
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);
593
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);
597
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);
601
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);
605
606
607   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4);
608
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);
615
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);
622
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);
629
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);
636
637   gst_harness_teardown (h);
638 }
639
640 GST_END_TEST;
641
642 GST_START_TEST (test_rtph264pay_marker_for_flag)
643 {
644   GstHarness *h = gst_harness_new_parse ("rtph264pay timestamp-offset=123");
645   GstFlowReturn ret;
646   GstBuffer *buffer;
647   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
648
649   gst_harness_set_src_caps_str (h,
650       "video/x-h264,alignment=nal,stream-format=byte-stream");
651
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);
655
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);
660
661   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
662
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);
668
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);
674
675   gst_harness_teardown (h);
676 }
677
678 GST_END_TEST;
679
680
681 GST_START_TEST (test_rtph264pay_marker_for_au)
682 {
683   GstHarness *h = gst_harness_new_parse ("rtph264pay timestamp-offset=123");
684   GstFlowReturn ret;
685   GstBuffer *slice1, *slice2, *buffer;
686   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
687
688   gst_harness_set_src_caps_str (h,
689       "video/x-h264,alignment=au,stream-format=byte-stream");
690
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);
694
695   ret = gst_harness_push (h, buffer);
696   fail_unless_equals_int (ret, GST_FLOW_OK);
697
698   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
699
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);
705
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);
711
712   gst_harness_teardown (h);
713 }
714
715 GST_END_TEST;
716
717
718 GST_START_TEST (test_rtph264pay_marker_for_fragmented_au)
719 {
720   GstHarness *h =
721       gst_harness_new_parse ("rtph264pay timestamp-offset=123 mtu=40");
722   GstFlowReturn ret;
723   GstBuffer *slice1, *slice2, *buffer;
724   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
725   gint i;
726
727   gst_harness_set_src_caps_str (h,
728       "video/x-h264,alignment=au,stream-format=byte-stream");
729
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);
733
734   ret = gst_harness_push (h, buffer);
735   fail_unless_equals_int (ret, GST_FLOW_OK);
736
737   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4);
738
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);
745   }
746
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);
752
753   gst_harness_teardown (h);
754 }
755
756 GST_END_TEST;
757
758
759 static Suite *
760 rtph264_suite (void)
761 {
762   Suite *s = suite_create ("rtph264");
763   TCase *tc_chain;
764
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);
771
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);
779
780   return s;
781 }
782
783 GST_CHECK_MAIN (rtph264);