1use std::{fmt, io, mem};
4
5use crate::shared::{FrmIvalType, FrmSizeType};
6use crate::{byte_array_to_str, raw, BufType, Device, Fract};
7
8pub use crate::pixel_format::PixelFormat;
9pub use crate::shared::FormatFlags;
10
11#[derive(Debug)]
13#[non_exhaustive]
14pub enum Format {
15 VideoCapture(PixFormat),
16 VideoOutput(PixFormat),
17 VideoCaptureMplane(PixFormatMplane),
18 VideoOutputMplane(PixFormatMplane),
19 VideoOverlay(Window),
20 MetaCapture(MetaFormat),
21 MetaOutput(MetaFormat),
22 }
24
25pub struct PixFormat(raw::PixFormat);
28
29pub struct PixFormatMplane(raw::PixFormatMplane);
30
31pub struct Window(raw::Window);
32
33pub struct PlanePixFormat(raw::PlanePixFormat);
34
35pub struct MetaFormat(raw::MetaFormat);
38
39impl Format {
40 pub(crate) unsafe fn from_raw(raw: raw::Format) -> Option<Self> {
41 Some(match raw.type_ {
42 BufType::VIDEO_CAPTURE => Self::VideoCapture(PixFormat(raw.fmt.pix)),
43 BufType::VIDEO_OUTPUT => Self::VideoOutput(PixFormat(raw.fmt.pix)),
44 BufType::VIDEO_CAPTURE_MPLANE => {
45 Self::VideoCaptureMplane(PixFormatMplane(raw.fmt.pix_mp))
46 }
47 BufType::VIDEO_OUTPUT_MPLANE => {
48 Self::VideoOutputMplane(PixFormatMplane(raw.fmt.pix_mp))
49 }
50 BufType::VIDEO_OVERLAY => Self::VideoOverlay(Window(raw.fmt.win)),
51 BufType::META_CAPTURE => Self::MetaCapture(MetaFormat(raw.fmt.meta)),
52 _ => return None,
53 })
54 }
55}
56
57impl PixFormat {
58 pub fn new(width: u32, height: u32, pixel_format: PixelFormat) -> Self {
59 Self(raw::PixFormat {
60 width,
61 height,
62 pixel_format,
63 ..unsafe { mem::zeroed() }
64 })
65 }
66
67 pub(crate) fn to_raw(self) -> raw::PixFormat {
68 self.0
69 }
70
71 pub fn width(&self) -> u32 {
72 self.0.width
73 }
74
75 pub fn height(&self) -> u32 {
76 self.0.height
77 }
78
79 pub fn pixel_format(&self) -> PixelFormat {
80 self.0.pixel_format
81 }
82
83 pub fn bytes_per_line(&self) -> u32 {
84 self.0.bytesperline
85 }
86
87 pub fn size_image(&self) -> u32 {
88 self.0.sizeimage
89 }
90}
91
92impl PixFormatMplane {
93 pub(crate) fn to_raw(self) -> raw::PixFormatMplane {
94 self.0
95 }
96
97 pub fn num_planes(&self) -> usize {
98 self.0.num_planes.into()
99 }
100
101 pub fn plane_formats(&self) -> impl Iterator<Item = PlanePixFormat> + '_ {
102 (0..self.num_planes()).map(move |i| PlanePixFormat(self.0.plane_fmt[i]))
104 }
105}
106
107impl PlanePixFormat {
108 pub fn size_image(&self) -> u32 {
109 self.0.sizeimage
110 }
111
112 pub fn bytes_per_line(&self) -> u32 {
113 self.0.bytesperline
114 }
115}
116
117impl Window {
118 pub(crate) fn to_raw(self) -> raw::Window {
119 self.0
120 }
121}
122
123impl MetaFormat {
124 pub fn new(format: PixelFormat) -> Self {
125 Self(raw::MetaFormat {
126 dataformat: format,
127 buffersize: 0, })
129 }
130
131 pub fn buffer_size(&self) -> u32 {
132 self.0.buffersize
133 }
134
135 pub(crate) fn to_raw(self) -> raw::MetaFormat {
136 self.0
137 }
138}
139
140impl fmt::Debug for PixFormat {
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 f.debug_struct("PixFormat")
143 .field("width", &self.0.width)
144 .field("height", &self.0.height)
145 .field("pixel_format", &self.0.pixel_format)
146 .field("field", &self.0.field)
147 .field("bytesperline", &self.0.bytesperline)
148 .field("sizeimage", &self.0.sizeimage)
149 .field("colorspace", &self.0.colorspace)
150 .field("flags", &self.0.flags)
151 .field("enc", &self.0.enc)
152 .field("quantization", &self.0.quantization)
153 .field("xfer_func", &self.0.xfer_func)
154 .finish()
155 }
156}
157
158impl fmt::Debug for PixFormatMplane {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 f.debug_struct("PixFormatMplane")
161 .field("width", &{ self.0.width })
162 .field("height", &{ self.0.height })
163 .field("pixel_format", &{ self.0.pixel_format })
164 .field("field", &{ self.0.field })
165 .field("colorspace", &{ self.0.colorspace })
166 .field("plane_fmt", &self.plane_formats().collect::<Vec<_>>())
167 .field("num_planes", &self.0.num_planes)
168 .finish()
169 }
170}
171
172impl fmt::Debug for PlanePixFormat {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 f.debug_struct("PlanePixFormat")
175 .field("sizeimage", &{ self.0.sizeimage })
176 .field("bytesperline", &{ self.0.bytesperline })
177 .finish()
178 }
179}
180
181impl fmt::Debug for Window {
182 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183 f.debug_struct("Window")
184 .field("rect", &self.0.w)
185 .field("field", &self.0.field)
186 .field("chromakey", &self.0.chromakey)
187 .field("clips", &self.0.clips)
188 .field("clipcount", &self.0.clipcount)
189 .field("bitmap", &self.0.bitmap)
190 .field("global_alpha", &self.0.global_alpha)
191 .finish()
192 }
193}
194
195impl fmt::Debug for MetaFormat {
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197 f.debug_struct("MetaFormat")
198 .field("dataformat", &{ self.0.dataformat })
199 .field("buffersize", &{ self.0.buffersize })
200 .finish()
201 }
202}
203
204pub struct FormatDescIter<'a> {
206 device: &'a Device,
207 buf_type: BufType,
208 next_index: u32,
209 finished: bool,
210}
211
212impl<'a> FormatDescIter<'a> {
213 pub(crate) fn new(device: &'a Device, buf_type: BufType) -> Self {
214 Self {
215 device,
216 buf_type,
217 next_index: 0,
218 finished: false,
219 }
220 }
221}
222
223impl Iterator for FormatDescIter<'_> {
224 type Item = io::Result<FormatDesc>;
225
226 fn next(&mut self) -> Option<Self::Item> {
227 if self.finished {
228 return None;
229 }
230
231 unsafe {
232 let mut desc = raw::FmtDesc {
233 index: self.next_index,
234 type_: self.buf_type,
235 mbus_code: 0,
236 ..mem::zeroed()
237 };
238 match raw::VIDIOC_ENUM_FMT.ioctl(self.device, &mut desc) {
239 Ok(_) => {}
240 Err(e) => {
241 self.finished = true;
242 if e.raw_os_error() == Some(libc::EINVAL as _) {
243 return None;
245 } else {
246 return Some(Err(e));
247 }
248 }
249 }
250
251 self.next_index += 1;
252
253 Some(Ok(FormatDesc(desc)))
254 }
255 }
256}
257
258pub struct FormatDesc(raw::FmtDesc);
259
260impl FormatDesc {
261 pub fn flags(&self) -> FormatFlags {
262 self.0.flags
263 }
264
265 pub fn description(&self) -> &str {
266 byte_array_to_str(&self.0.description)
267 }
268
269 pub fn pixel_format(&self) -> PixelFormat {
270 self.0.pixel_format
271 }
272}
273
274impl fmt::Debug for FormatDesc {
275 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276 f.debug_struct("Format")
277 .field("index", &self.0.index)
278 .field("type", &self.0.type_)
279 .field("flags", &self.0.flags)
280 .field("description", &self.description())
281 .field("pixel_format", &self.0.pixel_format)
282 .finish()
283 }
284}
285
286pub enum FrameSizes {
287 Discrete(Vec<DiscreteFrameSize>),
288 Stepwise(StepwiseFrameSizes),
289 Continuous(StepwiseFrameSizes),
290}
291
292impl FrameSizes {
293 pub(crate) fn new(device: &Device, pixel_format: PixelFormat) -> io::Result<Self> {
294 unsafe {
295 let mut desc = raw::FrmSizeEnum {
296 index: 0,
297 pixel_format,
298 ..mem::zeroed()
299 };
300 raw::VIDIOC_ENUM_FRAMESIZES.ioctl(device, &mut desc)?;
301
302 match desc.type_ {
303 FrmSizeType::DISCRETE => {
304 let mut sizes = vec![DiscreteFrameSize {
305 raw: desc.union.discrete,
306 index: 0,
307 }];
308 for index in 1.. {
309 let mut desc = raw::FrmSizeEnum {
310 index,
311 pixel_format,
312 ..mem::zeroed()
313 };
314 match raw::VIDIOC_ENUM_FRAMESIZES.ioctl(device, &mut desc) {
315 Ok(_) => {
316 assert_eq!(desc.type_, FrmSizeType::DISCRETE);
317 sizes.push(DiscreteFrameSize {
318 raw: desc.union.discrete,
319 index,
320 });
321 }
322 Err(e) if e.raw_os_error() == Some(libc::EINVAL as _) => break,
323 Err(e) => return Err(e.into()),
324 }
325 }
326
327 Ok(FrameSizes::Discrete(sizes))
328 }
329 FrmSizeType::CONTINUOUS => Ok(FrameSizes::Continuous(StepwiseFrameSizes(
330 desc.union.stepwise,
331 ))),
332 FrmSizeType::STEPWISE => Ok(FrameSizes::Stepwise(StepwiseFrameSizes(
333 desc.union.stepwise,
334 ))),
335 _ => unreachable!("unknown frame size type {:?}", desc.type_),
336 }
337 }
338 }
339
340 pub fn min_width(&self) -> u32 {
341 match self {
342 FrameSizes::Discrete(sizes) => sizes.iter().map(|size| size.width()).min().unwrap(),
343 FrameSizes::Stepwise(sizes) | FrameSizes::Continuous(sizes) => sizes.min_width(),
344 }
345 }
346
347 pub fn min_height(&self) -> u32 {
348 match self {
349 FrameSizes::Discrete(sizes) => sizes.iter().map(|size| size.height()).min().unwrap(),
350 FrameSizes::Stepwise(sizes) | FrameSizes::Continuous(sizes) => sizes.min_height(),
351 }
352 }
353
354 pub fn max_width(&self) -> u32 {
355 match self {
356 FrameSizes::Discrete(sizes) => sizes.iter().map(|size| size.width()).max().unwrap(),
357 FrameSizes::Stepwise(sizes) | FrameSizes::Continuous(sizes) => sizes.max_width(),
358 }
359 }
360
361 pub fn max_height(&self) -> u32 {
362 match self {
363 FrameSizes::Discrete(sizes) => sizes.iter().map(|size| size.height()).max().unwrap(),
364 FrameSizes::Stepwise(sizes) | FrameSizes::Continuous(sizes) => sizes.max_height(),
365 }
366 }
367}
368
369pub struct StepwiseFrameSizes(raw::FrmSizeStepwise);
370
371pub struct DiscreteFrameSize {
372 raw: raw::FrmSizeDiscrete,
373 index: u32,
374}
375
376impl StepwiseFrameSizes {
377 pub fn min_width(&self) -> u32 {
378 self.0.min_width
379 }
380
381 pub fn min_height(&self) -> u32 {
382 self.0.min_height
383 }
384
385 pub fn max_width(&self) -> u32 {
386 self.0.max_width
387 }
388
389 pub fn max_height(&self) -> u32 {
390 self.0.max_height
391 }
392
393 pub fn step_width(&self) -> u32 {
394 self.0.step_width
395 }
396
397 pub fn step_height(&self) -> u32 {
398 self.0.step_height
399 }
400}
401
402impl DiscreteFrameSize {
403 pub fn width(&self) -> u32 {
404 self.raw.width
405 }
406
407 pub fn height(&self) -> u32 {
408 self.raw.height
409 }
410
411 pub fn index(&self) -> u32 {
412 self.index
413 }
414}
415
416pub enum FrameIntervals {
417 Discrete(Vec<DiscreteFrameInterval>),
418 Stepwise(StepwiseFrameIntervals),
419 Continuous(StepwiseFrameIntervals),
420}
421
422impl FrameIntervals {
423 pub(crate) fn new(
424 device: &Device,
425 pixel_format: PixelFormat,
426 width: u32,
427 height: u32,
428 ) -> io::Result<Self> {
429 unsafe {
430 let mut desc = raw::FrmIvalEnum {
431 index: 0,
432 pixel_format,
433 width,
434 height,
435 ..mem::zeroed()
436 };
437 raw::VIDIOC_ENUM_FRAMEINTERVALS.ioctl(device, &mut desc)?;
438
439 match desc.type_ {
440 FrmIvalType::DISCRETE => {
441 let mut ivals = vec![DiscreteFrameInterval {
442 raw: desc.union.discrete,
443 index: 0,
444 }];
445 for index in 1.. {
446 let mut desc = raw::FrmIvalEnum {
447 index,
448 pixel_format,
449 width,
450 height,
451 ..mem::zeroed()
452 };
453 match raw::VIDIOC_ENUM_FRAMEINTERVALS.ioctl(device, &mut desc) {
454 Ok(_) => {
455 assert_eq!(desc.type_, FrmIvalType::DISCRETE);
456 ivals.push(DiscreteFrameInterval {
457 raw: desc.union.discrete,
458 index,
459 });
460 }
461 Err(e) if e.raw_os_error() == Some(libc::EINVAL as _) => break,
462 Err(e) => return Err(e.into()),
463 }
464 }
465
466 Ok(FrameIntervals::Discrete(ivals))
467 }
468 FrmIvalType::CONTINUOUS => Ok(FrameIntervals::Continuous(StepwiseFrameIntervals(
469 desc.union.stepwise,
470 ))),
471 FrmIvalType::STEPWISE => Ok(FrameIntervals::Stepwise(StepwiseFrameIntervals(
472 desc.union.stepwise,
473 ))),
474 _ => {
475 log::error!("driver bug: unknown frame interval type {:?}", desc.type_);
477 Ok(FrameIntervals::Continuous(StepwiseFrameIntervals(
478 raw::FrmIvalStepwise {
479 min: Fract::new(1, 600),
480 max: Fract::new(1, 1),
481 step: Fract::new(1, 1),
484 },
485 )))
486 }
487 }
488 }
489 }
490
491 pub fn min(&self) -> Fract {
492 match self {
493 FrameIntervals::Discrete(list) => list.iter().map(|ival| ival.raw).min().unwrap(),
494 FrameIntervals::Stepwise(ivals) | FrameIntervals::Continuous(ivals) => *ivals.min(),
495 }
496 }
497
498 pub fn max(&self) -> Fract {
499 match self {
500 FrameIntervals::Discrete(list) => list.iter().map(|ival| ival.raw).max().unwrap(),
501 FrameIntervals::Stepwise(ivals) | FrameIntervals::Continuous(ivals) => *ivals.max(),
502 }
503 }
504}
505
506impl fmt::Display for FrameIntervals {
507 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
508 match self {
509 FrameIntervals::Discrete(list) => {
510 for (i, ival) in list.iter().enumerate() {
511 if i != 0 {
512 f.write_str(", ")?;
513 }
514
515 write!(f, "{}", ival.fract())?;
516 }
517
518 Ok(())
519 }
520 FrameIntervals::Stepwise(ival) => {
521 write!(f, "{}-{} (step {})", ival.min(), ival.max(), ival.step())
522 }
523 FrameIntervals::Continuous(ival) => {
524 write!(f, "{}-{}", ival.min(), ival.max())
525 }
526 }
527 }
528}
529
530pub struct DiscreteFrameInterval {
531 index: u32,
532 raw: Fract,
533}
534
535impl DiscreteFrameInterval {
536 pub fn index(&self) -> u32 {
537 self.index
538 }
539
540 pub fn fract(&self) -> &Fract {
541 &self.raw
542 }
543}
544
545pub struct StepwiseFrameIntervals(raw::FrmIvalStepwise);
546
547impl StepwiseFrameIntervals {
548 pub fn min(&self) -> &Fract {
549 &self.0.min
550 }
551
552 pub fn max(&self) -> &Fract {
553 &self.0.max
554 }
555
556 pub fn step(&self) -> &Fract {
557 &self.0.step
558 }
559}