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