Skip to content

Commit

Permalink
Merge pull request #4 from katyo/stream-parm
Browse files Browse the repository at this point in the history
Add support stream parameters get/set
  • Loading branch information
katyo committed Aug 4, 2023
2 parents 51dc1b6 + 3fddedb commit 62659e4
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 5 deletions.
29 changes: 29 additions & 0 deletions async-std/src/lib.rs
Expand Up @@ -167,6 +167,35 @@ impl Device {
}
}

/// Get stream parameters
pub async fn param(&self, type_: BufferType) -> Result<StreamParm> {
let fd = self.as_raw_fd();
asyncify(move || {
let mut param = StreamParm::from(type_);
Internal::from(&mut param).get(fd)?;
Ok(param)
})
.await
}

/// Get stream parameters
pub async fn get_param(&self, param: &mut StreamParm) -> Result<()> {
*param = self.param(param.type_()).await?;
Ok(())
}

/// Set stream parameters
pub async fn set_param(&self, param: &mut StreamParm) -> Result<()> {
let fd = self.as_raw_fd();
let mut param_ = *param;
*param = asyncify(move || -> Result<StreamParm> {
Internal::from(&mut param_).set(fd)?;
Ok(param_)
})
.await?;
Ok(())
}

/// Create stream to input/output data
pub fn stream<Dir: Direction, Met: Method>(
&self,
Expand Down
2 changes: 2 additions & 0 deletions core/src/impls.rs
Expand Up @@ -7,6 +7,7 @@ mod format;
mod formats;
mod frmivals;
mod frmsizes;
mod streamparm;
mod timestamp;
mod types;

Expand All @@ -19,5 +20,6 @@ pub use format::*;
pub use formats::*;
pub use frmivals::*;
pub use frmsizes::*;
pub use streamparm::*;
pub use timestamp::*;
pub use types::*;
117 changes: 117 additions & 0 deletions core/src/impls/streamparm.rs
@@ -0,0 +1,117 @@
use crate::{calls, types::*, Internal, Result};
use std::os::unix::io::RawFd;

impl Internal<&mut StreamParm> {
pub fn get(&mut self, fd: RawFd) -> Result<()> {
unsafe_call!(calls::g_parm(fd, *self.as_mut() as *mut _)).map(|_| ())
}
}

impl Internal<&mut StreamParm> {
pub fn set(&self, fd: RawFd) -> Result<()> {
unsafe_call!(calls::s_parm(fd, *self.as_ref() as *const _ as *mut _)).map(|_| ())
}
}

unsafe impl Send for StreamParm {}

impl From<BufferType> for StreamParm {
fn from(type_: BufferType) -> Self {
Self {
type_,
parm: if type_.is_capture() {
StreamParmUnion {
capture: CaptureParm::default(),
}
} else {
StreamParmUnion {
output: OutputParm::default(),
}
},
}
}
}

impl StreamParm {
/// Create from value
pub fn new<T: IsStreamParm>(type_: BufferType, data: T) -> Option<Self> {
if T::OUTPUT == type_.is_output() {
let mut this = Self::from(type_);
*this.try_mut().unwrap() = data;
Some(this)
} else {
None
}
}

/// Get reference to value
pub fn try_ref<T: IsStreamParm>(&self) -> Option<&T> {
if T::OUTPUT == self.type_.is_output() {
Some(unsafe { &*(&self.parm as *const _ as *const T) })
} else {
None
}
}

/// Get mutable reference to value
pub fn try_mut<T: IsStreamParm>(&mut self) -> Option<&mut T> {
if T::OUTPUT == self.type_.is_output() {
Some(unsafe { &mut *(&mut self.parm as *mut _ as *mut T) })
} else {
None
}
}
}

/// Stream parameter types
pub trait IsStreamParm {
/// Stream direction
const OUTPUT: bool;
}

impl IsStreamParm for CaptureParm {
const OUTPUT: bool = false;
}

impl IsStreamParm for OutputParm {
const OUTPUT: bool = true;
}

impl core::fmt::Display for StreamParm {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
self.type_.fmt(f)?;
": ".fmt(f)?;
self.try_ref::<CaptureParm>()
.map(|parm| parm.fmt(f))
.or_else(|| self.try_ref::<OutputParm>().map(|parm| parm.fmt(f)))
.unwrap()
}
}

impl core::fmt::Display for CaptureParm {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
self.time_per_frame.fmt(f)?;
" #".fmt(f)?;
self.read_buffers.fmt(f)?;
' '.fmt(f)?;
self.capability.fmt(f)?;
','.fmt(f)?;
self.capture_mode.fmt(f)?;
" *".fmt(f)?;
self.extended_mode.fmt(f)
}
}

impl core::fmt::Display for OutputParm {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
self.time_per_frame.fmt(f)?;
" #".fmt(f)?;
self.write_buffers.fmt(f)?;
' '.fmt(f)?;
self.capability.fmt(f)?;
','.fmt(f)?;
self.output_mode.fmt(f)?;
" *".fmt(f)?;
self.extended_mode.fmt(f)
}
}
14 changes: 13 additions & 1 deletion core/src/types/enums.rs
Expand Up @@ -267,7 +267,7 @@ enum_impl! {
}

enum IoMode {
Defaut = 0,
Default = 0,
HighQuality = 1,
}

Expand Down Expand Up @@ -1669,3 +1669,15 @@ impl Quantization {
}
}
}

impl Default for IoCapabilityFlag {
fn default() -> Self {
Self::none()
}
}

impl Default for IoMode {
fn default() -> Self {
Self::Default
}
}
20 changes: 16 additions & 4 deletions core/src/types/structs.rs
Expand Up @@ -399,7 +399,7 @@ pub struct Rect {

/// Fraction value
#[repr(C)]
#[derive(Debug, Copy, Clone, CopyGetters, Setters)]
#[derive(Debug, Copy, Clone, Default, CopyGetters, Setters)]
pub struct Fract {
/// Numerator
#[getset(get_copy = "pub", set = "pub")]
Expand Down Expand Up @@ -1082,7 +1082,7 @@ pub struct Window {
}

#[repr(C)]
#[derive(Debug, Copy, Clone, CopyGetters, Setters)]
#[derive(Debug, Copy, Clone, Default, CopyGetters, Setters)]
pub struct CaptureParm {
#[getset(get_copy = "pub", set = "pub")]
pub(crate) capability: IoCapabilityFlag,
Expand All @@ -1103,13 +1103,23 @@ pub struct CaptureParm {
}

#[repr(C)]
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, Default, CopyGetters, Setters)]
pub struct OutputParm {
#[getset(get_copy = "pub", set = "pub")]
pub(crate) capability: IoCapabilityFlag,

#[getset(get_copy = "pub", set = "pub")]
pub(crate) output_mode: IoMode,

#[getset(get_copy = "pub", set = "pub")]
pub(crate) time_per_frame: Fract,

#[getset(get_copy = "pub", set = "pub")]
pub(crate) extended_mode: u32,

#[getset(get_copy = "pub", set = "pub")]
pub(crate) write_buffers: u32,

pub(crate) reserved: [u32; 4],
}

Expand Down Expand Up @@ -1819,8 +1829,10 @@ pub(crate) union FormatUnion {
}

#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Copy, Clone, CopyGetters)]
pub struct StreamParm {
/// Buffer type
#[getset(get_copy = "pub")]
pub(crate) type_: BufferType,
pub(crate) parm: StreamParmUnion,
}
Expand Down
4 changes: 4 additions & 0 deletions examples/capture.rs
Expand Up @@ -7,6 +7,10 @@ fn main() -> std::io::Result<()> {
let fmt = dev.format(BufferType::VideoCapture)?;
println!(" {fmt}");

// Get current params
let prm = dev.param(BufferType::VideoCapture)?;
println!(" {prm}");

// Start video capture stream
let stream = dev.stream::<In, Mmap>(ContentType::Video, 4)?;

Expand Down
17 changes: 17 additions & 0 deletions src/lib.rs
Expand Up @@ -134,6 +134,23 @@ impl Device {
}
}

/// Get stream parameters
pub fn param(&self, type_: BufferType) -> Result<StreamParm> {
let mut param = StreamParm::from(type_);
self.get_param(&mut param)?;
Ok(param)
}

/// Get stream parameters
pub fn get_param(&self, param: &mut StreamParm) -> Result<()> {
Internal::from(param).get(self.as_raw_fd())
}

/// Set stream parameters
pub fn set_param(&self, param: &mut StreamParm) -> Result<()> {
Internal::from(param).set(self.as_raw_fd())
}

/// Create stream to input/output data
pub fn stream<Dir: Direction, Met: Method>(
&self,
Expand Down
30 changes: 30 additions & 0 deletions tokio/src/lib.rs
Expand Up @@ -175,6 +175,36 @@ impl Device {
}
}

/// Get stream parameters
pub async fn param(&self, type_: BufferType) -> Result<StreamParm> {
let fd = self.as_raw_fd();
asyncify(move || {
let mut param = StreamParm::from(type_);
Internal::from(&mut param).get(fd)?;
Ok(param)
})
.await
}

/// Get stream parameters
pub async fn get_param(&self, param: &mut StreamParm) -> Result<()> {
let param_ = self.param(param.type_()).await?;
param.clone_from(&param_);
Ok(())
}

/// Set stream parameters
pub async fn set_param(&self, param: &mut StreamParm) -> Result<()> {
let fd = self.as_raw_fd();
let mut param_ = *param;
*param = asyncify(move || -> Result<StreamParm> {
Internal::from(&mut param_).set(fd)?;
Ok(param_)
})
.await?;
Ok(())
}

/// Create stream to input/output data
pub fn stream<Dir: Direction, Met: Method>(
&self,
Expand Down

0 comments on commit 62659e4

Please sign in to comment.