From 5319e517d98954de518d5bee2f6b1c98ff21bf59 Mon Sep 17 00:00:00 2001 From: l1npengtul Date: Sat, 13 Sep 2025 22:53:49 +0900 Subject: [PATCH] fix compile errors except for ffmpeg --- nokhwa-core/src/decoder.rs | 51 ++++- nokhwa-core/src/frame_format.rs | 1 + nokhwa-core/src/pixel_destination.rs | 1 + nokhwa-core/src/stream.rs | 2 +- nokhwa-core/src/types.rs | 2 +- nokhwa-decoders/Cargo.toml | 10 +- nokhwa-decoders/src/ffmpeg.rs | 111 ++-------- nokhwa-decoders/src/luma.rs | 250 +++++++++++------------ nokhwa-decoders/src/mjpeg.rs | 27 +-- nokhwa-decoders/src/yuv.rs | 151 +++++--------- nokhwa-iter-extensions/src/duplicate.rs | 50 ++--- nokhwa-iter-extensions/src/interweave.rs | 31 ++- nokhwa-iter-extensions/src/lib.rs | 2 +- 13 files changed, 279 insertions(+), 410 deletions(-) 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 { - 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,