1use std::str;
4
5use crate::ffi;
6use glib::translate::{from_glib, FromGlib, IntoGlib};
7use once_cell::sync::Lazy;
8
9#[cfg(feature = "v1_18")]
25pub static VIDEO_FORMATS_ALL: Lazy<Box<[crate::VideoFormat]>> = Lazy::new(|| unsafe {
26 let mut len: u32 = 0;
27 let mut res = Vec::with_capacity(len as usize);
28 let formats = ffi::gst_video_formats_raw(&mut len);
29 for i in 0..len {
30 let format = formats.offset(i as isize);
31 res.push(from_glib(*format));
32 }
33 res.into_boxed_slice()
34});
35
36#[cfg(not(feature = "v1_18"))]
37pub static VIDEO_FORMATS_ALL: Lazy<Box<[crate::VideoFormat]>> = Lazy::new(|| {
38 #[cfg(target_endian = "little")]
39 {
40 Box::new([
41 crate::VideoFormat::Ayuv64,
42 crate::VideoFormat::Argb64,
43 crate::VideoFormat::Gbra12le,
44 crate::VideoFormat::Gbra12be,
45 crate::VideoFormat::A44410le,
46 crate::VideoFormat::Gbra10le,
47 crate::VideoFormat::A44410be,
48 crate::VideoFormat::Gbra10be,
49 crate::VideoFormat::A42210le,
50 crate::VideoFormat::A42210be,
51 crate::VideoFormat::A42010le,
52 crate::VideoFormat::A42010be,
53 #[cfg(feature = "v1_16")]
54 crate::VideoFormat::Bgr10a2Le,
55 #[cfg(feature = "v1_16")]
56 crate::VideoFormat::Y410,
57 crate::VideoFormat::Gbra,
58 crate::VideoFormat::Ayuv,
59 #[cfg(feature = "v1_16")]
60 crate::VideoFormat::Vuya,
61 crate::VideoFormat::Rgba,
62 crate::VideoFormat::Argb,
63 crate::VideoFormat::Bgra,
64 crate::VideoFormat::Abgr,
65 crate::VideoFormat::A420,
66 crate::VideoFormat::V216,
67 crate::VideoFormat::Y44412le,
68 crate::VideoFormat::Gbr12le,
69 crate::VideoFormat::Y44412be,
70 crate::VideoFormat::Gbr12be,
71 crate::VideoFormat::I42212le,
72 crate::VideoFormat::I42212be,
73 crate::VideoFormat::I42012le,
74 crate::VideoFormat::I42012be,
75 crate::VideoFormat::Y44410le,
76 crate::VideoFormat::Gbr10le,
77 crate::VideoFormat::Y44410be,
78 crate::VideoFormat::Gbr10be,
79 crate::VideoFormat::R210,
80 crate::VideoFormat::I42210le,
81 crate::VideoFormat::I42210be,
82 crate::VideoFormat::Nv1610le32,
83 #[cfg(feature = "v1_16")]
84 crate::VideoFormat::Y210,
85 crate::VideoFormat::Uyvp,
86 crate::VideoFormat::V210,
87 crate::VideoFormat::I42010le,
88 crate::VideoFormat::I42010be,
89 crate::VideoFormat::P01010le,
90 #[cfg(feature = "v1_16")]
91 crate::VideoFormat::Nv1210le40,
92 crate::VideoFormat::Nv1210le32,
93 crate::VideoFormat::P01010be,
94 crate::VideoFormat::Y444,
95 crate::VideoFormat::Gbr,
96 crate::VideoFormat::Nv24,
97 crate::VideoFormat::V308,
98 crate::VideoFormat::Iyu2,
99 crate::VideoFormat::Rgbx,
100 crate::VideoFormat::Xrgb,
101 crate::VideoFormat::Bgrx,
102 crate::VideoFormat::Xbgr,
103 crate::VideoFormat::Rgb,
104 crate::VideoFormat::Bgr,
105 crate::VideoFormat::Y42b,
106 crate::VideoFormat::Nv16,
107 crate::VideoFormat::Nv61,
108 crate::VideoFormat::Yuy2,
109 crate::VideoFormat::Yvyu,
110 crate::VideoFormat::Uyvy,
111 crate::VideoFormat::Vyuy,
112 crate::VideoFormat::I420,
113 crate::VideoFormat::Yv12,
114 crate::VideoFormat::Nv12,
115 crate::VideoFormat::Nv21,
116 crate::VideoFormat::Nv1264z32,
117 crate::VideoFormat::Y41b,
118 crate::VideoFormat::Iyu1,
119 crate::VideoFormat::Yuv9,
120 crate::VideoFormat::Yvu9,
121 crate::VideoFormat::Bgr16,
122 crate::VideoFormat::Rgb16,
123 crate::VideoFormat::Bgr15,
124 crate::VideoFormat::Rgb15,
125 crate::VideoFormat::Rgb8p,
126 crate::VideoFormat::Gray16Le,
127 crate::VideoFormat::Gray16Be,
128 crate::VideoFormat::Gray10Le32,
129 crate::VideoFormat::Gray8,
130 ])
131 }
132 #[cfg(target_endian = "big")]
133 {
134 Box::new([
135 crate::VideoFormat::Ayuv64,
136 crate::VideoFormat::Argb64,
137 crate::VideoFormat::Gbra12be,
138 crate::VideoFormat::Gbra12le,
139 crate::VideoFormat::A44410be,
140 crate::VideoFormat::Gbra10be,
141 crate::VideoFormat::A44410le,
142 crate::VideoFormat::Gbra10le,
143 crate::VideoFormat::A42210be,
144 crate::VideoFormat::A42210le,
145 crate::VideoFormat::A42010be,
146 crate::VideoFormat::A42010le,
147 #[cfg(feature = "v1_16")]
148 crate::VideoFormat::Bgr10a2Le,
149 #[cfg(feature = "v1_16")]
150 crate::VideoFormat::Y410,
151 crate::VideoFormat::Gbra,
152 crate::VideoFormat::Ayuv,
153 #[cfg(feature = "v1_16")]
154 crate::VideoFormat::Vuya,
155 crate::VideoFormat::Rgba,
156 crate::VideoFormat::Argb,
157 crate::VideoFormat::Bgra,
158 crate::VideoFormat::Abgr,
159 crate::VideoFormat::A420,
160 crate::VideoFormat::V216,
161 crate::VideoFormat::Y44412be,
162 crate::VideoFormat::Gbr12be,
163 crate::VideoFormat::Y44412le,
164 crate::VideoFormat::Gbr12le,
165 crate::VideoFormat::I42212be,
166 crate::VideoFormat::I42212le,
167 crate::VideoFormat::I42012be,
168 crate::VideoFormat::I42012le,
169 crate::VideoFormat::Y44410be,
170 crate::VideoFormat::Gbr10be,
171 crate::VideoFormat::Y44410le,
172 crate::VideoFormat::Gbr10le,
173 crate::VideoFormat::R210,
174 crate::VideoFormat::I42210be,
175 crate::VideoFormat::I42210le,
176 crate::VideoFormat::Nv1610le32,
177 #[cfg(feature = "v1_16")]
178 crate::VideoFormat::Y210,
179 crate::VideoFormat::Uyvp,
180 crate::VideoFormat::V210,
181 crate::VideoFormat::I42010be,
182 crate::VideoFormat::I42010le,
183 crate::VideoFormat::P01010be,
184 crate::VideoFormat::P01010le,
185 #[cfg(feature = "v1_16")]
186 crate::VideoFormat::Nv1210le40,
187 crate::VideoFormat::Nv1210le32,
188 crate::VideoFormat::Y444,
189 crate::VideoFormat::Gbr,
190 crate::VideoFormat::Nv24,
191 crate::VideoFormat::V308,
192 crate::VideoFormat::Iyu2,
193 crate::VideoFormat::Rgbx,
194 crate::VideoFormat::Xrgb,
195 crate::VideoFormat::Bgrx,
196 crate::VideoFormat::Xbgr,
197 crate::VideoFormat::Rgb,
198 crate::VideoFormat::Bgr,
199 crate::VideoFormat::Y42b,
200 crate::VideoFormat::Nv16,
201 crate::VideoFormat::Nv61,
202 crate::VideoFormat::Yuy2,
203 crate::VideoFormat::Yvyu,
204 crate::VideoFormat::Uyvy,
205 crate::VideoFormat::Vyuy,
206 crate::VideoFormat::I420,
207 crate::VideoFormat::Yv12,
208 crate::VideoFormat::Nv12,
209 crate::VideoFormat::Nv21,
210 crate::VideoFormat::Nv1264z32,
211 crate::VideoFormat::Y41b,
212 crate::VideoFormat::Iyu1,
213 crate::VideoFormat::Yuv9,
214 crate::VideoFormat::Yvu9,
215 crate::VideoFormat::Bgr16,
216 crate::VideoFormat::Rgb16,
217 crate::VideoFormat::Bgr15,
218 crate::VideoFormat::Rgb15,
219 crate::VideoFormat::Rgb8p,
220 crate::VideoFormat::Gray16Be,
221 crate::VideoFormat::Gray16Le,
222 crate::VideoFormat::Gray10Le32,
223 crate::VideoFormat::Gray8,
224 ])
225 }
226});
227
228#[cfg(feature = "v1_24")]
232pub static VIDEO_FORMATS_ANY: Lazy<Box<[crate::VideoFormat]>> = Lazy::new(|| unsafe {
233 let mut len: u32 = 0;
234 let mut res = Vec::with_capacity(len as usize);
235 let formats = ffi::gst_video_formats_any(&mut len);
236 for i in 0..len {
237 let format = formats.offset(i as isize);
238 res.push(from_glib(*format));
239 }
240 res.into_boxed_slice()
241});
242
243#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
244pub enum VideoEndianness {
245 Unknown,
246 LittleEndian = 1234,
247 BigEndian = 4321,
248}
249
250impl FromGlib<i32> for VideoEndianness {
251 #[inline]
252 unsafe fn from_glib(value: i32) -> Self {
253 skip_assert_initialized!();
254
255 match value {
256 1234 => Self::LittleEndian,
257 4321 => Self::BigEndian,
258 _ => Self::Unknown,
259 }
260 }
261}
262
263impl IntoGlib for VideoEndianness {
264 type GlibType = i32;
265
266 #[inline]
267 fn into_glib(self) -> i32 {
268 match self {
269 Self::LittleEndian => 1234,
270 Self::BigEndian => 4321,
271 _ => 0,
272 }
273 }
274}
275
276impl crate::VideoFormat {
277 #[doc(alias = "gst_video_format_from_masks")]
278 pub fn from_masks(
279 depth: u32,
280 bpp: u32,
281 endianness: crate::VideoEndianness,
282 red_mask: u32,
283 green_mask: u32,
284 blue_mask: u32,
285 alpha_mask: u32,
286 ) -> Self {
287 assert_initialized_main_thread!();
288
289 unsafe {
290 from_glib(ffi::gst_video_format_from_masks(
291 depth as i32,
292 bpp as i32,
293 endianness.into_glib(),
294 red_mask,
295 green_mask,
296 blue_mask,
297 alpha_mask,
298 ))
299 }
300 }
301
302 #[doc(alias = "gst_video_format_to_string")]
303 pub fn to_str<'a>(self) -> &'a glib::GStr {
304 if self == Self::Unknown {
305 return glib::gstr!("UNKNOWN");
306 }
307 unsafe {
308 glib::GStr::from_ptr(
309 ffi::gst_video_format_to_string(self.into_glib())
310 .as_ref()
311 .expect("gst_video_format_to_string returned NULL"),
312 )
313 }
314 }
315
316 pub fn iter_raw() -> VideoFormatIterator {
317 VideoFormatIterator::default()
318 }
319
320 #[cfg(feature = "v1_24")]
321 pub fn iter_any() -> impl Iterator<Item = crate::VideoFormat> {
322 VIDEO_FORMATS_ANY.iter().copied()
323 }
324}
325
326impl str::FromStr for crate::VideoFormat {
327 type Err = glib::BoolError;
328
329 fn from_str(s: &str) -> Result<Self, Self::Err> {
330 skip_assert_initialized!();
331
332 let fmt = Self::from_string(s);
333 if fmt == Self::Unknown {
334 Err(glib::bool_error!(
335 "Failed to parse video format from string"
336 ))
337 } else {
338 Ok(fmt)
339 }
340 }
341}
342
343impl PartialOrd for crate::VideoFormat {
344 #[inline]
345 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
346 Some(self.cmp(other))
347 }
348}
349
350impl Ord for crate::VideoFormat {
351 #[inline]
352 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
353 crate::VideoFormatInfo::from_format(*self).cmp(&crate::VideoFormatInfo::from_format(*other))
354 }
355}
356
357pub struct VideoFormatIterator {
358 idx: usize,
359 len: usize,
360}
361
362impl Default for VideoFormatIterator {
363 fn default() -> Self {
364 Self {
365 idx: 0,
366 len: VIDEO_FORMATS_ALL.len(),
367 }
368 }
369}
370
371impl Iterator for VideoFormatIterator {
372 type Item = crate::VideoFormat;
373
374 fn next(&mut self) -> Option<Self::Item> {
375 if self.idx >= self.len {
376 None
377 } else {
378 let fmt = VIDEO_FORMATS_ALL[self.idx];
379 self.idx += 1;
380 Some(fmt)
381 }
382 }
383
384 fn size_hint(&self) -> (usize, Option<usize>) {
385 if self.idx == self.len {
386 return (0, Some(0));
387 }
388
389 let remaining = self.len - self.idx;
390
391 (remaining, Some(remaining))
392 }
393
394 fn count(self) -> usize {
395 self.len - self.idx
396 }
397
398 fn nth(&mut self, n: usize) -> Option<Self::Item> {
399 let (end, overflow) = self.idx.overflowing_add(n);
400 if end >= self.len || overflow {
401 self.idx = self.len;
402 None
403 } else {
404 self.idx = end + 1;
405 Some(VIDEO_FORMATS_ALL[end])
406 }
407 }
408
409 fn last(self) -> Option<Self::Item> {
410 if self.idx == self.len {
411 None
412 } else {
413 Some(VIDEO_FORMATS_ALL[self.len - 1])
414 }
415 }
416}
417
418impl ExactSizeIterator for VideoFormatIterator {}
419
420impl std::iter::FusedIterator for VideoFormatIterator {}
421
422impl DoubleEndedIterator for VideoFormatIterator {
423 fn next_back(&mut self) -> Option<Self::Item> {
424 if self.idx >= self.len {
425 None
426 } else {
427 let fmt = VIDEO_FORMATS_ALL[self.len - 1];
428 self.len -= 1;
429 Some(fmt)
430 }
431 }
432
433 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
434 let (end, overflow) = self.len.overflowing_sub(n);
435 if end <= self.idx || overflow {
436 self.idx = self.len;
437 None
438 } else {
439 self.len = end - 1;
440 let fmt = VIDEO_FORMATS_ALL[self.len];
441 Some(fmt)
442 }
443 }
444}
445pub trait VideoFormatIteratorExt {
446 fn into_video_caps(self) -> Option<crate::VideoCapsBuilder<gst::caps::NoFeature>>;
447}
448
449impl<T> VideoFormatIteratorExt for T
450where
451 T: Iterator<Item = crate::VideoFormat>,
452{
453 fn into_video_caps(self) -> Option<crate::VideoCapsBuilder<gst::caps::NoFeature>> {
454 let formats: Vec<crate::VideoFormat> = self.collect();
455 if !formats.is_empty() {
456 Some(crate::functions::video_make_raw_caps(&formats))
457 } else {
458 None
459 }
460 }
461}
462
463pub trait VideoFormatIteratorExtRef {
464 fn into_video_caps(self) -> Option<crate::VideoCapsBuilder<gst::caps::NoFeature>>;
465}
466
467impl<'a, T> VideoFormatIteratorExtRef for T
468where
469 T: Iterator<Item = &'a crate::VideoFormat>,
470{
471 fn into_video_caps(self) -> Option<crate::VideoCapsBuilder<gst::caps::NoFeature>> {
472 let formats: Vec<crate::VideoFormat> = self.copied().collect();
473 if !formats.is_empty() {
474 Some(crate::functions::video_make_raw_caps(&formats))
475 } else {
476 None
477 }
478 }
479}
480
481#[cfg(test)]
482mod tests {
483
484 #[test]
485 fn enum_to_string() {
486 gst::init().unwrap();
487
488 assert_eq!(&format!("{}", crate::VideoFormat::Argb), "ARGB");
489 assert_eq!(&format!("{:?}", crate::VideoFormat::Argb), "Argb");
490 assert_eq!(crate::VideoFormat::Argb.to_str(), "ARGB");
491
492 assert_eq!(&format!("{}", crate::VideoFormat::Unknown), "UNKNOWN");
493 assert_eq!(&format!("{:?}", crate::VideoFormat::Unknown), "Unknown");
494 assert_eq!(crate::VideoFormat::Unknown.to_str(), "UNKNOWN");
495
496 assert_eq!(
497 &format!("{:?}", crate::VideoFormat::__Unknown(-1)),
498 "__Unknown(-1)"
499 );
500 }
501
502 #[test]
503 fn test_display() {
504 gst::init().unwrap();
505
506 assert_eq!(format!("{}", crate::VideoFormat::Nv16), "NV16");
507 assert_eq!(format!("{:?}", crate::VideoFormat::Nv16), "Nv16");
508 }
509
510 #[test]
511 fn iter() {
512 use super::*;
513 gst::init().unwrap();
514
515 assert!(crate::VideoFormat::iter_raw().count() > 0);
516 assert_eq!(
517 crate::VideoFormat::iter_raw().count(),
518 crate::VideoFormat::iter_raw().len()
519 );
520
521 let mut i = crate::VideoFormat::iter_raw();
522 let mut count = 0;
523 loop {
524 if i.next().is_none() {
525 break;
526 }
527 count += 1;
528 if i.next_back().is_none() {
529 break;
530 }
531 count += 1;
532 }
533 assert_eq!(count, crate::VideoFormat::iter_raw().len());
534
535 assert!(crate::VideoFormat::iter_raw().any(|f| f == crate::VideoFormat::Nv12));
536 assert!(!crate::VideoFormat::iter_raw().any(|f| f == crate::VideoFormat::Encoded));
537
538 let caps = crate::VideoFormat::iter_raw().into_video_caps();
539 assert!(caps.is_some());
540
541 let caps = crate::VideoFormat::iter_raw()
542 .filter(|f| crate::VideoFormatInfo::from_format(*f).is_gray())
543 .into_video_caps();
544 assert!(caps.is_some());
545
546 let caps = crate::VideoFormat::iter_raw().skip(1000).into_video_caps();
547 assert!(caps.is_none());
548
549 let caps = [crate::VideoFormat::Nv12, crate::VideoFormat::Nv16]
550 .iter()
551 .into_video_caps()
552 .unwrap()
553 .build();
554 assert_eq!(caps.to_string(), "video/x-raw, format=(string){ NV12, NV16 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]");
555 }
556
557 #[test]
558 fn sort() {
559 use itertools::Itertools;
560
561 gst::init().unwrap();
562
563 assert!(
564 crate::VideoFormatInfo::from_format(crate::VideoFormat::Nv16)
565 > crate::VideoFormatInfo::from_format(crate::VideoFormat::Nv12)
566 );
567 assert!(crate::VideoFormat::I420 > crate::VideoFormat::Yv12);
568 assert!(crate::VideoFormat::Nv12 > crate::VideoFormat::Nv21);
569 assert!(crate::VideoFormat::Xrgb > crate::VideoFormat::Rgb);
570
571 let sorted: Vec<crate::VideoFormat> =
572 crate::VideoFormat::iter_raw().sorted().rev().collect();
573 assert_eq!(
575 sorted,
576 crate::VideoFormat::iter_raw().collect::<Vec<crate::VideoFormat>>()
577 );
578 }
579}