diff --git a/nokhwa-core/src/decoder.rs b/nokhwa-core/src/decoder.rs
index d4efe24..b1011ca 100644
--- a/nokhwa-core/src/decoder.rs
+++ b/nokhwa-core/src/decoder.rs
@@ -8,7 +8,7 @@ use bytemuck::try_cast_slice_mut;
use crate::pixel_destination::PixelDestination;
pub trait Decoder {
- type Config: Clone + Debug;
+ type Config: Clone + Debug + ConfigHasResolution;
type OutputMeta: Clone + Debug;
const SUPPORTED_DESTINATIONS: &'static [PixelDestination];
@@ -27,10 +27,7 @@ pub trait Decoder {
where
::Subpixel: NonFloatScalarWidth
{
- let destination = match PixelDestination::get_by_pixel::
() {
- Some(dest) => dest,
- None => return Err(NokhwaError::DecoderUnknownDestinationPixelFormat(P::COLOR_MODEL, P::Subpixel::WIDTH_BYTES))
- };
+ let Some(destination) = PixelDestination::get_by_pixel::
() else { return Err(NokhwaError::DecoderUnknownDestinationPixelFormat(P::COLOR_MODEL, P::Subpixel::WIDTH_BYTES)) };
if !Self::supports_destination(destination) {
return Err(NokhwaError::DecoderUnsupportedDestinationPixelFormat(destination))
@@ -43,13 +40,29 @@ pub trait Decoder {
self.decode_to_buffer(to_decode, cast_slice, destination)
}
-
fn decode(
&mut self,
- to_decode: FrameBuffer,
+ to_decode: FrameBuffer<'_>,
) -> Result, NokhwaError>
where
- ::Subpixel: NonFloatScalarWidth;
+
::Subpixel: NonFloatScalarWidth,
+ {
+ let resolution = self.config().resolution();
+ let min_size_alloc = self.output_decoder_min_size_pixel::
(resolution)?;
+ let mut out_buffer: Vec = vec![P::Subpixel::DEFAULT_MIN_VALUE; min_size_alloc];
+ let meta = self.decode_to_pixel_buffer::(to_decode, &mut out_buffer)?;
+ Ok(DecodedImage::new(
+ ImageBuffer::from_vec(
+ resolution.width(),
+ resolution.height(),
+ out_buffer,
+ )
+ .ok_or(NokhwaError::Decoder(
+ "failed to convert into an image buffer".to_string(),
+ ))?,
+ meta,
+ ))
+ }
fn output_decoder_min_size_pixel
(&self, resolution: Resolution) -> Result where
P: Pixel,
@@ -58,9 +71,29 @@ pub trait Decoder {
}
- fn output_decoder_min_size(&self, resolution: Resolution, destination_format: PixelDestination) -> Result;
+ fn output_decoder_min_size(&self, resolution: Resolution, destination_format: PixelDestination) -> Result {
+ if !Self::supports_destination(destination_format) {
+ return Err(NokhwaError::DecoderUnsupportedDestinationPixelFormat(destination_format))
+ }
+ let px_size = match destination_format {
+ PixelDestination::Rgb8 | PixelDestination::Bgr8 => 3_u32,
+ PixelDestination::Rgba8 | PixelDestination::Bgra8 | PixelDestination::LumaA16 => 4_u32,
+ PixelDestination::Rgb16 | PixelDestination::Bgr16 => 3_u32 * 2_u32,
+ PixelDestination::Rgba16 | PixelDestination::Bgra16 => 4_u32 * 2_u32,
+ PixelDestination::Luma8 => 1_u32,
+ PixelDestination::LumaA8 | PixelDestination::Luma16 => 2_u32,
+ };
+ let reso = resolution.width() * resolution.height();
+ Ok((reso as usize) * (px_size as usize))
+ }
+
+ #[must_use]
fn supports_destination(pixel_destination: PixelDestination) -> bool {
Self::SUPPORTED_DESTINATIONS.contains(&pixel_destination)
}
}
+
+pub trait ConfigHasResolution {
+ fn resolution(&self) -> Resolution;
+}
diff --git a/nokhwa-core/src/frame_format.rs b/nokhwa-core/src/frame_format.rs
index 3d94e12..0898340 100644
--- a/nokhwa-core/src/frame_format.rs
+++ b/nokhwa-core/src/frame_format.rs
@@ -206,6 +206,7 @@ define_frame_format_with_groups! {
}
impl FrameFormat {
+ #[must_use]
pub fn is_custom(&self) -> bool {
if let FrameFormat::Custom(_) = self {
return true
diff --git a/nokhwa-core/src/pixel_destination.rs b/nokhwa-core/src/pixel_destination.rs
index c2ee930..8f58b48 100644
--- a/nokhwa-core/src/pixel_destination.rs
+++ b/nokhwa-core/src/pixel_destination.rs
@@ -19,6 +19,7 @@ pub enum PixelDestination {
}
impl PixelDestination {
+ #[must_use]
pub fn get_by_pixel() -> Option
where
P: Pixel,
diff --git a/nokhwa-core/src/stream.rs b/nokhwa-core/src/stream.rs
index 4ab5f07..b1b33cc 100644
--- a/nokhwa-core/src/stream.rs
+++ b/nokhwa-core/src/stream.rs
@@ -165,7 +165,7 @@ impl<'a> StreamHandle<'a> {
return Err(NokhwaError::ReadFrameError(why));
}
}
- Event::Error(e) => return Err(NokhwaError::ReadFrameError(e.to_string())),
+ Event::Error(e) => return Err(NokhwaError::ReadFrameError(e.clone())),
_ => {}
}
}
diff --git a/nokhwa-core/src/types.rs b/nokhwa-core/src/types.rs
index 7e44381..7689673 100644
--- a/nokhwa-core/src/types.rs
+++ b/nokhwa-core/src/types.rs
@@ -43,7 +43,7 @@ impl CameraIndex {
pub fn as_string(&self) -> String {
match self {
CameraIndex::Index(i) => i.to_string(),
- CameraIndex::String(s) | CameraIndex::Stable(s) => s.to_string(),
+ CameraIndex::String(s) | CameraIndex::Stable(s) => s.clone(),
}
}
diff --git a/nokhwa-decoders/Cargo.toml b/nokhwa-decoders/Cargo.toml
index e301f27..c50dcb4 100644
--- a/nokhwa-decoders/Cargo.toml
+++ b/nokhwa-decoders/Cargo.toml
@@ -7,8 +7,8 @@ edition = "2024"
ffmpeg = ["ffmpeg-the-third"]
yuyv = ["dcv-color-primitives", "yuv"]
mjpeg = ["zune-jpeg", "zune-core"]
-luma = ["itertools", "nokhwa-iter-extensions", "itermore"]
-#static = ["ffmpeg-the-third/static"]
+luma = ["nokhwa-iter-extensions", "itermore"]
+static = ["ffmpeg-the-third/static"]
#async = []
[dependencies]
@@ -19,7 +19,7 @@ version = "0.2"
path = "../nokhwa-core"
[dependencies.ffmpeg-the-third]
-version = "4.0.0+ffmpeg-8.0"
+version = "4.0.0"
optional = true
[dependencies.yuv]
@@ -38,10 +38,6 @@ optional = true
version = "0.5.0-rc2"
optional = true
-[dependencies.itertools]
-version = "0.14"
-optional = true
-
[dependencies.itermore]
version = "0.8"
features = ["array_chunks"]
diff --git a/nokhwa-decoders/src/ffmpeg.rs b/nokhwa-decoders/src/ffmpeg.rs
index 655405d..15bc3d4 100644
--- a/nokhwa-decoders/src/ffmpeg.rs
+++ b/nokhwa-decoders/src/ffmpeg.rs
@@ -12,11 +12,12 @@ use ffmpeg_the_third::ffi::{
use ffmpeg_the_third::packet::{Borrow, Ref};
use ffmpeg_the_third::{Frame, decoder, packet::Packet};
use nokhwa_core::codec::Codec;
-use nokhwa_core::decoder::{Decoder, ImageBuffer, Pixel, Primitive};
+use nokhwa_core::decoder::{ConfigHasResolution, Decoder, Pixel};
use nokhwa_core::error::NokhwaError;
use nokhwa_core::frame_buffer::FrameBuffer;
use nokhwa_core::frame_format::{CustomFrameFormat, FrameFormat};
-use nokhwa_core::image::{DecodedImage, NonFloatScalarWidth};
+use nokhwa_core::image::{NonFloatScalarWidth};
+use nokhwa_core::pixel_destination::PixelDestination;
use nokhwa_core::types::{CameraFormat, FrameRate, Resolution};
pub struct FfmpegDecoder {
@@ -56,7 +57,8 @@ impl FfmpegDecoder {
impl Decoder for FfmpegDecoder {
type Config = ::Config;
type OutputMeta = ::WrittenMeta;
- type DestinationFormatHint = AVPixelFormat;
+ const SUPPORTED_DESTINATIONS: &'static [PixelDestination] = &[];
+
fn config(&self) -> &Self::Config {
self.codec.config()
@@ -71,7 +73,7 @@ impl Decoder for FfmpegDecoder {
&mut self,
to_decode: FrameBuffer,
mut buffer: impl AsMut<[u8]>,
- _destination_format: Option,
+ _destination_format: PixelDestination,
) -> Result {
// TODO: add an extra zippy happy path for rgb/bgr/luma
let (frame, metadata) = self.receive_decoded_frame(to_decode)?;
@@ -188,54 +190,6 @@ impl Decoder for FfmpegDecoder {
Ok(decoded_meta)
}
}
-
- fn decode(
- &mut self,
- to_decode: FrameBuffer,
- ) -> Result, NokhwaError>
- where
- ::Subpixel: NonFloatScalarWidth,
- {
- let min_size = self.output_decoder_min_size_pixel::
(self.config().resolution);
- let mut buffer: Vec = vec![::DEFAULT_MIN_VALUE; min_size];
- let meta = self.decode_to_buffer(
- to_decode,
- try_cast_slice_mut(&mut buffer)
- .map_err(|why| NokhwaError::DecoderInvalidBuffer(why.to_string()))?,
- None,
- )?;
- Ok(DecodedImage::new(
- ImageBuffer::from_vec(
- self.codec.config.resolution.width(),
- self.codec.config.resolution.height(),
- buffer,
- )
- .ok_or(NokhwaError::Decoder(
- "Failed to create Image Buffer".to_string(),
- ))?,
- meta,
- ))
- }
-
- fn output_decoder_min_size(
- &self,
- resolution: Resolution,
- destination_format: Self::DestinationFormatHint,
- ) -> usize {
- let size = unsafe {
- av_image_get_buffer_size(
- destination_format,
- resolution.width() as i32,
- resolution.height() as i32,
- 1,
- )
- };
- size as usize
- }
-
- fn buffer_takes_destination_hint(&self) -> bool {
- false
- }
}
fn create_sws_context(
@@ -261,53 +215,6 @@ fn create_sws_context(
Ok(new_sws)
}
-fn pixel_to_destination_px_fmt() -> Option
-where
- ::Subpixel: NonFloatScalarWidth,
-{
- match P::COLOR_MODEL {
- "RGB" => match <
::Subpixel>::WIDTH_BYTES {
- 1 => Some(AVPixelFormat::AV_PIX_FMT_RGB24),
- _ => None,
- },
-
- "RGBA" => match <
::Subpixel>::WIDTH_BYTES {
- 1 => Some(AVPixelFormat::AV_PIX_FMT_RGBA),
- 2 => Some(switch_endian(
- AVPixelFormat::AV_PIX_FMT_RGBA64LE,
- AVPixelFormat::AV_PIX_FMT_RGBA64BE,
- )),
- _ => None,
- },
- "BGR" => match <
::Subpixel>::WIDTH_BYTES {
- 1 => Some(AVPixelFormat::AV_PIX_FMT_BGR24),
- _ => None,
- },
-
- "BGRA" => match <
::Subpixel>::WIDTH_BYTES {
- 1 => Some(AVPixelFormat::AV_PIX_FMT_BGRA),
- 2 => Some(switch_endian(
- AVPixelFormat::AV_PIX_FMT_BGRA64LE,
- AVPixelFormat::AV_PIX_FMT_BGRA64BE,
- )),
- _ => None,
- },
- "Y" => match <
::Subpixel>::WIDTH_BYTES {
- 1 => Some(AVPixelFormat::AV_PIX_FMT_GRAY8),
- 2 => Some(switch_endian(
- AVPixelFormat::AV_PIX_FMT_GRAY16LE,
- AVPixelFormat::AV_PIX_FMT_GRAY16BE,
- )),
- _ => None,
- },
- "YA" => match <
::Subpixel>::WIDTH_BYTES {
- 1 => Some(AVPixelFormat::AV_PIX_FMT_GRAY8A),
- _ => None,
- },
- _ => None,
- }
-}
-
pub struct Sws {
pub sws: *mut SwsContext,
pub source_pixel_format: AVPixelFormat,
@@ -686,6 +593,12 @@ pub struct FfmpegDecoderConfig {
pub video_delay: i32,
}
+impl ConfigHasResolution for FfmpegDecoderConfig {
+ fn resolution(&self) -> Resolution {
+ self.resolution
+ }
+}
+
impl FfmpegDecoderConfig {
pub fn with_camera_format(camera_format: &CameraFormat) -> Self {
FfmpegDecoderConfig::from(*camera_format)
diff --git a/nokhwa-decoders/src/luma.rs b/nokhwa-decoders/src/luma.rs
index e6eb0aa..e102b43 100644
--- a/nokhwa-decoders/src/luma.rs
+++ b/nokhwa-decoders/src/luma.rs
@@ -1,20 +1,16 @@
use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt::Debug;
-use std::mem::swap;
-use bytemuck::{cast_mut, cast_slice, cast_slice_mut, try_cast_slice_mut};
-use image::Pixel;
-use itertools::Itertools;
-use nokhwa_core::decoder::Decoder;
+use bytemuck::{cast_slice, cast_slice_mut};
+use nokhwa_core::decoder::{ConfigHasResolution, Decoder};
use nokhwa_core::error::NokhwaError;
use nokhwa_core::frame_buffer::FrameBuffer;
use nokhwa_core::frame_format::{CustomFrameFormat, FrameFormat};
-use nokhwa_core::image::{DecodedImage, NonFloatScalarWidth};
-use nokhwa_core::types::{CameraFormat, Resolution};
use nokhwa_iter_extensions::duplicate::IterDuplicateConst;
use nokhwa_iter_extensions::interweave::IterInterweave;
use itermore::{IterArrayChunks};
use nokhwa_core::pixel_destination::PixelDestination;
+use nokhwa_core::types::{CameraFormat, Resolution};
#[derive(Clone, Debug, PartialEq)]
pub struct LumaDecoder {
@@ -44,29 +40,15 @@ impl Decoder for LumaDecoder {
Ok(())
}
- fn decode_to_buffer(&mut self, mut to_decode: FrameBuffer, mut buffer: impl AsMut<[u8]>, destination_format: PixelDestination) -> Result {
- let destination_hint = match destination_format {
- Some(h) => h,
- None => return Err(NokhwaError::DecoderDestinationHintRequired)
- };
-
- let (width, max_value) = match self.config().format {
- FrameFormat::Luma_8 => (1, u8::MAX as u32),
- FrameFormat::Luma_10 => (2, 2_u32.pow(10)),
- FrameFormat::Luma_12 => (2, 2_u32.pow(12)),
- FrameFormat::Luma_14 => (2, 2_u32.pow(14)),
- FrameFormat::Luma_16 | FrameFormat::Depth_16 => (2, u16::MAX as u32),
- fmt => return Err(NokhwaError::DecoderUnsupportedFrameFormat(fmt))
- };
-
- let format = self.config().custom_frame_format_map.as_ref().map(|m| {
+ fn decode_to_buffer(&mut self, to_decode: FrameBuffer, mut buffer: impl AsMut<[u8]>, destination_format: PixelDestination) -> Result {
+ let format = self.config().custom_frame_format_map.as_ref().and_then(|m| {
match self.config().format {
FrameFormat::Custom(cfmt) => {
m.get(&cfmt).copied()
}
_ => None,
}
- }).flatten().unwrap_or(self.config().format);
+ }).unwrap_or(self.config().format);
let r = filter_to_u8(self.config().channel_filters.red);
let g = filter_to_u8(self.config().channel_filters.green);
@@ -82,18 +64,20 @@ impl Decoder for LumaDecoder {
match format {
FrameFormat::Luma_8 => {
- match destination_hint {
+ match destination_format {
PixelDestination::Luma8 => {
if to_decode.len() != buffer.len() {
- return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
+ return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
}
match to_decode.consume().0 {
Cow::Borrowed(data) => {
- buffer.copy_from_slice(data)
+ buffer.copy_from_slice(data);
+ Ok(())
}
Cow::Owned(mut owned) => {
- buffer.swap_with_slice(owned.as_mut_slice())
+ buffer.swap_with_slice(owned.as_mut_slice());
+ Ok(())
}
}
}
@@ -101,52 +85,56 @@ impl Decoder for LumaDecoder {
let default_alpha = u8::MAX * a;
if (to_decode.len() * 2) != buffer.len() {
- return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
+ return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
}
- to_decode.buffer().into_iter().interweave(&default_alpha, false).enumerate()
+ to_decode.buffer().iter().interweave::<0>(&default_alpha, false).enumerate()
.for_each(|(len, data)| {
unsafe {
*buffer.get_unchecked_mut(len) = *data;
}
});
+ Ok(())
}
PixelDestination::Rgb8 => {
if (to_decode.len() * 3) != buffer.len() {
- return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
+ return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
}
- to_decode.buffer().into_iter().duplicate_const::<3>().arrays::<3>().map(|pixel| {
- let px_r = &pixel[0_usize] * r;
- let px_g = &pixel[1_usize] * g;
- let px_b = &pixel[2_usize] * b;
+ to_decode.buffer().iter().duplicate_const::<3>().arrays::<3>().flat_map(|pixel| {
+ let px_r = *pixel[0_usize] * r;
+ let px_g = *pixel[1_usize] * g;
+ let px_b = *pixel[2_usize] * b;
[px_r, px_g, px_b]
- }).flatten().enumerate().for_each(|(len, data)| {
+ }).enumerate().for_each(|(len, data)| {
unsafe {
- *buffer.get_unchecked_mut(len) = *data;
+ *buffer.get_unchecked_mut(len) = data;
}
});
+ Ok(())
+
}
PixelDestination::Rgba8 => {
if (to_decode.len() * 4) != buffer.len() {
- return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
+ return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
}
- to_decode.buffer().into_iter().duplicate_const::<3>().arrays::<3>().map(|pixel| {
- let px_r = &pixel[0_usize] * r;
- let px_g = &pixel[1_usize] * g;
- let px_b = &pixel[2_usize] * b;
+ to_decode.buffer().iter().duplicate_const::<3>().arrays::<3>().flat_map(|pixel| {
+ let px_r = *pixel[0_usize] * r;
+ let px_g = *pixel[1_usize] * g;
+ let px_b = *pixel[2_usize] * b;
let px_a = 255 * b;
[px_r, px_g, px_b, px_a]
- }).flatten().enumerate().for_each(|(len, data)| {
+ }).enumerate().for_each(|(len, data)| {
unsafe {
- *buffer.get_unchecked_mut(len) = *data;
+ *buffer.get_unchecked_mut(len) = data;
}
});
+ Ok(())
}
PixelDestination::Rgb16 => {
if (to_decode.len() * 6) != buffer.len() {
- return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
+ return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
}
let temp_buffer = cast_slice_mut::(buffer);
@@ -159,20 +147,21 @@ impl Decoder for LumaDecoder {
}
};
- to_decode.buffer().into_iter().duplicate_const::<3>().arrays::<3>().map(|pixel| {
- let px_r = (&pixel[0_usize] as u16) * r_u16 * factor;
- let px_g = (&pixel[1_usize] as u16) * g_u16 * factor;
- let px_b = (&pixel[2_usize] as u16) * b_u16 * factor;
+ to_decode.buffer().iter().duplicate_const::<3>().arrays::<3>().flat_map(|pixel| {
+ let px_r = (*pixel[0_usize] as u16) * r_u16 * factor;
+ let px_g = (*pixel[1_usize] as u16) * g_u16 * factor;
+ let px_b = (*pixel[2_usize] as u16) * b_u16 * factor;
[px_r, px_g, px_b]
- }).flatten().enumerate().for_each(|(len, data)| {
+ }).enumerate().for_each(|(len, data)| {
unsafe {
- *temp_buffer.get_unchecked_mut(len) = *data;
+ *temp_buffer.get_unchecked_mut(len) = data;
}
- });
+ }); Ok(())
+
}
PixelDestination::Rgba16 => {
if (to_decode.len() * 8) != buffer.len() {
- return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
+ return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
}
let temp_buffer = cast_slice_mut::(buffer);
@@ -185,23 +174,24 @@ impl Decoder for LumaDecoder {
}
};
- to_decode.buffer().into_iter().duplicate_const::<3>().arrays::<3>().map(|pixel| {
- let px_r = (&pixel[0_usize] as u16) * r_u16 * factor;
- let px_g = (&pixel[1_usize] as u16) * g_u16 * factor;
- let px_b = (&pixel[2_usize] as u16) * b_u16 * factor;
+ to_decode.buffer().iter().duplicate_const::<3>().arrays::<3>().flat_map(|pixel| {
+ let px_r = (*pixel[0_usize] as u16) * r_u16 * factor;
+ let px_g = (*pixel[1_usize] as u16) * g_u16 * factor;
+ let px_b = (*pixel[2_usize] as u16) * b_u16 * factor;
let px_a = u16::MAX * a_u16;
[px_r, px_g, px_b, px_a]
- }).flatten().enumerate().for_each(|(len, data)| {
+ }).enumerate().for_each(|(len, data)| {
unsafe {
- *temp_buffer.get_unchecked_mut(len) = *data;
+ *temp_buffer.get_unchecked_mut(len) = data;
}
- });
+ }); Ok(())
+
}
PixelDestination::Luma16 => {
let buffer_u16 = cast_slice_mut::(buffer);
if to_decode.len() != buffer_u16.len() {
- return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
+ return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
}
let factor = match self.config().mode {
@@ -209,21 +199,22 @@ impl Decoder for LumaDecoder {
ConvertMode::Clipped => 0,
};
- to_decode.buffer().into_iter().map(|px| {
+ to_decode.buffer().iter().map(|px| {
(*px as u16) << factor
}).enumerate()
.for_each(|(len, data)| {
unsafe {
- *buffer_u16.get_unchecked_mut(len) = *data;
+ *buffer_u16.get_unchecked_mut(len) = data;
}
- });
+ }); Ok(())
+
}
PixelDestination::LumaA16 => {
let default_alpha = u16::MAX * a_u16;
let buffer_u16 = cast_slice_mut::(buffer);
if (to_decode.len() * 2) != buffer_u16.len() {
- return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
+ return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
}
let factor = match self.config().mode {
@@ -231,38 +222,28 @@ impl Decoder for LumaDecoder {
ConvertMode::Clipped => 0,
};
- to_decode.buffer().into_iter().map(|px| {
+ to_decode.buffer().iter().map(|px| {
(*px as u16) << factor
- }).interweave(&default_alpha, false).enumerate()
+ }).interweave::<0>(default_alpha, false).enumerate()
.for_each(|(len, data)| {
unsafe {
- *buffer_u16.get_unchecked_mut(len) = *data;
+ *buffer_u16.get_unchecked_mut(len) = data;
}
- });
+ }); Ok(())
+
}
+ fmt => Err(NokhwaError::DecoderUnsupportedDestinationPixelFormat(fmt))
}
}
- FrameFormat::Luma_10 => convert_u16_type_buffers(to_decode, buffer, destination_hint, self.config().mode, self.config().channel_filters, 10),
- FrameFormat::Luma_12 => convert_u16_type_buffers(to_decode, buffer, destination_hint, self.config().mode, self.config().channel_filters, 12),
- FrameFormat::Luma_14 => convert_u16_type_buffers(to_decode, buffer, destination_hint, self.config().mode, self.config().channel_filters, 14),
- FrameFormat::Luma_16 | FrameFormat::Depth_16 => convert_u16_type_buffers(to_decode, buffer, destination_hint, self.config().mode, self.config().channel_filters, 16),
+ FrameFormat::Luma_10 => convert_u16_type_buffers(to_decode, buffer, destination_format, self.config().mode, self.config().channel_filters, 10),
+ FrameFormat::Luma_12 => convert_u16_type_buffers(to_decode, buffer, destination_format, self.config().mode, self.config().channel_filters, 12),
+ FrameFormat::Luma_14 => convert_u16_type_buffers(to_decode, buffer, destination_format, self.config().mode, self.config().channel_filters, 14),
+ FrameFormat::Luma_16 | FrameFormat::Depth_16 => convert_u16_type_buffers(to_decode, buffer, destination_format, self.config().mode, self.config().channel_filters, 16),
fmt => {
- return Err(NokhwaError::DecoderUnsupportedFrameFormat(fmt))
+ Err(NokhwaError::DecoderUnsupportedFrameFormat(fmt))
}
}
}
-
- fn decode(&mut self, to_decode: FrameBuffer) -> Result, NokhwaError>
- where
- ::Subpixel: NonFloatScalarWidth
- {
- todo!()
- }
-
- fn output_decoder_min_size(&self, resolution: Resolution, destination_format: PixelDestination) -> usize {
- todo!()
- }
-
}
fn filter_to_u8(filter: bool) -> u8 {
@@ -288,9 +269,9 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
let b_u16 = filter_to_u16(channel_filters.blue);
let a_u16 = filter_to_u16(channel_filters.alpha);
- let r = filter_to_u8(channel_filters.red);
- let g = filter_to_u8(channel_filters.green);
- let b = filter_to_u8(channel_filters.blue);
+ // let r = filter_to_u8(channel_filters.red);
+ // let g = filter_to_u8(channel_filters.green);
+ // let b = filter_to_u8(channel_filters.blue);
let a = filter_to_u8(channel_filters.alpha);
match hint {
@@ -308,12 +289,12 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
ConvertMode::Clipped => 0,
};
- to_decode_u16.into_iter().map(|px| {
+ to_decode_u16.iter().map(|px| {
(*px >> factor) as u8
}).enumerate()
.for_each(|(len, data)| {
unsafe {
- *destination.get_unchecked_mut(len) = *data;
+ *destination.get_unchecked_mut(len) = data;
}
});
Ok(())
@@ -332,12 +313,12 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
ConvertMode::Clipped => 0,
};
- to_decode_u16.into_iter().map(|px| {
+ to_decode_u16.iter().map(|px| {
(*px >> factor) as u8
- }).interweave(255 * a, false).enumerate()
+ }).interweave::<0>(255 * a, false).enumerate()
.for_each(|(len, data)| {
unsafe {
- *destination.get_unchecked_mut(len) = *data;
+ *destination.get_unchecked_mut(len) = data;
}
});
Ok(())
@@ -356,14 +337,14 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
ConvertMode::Clipped => 0,
};
- to_decode_u16.into_iter().duplicate_const::<3>().array_chunks::<3>().map(|px| {
- let px_r = (&px[0_usize] >> factor) * r;
- let px_g = (&px[1_usize] >> factor) * g;
- let px_b = (&px[2_usize] >> factor)* b;
+ to_decode_u16.iter().duplicate_const::<3>().arrays::<3>().flat_map(|px| {
+ let px_r = (*px[0_usize] >> factor) * r_u16;
+ let px_g = (*px[1_usize] >> factor) * g_u16;
+ let px_b = (*px[2_usize] >> factor)* b_u16;
[px_r as u8, px_g as u8, px_b as u8]
- }).flatten().for_each(|(len, data)| {
+ }).enumerate().for_each(|(len, data)| {
unsafe {
- *destination.get_unchecked_mut(len) = *data;
+ *destination.get_unchecked_mut(len) = data;
}
});
Ok(())
@@ -382,15 +363,15 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
ConvertMode::Clipped => 0,
};
- to_decode_u16.into_iter().duplicate_const::<3>().array_chunks::<3>().map(|px| {
- let px_r = (&px[0_usize] >> factor) * r_u16 ;
- let px_g = (&px[1_usize] >> factor) * g_u16 ;
- let px_b = (&px[2_usize] >> factor) * b_u16 ;
+ to_decode_u16.iter().duplicate_const::<3>().arrays::<3>().flat_map(|px| {
+ let px_r = (*px[0_usize] >> factor) * r_u16 ;
+ let px_g = (*px[1_usize] >> factor) * g_u16 ;
+ let px_b = (*px[2_usize] >> factor) * b_u16 ;
let px_a = u8::MAX * a;
[px_r as u8, px_g as u8, px_b as u8, px_a]
- }).flatten().for_each(|(len, data)| {
+ }).enumerate().for_each(|(len, data)| {
unsafe {
- *destination.get_unchecked_mut(len) = *data;
+ *destination.get_unchecked_mut(len) = data;
}
});
Ok(())
@@ -410,14 +391,14 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
ConvertMode::Clipped => 0,
};
- to_decode_u16.into_iter().duplicate_const::<3>().array_chunks::<3>().map(|px| {
- let px_r = (&px[0_usize] >> factor) * r_u16;
- let px_g = (&px[1_usize] >> factor) * g_u16;
- let px_b = (&px[2_usize] >> factor) * b_u16;
+ to_decode_u16.iter().duplicate_const::<3>().arrays::<3>().flat_map(|px| {
+ let px_r = (*px[0_usize] >> factor) * r_u16;
+ let px_g = (*px[1_usize] >> factor) * g_u16;
+ let px_b = (*px[2_usize] >> factor) * b_u16;
[px_r, px_g, px_b]
- }).flatten().for_each(|(len, data)| {
+ }).enumerate().for_each(|(len, data)| {
unsafe {
- *destination_buffer_u16.get_unchecked_mut(len) = *data;
+ *destination_buffer_u16.get_unchecked_mut(len) = data;
}
});
Ok(())
@@ -437,15 +418,15 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
ConvertMode::Clipped => 0,
};
- to_decode_u16.into_iter().duplicate_const::<3>().array_chunks::<3>().map(|px| {
- let px_r = (&px[0_usize] >> factor) * r_u16;
- let px_g = (&px[1_usize] >> factor) * g_u16;
- let px_b = (&px[2_usize] >> factor) * b_u16;
+ to_decode_u16.iter().duplicate_const::<3>().arrays::<3>().flat_map(|px| {
+ let px_r = (*px[0_usize] >> factor) * r_u16;
+ let px_g = (*px[1_usize] >> factor) * g_u16;
+ let px_b = (*px[2_usize] >> factor) * b_u16;
let px_a = u16::MAX * a_u16;
[px_r, px_g, px_b, px_a]
- }).flatten().for_each(|(len, data)| {
+ }).enumerate().for_each(|(len, data)| {
unsafe {
- *destination_buffer_u16.get_unchecked_mut(len) = *data;
+ *destination_buffer_u16.get_unchecked_mut(len) = data;
}
});
Ok(())
@@ -473,9 +454,9 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
let to_decode_u16 = cast_slice::(to_decode.buffer());
let destination_buffer_u16 = cast_slice_mut::(destination);
- to_decode_u16.into_iter().interweave(&(u16::MAX * a_u16), false).enumerate().for_each(|(len, data)| {
+ to_decode_u16.iter().interweave::<0>(&(u16::MAX * a_u16), false).enumerate().for_each(|(len, data)| {
unsafe {
- *destination.get_unchecked_mut(len) = *data;
+ *destination_buffer_u16.get_unchecked_mut(len) = *data;
}
});
@@ -491,38 +472,41 @@ pub struct LumaConfig {
pub mode: ConvertMode,
pub channel_filters: ChannelFilters,
pub format: FrameFormat,
- pub custom_frame_format_map: Option>
+ pub custom_frame_format_map: Option>,
+ pub resolution: Resolution,
}
-impl TryFrom for LumaConfig {
+impl ConfigHasResolution for LumaConfig {
+ fn resolution(&self) -> Resolution {
+ self.resolution
+ }
+}
+
+impl TryFrom for LumaConfig {
type Error = NokhwaError;
- fn try_from(value: FrameFormat) -> Result {
- if !FrameFormat::BRIGHTNESS_LUMA.contains(&value) {
- return Err(NokhwaError::DecoderUnsupportedFrameFormat(value))
+ fn try_from(value: CameraFormat) -> Result {
+ if !FrameFormat::BRIGHTNESS_LUMA.contains(&value.format()) {
+ return Err(NokhwaError::DecoderUnsupportedFrameFormat(value.format()))
}
Ok(LumaConfig {
mode: ConvertMode::default(),
channel_filters: ChannelFilters::default(),
- format: value,
+ format: value.format(),
custom_frame_format_map: None,
+ resolution: value.resolution(),
})
}
}
-#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
+#[derive(Copy, Clone, Default, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub enum ConvertMode {
+ #[default]
Scaled,
Clipped
}
-impl Default for ConvertMode {
- fn default() -> Self {
- ConvertMode::Scaled
- }
-}
-
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub struct ChannelFilters {
pub red: bool,
diff --git a/nokhwa-decoders/src/mjpeg.rs b/nokhwa-decoders/src/mjpeg.rs
index 1c6f53c..9af3d56 100644
--- a/nokhwa-decoders/src/mjpeg.rs
+++ b/nokhwa-decoders/src/mjpeg.rs
@@ -1,4 +1,4 @@
-use nokhwa_core::decoder::{Decoder, ImageBuffer, Pixel};
+use nokhwa_core::decoder::{ConfigHasResolution, Decoder, ImageBuffer, Pixel};
use nokhwa_core::error::NokhwaError;
use nokhwa_core::frame_buffer::FrameBuffer;
use nokhwa_core::image::Primitive;
@@ -51,7 +51,7 @@ impl Decoder for MJpegDecoder {
let colorspace = convert_destination_to_colorspace(destination_format).ok_or(NokhwaError::DecoderUnsupportedDestinationPixelFormat(destination_format))?;
- let mut config = self.config.decoder_options.jpeg_set_out_colorspace(colorspace);
+ let config = self.config.decoder_options.jpeg_set_out_colorspace(colorspace);
decoder.set_options(config);
decoder.decode_into(buffer).map_err(err_to_err)?;
@@ -89,23 +89,6 @@ impl Decoder for MJpegDecoder {
))?;
Ok(DecodedImage::new(image_buffer, output_metadata))
}
-
- fn output_decoder_min_size(
- &self,
- resolution: Resolution,
- destination_format: PixelDestination,
- ) -> Result {
- let stride = match destination_format {
- PixelDestination::Rgb8 => 3,
- PixelDestination::Rgba8 => 4,
- PixelDestination::Bgr8 => 3,
- PixelDestination::Bgra8 => 4,
- PixelDestination::Luma8 => 1,
- PixelDestination::LumaA8 => 2,
- fmt => return Err(NokhwaError::DecoderUnsupportedDestinationPixelFormat(fmt))
- };
- Ok((resolution.width() * resolution.height() * stride) as usize)
- }
}
#[derive(Clone, Debug, PartialEq)]
@@ -137,6 +120,12 @@ pub struct MJpegOptions {
pub decoder_options: DecoderOptions,
}
+impl ConfigHasResolution for MJpegOptions {
+ fn resolution(&self) -> Resolution {
+ self.resolution
+ }
+}
+
fn err_to_err(decode_errors: DecodeErrors) -> NokhwaError {
match decode_errors {
DecodeErrors::Format(fmt) => NokhwaError::Decoder(fmt),
diff --git a/nokhwa-decoders/src/yuv.rs b/nokhwa-decoders/src/yuv.rs
index c3dda88..f7aac3b 100644
--- a/nokhwa-decoders/src/yuv.rs
+++ b/nokhwa-decoders/src/yuv.rs
@@ -1,11 +1,10 @@
use std::collections::HashMap;
-use bytemuck::{cast_slice, cast_slice_mut, try_cast_slice_mut};
+use bytemuck::{cast_slice, cast_slice_mut};
-use nokhwa_core::decoder::{Decoder, ImageBuffer, Pixel, Primitive};
+use nokhwa_core::decoder::{ConfigHasResolution, Decoder};
use nokhwa_core::error::NokhwaError;
use nokhwa_core::frame_buffer::FrameBuffer;
use nokhwa_core::frame_format::{CustomFrameFormat, FrameFormat};
-use nokhwa_core::image::{DecodedImage, NonFloatScalarWidth};
use nokhwa_core::types::{CameraFormat, Resolution};
use yuv::{
YuvBiPlanarImage, YuvConversionMode, YuvPackedImage, YuvPlanarImage, YuvRange,
@@ -53,13 +52,12 @@ impl Decoder for YUVDecoder {
return Err(NokhwaError::DecoderUnsupportedFrameFormat(config.yuv_type));
}
- if let Some(custom_map) = &config.custom_frame_format_map {
- if let Some((src, dest)) = custom_map.iter().find(|(_, value)| {
+ if let Some(custom_map) = &config.custom_frame_format_map
+ && let Some((src, dest)) = custom_map.iter().find(|(_, value)| {
FrameFormat::YCBCR.contains(value)
}) {
return Err(NokhwaError::DecoderUnsupportedCustomFrameFormatDestination(*src, *dest))
}
- }
self.config = config;
Ok(())
@@ -71,29 +69,23 @@ impl Decoder for YUVDecoder {
mut buffer: impl AsMut<[u8]>,
destination_format: PixelDestination,
) -> Result {
- let destination_format = match destination_format {
- Some(df) => df,
- None => return Err(NokhwaError::DecoderDestinationHintRequired),
- };
-
-
- let yuv_format = self.config().custom_frame_format_map.as_ref().map(|m| {
- match self.config.yuv_type {
+ let format = self.config().custom_frame_format_map.as_ref().and_then(|m| {
+ match self.config().yuv_type {
FrameFormat::Custom(cfmt) => {
m.get(&cfmt).copied()
}
_ => None,
}
- }).flatten().unwrap_or(self.config.yuv_type);
+ }).unwrap_or(self.config().yuv_type);
let buffer = buffer.as_mut();
- if buffer.len() < self.output_decoder_min_size(self.config.resolution, destination_format) {
+ if buffer.len() < self.output_decoder_min_size(self.config.resolution, destination_format)? {
return Err(NokhwaError::DecoderInvalidBuffer("Too small!".to_string()));
}
- let stride = figure_out_stride(yuv_format).ok_or(NokhwaError::DecoderUnsupportedFrameFormat(yuv_format))?;
- let byte_width = figure_out_byte_width(yuv_format).ok_or(NokhwaError::DecoderUnsupportedFrameFormat(yuv_format))?;
+ let stride = figure_out_stride(format).ok_or(NokhwaError::DecoderUnsupportedFrameFormat(format))?;
+ let byte_width = figure_out_byte_width(format).ok_or(NokhwaError::DecoderUnsupportedFrameFormat(format))?;
let stride_3px = 3 *
@@ -103,10 +95,10 @@ impl Decoder for YUVDecoder {
let stride_4px_2w = 8 * self.config.resolution.width();
// todo: clean up ts into a macro 3
- let decode_status = match stride {
+ let decode_status = match stride {
Stride::Packed(stride) => {
- let image = prepare_to_packed_image(&to_decode, self.config.resolution, byte_width, stride);
- match yuv_format {
+ let image = prepare_to_packed_image(&to_decode, self.config.resolution, stride);
+ match format {
FrameFormat::Ayuv_32 => {
match destination_format {
PixelDestination::Rgb8 => Some(ayuv_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.premultiply_alpha)),
@@ -117,41 +109,45 @@ impl Decoder for YUVDecoder {
FrameFormat::Yuyv_4_2_2 => {
match destination_format {
PixelDestination::Rgb8 => Some(yuyv422_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
- PixelDestination::Rgba8 => Some(yuyv422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ PixelDestination::Rgba8 => Some(yuyv422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
PixelDestination::Rgb16 => Some(yuyv422_to_rgb_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
PixelDestination::Rgba16 => Some(yuyv422_to_rgba_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
PixelDestination::Bgr8 => Some(yuyv422_to_bgr(&image, buffer, stride_4px_2w, self.config.range, self.config.matrix)),
- PixelDestination::Bgra8 => Some(yuyv422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ PixelDestination::Bgra8 => Some(yuyv422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ _ => None,
}
}
FrameFormat::Uyvy_4_2_2 => {
match destination_format {
PixelDestination::Rgb8 => Some(uyvy422_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
- PixelDestination::Rgba8 => Some(uyvy422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ PixelDestination::Rgba8 => Some(uyvy422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
PixelDestination::Rgb16 => Some(uyvy422_to_rgb_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
PixelDestination::Rgba16 => Some(uyvy422_to_rgba_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
PixelDestination::Bgr8 => Some(uyvy422_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
- PixelDestination::Bgra8 => Some(uyvy422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ PixelDestination::Bgra8 => Some(uyvy422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ _ => None,
}
}
FrameFormat::Vyuy_4_2_2 => {
match destination_format {
PixelDestination::Rgb8 => Some(vyuy422_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
- PixelDestination::Rgba8 => Some(vyuy422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ PixelDestination::Rgba8 => Some(vyuy422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
PixelDestination::Rgb16 => Some(vyuy422_to_rgb_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
PixelDestination::Rgba16 => Some(vyuy422_to_rgba_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
PixelDestination::Bgr8 => Some(vyuy422_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
- PixelDestination::Bgra8 => Some(vyuy422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ PixelDestination::Bgra8 => Some(vyuy422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ _ => None,
}
}
FrameFormat::Yvyu_4_2_2 => {
match destination_format {
PixelDestination::Rgb8 => Some(yvyu422_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
- PixelDestination::Rgba8 => Some(yvyu422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ PixelDestination::Rgba8 => Some(yvyu422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
PixelDestination::Rgb16 => Some(yvyu422_to_rgb_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
PixelDestination::Rgba16 => Some(yvyu422_to_rgba_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
PixelDestination::Bgr8 => Some(yvyu422_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
- PixelDestination::Bgra8 => Some(yvyu422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ PixelDestination::Bgra8 => Some(yvyu422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ _ => None,
}
}
_ => {
@@ -159,64 +155,64 @@ impl Decoder for YUVDecoder {
return Err(NokhwaError::NotImplementedError("etto blehhh! ()".to_string()))
}
// shouldnt happen
- return Err(NokhwaError::DecoderUnsupportedFrameFormat(yuv_format))
+ return Err(NokhwaError::DecoderUnsupportedFrameFormat(format))
}
}
}
Stride::Semi(y_stride, uv_stride) => {
let image = prepare_to_semi_planar_image(&to_decode, self.config.resolution, byte_width, y_stride, uv_stride);
- match yuv_format {
+ match format {
FrameFormat::NV24 => {
match destination_format {
PixelDestination::Rgb8 => Some(yuv_nv24_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Rgba8 => Some(yuv_nv24_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Rgba8 => Some(yuv_nv24_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
PixelDestination::Bgr8 => Some(yuv_nv24_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Bgra8 => Some(yuv_nv24_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Bgra8 => Some(yuv_nv24_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
_ => None,
}
}
FrameFormat::NV42 => {
match destination_format {
PixelDestination::Rgb8 => Some(yuv_nv42_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Rgba8 => Some(yuv_nv42_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Rgba8 => Some(yuv_nv42_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
PixelDestination::Bgr8 => Some(yuv_nv42_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Bgra8 => Some(yuv_nv42_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Bgra8 => Some(yuv_nv42_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
_ => None,
}
}
FrameFormat::NV16 => {
match destination_format {
PixelDestination::Rgb8 => Some(yuv_nv16_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Rgba8 => Some(yuv_nv16_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Rgba8 => Some(yuv_nv16_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
PixelDestination::Bgr8 => Some(yuv_nv16_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Bgra8 => Some(yuv_nv16_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Bgra8 => Some(yuv_nv16_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
_ => None,
}
}
FrameFormat::NV61 => {
match destination_format {
PixelDestination::Rgb8 => Some(yuv_nv61_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Rgba8 => Some(yuv_nv61_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Rgba8 => Some(yuv_nv61_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
PixelDestination::Bgr8 => Some(yuv_nv61_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Bgra8 => Some(yuv_nv61_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Bgra8 => Some(yuv_nv61_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
_ => None,
}
}
FrameFormat::NV12 => {
match destination_format {
PixelDestination::Rgb8 => Some(yuv_nv12_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Rgba8 => Some(yuv_nv12_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Rgba8 => Some(yuv_nv12_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
PixelDestination::Bgr8 => Some(yuv_nv12_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Bgra8 => Some(yuv_nv12_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Bgra8 => Some(yuv_nv12_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
_ => None,
}
}
FrameFormat::NV21 => {
match destination_format {
PixelDestination::Rgb8 => Some(yuv_nv21_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Rgba8 => Some(yuv_nv21_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Rgba8 => Some(yuv_nv21_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
PixelDestination::Bgr8 => Some(yuv_nv21_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Bgra8 => Some(yuv_nv21_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Bgra8 => Some(yuv_nv21_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
_ => None,
}
}
@@ -224,12 +220,12 @@ impl Decoder for YUVDecoder {
let a = convert_bi_planar_image_to_u16(image);
match destination_format {
PixelDestination::Rgb8 => Some(p010_to_rgb(&a, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Rgba8 => Some(p010_to_rgba(&a, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Rgba8 => Some(p010_to_rgba(&a, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
PixelDestination::Bgr8 => Some(p010_to_bgr(&a, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
- PixelDestination::Bgra8 => Some(p010_to_bgra(&a, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
+ PixelDestination::Bgra8 => Some(p010_to_bgra(&a, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
PixelDestination::Rgb16 => Some(p010_to_rgb10(&a, cast_slice_mut(buffer), stride_3px_2w, self.config.range, self.config.matrix)),
PixelDestination::Rgba16 => Some(p010_to_rgba10(&a, cast_slice_mut(buffer), stride_4px, self.config.range, self.config.matrix)),
- // _ => None,
+ _ => None,
}
}
FrameFormat::P012 => {
@@ -240,32 +236,32 @@ impl Decoder for YUVDecoder {
}
}
_ => {
- if FrameFormat::YCBCR_SEMI.contains(&yuv_format) {
+ if FrameFormat::YCBCR_SEMI.contains(&format) {
return Err(NokhwaError::NotImplementedError("etto blehhh!".to_string()))
}
// shouldnt happen
- return Err(NokhwaError::DecoderUnsupportedFrameFormat(yuv_format))
+ return Err(NokhwaError::DecoderUnsupportedFrameFormat(format))
}
}
}
Stride::Planar(y_stride, u_stride, v_stride, line_ratio) => {
let image = prepare_to_planar_image(&to_decode, self.config.resolution, byte_width, y_stride, u_stride, v_stride, line_ratio);
- match yuv_format {
+ match format {
FrameFormat::Yuv_4_2_0 => {
match destination_format {
PixelDestination::Rgb8 => Some(yuv420_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
- PixelDestination::Rgba8 => Some(yuv420_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ PixelDestination::Rgba8 => Some(yuv420_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
PixelDestination::Bgr8 => Some(yuv420_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
- PixelDestination::Bgra8 => Some(yuv420_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
+ PixelDestination::Bgra8 => Some(yuv420_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
_ => None,
}
}
_ => {
- if FrameFormat::YCBCR_PLANAR.contains(&yuv_format) {
+ if FrameFormat::YCBCR_PLANAR.contains(&format) {
return Err(NokhwaError::NotImplementedError("etto blehhh!".to_string()))
}
// shouldnt happen
- return Err(NokhwaError::DecoderUnsupportedFrameFormat(yuv_format))
+ return Err(NokhwaError::DecoderUnsupportedFrameFormat(format))
}
}
}
@@ -274,50 +270,10 @@ impl Decoder for YUVDecoder {
Some(Ok(_)) => Ok(()),
Some(Err(why)) => Err(NokhwaError::Decoder(why.to_string())),
None => Err(NokhwaError::DecoderUnsupportedFrameFormat(
- yuv_format,
+ format,
)),
}
}
-
- fn decode(
- &mut self,
- to_decode: FrameBuffer<'_>,
- ) -> Result, NokhwaError>
- where
- ::Subpixel: NonFloatScalarWidth,
- {
- let min_size_alloc = self.output_decoder_min_size_pixel::
(self.config.resolution);
- let mut out_buffer: Vec = vec![P::Subpixel::DEFAULT_MIN_VALUE; min_size_alloc];
- self.decode_to_pixel_buffer::(to_decode, &mut out_buffer)?;
- Ok(DecodedImage::new(
- ImageBuffer::from_vec(
- self.config.resolution.width(),
- self.config.resolution.height(),
- out_buffer,
- )
- .ok_or(NokhwaError::Decoder(
- "failed to convert into an image buffer".to_string(),
- ))?,
- (),
- ))
- }
-
- fn output_decoder_min_size(
- &self,
- resolution: Resolution,
- destination_format: PixelDestination,
- ) -> Result {
- let px_size = match destination_format {
- PixelDestination::Rgb8 | PixelDestination::Bgr8 => 3,
- PixelDestination::Rgba8 | PixelDestination::Bgra8 => 4,
- PixelDestination::Rgb16 => 3 * 2,
- PixelDestination::Rgba16 => 4 * 2,
- _ => return Err(NokhwaError::DecoderUnsupportedDestinationPixelFormat(destination_format))
- };
- let reso = resolution.width() * resolution.height();
- Ok((reso as usize) * (px_size as usize))
- }
-
}
#[derive(Clone, Debug, PartialEq)]
@@ -331,6 +287,12 @@ pub struct YUVConfig {
pub custom_frame_format_map: Option>,
}
+impl ConfigHasResolution for YUVConfig {
+ fn resolution(&self) -> Resolution {
+ self.resolution
+ }
+}
+
impl TryFrom for YUVConfig {
type Error = NokhwaError;
@@ -420,7 +382,6 @@ fn planar_stride(format: FrameFormat) -> Option<(u32, u32, u32, u32)> {
fn prepare_to_packed_image<'a>(
frame_buffer: &'a FrameBuffer<'a>,
resolution: Resolution,
- byte_width: u32,
yuy_stride: u32,
) -> YuvPackedImage<'a, u8> {
YuvPackedImage {
diff --git a/nokhwa-iter-extensions/src/duplicate.rs b/nokhwa-iter-extensions/src/duplicate.rs
index 24da5ba..59c1a95 100644
--- a/nokhwa-iter-extensions/src/duplicate.rs
+++ b/nokhwa-iter-extensions/src/duplicate.rs
@@ -44,45 +44,39 @@ impl Iterator for DuplicateConst wher
fn next(&mut self) -> Option {
match self.state {
DuplicateConstState::Started => {
- match self.iter.next() {
- Some(i) => {
- if MULTIPLIER <= 1 {
- self.state = DuplicateConstState::EmitReal;
- } else {
- self.state = DuplicateConstState::EmitDupe;
- }
- self.last_iter_item = Some(i.clone());
- Some(i)
- }
- None => {
- self.state = DuplicateConstState::Finished;
- None
+ if let Some(i) = self.iter.next() {
+ if MULTIPLIER <= 1 {
+ self.state = DuplicateConstState::EmitReal;
+ } else {
+ self.state = DuplicateConstState::EmitDupe;
}
+ self.last_iter_item = Some(i.clone());
+ Some(i)
+ } else {
+ self.state = DuplicateConstState::Finished;
+ None
}
}
DuplicateConstState::EmitDupe => {
self.running_count = self.running_count.saturating_sub(1);
- if self.running_count <= 0 {
+ if self.running_count == 0 {
self.state = DuplicateConstState::EmitReal;
}
self.last_iter_item.clone()
}
DuplicateConstState::EmitReal => {
- match self.iter.next() {
- Some(i) => {
- self.last_iter_item = Some(i.clone());
- self.running_count = MULTIPLIER.saturating_sub(1);
- if MULTIPLIER <= 1 {
- self.state = DuplicateConstState::EmitReal;
- } else {
- self.state = DuplicateConstState::EmitDupe;
- }
- Some(i)
- }
- None => {
- self.state = DuplicateConstState::Finished;
- None
+ if let Some(i) = self.iter.next() {
+ self.last_iter_item = Some(i.clone());
+ self.running_count = MULTIPLIER.saturating_sub(1);
+ if MULTIPLIER <= 1 {
+ self.state = DuplicateConstState::EmitReal;
+ } else {
+ self.state = DuplicateConstState::EmitDupe;
}
+ Some(i)
+ } else {
+ self.state = DuplicateConstState::Finished;
+ None
}
}
DuplicateConstState::Finished => {
diff --git a/nokhwa-iter-extensions/src/interweave.rs b/nokhwa-iter-extensions/src/interweave.rs
index bdf4721..2abe6b6 100644
--- a/nokhwa-iter-extensions/src/interweave.rs
+++ b/nokhwa-iter-extensions/src/interweave.rs
@@ -58,23 +58,20 @@ impl Iterator for Interweave where I: Iterator, {
self.count = self.count.saturating_sub(1);
- match self.iter.next() {
- Some(i) => {
- if self.count <= 0 {
- self.state = InterweaveState::EmitFake;
- } else {
- self.state = InterweaveState::EmitReal;
- }
- self.prev_state = InterweaveState::EmitReal;
- Some(i)
+ if let Some(i) = self.iter.next() {
+ if self.count == 0 {
+ self.state = InterweaveState::EmitFake;
+ } else {
+ self.state = InterweaveState::EmitReal;
}
- None => {
- self.state = InterweaveState::Finished;
- if self.emit_last && self.prev_state != InterweaveState::EmitFake {
- Some(self.element.clone())
- } else {
- None
- }
+ self.prev_state = InterweaveState::EmitReal;
+ Some(i)
+ } else {
+ self.state = InterweaveState::Finished;
+ if self.emit_last && self.prev_state != InterweaveState::EmitFake {
+ Some(self.element.clone())
+ } else {
+ None
}
}
}
@@ -91,7 +88,7 @@ impl Iterator for Interweave where I: Iterator,