• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * GStreamer
3  *
4  * unit test for h265parse
5  *
6  * Copyright (C) 2019 Stéphane Cerveau <scerveau@collabora.com>
7  * Copyright (C) 2019 Collabora Ltd.
8  *   @author George Kiagiadakis <george.kiagiadakis@collabora.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25 
26 #include <gst/check/check.h>
27 #include "parser.h"
28 
29 #define SRC_CAPS_TMPL   "video/x-h265, parsed=(boolean)false"
30 #define SINK_CAPS_TMPL  "video/x-h265, parsed=(boolean)true"
31 
32 GstStaticPadTemplate sinktemplate_bs_au = GST_STATIC_PAD_TEMPLATE ("sink",
33     GST_PAD_SINK,
34     GST_PAD_ALWAYS,
35     GST_STATIC_CAPS (SINK_CAPS_TMPL
36         ", stream-format = (string) byte-stream, alignment = (string) au")
37     );
38 
39 GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
40     GST_PAD_SRC,
41     GST_PAD_ALWAYS,
42     GST_STATIC_CAPS (SRC_CAPS_TMPL)
43     );
44 
45 /* Data generated with:
46  *
47  * gst-launch-1.0 videotestsrc num-buffers=1 ! video/x-raw,width=16,height=16 ! x265enc option-string="max-cll=1000,400:master-display=G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1)" ! h265parse ! fakesink
48  *
49  * x265enc SEI has been dropped.
50  *
51  */
52 
53 static const guint8 h265_vps[] = {
54   0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x60, 0x00,
55   0x00, 0x03, 0x00, 0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x3f, 0x95,
56   0x98, 0x09
57 };
58 
59 static const guint8 h265_sps[] = {
60   0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00,
61   0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x3f, 0xa0, 0x88, 0x45, 0x96,
62   0x56, 0x6a, 0xbc, 0xaf, 0xff, 0x00, 0x01, 0x00, 0x01, 0x6a, 0x0c, 0x02, 0x0c,
63   0x08, 0x00, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0xf0, 0x40
64 };
65 
66 static const guint8 h265_pps[] = {
67   0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x73, 0xd0, 0x89
68 };
69 
70 static const guint8 h265_idr[] = {
71   0x00, 0x00, 0x00, 0x01, 0x26, 0x01, 0xaf, 0x06, 0xb8, 0xcf, 0xbc, 0x65, 0x85,
72   0x3b, 0x49, 0xff, 0xd0, 0x2c, 0xff, 0x3b, 0x61, 0x6d, 0x1b, 0xae, 0xf1, 0xf4,
73   0x96, 0x15, 0xef, 0x3e, 0xc6, 0x67, 0x3c, 0x0a, 0xd0, 0x6a, 0xb9, 0xfb, 0xf8,
74   0xb4, 0xb8, 0x4a, 0x4c, 0x4e, 0xe2, 0xf6, 0xb0, 0x29, 0x41, 0x4e, 0x14, 0xe8,
75   0x1f, 0x41, 0x58, 0xcb, 0x7a, 0x94, 0xdc, 0xba, 0x3d, 0x2e, 0xe0, 0x83, 0x4d,
76   0x3c, 0x3d, 0x2d, 0x70, 0xd1, 0xc4, 0x3d, 0x65, 0xf8, 0x3a, 0xe3, 0xdf, 0xb1,
77   0xf1, 0x1c, 0x48, 0x45, 0x63, 0x5b, 0x55, 0x0e, 0x0d, 0xef, 0xfc, 0x07, 0xd3,
78   0xce, 0x14, 0xc2, 0xac, 0x79, 0xd6, 0x1c, 0x44, 0x2c, 0xbd, 0x00, 0xff, 0xe5,
79   0x0c, 0x09, 0x3a, 0x3b, 0x53, 0xa8, 0x58, 0xb5, 0xb0, 0x29, 0xe6, 0x64, 0x14,
80   0x3a, 0xec, 0x8c, 0x7d, 0xd9, 0x19, 0xb4, 0xc2, 0x75, 0x37, 0xa2, 0x64, 0xa3,
81   0x1f, 0x26, 0x78, 0xe0, 0xa4, 0xde, 0xed, 0xb1, 0x52, 0x67, 0x90, 0xf1, 0x8e,
82   0xf9, 0x99, 0xa8, 0x9e, 0xfa, 0x55, 0xfc, 0x92, 0x3d, 0xd1, 0x03, 0xff, 0xff,
83   0xf7, 0x79, 0xaf, 0xa5, 0x90, 0x72, 0x35, 0x4e, 0x64, 0x16, 0x48, 0xa8, 0x28,
84   0xc4, 0xcf, 0x51, 0x83, 0x78, 0x6d, 0x90, 0x3a, 0xdf, 0xff, 0xb1, 0x1b, 0xb4,
85   0x3e, 0xa5, 0xd3, 0xc9, 0x2b, 0x75, 0x16, 0x01, 0x16, 0xa6, 0xc5, 0x1d, 0x1e,
86   0xd6, 0x63, 0x0c, 0xba, 0x2f, 0x77, 0x58, 0x5a, 0x4c, 0xb6, 0x49, 0x63, 0xb4,
87   0xa5, 0xb3, 0x25, 0x1b, 0xfd, 0xea, 0x13, 0x8b, 0xb3, 0x8f, 0x42, 0x81, 0xa1,
88   0x89, 0xe1, 0x36, 0x80, 0x11, 0x3c, 0x88, 0x84, 0x29, 0x51, 0x59, 0x2c, 0xb2,
89   0x9c, 0x90, 0xa5, 0x12, 0x80, 0x2d, 0x16, 0x61, 0x8e, 0xf1, 0x28, 0xba, 0x0f,
90   0x71, 0xdf, 0x7b, 0xdb, 0xd7, 0xb0, 0x3d, 0xa1, 0xbe, 0x4f, 0x7c, 0xcf, 0x09,
91   0x73, 0xe1, 0x10, 0xea, 0x64, 0x96, 0x89, 0x5d, 0x7e, 0x7f, 0x26, 0x18, 0x43,
92   0xbb, 0x0d, 0x2c, 0x95, 0xaa, 0xec, 0x03, 0x9d, 0x55, 0x56, 0xdf, 0xd3, 0x7e,
93   0x4f, 0xf7, 0x47, 0x60, 0x89, 0x35, 0x6e, 0x08, 0x9a, 0xcf, 0x11, 0x26, 0xc3,
94   0xec, 0x31, 0x23, 0xca, 0x51, 0x10, 0x80
95 };
96 
97 /* Content light level information SEI message */
98 static const guint8 h265_sei_clli[] = {
99   0x00, 0x00, 0x00, 0x01, 0x4e, 0x01, 0x90, 0x04, 0x03, 0xe8, 0x01, 0x90, 0x80
100 };
101 
102 /* Mastering display colour volume information SEI message */
103 static const guint8 h265_sei_mdcv[] = {
104   0x00, 0x00, 0x00, 0x01, 0x4e, 0x01, 0x89, 0x18, 0x33, 0xc2, 0x86, 0xc4, 0x1d,
105   0x4c, 0x0b, 0xb8, 0x84, 0xd0, 0x3e, 0x80, 0x3d, 0x13, 0x40, 0x42, 0x00, 0x98,
106   0x96, 0x80, 0x00, 0x00, 0x03, 0x00, 0x01, 0x80
107 };
108 
109 
110 /* single-sliced data, generated with:
111  * gst-launch-1.0 videotestsrc num-buffers=1 pattern=green \
112  *    ! video/x-raw,width=128,height=128 \
113  *    ! x265enc
114  *    ! fakesink dump=1
115  */
116 
117 static const guint8 h265_128x128_vps[] = {
118   0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01,
119   0xff, 0xff, 0x01, 0x60, 0x00, 0x00, 0x03, 0x00,
120   0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00,
121   0x3f, 0x95, 0x98, 0x09
122 };
123 
124 static const guint8 h265_128x128_sps[] = {
125   0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01,
126   0x60, 0x00, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00,
127   0x03, 0x00, 0x00, 0x03, 0x00, 0x3f, 0xa0, 0x10,
128   0x20, 0x20, 0x59, 0x65, 0x66, 0x92, 0x4c, 0xaf,
129   0xff, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00,
130   0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x1e,
131   0x08
132 };
133 
134 static const guint8 h265_128x128_pps[] = {
135   0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc1, 0x72,
136   0xb4, 0x22, 0x40
137 };
138 
139 static const guint8 h265_128x128_slice_idr_n_lp[] = {
140   0x00, 0x00, 0x00, 0x01, 0x28, 0x01, 0xaf, 0x0e,
141   0xe0, 0x34, 0x82, 0x15, 0x84, 0xf4, 0x70, 0x4f,
142   0xff, 0xed, 0x41, 0x3f, 0xff, 0xe4, 0xcd, 0xc4,
143   0x7c, 0x03, 0x0c, 0xc2, 0xbb, 0xb0, 0x74, 0xe5,
144   0xef, 0x4f, 0xe1, 0xa3, 0xd4, 0x00, 0x02, 0xc2
145 };
146 
147 /* multi-sliced data, generated on zynqultrascaleplus with:
148  * gst-launch-1.0 videotestsrc num-buffers=1 pattern=green \
149  *    ! video/x-raw,width=128,height=128 \
150  *    ! omxh265enc num-slices=2 \
151  *    ! fakesink dump=1
152  */
153 
154 static const guint8 h265_128x128_sliced_vps[] = {
155   0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x0c, 0x01,
156   0xff, 0xff, 0x01, 0x40, 0x00, 0x00, 0x03, 0x00,
157   0x90, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00,
158   0x1e, 0x25, 0x02, 0x40
159 };
160 
161 static const guint8 h265_128x128_sliced_sps[] = {
162   0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01,
163   0x40, 0x00, 0x00, 0x03, 0x00, 0x90, 0x00, 0x00,
164   0x03, 0x00, 0x00, 0x03, 0x00, 0x1e, 0xa0, 0x10,
165   0x20, 0x20, 0x59, 0xe9, 0x6e, 0x44, 0xa1, 0x73,
166   0x50, 0x60, 0x20, 0x2e, 0x10, 0x00, 0x00, 0x03,
167   0x00, 0x10, 0x00, 0x00, 0x03, 0x01, 0xe5, 0x1a,
168   0xff, 0xff, 0x10, 0x3e, 0x80, 0x5d, 0xf7, 0xc2,
169   0x01, 0x04
170 };
171 
172 static const guint8 h265_128x128_sliced_pps[] = {
173   0x00, 0x00, 0x00, 0x01, 0x44, 0x01, 0xc0, 0x71,
174   0x81, 0x8d, 0xb2
175 };
176 
177 static const guint8 h265_128x128_slice_1_idr_n_lp[] = {
178   0x00, 0x00, 0x00, 0x01, 0x28, 0x01, 0xac, 0x46,
179   0x13, 0xb6, 0x45, 0x43, 0xaf, 0xee, 0x3d, 0x3f,
180   0x76, 0xe5, 0x73, 0x2f, 0xee, 0xd2, 0xeb, 0xbf,
181   0x80
182 };
183 
184 static const guint8 h265_128x128_slice_2_idr_n_lp[] = {
185   0x00, 0x00, 0x00, 0x01, 0x28, 0x01, 0x30, 0xc4,
186   0x60, 0x13, 0xb6, 0x45, 0x43, 0xaf, 0xee, 0x3d,
187   0x3f, 0x76, 0xe5, 0x73, 0x2f, 0xee, 0xd2, 0xeb,
188   0xbf, 0x80
189 };
190 
191 static const gchar *ctx_suite;
192 static gboolean ctx_codec_data;
193 
194 /* A single access unit comprising of VPS, SPS, PPS and IDR frame */
195 static gboolean
verify_buffer_bs_au(buffer_verify_data_s * vdata,GstBuffer * buffer)196 verify_buffer_bs_au (buffer_verify_data_s * vdata, GstBuffer * buffer)
197 {
198   GstMapInfo map;
199 
200   fail_unless (ctx_sink_template == &sinktemplate_bs_au);
201 
202   gst_buffer_map (buffer, &map, GST_MAP_READ);
203   fail_unless (map.size > 4);
204 
205   if (vdata->buffer_counter == 0) {
206     guint8 *data = map.data;
207 
208     /* VPS, SPS, PPS */
209     fail_unless (map.size == vdata->data_to_verify_size +
210         ctx_headers[0].size + ctx_headers[1].size + ctx_headers[2].size);
211 
212     fail_unless (memcmp (data, ctx_headers[0].data, ctx_headers[0].size) == 0);
213     data += ctx_headers[0].size;
214     fail_unless (memcmp (data, ctx_headers[1].data, ctx_headers[1].size) == 0);
215     data += ctx_headers[1].size;
216     fail_unless (memcmp (data, ctx_headers[2].data, ctx_headers[2].size) == 0);
217     data += ctx_headers[2].size;
218 
219     /* IDR frame */
220     fail_unless (memcmp (data, vdata->data_to_verify,
221             vdata->data_to_verify_size) == 0);
222   } else {
223     /* IDR frame */
224     fail_unless (map.size == vdata->data_to_verify_size);
225 
226     fail_unless (memcmp (map.data, vdata->data_to_verify, map.size) == 0);
227   }
228 
229   gst_buffer_unmap (buffer, &map);
230   return TRUE;
231 }
232 
GST_START_TEST(test_parse_normal)233 GST_START_TEST (test_parse_normal)
234 {
235   gst_parser_test_normal (h265_idr, sizeof (h265_idr));
236 }
237 
238 GST_END_TEST;
239 
240 
GST_START_TEST(test_parse_drain_single)241 GST_START_TEST (test_parse_drain_single)
242 {
243   gst_parser_test_drain_single (h265_idr, sizeof (h265_idr));
244 }
245 
246 GST_END_TEST;
247 
248 
GST_START_TEST(test_parse_split)249 GST_START_TEST (test_parse_split)
250 {
251   gst_parser_test_split (h265_idr, sizeof (h265_idr));
252 }
253 
254 GST_END_TEST;
255 
256 
257 #define structure_get_int(s,f) \
258     (g_value_get_int(gst_structure_get_value(s,f)))
259 #define fail_unless_structure_field_int_equals(s,field,num) \
260     fail_unless_equals_int (structure_get_int(s,field), num)
261 
262 #define structure_get_string(s,f) \
263     (g_value_get_string(gst_structure_get_value(s,f)))
264 #define fail_unless_structure_field_string_equals(s,field,name) \
265     fail_unless_equals_string (structure_get_string(s,field), name)
266 
GST_START_TEST(test_parse_detect_stream)267 GST_START_TEST (test_parse_detect_stream)
268 {
269   GstCaps *caps;
270   GstStructure *s;
271 
272   caps = gst_parser_test_get_output_caps (h265_idr, sizeof (h265_idr), NULL);
273   fail_unless (caps != NULL);
274 
275   /* Check that the negotiated caps are as expected */
276   GST_DEBUG ("output caps: %" GST_PTR_FORMAT, caps);
277   s = gst_caps_get_structure (caps, 0);
278   fail_unless (gst_structure_has_name (s, "video/x-h265"));
279   fail_unless_structure_field_int_equals (s, "width", 16);
280   fail_unless_structure_field_int_equals (s, "height", 16);
281   fail_unless_structure_field_string_equals (s, "stream-format", "byte-stream");
282   fail_unless_structure_field_string_equals (s, "alignment", "au");
283   fail_unless_structure_field_string_equals (s, "profile", "main");
284   fail_unless_structure_field_string_equals (s, "tier", "main");
285   fail_unless_structure_field_string_equals (s, "level", "2.1");
286 
287   gst_caps_unref (caps);
288 }
289 
290 GST_END_TEST;
291 
GST_START_TEST(test_parse_detect_stream_with_hdr_sei)292 GST_START_TEST (test_parse_detect_stream_with_hdr_sei)
293 {
294   GstCaps *caps;
295   GstStructure *s;
296   guint8 *h265_idr_plus_sei;
297   gsize h265_idr_plus_sei_size =
298       sizeof (h265_sei_clli) + sizeof (h265_sei_mdcv) + sizeof (h265_idr);
299 
300   h265_idr_plus_sei = malloc (h265_idr_plus_sei_size);
301 
302   memcpy (h265_idr_plus_sei, h265_sei_clli, sizeof (h265_sei_clli));
303   memcpy (h265_idr_plus_sei + sizeof (h265_sei_clli), h265_sei_mdcv,
304       sizeof (h265_sei_mdcv));
305   memcpy (h265_idr_plus_sei + sizeof (h265_sei_clli) + sizeof (h265_sei_mdcv),
306       h265_idr, sizeof (h265_idr));
307 
308   caps =
309       gst_parser_test_get_output_caps (h265_idr_plus_sei,
310       h265_idr_plus_sei_size, NULL);
311   fail_unless (caps != NULL);
312 
313   /* Check that the negotiated caps are as expected */
314   GST_DEBUG ("output caps: %" GST_PTR_FORMAT, caps);
315   s = gst_caps_get_structure (caps, 0);
316   fail_unless (gst_structure_has_name (s, "video/x-h265"));
317   fail_unless_structure_field_int_equals (s, "width", 16);
318   fail_unless_structure_field_int_equals (s, "height", 16);
319   fail_unless_structure_field_string_equals (s, "stream-format", "byte-stream");
320   fail_unless_structure_field_string_equals (s, "alignment", "au");
321   fail_unless_structure_field_string_equals (s, "profile", "main");
322   fail_unless_structure_field_string_equals (s, "tier", "main");
323   fail_unless_structure_field_string_equals (s, "level", "2.1");
324   fail_unless_structure_field_string_equals (s, "mastering-display-info",
325       "34000:16000:13250:34500:7500:3000:15635:16450:10000000:1");
326   fail_unless_structure_field_string_equals (s, "content-light-level",
327       "1000:400");
328 
329   g_free (h265_idr_plus_sei);
330   gst_caps_unref (caps);
331 }
332 
333 GST_END_TEST;
334 
335 static Suite *
h265parse_suite(void)336 h265parse_suite (void)
337 {
338   Suite *s = suite_create (ctx_suite);
339   TCase *tc_chain = tcase_create ("general");
340 
341   suite_add_tcase (s, tc_chain);
342   tcase_add_test (tc_chain, test_parse_normal);
343   tcase_add_test (tc_chain, test_parse_drain_single);
344   tcase_add_test (tc_chain, test_parse_split);
345   tcase_add_test (tc_chain, test_parse_detect_stream);
346   tcase_add_test (tc_chain, test_parse_detect_stream_with_hdr_sei);
347 
348   return s;
349 }
350 
351 
352 /* helper methods for GstHasness based tests */
353 
354 static inline GstBuffer *
wrap_buffer(const guint8 * buf,gsize size,GstClockTime pts,GstBufferFlags flags)355 wrap_buffer (const guint8 * buf, gsize size, GstClockTime pts,
356     GstBufferFlags flags)
357 {
358   GstBuffer *buffer;
359 
360   buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
361       (gpointer) buf, size, 0, size, NULL, NULL);
362   GST_BUFFER_PTS (buffer) = pts;
363   GST_BUFFER_FLAGS (buffer) |= flags;
364 
365   return buffer;
366 }
367 
368 static inline GstBuffer *
composite_buffer(GstClockTime pts,GstBufferFlags flags,gint count,...)369 composite_buffer (GstClockTime pts, GstBufferFlags flags, gint count, ...)
370 {
371   va_list vl;
372   gint i;
373   const guint8 *data;
374   gsize size;
375   GstBuffer *buffer;
376 
377   va_start (vl, count);
378 
379   buffer = gst_buffer_new ();
380   for (i = 0; i < count; i++) {
381     data = va_arg (vl, guint8 *);
382     size = va_arg (vl, gsize);
383 
384     buffer = gst_buffer_append (buffer, wrap_buffer (data, size, 0, 0));
385   }
386   GST_BUFFER_PTS (buffer) = pts;
387   GST_BUFFER_FLAGS (buffer) |= flags;
388 
389   va_end (vl);
390 
391   return buffer;
392 }
393 
394 static inline void
pull_and_check_full(GstHarness * h,const guint8 * data,gsize size,GstClockTime pts,GstBufferFlags flags)395 pull_and_check_full (GstHarness * h, const guint8 * data, gsize size,
396     GstClockTime pts, GstBufferFlags flags)
397 {
398   GstBuffer *b = gst_harness_pull (h);
399   gst_check_buffer_data (b, data, size);
400   fail_unless_equals_clocktime (GST_BUFFER_PTS (b), pts);
401   if (flags)
402     fail_unless (GST_BUFFER_FLAG_IS_SET (b, flags));
403   gst_buffer_unref (b);
404 }
405 
406 #define pull_and_check(h, data, pts, flags) \
407   pull_and_check_full (h, data, sizeof (data), pts, flags)
408 
409 #define pull_and_check_composite(h, pts, flags, ...) \
410   G_STMT_START { \
411     GstMapInfo info; \
412     GstBuffer *cb; \
413     \
414     cb = composite_buffer (0, 0, __VA_ARGS__); \
415     gst_buffer_map (cb, &info, GST_MAP_READ); \
416     \
417     pull_and_check_full (h, info.data, info.size, pts, flags); \
418     \
419     gst_buffer_unmap (cb, &info); \
420     gst_buffer_unref (cb); \
421   } G_STMT_END
422 
423 #define pull_and_drop(h) \
424   G_STMT_START { \
425     GstBuffer *b = gst_harness_pull (h); \
426     gst_buffer_unref (b); \
427   } G_STMT_END
428 
429 #define HEADER_DATA \
430   const guint8 * const vps = sliced ? h265_128x128_sliced_vps : h265_128x128_vps; \
431   const guint8 * const sps = sliced ? h265_128x128_sliced_sps : h265_128x128_sps; \
432   const guint8 * const pps = sliced ? h265_128x128_sliced_pps : h265_128x128_pps; \
433   const gsize vps_size = sliced ? sizeof (h265_128x128_sliced_vps) : sizeof (h265_128x128_vps); \
434   const gsize sps_size = sliced ? sizeof (h265_128x128_sliced_sps) : sizeof (h265_128x128_sps); \
435   const gsize pps_size = sliced ? sizeof (h265_128x128_sliced_pps) : sizeof (h265_128x128_pps)
436 
437 #define SLICE_DATA \
438   const guint8 * const slice_1 = sliced ? h265_128x128_slice_1_idr_n_lp : h265_128x128_slice_idr_n_lp; \
439   const guint8 * const slice_2 = sliced ? h265_128x128_slice_2_idr_n_lp : NULL; \
440   const gsize slice_1_size = sliced ? sizeof (h265_128x128_slice_1_idr_n_lp) : sizeof (h265_128x128_slice_idr_n_lp); \
441   const gsize slice_2_size = sliced ? sizeof (h265_128x128_slice_2_idr_n_lp) : 0
442 
443 #define bytestream_set_caps(h, in_align, out_align) \
444   gst_harness_set_caps_str (h, \
445       "video/x-h265, parsed=(boolean)false, stream-format=byte-stream, alignment=" in_align ", framerate=30/1", \
446       "video/x-h265, parsed=(boolean)true, stream-format=byte-stream, alignment=" out_align)
447 
448 static inline void
bytestream_push_first_au_inalign_nal(GstHarness * h,gboolean sliced)449 bytestream_push_first_au_inalign_nal (GstHarness * h, gboolean sliced)
450 {
451   HEADER_DATA;
452   SLICE_DATA;
453   GstBuffer *buf;
454 
455   buf = wrap_buffer (vps, vps_size, 10, 0);
456   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
457 
458   buf = wrap_buffer (sps, sps_size, 10, 0);
459   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
460 
461   buf = wrap_buffer (pps, pps_size, 10, 0);
462   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
463 
464   buf = wrap_buffer (slice_1, slice_1_size, 10, 0);
465   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
466 
467   if (sliced) {
468     buf = wrap_buffer (slice_2, slice_2_size, 10, 0);
469     fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
470   }
471 }
472 
473 static inline void
bytestream_push_first_au_inalign_au(GstHarness * h,gboolean sliced)474 bytestream_push_first_au_inalign_au (GstHarness * h, gboolean sliced)
475 {
476   HEADER_DATA;
477   SLICE_DATA;
478   GstBuffer *buf;
479 
480   buf = composite_buffer (10, 0, sliced ? 5 : 4,
481       vps, vps_size, sps, sps_size, pps, pps_size,
482       slice_1, slice_1_size, slice_2, slice_2_size);
483   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
484 }
485 
486 /* tests */
487 
488 static void
test_flow_outalign_nal(GstHarness * h)489 test_flow_outalign_nal (GstHarness * h)
490 {
491   GstBuffer *buf;
492 
493   /* drop the first AU - tested separately */
494   fail_unless (gst_harness_buffers_in_queue (h) > 0);
495   while (gst_harness_buffers_in_queue (h) > 0)
496     pull_and_drop (h);
497 
498   buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
499       sizeof (h265_128x128_slice_idr_n_lp), 100, 0);
500   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
501   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
502   pull_and_check (h, h265_128x128_slice_idr_n_lp, 100, 0);
503 
504   buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
505       sizeof (h265_128x128_slice_idr_n_lp), 200, 0);
506   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
507   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
508   pull_and_check (h, h265_128x128_slice_idr_n_lp, 200, 0);
509 }
510 
511 static void
test_flow_outalign_au(GstHarness * h)512 test_flow_outalign_au (GstHarness * h)
513 {
514   GstBuffer *buf;
515 
516   /* drop the first AU - tested separately */
517   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
518   pull_and_drop (h);
519 
520   buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
521       sizeof (h265_128x128_slice_idr_n_lp), 100, 0);
522   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
523   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
524   pull_and_check (h, h265_128x128_slice_idr_n_lp, 100, 0);
525 
526   buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
527       sizeof (h265_128x128_slice_idr_n_lp), 200, 0);
528   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
529   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
530   pull_and_check (h, h265_128x128_slice_idr_n_lp, 200, 0);
531 }
532 
GST_START_TEST(test_flow_nal_nal)533 GST_START_TEST (test_flow_nal_nal)
534 {
535   GstHarness *h = gst_harness_new ("h265parse");
536 
537   bytestream_set_caps (h, "nal", "nal");
538   bytestream_push_first_au_inalign_nal (h, FALSE);
539   test_flow_outalign_nal (h);
540 
541   gst_harness_teardown (h);
542 }
543 
544 GST_END_TEST;
545 
GST_START_TEST(test_flow_au_nal)546 GST_START_TEST (test_flow_au_nal)
547 {
548   GstHarness *h = gst_harness_new ("h265parse");
549 
550   bytestream_set_caps (h, "au", "nal");
551   bytestream_push_first_au_inalign_au (h, FALSE);
552   test_flow_outalign_nal (h);
553 
554   gst_harness_teardown (h);
555 }
556 
557 GST_END_TEST;
558 
GST_START_TEST(test_flow_nal_au)559 GST_START_TEST (test_flow_nal_au)
560 {
561   GstHarness *h = gst_harness_new ("h265parse");
562   GstBuffer *buf;
563 
564   bytestream_set_caps (h, "nal", "au");
565   bytestream_push_first_au_inalign_nal (h, FALSE);
566 
567   /* special case because we have latency */
568 
569   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
570 
571   buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
572       sizeof (h265_128x128_slice_idr_n_lp), 100, 0);
573   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
574 
575   /* drop the first AU - tested separately */
576   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
577   pull_and_drop (h);
578 
579   buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
580       sizeof (h265_128x128_slice_idr_n_lp), 200, 0);
581   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
582 
583   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
584   pull_and_check (h, h265_128x128_slice_idr_n_lp, 100, 0);
585 
586   gst_harness_teardown (h);
587 }
588 
589 GST_END_TEST;
590 
GST_START_TEST(test_flow_au_au)591 GST_START_TEST (test_flow_au_au)
592 {
593   GstHarness *h = gst_harness_new ("h265parse");
594 
595   bytestream_set_caps (h, "au", "au");
596   bytestream_push_first_au_inalign_au (h, FALSE);
597   test_flow_outalign_au (h);
598 
599   gst_harness_teardown (h);
600 }
601 
602 GST_END_TEST;
603 
604 static void
test_headers_outalign_nal(GstHarness * h)605 test_headers_outalign_nal (GstHarness * h)
606 {
607   /* 5 -> AUD + VPS + SPS + PPS + slice */
608   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4);
609 
610   /* parser must have inserted AUD before the headers, with the same PTS */
611   pull_and_check (h, h265_128x128_vps, 10, 0);
612   pull_and_check (h, h265_128x128_sps, 10, 0);
613   pull_and_check (h, h265_128x128_pps, 10, 0);
614 
615   /* FIXME The timestamp should be 10 really, but base parse refuse to repeat
616    * the same TS for two consecutive calls to _finish_frame(), see [0] for
617    * more details. It's not a huge issue, the decoder can fix it for now.
618    *
619    * [0] https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/287
620    */
621   pull_and_check (h, h265_128x128_slice_idr_n_lp, -1, 0);
622 }
623 
624 static void
test_headers_outalign_au(GstHarness * h)625 test_headers_outalign_au (GstHarness * h)
626 {
627   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
628   pull_and_check_composite (h, 10, 0, 4,
629       h265_128x128_vps, sizeof (h265_128x128_vps),
630       h265_128x128_sps, sizeof (h265_128x128_sps),
631       h265_128x128_pps, sizeof (h265_128x128_pps),
632       h265_128x128_slice_idr_n_lp, sizeof (h265_128x128_slice_idr_n_lp));
633 }
634 
GST_START_TEST(test_headers_nal_nal)635 GST_START_TEST (test_headers_nal_nal)
636 {
637   GstHarness *h = gst_harness_new ("h265parse");
638 
639   bytestream_set_caps (h, "nal", "nal");
640   bytestream_push_first_au_inalign_nal (h, FALSE);
641   test_headers_outalign_nal (h);
642 
643   gst_harness_teardown (h);
644 }
645 
646 GST_END_TEST;
647 
GST_START_TEST(test_headers_au_nal)648 GST_START_TEST (test_headers_au_nal)
649 {
650   GstHarness *h = gst_harness_new ("h265parse");
651 
652   bytestream_set_caps (h, "au", "nal");
653   bytestream_push_first_au_inalign_au (h, FALSE);
654   test_headers_outalign_nal (h);
655 
656   gst_harness_teardown (h);
657 }
658 
659 GST_END_TEST;
660 
GST_START_TEST(test_headers_au_au)661 GST_START_TEST (test_headers_au_au)
662 {
663   GstHarness *h = gst_harness_new ("h265parse");
664 
665   bytestream_set_caps (h, "au", "au");
666   bytestream_push_first_au_inalign_au (h, FALSE);
667   test_headers_outalign_au (h);
668 
669   gst_harness_teardown (h);
670 }
671 
672 GST_END_TEST;
673 
GST_START_TEST(test_latency_nal_nal)674 GST_START_TEST (test_latency_nal_nal)
675 {
676   GstHarness *h = gst_harness_new ("h265parse");
677 
678   bytestream_set_caps (h, "nal", "nal");
679   bytestream_push_first_au_inalign_nal (h, FALSE);
680 
681   fail_unless_equals_clocktime (gst_harness_query_latency (h), 0);
682 
683   gst_harness_teardown (h);
684 }
685 
686 GST_END_TEST;
687 
GST_START_TEST(test_latency_au_nal)688 GST_START_TEST (test_latency_au_nal)
689 {
690   GstHarness *h = gst_harness_new ("h265parse");
691 
692   bytestream_set_caps (h, "au", "nal");
693   bytestream_push_first_au_inalign_au (h, FALSE);
694 
695   fail_unless_equals_clocktime (gst_harness_query_latency (h), 0);
696 
697   gst_harness_teardown (h);
698 }
699 
700 GST_END_TEST;
701 
GST_START_TEST(test_latency_nal_au)702 GST_START_TEST (test_latency_nal_au)
703 {
704   GstHarness *h = gst_harness_new ("h265parse");
705   GstBuffer *buf;
706 
707   bytestream_set_caps (h, "nal", "au");
708   bytestream_push_first_au_inalign_nal (h, FALSE);
709 
710   /* special case because we have latency;
711    * the first buffer needs to be pushed out
712    * before we can correctly query the latency */
713   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
714   buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
715       sizeof (h265_128x128_slice_idr_n_lp), 100, 0);
716   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
717 
718   /* our input caps declare framerate=30fps, so the latency must be 1/30 sec */
719   fail_unless_equals_clocktime (gst_harness_query_latency (h),
720       gst_util_uint64_scale (GST_SECOND, 1, 30));
721 
722   gst_harness_teardown (h);
723 }
724 
725 GST_END_TEST;
726 
GST_START_TEST(test_latency_au_au)727 GST_START_TEST (test_latency_au_au)
728 {
729   GstHarness *h = gst_harness_new ("h265parse");
730 
731   bytestream_set_caps (h, "au", "au");
732   bytestream_push_first_au_inalign_au (h, FALSE);
733 
734   fail_unless_equals_clocktime (gst_harness_query_latency (h), 0);
735 
736   gst_harness_teardown (h);
737 }
738 
739 GST_END_TEST;
740 
741 static void
test_discont_outalign_nal(GstHarness * h)742 test_discont_outalign_nal (GstHarness * h)
743 {
744   GstBuffer *buf;
745 
746   /* drop the first AU - tested separately */
747   fail_unless (gst_harness_buffers_in_queue (h) > 0);
748   while (gst_harness_buffers_in_queue (h) > 0)
749     pull_and_drop (h);
750 
751   /* FIXME: I think the AUD ought to have DISCONT */
752   buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
753       sizeof (h265_128x128_slice_idr_n_lp), 1000, GST_BUFFER_FLAG_DISCONT);
754   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
755   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
756   pull_and_check (h, h265_128x128_slice_idr_n_lp, 1000,
757       GST_BUFFER_FLAG_DISCONT);
758 }
759 
760 static void
test_discont_outalign_au(GstHarness * h)761 test_discont_outalign_au (GstHarness * h)
762 {
763   GstBuffer *buf;
764 
765   /* drop the first AU - tested separately */
766   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
767   pull_and_drop (h);
768 
769   buf = wrap_buffer (h265_128x128_slice_idr_n_lp,
770       sizeof (h265_128x128_slice_idr_n_lp), 1000, GST_BUFFER_FLAG_DISCONT);
771   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
772   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
773   pull_and_check (h, h265_128x128_slice_idr_n_lp, 1000,
774       GST_BUFFER_FLAG_DISCONT);
775 }
776 
GST_START_TEST(test_discont_nal_nal)777 GST_START_TEST (test_discont_nal_nal)
778 {
779   GstHarness *h = gst_harness_new ("h265parse");
780 
781   bytestream_set_caps (h, "nal", "nal");
782   bytestream_push_first_au_inalign_nal (h, FALSE);
783   test_discont_outalign_nal (h);
784 
785   gst_harness_teardown (h);
786 }
787 
788 GST_END_TEST;
789 
GST_START_TEST(test_discont_au_nal)790 GST_START_TEST (test_discont_au_nal)
791 {
792   GstHarness *h = gst_harness_new ("h265parse");
793 
794   bytestream_set_caps (h, "au", "nal");
795   bytestream_push_first_au_inalign_au (h, FALSE);
796   test_discont_outalign_nal (h);
797 
798   gst_harness_teardown (h);
799 }
800 
801 GST_END_TEST;
802 
GST_START_TEST(test_discont_au_au)803 GST_START_TEST (test_discont_au_au)
804 {
805   GstHarness *h = gst_harness_new ("h265parse");
806 
807   bytestream_set_caps (h, "au", "au");
808   bytestream_push_first_au_inalign_au (h, FALSE);
809   test_discont_outalign_au (h);
810 
811   gst_harness_teardown (h);
812 }
813 
814 GST_END_TEST;
815 
GST_START_TEST(test_sliced_nal_nal)816 GST_START_TEST (test_sliced_nal_nal)
817 {
818   GstHarness *h = gst_harness_new ("h265parse");
819   GstBuffer *buf;
820 
821   bytestream_set_caps (h, "nal", "nal");
822   bytestream_push_first_au_inalign_nal (h, TRUE);
823 
824   /* drop the header buffers */
825   fail_unless (gst_harness_buffers_in_queue (h) > 2);
826   while (gst_harness_buffers_in_queue (h) > 2)
827     pull_and_drop (h);
828 
829   /* but expect 2 slices */
830   pull_and_check (h, h265_128x128_slice_1_idr_n_lp, -1, 0);
831   pull_and_check (h, h265_128x128_slice_2_idr_n_lp, -1, 0);
832 
833   /* push some more */
834   buf = wrap_buffer (h265_128x128_slice_1_idr_n_lp,
835       sizeof (h265_128x128_slice_1_idr_n_lp), 100, 0);
836   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
837   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
838   pull_and_check (h, h265_128x128_slice_1_idr_n_lp, 100, 0);
839 
840   buf = wrap_buffer (h265_128x128_slice_2_idr_n_lp,
841       sizeof (h265_128x128_slice_2_idr_n_lp), 100, 0);
842   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
843   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
844   pull_and_check (h, h265_128x128_slice_2_idr_n_lp, -1, 0);
845 
846   gst_harness_teardown (h);
847 }
848 
849 GST_END_TEST;
850 
GST_START_TEST(test_sliced_au_nal)851 GST_START_TEST (test_sliced_au_nal)
852 {
853   GstHarness *h = gst_harness_new ("h265parse");
854   GstBuffer *buf;
855 
856   bytestream_set_caps (h, "au", "nal");
857   bytestream_push_first_au_inalign_au (h, TRUE);
858 
859   /* drop the header buffers */
860   fail_unless (gst_harness_buffers_in_queue (h) > 2);
861   while (gst_harness_buffers_in_queue (h) > 2)
862     pull_and_drop (h);
863 
864   /* but expect 2 slices */
865   pull_and_check (h, h265_128x128_slice_1_idr_n_lp, -1, 0);
866   pull_and_check (h, h265_128x128_slice_2_idr_n_lp, -1, 0);
867 
868   /* push some more */
869   buf = composite_buffer (100, 0, 2,
870       h265_128x128_slice_1_idr_n_lp, sizeof (h265_128x128_slice_1_idr_n_lp),
871       h265_128x128_slice_2_idr_n_lp, sizeof (h265_128x128_slice_2_idr_n_lp));
872   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
873   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2);
874   pull_and_check (h, h265_128x128_slice_1_idr_n_lp, 100, 0);
875   pull_and_check (h, h265_128x128_slice_2_idr_n_lp, -1, 0);
876 
877   gst_harness_teardown (h);
878 }
879 
880 GST_END_TEST;
881 
GST_START_TEST(test_sliced_nal_au)882 GST_START_TEST (test_sliced_nal_au)
883 {
884   GstHarness *h = gst_harness_new ("h265parse");
885   GstBuffer *buf;
886 
887   bytestream_set_caps (h, "nal", "au");
888   bytestream_push_first_au_inalign_nal (h, TRUE);
889 
890   /* nal -> au has latency; we need to start the next AU to get output */
891   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
892 
893 
894   /* push some more */
895   buf = wrap_buffer (h265_128x128_slice_1_idr_n_lp,
896       sizeof (h265_128x128_slice_1_idr_n_lp), 100, 0);
897   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
898 
899   /* now we can see the initial AU on the output */
900   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
901   pull_and_check_composite (h, 10, 0, 5,
902       h265_128x128_sliced_vps, sizeof (h265_128x128_sliced_vps),
903       h265_128x128_sliced_sps, sizeof (h265_128x128_sliced_sps),
904       h265_128x128_sliced_pps, sizeof (h265_128x128_sliced_pps),
905       h265_128x128_slice_1_idr_n_lp, sizeof (h265_128x128_slice_1_idr_n_lp),
906       h265_128x128_slice_2_idr_n_lp, sizeof (h265_128x128_slice_2_idr_n_lp));
907 
908   buf = wrap_buffer (h265_128x128_slice_2_idr_n_lp,
909       sizeof (h265_128x128_slice_2_idr_n_lp), 100, 0);
910   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
911   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
912 
913   buf = wrap_buffer (h265_128x128_slice_1_idr_n_lp,
914       sizeof (h265_128x128_slice_1_idr_n_lp), 200, 0);
915   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
916 
917   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
918   pull_and_check_composite (h, 100, 0, 2,
919       h265_128x128_slice_1_idr_n_lp, sizeof (h265_128x128_slice_1_idr_n_lp),
920       h265_128x128_slice_2_idr_n_lp, sizeof (h265_128x128_slice_2_idr_n_lp));
921 
922   gst_harness_teardown (h);
923 }
924 
925 GST_END_TEST;
926 
GST_START_TEST(test_sliced_au_au)927 GST_START_TEST (test_sliced_au_au)
928 {
929   GstHarness *h = gst_harness_new ("h265parse");
930   GstBuffer *buf;
931 
932   bytestream_set_caps (h, "au", "au");
933   bytestream_push_first_au_inalign_au (h, TRUE);
934 
935   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
936   pull_and_check_composite (h, 10, 0, 5,
937       h265_128x128_sliced_vps, sizeof (h265_128x128_sliced_vps),
938       h265_128x128_sliced_sps, sizeof (h265_128x128_sliced_sps),
939       h265_128x128_sliced_pps, sizeof (h265_128x128_sliced_pps),
940       h265_128x128_slice_1_idr_n_lp, sizeof (h265_128x128_slice_1_idr_n_lp),
941       h265_128x128_slice_2_idr_n_lp, sizeof (h265_128x128_slice_2_idr_n_lp));
942 
943   /* push some more */
944   buf = composite_buffer (100, 0, 2,
945       h265_128x128_slice_1_idr_n_lp, sizeof (h265_128x128_slice_1_idr_n_lp),
946       h265_128x128_slice_2_idr_n_lp, sizeof (h265_128x128_slice_2_idr_n_lp));
947   fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK);
948   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
949   pull_and_check_composite (h, 100, 0, 2,
950       h265_128x128_slice_1_idr_n_lp, sizeof (h265_128x128_slice_1_idr_n_lp),
951       h265_128x128_slice_2_idr_n_lp, sizeof (h265_128x128_slice_2_idr_n_lp));
952 
953   gst_harness_teardown (h);
954 }
955 
956 GST_END_TEST;
957 
GST_START_TEST(test_parse_skip_to_4bytes_sc)958 GST_START_TEST (test_parse_skip_to_4bytes_sc)
959 {
960   GstHarness *h;
961   GstBuffer *buf1, *buf2;
962   const guint8 initial_bytes[] = { 0x00, 0x00, 0x00, 0x00, 0x01, h265_vps[4] };
963   GstMapInfo map;
964 
965   h = gst_harness_new ("h265parse");
966 
967   gst_harness_set_caps_str (h, "video/x-h265, stream-format=byte-stream",
968       "video/x-h265, stream-format=byte-stream, alignment=nal");
969 
970   /* padding bytes, four bytes start code and 1 of the two identification
971    * bytes. */
972   buf1 = wrap_buffer (initial_bytes, sizeof (initial_bytes), 100, 0);
973 
974   /* The second contains the an VPS, starting from second NAL identification
975    * byte and is followed by an SPS, IDR to ensure that the NAL end can be
976    * found */
977   buf2 = composite_buffer (100, 0, 4, h265_vps + 5, sizeof (h265_vps) - 5,
978       h265_sps, sizeof (h265_sps), h265_pps, sizeof (h265_pps),
979       h265_idr, sizeof (h265_idr));
980 
981   fail_unless_equals_int (gst_harness_push (h, buf1), GST_FLOW_OK);
982   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
983 
984   fail_unless_equals_int (gst_harness_push (h, buf2), GST_FLOW_OK);
985   /* The parser will deliver VPS, SPS, PPS as it now have complete cpas */
986   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 3);
987 
988   buf1 = gst_harness_pull (h);
989   gst_buffer_map (buf1, &map, GST_MAP_READ);
990   fail_unless_equals_int (gst_buffer_get_size (buf1), sizeof (h265_vps));
991   gst_buffer_unmap (buf1, &map);
992   gst_buffer_unref (buf1);
993 
994   gst_harness_teardown (h);
995 }
996 
997 GST_END_TEST;
998 
GST_START_TEST(test_parse_sc_with_half_header)999 GST_START_TEST (test_parse_sc_with_half_header)
1000 {
1001   GstHarness *h;
1002   GstBuffer *buf1, *buf2;
1003   GstMapInfo map;
1004 
1005   h = gst_harness_new ("h265parse");
1006 
1007   gst_harness_set_caps_str (h, "video/x-h265, stream-format=byte-stream",
1008       "video/x-h265, stream-format=byte-stream, alignment=nal");
1009 
1010   buf1 = composite_buffer (100, 0, 4, h265_vps, sizeof (h265_vps),
1011       h265_sps, sizeof (h265_sps), h265_pps, sizeof (h265_pps), h265_idr, 5);
1012   buf2 = wrap_buffer (h265_idr + 5, sizeof (h265_idr) - 5, 100, 0);
1013 
1014   fail_unless_equals_int (gst_harness_push (h, buf1), GST_FLOW_OK);
1015   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1016 
1017   fail_unless_equals_int (gst_harness_push (h, buf2), GST_FLOW_OK);
1018   /* The parser will deliver VPS, SPS, PPS as it now have complete cpas */
1019   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 3);
1020 
1021   buf1 = gst_harness_pull (h);
1022   gst_buffer_map (buf1, &map, GST_MAP_READ);
1023   fail_unless_equals_int (gst_buffer_get_size (buf1), sizeof (h265_vps));
1024   gst_buffer_unmap (buf1, &map);
1025   gst_buffer_unref (buf1);
1026 
1027   gst_harness_teardown (h);
1028 }
1029 
1030 GST_END_TEST;
1031 
1032 
1033 
1034 /* nal->au has latency, but EOS should force the last AU out */
GST_START_TEST(test_drain)1035 GST_START_TEST (test_drain)
1036 {
1037   GstHarness *h = gst_harness_new ("h265parse");
1038 
1039   bytestream_set_caps (h, "nal", "au");
1040   bytestream_push_first_au_inalign_nal (h, FALSE);
1041 
1042   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0);
1043 
1044   gst_harness_push_event (h, gst_event_new_eos ());
1045 
1046   fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1);
1047   pull_and_drop (h);
1048 
1049   gst_harness_teardown (h);
1050 }
1051 
1052 GST_END_TEST;
1053 
1054 
1055 static Suite *
h265parse_harnessed_suite(void)1056 h265parse_harnessed_suite (void)
1057 {
1058   Suite *s = suite_create ("h265parse");
1059   TCase *tc_chain = tcase_create ("general");
1060 
1061   suite_add_tcase (s, tc_chain);
1062   tcase_add_test (tc_chain, test_flow_nal_nal);
1063   tcase_add_test (tc_chain, test_flow_au_nal);
1064   tcase_add_test (tc_chain, test_flow_nal_au);
1065   tcase_add_test (tc_chain, test_flow_au_au);
1066 
1067   tcase_add_test (tc_chain, test_headers_nal_nal);
1068   tcase_add_test (tc_chain, test_headers_au_nal);
1069   tcase_add_test (tc_chain, test_headers_au_au);
1070 
1071   tcase_add_test (tc_chain, test_latency_nal_nal);
1072   tcase_add_test (tc_chain, test_latency_au_nal);
1073   tcase_add_test (tc_chain, test_latency_nal_au);
1074   tcase_add_test (tc_chain, test_latency_au_au);
1075 
1076   tcase_add_test (tc_chain, test_discont_nal_nal);
1077   tcase_add_test (tc_chain, test_discont_au_nal);
1078   tcase_add_test (tc_chain, test_discont_au_au);
1079 
1080   tcase_add_test (tc_chain, test_sliced_nal_nal);
1081   tcase_add_test (tc_chain, test_sliced_au_nal);
1082   tcase_add_test (tc_chain, test_sliced_nal_au);
1083   tcase_add_test (tc_chain, test_sliced_au_au);
1084 
1085   tcase_add_test (tc_chain, test_parse_skip_to_4bytes_sc);
1086   tcase_add_test (tc_chain, test_parse_sc_with_half_header);
1087 
1088   tcase_add_test (tc_chain, test_drain);
1089 
1090   return s;
1091 }
1092 
1093 int
main(int argc,char ** argv)1094 main (int argc, char **argv)
1095 {
1096   int nf = 0;
1097 
1098   Suite *s;
1099 
1100   gst_check_init (&argc, &argv);
1101 
1102   /* init test context */
1103   ctx_factory = "h265parse";
1104   ctx_sink_template = &sinktemplate_bs_au;
1105   ctx_src_template = &srctemplate;
1106   /* no timing info to parse */
1107   ctx_headers[0].data = h265_vps;
1108   ctx_headers[0].size = sizeof (h265_vps);
1109   ctx_headers[1].data = h265_sps;
1110   ctx_headers[1].size = sizeof (h265_sps);
1111   ctx_headers[2].data = h265_pps;
1112   ctx_headers[2].size = sizeof (h265_pps);
1113   ctx_verify_buffer = verify_buffer_bs_au;
1114 
1115   /* discard initial vps/sps/pps buffers */
1116   ctx_discard = 0;
1117   /* no timing info to parse */
1118   ctx_no_metadata = TRUE;
1119   ctx_codec_data = FALSE;
1120 
1121   ctx_suite = "h265parse_to_bs_au";
1122   s = h265parse_suite ();
1123   nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_to_bs_au.c");
1124 
1125   ctx_suite = "h265parse_harnessed";
1126   s = h265parse_harnessed_suite ();
1127   nf += gst_check_run_suite (s, ctx_suite, __FILE__ "_harnessed.c");
1128 
1129   return nf;
1130 }
1131