1 /* GStreamer
2 *
3 * Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include <gst/gst.h>
25 #include <gst/check/gstcheck.h>
26 #include <gst/check/gstharness.h>
27 #include <gst/video/video.h>
28
29 #include <string.h>
30
31 #define VIDEO_CAPS_STR "video/x-raw, " \
32 "format = (string) UYVY, " \
33 "width = (int) 1920, " \
34 "height = (int) 1080, " \
35 "framerate = (fraction) 30/1"
36
37 static GstStaticCaps video_caps = GST_STATIC_CAPS (VIDEO_CAPS_STR);
38 static GstStaticCaps cea708_cc_data_caps =
39 GST_STATIC_CAPS
40 ("closedcaption/x-cea-708,format=(string) cc_data, framerate = (fraction) 30/1");
41 static GstStaticCaps cea708_cdp_caps =
42 GST_STATIC_CAPS
43 ("closedcaption/x-cea-708,format=(string) cdp, framerate = (fraction) 30/1");
44
GST_START_TEST(no_captions)45 GST_START_TEST (no_captions)
46 {
47 GstHarness *h;
48 GstBuffer *buf, *outbuf;
49 GstCaps *caps;
50
51 h = gst_harness_new ("ccextractor");
52
53 gst_harness_set_src_caps_str (h, VIDEO_CAPS_STR);
54
55 buf = gst_buffer_new_and_alloc (128);
56 outbuf = gst_harness_push_and_pull (h, gst_buffer_ref (buf));
57
58 fail_unless (outbuf != NULL);
59 fail_unless (outbuf == buf);
60 fail_unless (gst_element_get_static_pad (h->element, "caption") == NULL);
61
62 caps = gst_pad_get_current_caps (h->sinkpad);
63 fail_unless (caps != NULL);
64 fail_unless (gst_caps_can_intersect (caps,
65 gst_static_caps_get (&video_caps)));
66 gst_caps_unref (caps);
67
68 gst_buffer_unref (buf);
69 gst_buffer_unref (outbuf);
70
71 gst_harness_teardown (h);
72 }
73
74 GST_END_TEST;
75
76 static void
on_caption_pad_added(GstElement * ccextractor,GstPad * pad,GstHarness * h)77 on_caption_pad_added (GstElement * ccextractor, GstPad * pad, GstHarness * h)
78 {
79 fail_unless (strcmp (GST_OBJECT_NAME (pad), "caption") == 0);
80 gst_harness_add_element_src_pad (h, pad);
81 }
82
GST_START_TEST(captions)83 GST_START_TEST (captions)
84 {
85 GstHarness *h, *h2;
86 GstBuffer *buf, *outbuf;
87 const guint8 caption_data[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
88 GstCaps *caps;
89 GstVideoTimeCode *tc;
90 GstVideoTimeCodeMeta *tc_meta;
91
92 h = gst_harness_new ("ccextractor");
93 h2 = gst_harness_new_with_element (h->element, NULL, NULL);
94
95 g_signal_connect (h->element, "pad-added", G_CALLBACK (on_caption_pad_added),
96 h2);
97
98 gst_harness_set_src_caps_str (h, VIDEO_CAPS_STR);
99
100 buf = gst_buffer_new_and_alloc (128);
101 gst_buffer_add_video_caption_meta (buf, GST_VIDEO_CAPTION_TYPE_CEA708_RAW,
102 caption_data, sizeof (caption_data));
103
104 tc = gst_video_time_code_new (30, 1, NULL, GST_VIDEO_TIME_CODE_FLAGS_NONE, 0,
105 0, 0, 0, 0);
106 gst_buffer_add_video_time_code_meta (buf, tc);
107
108 outbuf = gst_harness_push_and_pull (h, gst_buffer_ref (buf));
109
110 fail_unless (outbuf != NULL);
111 fail_unless (outbuf == buf);
112
113 tc_meta = gst_buffer_get_video_time_code_meta (outbuf);
114 fail_unless (tc_meta != NULL);
115 fail_unless_equals_int (gst_video_time_code_compare (&tc_meta->tc, tc), 0);
116
117 gst_buffer_unref (outbuf);
118 gst_buffer_unref (buf);
119
120 fail_unless (h2->sinkpad != NULL);
121 outbuf = gst_harness_pull (h2);
122 fail_unless (outbuf != NULL);
123 fail_unless (gst_buffer_memcmp (outbuf, 0, caption_data,
124 sizeof (caption_data)) == 0);
125
126 tc_meta = gst_buffer_get_video_time_code_meta (outbuf);
127 fail_unless (tc_meta != NULL);
128 fail_unless_equals_int (gst_video_time_code_compare (&tc_meta->tc, tc), 0);
129 gst_video_time_code_free (tc);
130
131 gst_buffer_unref (outbuf);
132
133 caps = gst_pad_get_current_caps (h->sinkpad);
134 fail_unless (caps != NULL);
135 fail_unless (gst_caps_can_intersect (caps,
136 gst_static_caps_get (&video_caps)));
137 gst_caps_unref (caps);
138
139 caps = gst_pad_get_current_caps (h2->sinkpad);
140 fail_unless (caps != NULL);
141 fail_unless (gst_caps_can_intersect (caps,
142 gst_static_caps_get (&cea708_cc_data_caps)));
143 gst_caps_unref (caps);
144
145 buf = gst_buffer_new_and_alloc (128);
146 gst_buffer_add_video_caption_meta (buf, GST_VIDEO_CAPTION_TYPE_CEA708_RAW,
147 caption_data, sizeof (caption_data));
148
149 tc = gst_video_time_code_new (30, 1, NULL, GST_VIDEO_TIME_CODE_FLAGS_NONE, 0,
150 0, 0, 1, 0);
151 gst_buffer_add_video_time_code_meta (buf, tc);
152
153 outbuf = gst_harness_push_and_pull (h, gst_buffer_ref (buf));
154
155 fail_unless (outbuf != NULL);
156 fail_unless (outbuf == buf);
157
158 tc_meta = gst_buffer_get_video_time_code_meta (outbuf);
159 fail_unless (tc_meta != NULL);
160 fail_unless_equals_int (gst_video_time_code_compare (&tc_meta->tc, tc), 0);
161
162 gst_buffer_unref (outbuf);
163 gst_buffer_unref (buf);
164
165 fail_unless (h2->sinkpad != NULL);
166 outbuf = gst_harness_pull (h2);
167 fail_unless (outbuf != NULL);
168 fail_unless (gst_buffer_memcmp (outbuf, 0, caption_data,
169 sizeof (caption_data)) == 0);
170
171 tc_meta = gst_buffer_get_video_time_code_meta (outbuf);
172 fail_unless (tc_meta != NULL);
173 fail_unless_equals_int (gst_video_time_code_compare (&tc_meta->tc, tc), 0);
174 gst_video_time_code_free (tc);
175
176 gst_buffer_unref (outbuf);
177
178 caps = gst_pad_get_current_caps (h->sinkpad);
179 fail_unless (caps != NULL);
180 fail_unless (gst_caps_can_intersect (caps,
181 gst_static_caps_get (&video_caps)));
182 gst_caps_unref (caps);
183
184 caps = gst_pad_get_current_caps (h2->sinkpad);
185 fail_unless (caps != NULL);
186 fail_unless (gst_caps_can_intersect (caps,
187 gst_static_caps_get (&cea708_cc_data_caps)));
188 gst_caps_unref (caps);
189
190 gst_harness_teardown (h);
191 gst_harness_teardown (h2);
192 }
193
194 GST_END_TEST;
195
GST_START_TEST(no_captions_at_beginning_and_end)196 GST_START_TEST (no_captions_at_beginning_and_end)
197 {
198 GstHarness *h, *h2;
199 GstBuffer *buf, *outbuf;
200 const guint8 caption_data[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
201 GstCaps *caps;
202
203 h = gst_harness_new ("ccextractor");
204 h2 = gst_harness_new_with_element (h->element, NULL, NULL);
205
206 g_signal_connect (h->element, "pad-added", G_CALLBACK (on_caption_pad_added),
207 h2);
208
209 gst_harness_set_src_caps_str (h, VIDEO_CAPS_STR);
210
211 buf = gst_buffer_new_and_alloc (128);
212
213 outbuf = gst_harness_push_and_pull (h, gst_buffer_ref (buf));
214
215 fail_unless (outbuf != NULL);
216 fail_unless (outbuf == buf);
217 gst_buffer_unref (outbuf);
218 gst_buffer_unref (buf);
219
220 buf = gst_buffer_new_and_alloc (128);
221 gst_buffer_add_video_caption_meta (buf, GST_VIDEO_CAPTION_TYPE_CEA708_RAW,
222 caption_data, sizeof (caption_data));
223
224 outbuf = gst_harness_push_and_pull (h, gst_buffer_ref (buf));
225
226 fail_unless (outbuf != NULL);
227 fail_unless (outbuf == buf);
228 gst_buffer_unref (outbuf);
229 gst_buffer_unref (buf);
230
231 caps = gst_pad_get_current_caps (h->sinkpad);
232 fail_unless (caps != NULL);
233 fail_unless (gst_caps_can_intersect (caps,
234 gst_static_caps_get (&video_caps)));
235 gst_caps_unref (caps);
236
237 fail_unless (h2->sinkpad != NULL);
238 outbuf = gst_harness_pull (h2);
239 fail_unless (outbuf != NULL);
240 fail_unless (gst_buffer_memcmp (outbuf, 0, caption_data,
241 sizeof (caption_data)) == 0);
242 gst_buffer_unref (outbuf);
243
244 caps = gst_pad_get_current_caps (h->sinkpad);
245 fail_unless (caps != NULL);
246 fail_unless (gst_caps_can_intersect (caps,
247 gst_static_caps_get (&video_caps)));
248 gst_caps_unref (caps);
249
250 caps = gst_pad_get_current_caps (h2->sinkpad);
251 fail_unless (caps != NULL);
252 fail_unless (gst_caps_can_intersect (caps,
253 gst_static_caps_get (&cea708_cc_data_caps)));
254 gst_caps_unref (caps);
255
256 buf = gst_buffer_new_and_alloc (128);
257
258 outbuf = gst_harness_push_and_pull (h, gst_buffer_ref (buf));
259
260 fail_unless (outbuf != NULL);
261 fail_unless (outbuf == buf);
262 gst_buffer_unref (outbuf);
263 gst_buffer_unref (buf);
264
265 fail_if (gst_harness_try_pull (h2) != NULL);
266
267 caps = gst_pad_get_current_caps (h->sinkpad);
268 fail_unless (caps != NULL);
269 fail_unless (gst_caps_can_intersect (caps,
270 gst_static_caps_get (&video_caps)));
271 gst_caps_unref (caps);
272
273 caps = gst_pad_get_current_caps (h2->sinkpad);
274 fail_unless (caps != NULL);
275 fail_unless (gst_caps_can_intersect (caps,
276 gst_static_caps_get (&cea708_cc_data_caps)));
277 gst_caps_unref (caps);
278
279 gst_harness_teardown (h);
280 gst_harness_teardown (h2);
281 }
282
283 GST_END_TEST;
284
GST_START_TEST(captions_format_change)285 GST_START_TEST (captions_format_change)
286 {
287 GstHarness *h, *h2;
288 GstBuffer *buf, *outbuf;
289 const guint8 caption_data[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
290 GstCaps *caps;
291
292 h = gst_harness_new ("ccextractor");
293 h2 = gst_harness_new_with_element (h->element, NULL, NULL);
294
295 g_signal_connect (h->element, "pad-added", G_CALLBACK (on_caption_pad_added),
296 h2);
297
298 gst_harness_set_src_caps_str (h, VIDEO_CAPS_STR);
299
300 buf = gst_buffer_new_and_alloc (128);
301 gst_buffer_add_video_caption_meta (buf, GST_VIDEO_CAPTION_TYPE_CEA708_RAW,
302 caption_data, sizeof (caption_data));
303
304 outbuf = gst_harness_push_and_pull (h, gst_buffer_ref (buf));
305
306 fail_unless (outbuf != NULL);
307 fail_unless (outbuf == buf);
308 gst_buffer_unref (outbuf);
309 gst_buffer_unref (buf);
310
311 fail_unless (h2->sinkpad != NULL);
312 outbuf = gst_harness_pull (h2);
313 fail_unless (outbuf != NULL);
314 fail_unless (gst_buffer_memcmp (outbuf, 0, caption_data,
315 sizeof (caption_data)) == 0);
316 gst_buffer_unref (outbuf);
317
318 caps = gst_pad_get_current_caps (h->sinkpad);
319 fail_unless (caps != NULL);
320 fail_unless (gst_caps_can_intersect (caps,
321 gst_static_caps_get (&video_caps)));
322 gst_caps_unref (caps);
323
324 caps = gst_pad_get_current_caps (h2->sinkpad);
325 fail_unless (caps != NULL);
326 fail_unless (gst_caps_can_intersect (caps,
327 gst_static_caps_get (&cea708_cc_data_caps)));
328 gst_caps_unref (caps);
329
330 buf = gst_buffer_new_and_alloc (128);
331 gst_buffer_add_video_caption_meta (buf, GST_VIDEO_CAPTION_TYPE_CEA708_CDP,
332 caption_data, sizeof (caption_data));
333
334 outbuf = gst_harness_push_and_pull (h, gst_buffer_ref (buf));
335
336 fail_unless (outbuf != NULL);
337 fail_unless (outbuf == buf);
338 gst_buffer_unref (outbuf);
339 gst_buffer_unref (buf);
340
341 fail_unless (h2->sinkpad != NULL);
342 outbuf = gst_harness_pull (h2);
343 fail_unless (outbuf != NULL);
344 fail_unless (gst_buffer_memcmp (outbuf, 0, caption_data,
345 sizeof (caption_data)) == 0);
346 gst_buffer_unref (outbuf);
347
348 caps = gst_pad_get_current_caps (h->sinkpad);
349 fail_unless (caps != NULL);
350 fail_unless (gst_caps_can_intersect (caps,
351 gst_static_caps_get (&video_caps)));
352 gst_caps_unref (caps);
353
354 caps = gst_pad_get_current_caps (h2->sinkpad);
355 fail_unless (caps != NULL);
356 fail_unless (gst_caps_can_intersect (caps,
357 gst_static_caps_get (&cea708_cdp_caps)));
358 gst_caps_unref (caps);
359
360 gst_harness_teardown (h);
361 gst_harness_teardown (h2);
362 }
363
364 GST_END_TEST;
365
366 static Suite *
ccextractor_suite(void)367 ccextractor_suite (void)
368 {
369 Suite *s = suite_create ("ccextractor");
370 TCase *tc = tcase_create ("general");
371
372 suite_add_tcase (s, tc);
373
374 tcase_add_test (tc, no_captions);
375 tcase_add_test (tc, captions);
376 tcase_add_test (tc, no_captions_at_beginning_and_end);
377 tcase_add_test (tc, captions_format_change);
378
379 return s;
380 }
381
382 GST_CHECK_MAIN (ccextractor);
383