1 // Copyright (C) 2019 Sebastian Dröge <sebastian@centricular.com>
2 // Copyright (C) 2019 Jordan Petridis <jordan@centricular.com>
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Library General Public
6 // License as published by the Free Software Foundation; either
7 // version 2 of the License, or (at your option) any later version.
8 //
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Library General Public License for more details.
13 //
14 // You should have received a copy of the GNU Library General Public
15 // License along with this library; if not, write to the
16 // Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
17 // Boston, MA 02110-1335, USA.
18
19 use pretty_assertions::assert_eq;
20
init()21 fn init() {
22 use std::sync::Once;
23 static INIT: Once = Once::new();
24
25 INIT.call_once(|| {
26 gst::init().unwrap();
27 gstrsclosedcaption::plugin_register_static().unwrap();
28 });
29 }
30
31 /// Encode a single raw CEA608 packet and compare the output
32 #[test]
test_encode_single_packet()33 fn test_encode_single_packet() {
34 init();
35
36 let input = [148, 44];
37 let expected_output = b"Scenarist_SCC V1.0\r\n\r\n11:12:13;14\t942c\r\n\r\n";
38
39 let mut h = gst_check::Harness::new("sccenc");
40 h.set_src_caps_str("closedcaption/x-cea-608, format=raw, framerate=(fraction)30000/1001");
41 let tc = gst_video::ValidVideoTimeCode::new(
42 gst::Fraction::new(30000, 1001),
43 None,
44 gst_video::VideoTimeCodeFlags::DROP_FRAME,
45 11,
46 12,
47 13,
48 14,
49 0,
50 )
51 .unwrap();
52
53 let buf = {
54 let mut buf = gst::Buffer::from_mut_slice(Vec::from(&input[..]));
55 let buf_ref = buf.get_mut().unwrap();
56 gst_video::VideoTimeCodeMeta::add(buf_ref, &tc);
57 buf_ref.set_pts(gst::ClockTime::from_seconds(0));
58 buf
59 };
60
61 assert_eq!(h.push(buf), Ok(gst::FlowSuccess::Ok));
62 h.push_event(gst::event::Eos::new());
63
64 let buf = h.pull().expect("Couldn't pull buffer");
65
66 let timecode = buf
67 .meta::<gst_video::VideoTimeCodeMeta>()
68 .expect("No timecode for buffer")
69 .tc();
70 assert_eq!(timecode, tc);
71
72 let pts = buf.pts().unwrap();
73 assert_eq!(pts, gst::ClockTime::ZERO);
74
75 let map = buf.map_readable().expect("Couldn't map buffer readable");
76 assert_eq!(
77 std::str::from_utf8(map.as_ref()),
78 std::str::from_utf8(expected_output.as_ref())
79 );
80 }
81
82 /// Encode a multiple raw CEA608 packets and compare the output
83 #[test]
test_encode_multiple_packets()84 fn test_encode_multiple_packets() {
85 init();
86
87 let input1 = [148, 44];
88 let input2 = [
89 148, 32, 148, 32, 148, 174, 148, 174, 148, 84, 148, 84, 16, 174, 16, 174, 70, 242, 239,
90 109, 32, 206, 229, 247, 32, 217, 239, 242, 107, 44, 148, 242, 148, 242, 16, 174, 16, 174,
91 244, 104, 233, 115, 32, 233, 115, 32, 196, 229, 109, 239, 227, 242, 97, 227, 121, 32, 206,
92 239, 247, 161, 148, 47, 148, 47,
93 ];
94
95 let expected_output1 = b"Scenarist_SCC V1.0\r\n\r\n00:00:00;00\t942c 942c\r\n\r\n";
96 let expected_output2 = b"00:00:14;01\t9420 9420 94ae 94ae 9454 9454 10ae 10ae 46f2 ef6d 20ce e5f7 20d9 eff2 6b2c 94f2\r\n\r\n";
97 let expected_output3 = b"00:00:14;17\t94f2 10ae 10ae f468 e973 20e9 7320 c4e5 6def e3f2 61e3 7920 ceef f7a1 942f 942f\r\n\r\n";
98
99 let mut h = gst_check::Harness::new("sccenc");
100 h.set_src_caps_str("closedcaption/x-cea-608, format=raw, framerate=(fraction)30000/1001");
101 let tc1 = gst_video::ValidVideoTimeCode::new(
102 gst::Fraction::new(30000, 1001),
103 None,
104 gst_video::VideoTimeCodeFlags::DROP_FRAME,
105 0,
106 0,
107 0,
108 0,
109 0,
110 )
111 .unwrap();
112
113 let tc2 = gst_video::ValidVideoTimeCode::new(
114 gst::Fraction::new(30000, 1001),
115 None,
116 gst_video::VideoTimeCodeFlags::DROP_FRAME,
117 0,
118 0,
119 14,
120 1,
121 0,
122 )
123 .unwrap();
124
125 let buf1 = {
126 let mut buf = gst::Buffer::from_mut_slice(Vec::from(&input1[..]));
127 let buf_ref = buf.get_mut().unwrap();
128 gst_video::VideoTimeCodeMeta::add(buf_ref, &tc1);
129 buf_ref.set_pts(gst::ClockTime::from_seconds(0));
130 buf
131 };
132
133 let buf2 = {
134 let mut buf = gst::Buffer::from_mut_slice(Vec::from(&input1[..]));
135 let buf_ref = buf.get_mut().unwrap();
136 let mut tc = tc1.clone();
137 tc.increment_frame();
138 gst_video::VideoTimeCodeMeta::add(buf_ref, &tc);
139 buf_ref.set_pts(gst::ClockTime::from_seconds(0));
140 buf
141 };
142
143 let mut t = tc2.clone();
144 let mut buffers = input2
145 .chunks(2)
146 .map(move |bytes| {
147 let mut buf = gst::Buffer::from_mut_slice(Vec::from(bytes));
148 let buf_ref = buf.get_mut().unwrap();
149 gst_video::VideoTimeCodeMeta::add(buf_ref, &t);
150 t.increment_frame();
151 buf
152 })
153 .collect::<Vec<gst::Buffer>>();
154 buffers.insert(0, buf1);
155 buffers.insert(1, buf2);
156
157 buffers.iter().for_each(|buf| {
158 assert_eq!(h.push(buf.clone()), Ok(gst::FlowSuccess::Ok));
159 });
160 h.push_event(gst::event::Eos::new());
161
162 // Pull 1
163 let buf = h.pull().expect("Couldn't pull buffer");
164
165 let timecode = buf
166 .meta::<gst_video::VideoTimeCodeMeta>()
167 .expect("No timecode for buffer")
168 .tc();
169 assert_eq!(timecode, tc1);
170
171 let pts = buf.pts().unwrap();
172 assert_eq!(pts, gst::ClockTime::ZERO);
173
174 let map = buf.map_readable().expect("Couldn't map buffer readable");
175
176 assert_eq!(
177 std::str::from_utf8(map.as_ref()),
178 std::str::from_utf8(expected_output1.as_ref())
179 );
180
181 // Pull 2
182 let buf = h.pull().expect("Couldn't pull buffer");
183 let timecode = buf
184 .meta::<gst_video::VideoTimeCodeMeta>()
185 .expect("No timecode for buffer")
186 .tc();
187 assert_eq!(timecode, tc2);
188
189 // let pts = buf.get_pts().unwrap();
190 // assert_eq!(pts, gst::ClockTime::ZERO);
191
192 let map = buf.map_readable().expect("Couldn't map buffer readable");
193 assert_eq!(
194 std::str::from_utf8(map.as_ref()),
195 std::str::from_utf8(expected_output2.as_ref())
196 );
197
198 let tc3 = gst_video::ValidVideoTimeCode::new(
199 gst::Fraction::new(30000, 1001),
200 None,
201 gst_video::VideoTimeCodeFlags::DROP_FRAME,
202 0,
203 0,
204 14,
205 17,
206 0,
207 )
208 .unwrap();
209
210 // Pull 3
211 let buf = h.pull().expect("Couldn't pull buffer");
212 let timecode = buf
213 .meta::<gst_video::VideoTimeCodeMeta>()
214 .expect("No timecode for buffer")
215 .tc();
216 assert_eq!(timecode, tc3);
217
218 // let pts = buf.get_pts().unwrap();
219 // assert_eq!(pts, gst::ClockTime::ZERO);
220
221 let map = buf.map_readable().expect("Couldn't map buffer readable");
222 assert_eq!(
223 std::str::from_utf8(map.as_ref()),
224 std::str::from_utf8(expected_output3.as_ref())
225 );
226 }
227