1use crate::{ffi, VideoFormat};
4use glib::translate::*;
5
6use crate::video_vbi::line_buffer_len;
7use crate::{VideoAncillaryDID, VideoAncillaryDID16, VideoVBIError, VBI_HD_MIN_PIXEL_WIDTH};
8
9glib::wrapper! {
10 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11 struct VideoVBIEncoderInner(Boxed<ffi::GstVideoVBIEncoder>);
12
13 match fn {
14 copy => |ptr| ffi::gst_video_vbi_encoder_copy(ptr),
15 free => |ptr| ffi::gst_video_vbi_encoder_free(ptr),
16 type_ => || ffi::gst_video_vbi_encoder_get_type(),
17 }
18}
19
20#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
23pub struct VideoVBIEncoder {
24 inner: VideoVBIEncoderInner,
25 format: VideoFormat,
26 pixel_width: u32,
27 line_buffer_len: usize,
28 anc_len: usize,
29}
30
31unsafe impl Send for VideoVBIEncoder {}
32unsafe impl Sync for VideoVBIEncoder {}
33
34#[derive(Clone, Copy, Debug, Eq, PartialEq)]
35pub enum VideoAFDDescriptionMode {
36 Composite,
37 Component,
38}
39
40impl VideoAFDDescriptionMode {
41 pub fn is_composite(&self) -> bool {
42 matches!(self, VideoAFDDescriptionMode::Composite)
43 }
44
45 pub fn is_component(&self) -> bool {
46 matches!(self, VideoAFDDescriptionMode::Component)
47 }
48}
49
50impl VideoVBIEncoder {
51 #[doc(alias = "gst_video_vbi_encoder_new")]
52 pub fn try_new(
53 format: VideoFormat,
54 pixel_width: u32,
55 ) -> Result<VideoVBIEncoder, VideoVBIError> {
56 skip_assert_initialized!();
57 let res: Option<VideoVBIEncoderInner> = unsafe {
58 from_glib_full(ffi::gst_video_vbi_encoder_new(
59 format.into_glib(),
60 pixel_width,
61 ))
62 };
63
64 Ok(VideoVBIEncoder {
65 inner: res.ok_or(VideoVBIError::Unsupported)?,
66 format,
67 pixel_width,
68 line_buffer_len: line_buffer_len(format, pixel_width),
69 anc_len: 0,
70 })
71 }
72
73 pub fn add_did_ancillary(
76 &mut self,
77 adf_mode: VideoAFDDescriptionMode,
78 did: VideoAncillaryDID,
79 block_number: u8,
80 data: &[u8],
81 ) -> Result<(), VideoVBIError> {
82 self.add_ancillary(adf_mode, did.into_glib() as u8, block_number, data)
83 }
84
85 pub fn add_did16_ancillary(
88 &mut self,
89 adf_mode: VideoAFDDescriptionMode,
90 did16: VideoAncillaryDID16,
91 data: &[u8],
92 ) -> Result<(), VideoVBIError> {
93 let did16 = did16.into_glib();
94
95 self.add_ancillary(
96 adf_mode,
97 ((did16 & 0xff00) >> 8) as u8,
98 (did16 & 0xff) as u8,
99 data,
100 )
101 }
102
103 #[doc(alias = "gst_video_vbi_encoder_add_ancillary")]
123 pub fn add_ancillary(
124 &mut self,
125 adf_mode: VideoAFDDescriptionMode,
126 did: u8,
127 sdid_block_number: u8,
128 data: &[u8],
129 ) -> Result<(), VideoVBIError> {
130 let data_count = data.len() as _;
131 let res: bool = unsafe {
132 from_glib(ffi::gst_video_vbi_encoder_add_ancillary(
133 self.inner.to_glib_none_mut().0,
134 adf_mode.is_composite().into_glib(),
135 did,
136 sdid_block_number,
137 data.to_glib_none().0,
138 data_count,
139 ))
140 };
141
142 if !res {
143 return Err(VideoVBIError::NotEnoughSpace);
144 }
145
146 let mut len = 1 + 3 + (data_count as usize) + 1;
151 if adf_mode.is_component() {
152 len += 2;
153 }
154
155 if matches!(self.format, VideoFormat::V210) {
156 len *= 2;
158 }
159
160 self.anc_len += len;
161
162 Ok(())
163 }
164
165 pub fn line_buffer_len(&self) -> usize {
168 self.line_buffer_len
169 }
170
171 #[doc(alias = "gst_video_vbi_encoder_write_line")]
186 pub fn write_line(&mut self, data: &mut [u8]) -> Result<usize, VideoVBIError> {
187 if data.len() < self.line_buffer_len {
188 return Err(VideoVBIError::InsufficientLineBufLen {
189 found: data.len(),
190 expected: self.line_buffer_len,
191 });
192 }
193
194 unsafe {
195 let dest = data.as_mut_ptr();
196 ffi::gst_video_vbi_encoder_write_line(self.inner.to_glib_none_mut().0, dest);
197 }
198
199 let mut anc_len = std::mem::take(&mut self.anc_len);
200 match self.format {
201 VideoFormat::V210 => {
202 let word_count = anc_len / 2;
204
205 if self.pixel_width < VBI_HD_MIN_PIXEL_WIDTH {
206 anc_len = 4 * 4 * word_count.div_ceil(12);
208 } else {
209 let pair_count = usize::min(word_count, self.pixel_width as usize);
213 anc_len = 4 * 4 * pair_count.div_ceil(6);
214 }
215 }
216 VideoFormat::Uyvy => {
217 if self.pixel_width < VBI_HD_MIN_PIXEL_WIDTH {
220 anc_len = 4 * anc_len.div_ceil(4);
222 } else {
223 let pair_count = usize::min(anc_len, self.pixel_width as usize);
228 anc_len = 4 * pair_count.div_ceil(2);
229 }
230 }
231 _ => unreachable!(),
232 }
233
234 assert!(anc_len < self.line_buffer_len);
235
236 Ok(anc_len)
237 }
238}
239
240impl<'a> TryFrom<&'a crate::VideoInfo> for VideoVBIEncoder {
241 type Error = VideoVBIError;
242
243 fn try_from(info: &'a crate::VideoInfo) -> Result<VideoVBIEncoder, VideoVBIError> {
244 skip_assert_initialized!();
245 VideoVBIEncoder::try_new(info.format(), info.width())
246 }
247}
248
249#[cfg(test)]
250mod tests {
251 use super::*;
252
253 #[test]
254 fn cea608_component() {
255 let mut encoder =
256 VideoVBIEncoder::try_new(VideoFormat::V210, VBI_HD_MIN_PIXEL_WIDTH).unwrap();
257 encoder
258 .add_did16_ancillary(
259 VideoAFDDescriptionMode::Component,
260 VideoAncillaryDID16::S334Eia608,
261 &[0x80, 0x94, 0x2c],
262 )
263 .unwrap();
264
265 let mut buf = vec![0; encoder.line_buffer_len()];
266 let anc_len = encoder.write_line(buf.as_mut_slice()).unwrap();
267 assert_eq!(32, anc_len);
268 assert_eq!(
269 buf[0..anc_len],
270 [
271 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xf0, 0x3f, 0x00, 0x84, 0x05, 0x00, 0x02, 0x01,
272 0x30, 0x20, 0x00, 0x00, 0x06, 0x00, 0x94, 0x01, 0xc0, 0x12, 0x00, 0x98, 0x0a, 0x00,
273 0x00, 0x00, 0x00, 0x00
274 ]
275 );
276 }
277
278 #[test]
279 fn cea608_component_sd() {
280 let mut encoder = VideoVBIEncoder::try_new(VideoFormat::V210, 768).unwrap();
281 encoder
282 .add_did16_ancillary(
283 VideoAFDDescriptionMode::Component,
284 VideoAncillaryDID16::S334Eia608,
285 &[0x80, 0x94, 0x2c],
286 )
287 .unwrap();
288
289 let mut buf = vec![0; encoder.line_buffer_len()];
290 let anc_len = encoder.write_line(buf.as_mut_slice()).unwrap();
291 assert_eq!(16, anc_len);
292 assert_eq!(
293 buf[0..anc_len],
294 [
295 0x00, 0xfc, 0xff, 0x3f, 0x61, 0x09, 0x34, 0x20, 0x80, 0x51, 0xc6, 0x12, 0xa6, 0x02,
296 0x00, 0x00
297 ]
298 );
299 }
300
301 #[test]
302 fn cea608_composite() {
303 let mut encoder =
304 VideoVBIEncoder::try_new(VideoFormat::V210, VBI_HD_MIN_PIXEL_WIDTH).unwrap();
305 encoder
306 .add_did16_ancillary(
307 VideoAFDDescriptionMode::Composite,
308 VideoAncillaryDID16::S334Eia608,
309 &[0x15, 0x94, 0x2c],
310 )
311 .unwrap();
312
313 let mut buf = vec![0; encoder.line_buffer_len()];
314 let anc_len = encoder.write_line(buf.as_mut_slice()).unwrap();
315 assert_eq!(32, anc_len);
316 assert_eq!(
317 buf[0..anc_len],
318 [
319 0x00, 0xf0, 0x0f, 0x00, 0x61, 0x01, 0x20, 0x10, 0x00, 0x0c, 0x08, 0x00, 0x15, 0x01,
320 0x40, 0x19, 0x00, 0xb0, 0x04, 0x00, 0x3b, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0x00
322 ]
323 );
324 }
325
326 #[test]
327 fn cea608_composite_sd() {
328 let mut encoder = VideoVBIEncoder::try_new(VideoFormat::V210, 768).unwrap();
329 encoder
330 .add_did16_ancillary(
331 VideoAFDDescriptionMode::Composite,
332 VideoAncillaryDID16::S334Eia608,
333 &[0x15, 0x94, 0x2c],
334 )
335 .unwrap();
336
337 let mut buf = vec![0; encoder.line_buffer_len()];
338 let anc_len = encoder.write_line(buf.as_mut_slice()).unwrap();
339 assert_eq!(16, anc_len);
340 assert_eq!(
341 buf[0..anc_len],
342 [
343 0xfc, 0x87, 0x25, 0x10, 0x03, 0x56, 0x44, 0x19, 0x2c, 0xed, 0x08, 0x00, 0x00, 0x00,
344 0x00, 0x00
345 ]
346 );
347 }
348
349 #[test]
350 fn cea608_component_uyvy() {
351 let mut encoder =
352 VideoVBIEncoder::try_new(VideoFormat::Uyvy, VBI_HD_MIN_PIXEL_WIDTH).unwrap();
353 encoder
354 .add_did16_ancillary(
355 VideoAFDDescriptionMode::Component,
356 VideoAncillaryDID16::S334Eia608,
357 &[0x80, 0x94, 0x2c],
358 )
359 .unwrap();
360
361 let mut buf = vec![0; encoder.line_buffer_len()];
362 let anc_len = encoder.write_line(buf.as_mut_slice()).unwrap();
363 assert_eq!(20, anc_len);
364 assert_eq!(
365 buf[0..anc_len],
366 [
367 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x61, 0x00, 0x02, 0x00, 0x03, 0x00, 0x80,
368 0x00, 0x94, 0x00, 0x2c, 0x00, 0xa6
369 ]
370 );
371 }
372
373 #[test]
374 fn cea608_component_sd_uyvy() {
375 let mut encoder = VideoVBIEncoder::try_new(VideoFormat::Uyvy, 768).unwrap();
376 encoder
377 .add_did16_ancillary(
378 VideoAFDDescriptionMode::Component,
379 VideoAncillaryDID16::S334Eia608,
380 &[0x80, 0x94, 0x2c],
381 )
382 .unwrap();
383
384 let mut buf = vec![0; encoder.line_buffer_len()];
385 let anc_len = encoder.write_line(buf.as_mut_slice()).unwrap();
386 assert_eq!(12, anc_len);
387 assert_eq!(
388 buf[0..anc_len],
389 [0x00, 0xff, 0xff, 0x61, 0x02, 0x03, 0x80, 0x94, 0x2c, 0xa6, 0x00, 0x00]
390 );
391 }
392
393 #[test]
394 fn cea608_composite_uyvy() {
395 let mut encoder =
396 VideoVBIEncoder::try_new(VideoFormat::Uyvy, VBI_HD_MIN_PIXEL_WIDTH).unwrap();
397 encoder
398 .add_did16_ancillary(
399 VideoAFDDescriptionMode::Composite,
400 VideoAncillaryDID16::S334Eia608,
401 &[0x15, 0x94, 0x2c],
402 )
403 .unwrap();
404
405 let mut buf = vec![0; encoder.line_buffer_len()];
406 let anc_len = encoder.write_line(buf.as_mut_slice()).unwrap();
407 assert_eq!(16, anc_len);
408 assert_eq!(
409 buf[0..anc_len],
410 [
411 0x00, 0xfc, 0x00, 0x61, 0x00, 0x02, 0x00, 0x03, 0x00, 0x15, 0x00, 0x94, 0x00, 0x2c,
412 0x00, 0x3b
413 ]
414 );
415 }
416
417 #[test]
418 fn cea608_composite_sd_uyvy() {
419 let mut encoder = VideoVBIEncoder::try_new(VideoFormat::Uyvy, 768).unwrap();
420 encoder
421 .add_did16_ancillary(
422 VideoAFDDescriptionMode::Composite,
423 VideoAncillaryDID16::S334Eia608,
424 &[0x15, 0x94, 0x2c],
425 )
426 .unwrap();
427
428 let mut buf = vec![0; encoder.line_buffer_len()];
429 let anc_len = encoder.write_line(buf.as_mut_slice()).unwrap();
430 assert_eq!(8, anc_len);
431 assert_eq!(
432 buf[0..anc_len],
433 [0xfc, 0x61, 0x02, 0x03, 0x15, 0x94, 0x2c, 0x3b]
434 );
435 }
436
437 #[test]
438 fn insufficient_line_buf_len() {
439 let mut encoder =
440 VideoVBIEncoder::try_new(VideoFormat::V210, VBI_HD_MIN_PIXEL_WIDTH).unwrap();
441 encoder
442 .add_did16_ancillary(
443 VideoAFDDescriptionMode::Component,
444 VideoAncillaryDID16::S334Eia608,
445 &[0x80, 0x94, 0x2c],
446 )
447 .unwrap();
448 let mut buf = vec![0; 10];
449 assert_eq!(
450 encoder.write_line(buf.as_mut_slice()).unwrap_err(),
451 VideoVBIError::InsufficientLineBufLen {
452 found: 10,
453 expected: encoder.line_buffer_len()
454 },
455 );
456 }
457
458 #[test]
459 fn cea708_component() {
460 let mut encoder =
461 VideoVBIEncoder::try_new(VideoFormat::V210, VBI_HD_MIN_PIXEL_WIDTH).unwrap();
462 encoder
463 .add_did16_ancillary(
464 VideoAFDDescriptionMode::Component,
465 VideoAncillaryDID16::S334Eia708,
466 &[
467 0x96, 0x69, 0x55, 0x3f, 0x43, 0x00, 0x00, 0x72, 0xf8, 0xfc, 0x94, 0x2c, 0xf9,
468 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00,
469 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
470 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
471 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00,
472 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
473 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x1b,
474 ],
475 )
476 .unwrap();
477
478 let mut buf = vec![0; encoder.line_buffer_len()];
479 let anc_len = encoder.write_line(buf.as_mut_slice()).unwrap();
480 assert_eq!(256, anc_len);
481 assert_eq!(
482 buf[0..anc_len],
483 [
484 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xf0, 0x3f, 0x00, 0x84, 0x05, 0x00, 0x01, 0x01,
485 0x50, 0x25, 0x00, 0x58, 0x0a, 0x00, 0x69, 0x02, 0x50, 0x25, 0x00, 0xfc, 0x08, 0x00,
486 0x43, 0x01, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0x72, 0x02, 0x80, 0x1f, 0x00, 0xf0,
487 0x0b, 0x00, 0x94, 0x01, 0xc0, 0x12, 0x00, 0xe4, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20,
488 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02,
489 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00,
490 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8,
491 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20,
492 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02,
493 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00,
494 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8,
495 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20,
496 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02,
497 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00,
498 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8,
499 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20,
500 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0xd0, 0x09, 0x00, 0x00, 0x02,
501 0x00, 0x20, 0x00, 0x6c, 0x08, 0x00, 0xb7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00
503 ]
504 );
505 }
506
507 #[test]
508 fn cea608_and_cea708_component() {
509 let mut encoder =
510 VideoVBIEncoder::try_new(VideoFormat::V210, VBI_HD_MIN_PIXEL_WIDTH).unwrap();
511 encoder
512 .add_did16_ancillary(
513 VideoAFDDescriptionMode::Component,
514 VideoAncillaryDID16::S334Eia608,
515 &[0x80, 0x94, 0x2c],
516 )
517 .unwrap();
518
519 encoder
520 .add_did16_ancillary(
521 VideoAFDDescriptionMode::Component,
522 VideoAncillaryDID16::S334Eia708,
523 &[
524 0x96, 0x69, 0x55, 0x3f, 0x43, 0x00, 0x00, 0x72, 0xf8, 0xfc, 0x94, 0x2c, 0xf9,
525 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00,
526 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
527 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
528 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00,
529 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
530 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x1b,
531 ],
532 )
533 .unwrap();
534
535 let mut buf = vec![0; encoder.line_buffer_len()];
536 let anc_len = encoder.write_line(buf.as_mut_slice()).unwrap();
537 assert_eq!(272, anc_len);
538 assert_eq!(
539 buf[0..anc_len],
540 [
541 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xf0, 0x3f, 0x00, 0x84, 0x05, 0x00, 0x02, 0x01,
542 0x30, 0x20, 0x00, 0x00, 0x06, 0x00, 0x94, 0x01, 0xc0, 0x12, 0x00, 0x98, 0x0a, 0x00,
543 0x00, 0x00, 0xf0, 0x3f, 0x00, 0xfc, 0x0f, 0x00, 0x61, 0x01, 0x10, 0x10, 0x00, 0x54,
544 0x09, 0x00, 0x96, 0x02, 0x90, 0x26, 0x00, 0x54, 0x09, 0x00, 0x3f, 0x02, 0x30, 0x14,
545 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x20, 0x27, 0x00, 0xe0, 0x07, 0x00, 0xfc, 0x02,
546 0x40, 0x19, 0x00, 0xb0, 0x04, 0x00, 0xf9, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00,
547 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00,
548 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20,
549 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02,
550 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00,
551 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00,
552 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20,
553 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02,
554 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00,
555 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00,
556 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20,
557 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02,
558 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00,
559 0xfa, 0x02, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0x74, 0x02, 0x00, 0x20, 0x00, 0x00,
560 0x08, 0x00, 0x1b, 0x02, 0x70, 0x2b
561 ]
562 );
563 }
564}