nokhwa-decoders basic implemention: todo tests

This commit is contained in:
l1npengtul
2025-09-13 21:52:28 +09:00
parent f6594f7852
commit 6db4a46e60
13 changed files with 615 additions and 320 deletions
+30 -15
View File
@@ -4,11 +4,13 @@ use crate::image::{DecodedImage, NonFloatScalarWidth};
use crate::types::{Resolution};
pub use image::{ImageBuffer, Pixel, Primitive};
use std::fmt::Debug;
use bytemuck::try_cast_slice_mut;
use crate::pixel_destination::PixelDestination;
pub trait Decoder {
type Config: Clone + Debug;
type OutputMeta: Clone + Debug;
type DestinationFormatHint: Clone + Debug;
const SUPPORTED_DESTINATIONS: &'static [PixelDestination];
fn config(&self) -> &Self::Config;
@@ -18,16 +20,29 @@ pub trait Decoder {
&mut self,
to_decode: FrameBuffer,
buffer: impl AsMut<[u8]>,
destination_format_hint: Option<Self::DestinationFormatHint>,
destination_format: PixelDestination,
) -> Result<Self::OutputMeta, NokhwaError>;
fn decode_to_pixel_buffer<P: Pixel>(
&mut self,
to_decode: FrameBuffer,
buffer: impl AsMut<[P::Subpixel]>,
) -> Result<Self::OutputMeta, NokhwaError>
fn decode_to_pixel_buffer<P: Pixel>(&mut self, to_decode: FrameBuffer, mut buffer: impl AsMut<[P::Subpixel]>) -> Result<Self::OutputMeta, NokhwaError>
where
<P as Pixel>::Subpixel: NonFloatScalarWidth;
<P as Pixel>::Subpixel: NonFloatScalarWidth
{
let destination = match PixelDestination::get_by_pixel::<P>() {
Some(dest) => dest,
None => return Err(NokhwaError::DecoderUnknownDestinationPixelFormat(P::COLOR_MODEL, P::Subpixel::WIDTH_BYTES))
};
if !Self::supports_destination(destination) {
return Err(NokhwaError::DecoderUnsupportedDestinationPixelFormat(destination))
}
let buffer = buffer.as_mut();
let cast_slice = try_cast_slice_mut::<P::Subpixel, u8>(buffer)
.map_err(|why| NokhwaError::DecoderInvalidBuffer(why.to_string()))?;
self.decode_to_buffer(to_decode, cast_slice, destination)
}
fn decode<P: Pixel>(
&mut self,
@@ -36,16 +51,16 @@ pub trait Decoder {
where
<P as Pixel>::Subpixel: NonFloatScalarWidth;
fn output_decoder_min_size_pixel<P>(&self, resolution: Resolution) -> usize where
fn output_decoder_min_size_pixel<P>(&self, resolution: Resolution) -> Result<usize, NokhwaError> where
P: Pixel,
<P as Pixel>::Subpixel: NonFloatScalarWidth {
let channels = P::CHANNEL_COUNT as usize;
let width_bytes = <<P as Pixel>::Subpixel as NonFloatScalarWidth>::WIDTH_BYTES;
let resolution_mult = resolution.height() * resolution.width();
(resolution_mult as usize) * (width_bytes as usize) * channels
PixelDestination::get_by_pixel::<P>().map(|dest| self.output_decoder_min_size(resolution, dest)).ok_or(NokhwaError::DecoderUnknownDestinationPixelFormat(P::COLOR_MODEL, P::Subpixel::WIDTH_BYTES))?
}
fn output_decoder_min_size(&self, resolution: Resolution, destination_format: Self::DestinationFormatHint) -> usize;
fn output_decoder_min_size(&self, resolution: Resolution, destination_format: PixelDestination) -> Result<usize, NokhwaError>;
fn buffer_takes_destination_hint(&self) -> bool;
fn supports_destination(pixel_destination: PixelDestination) -> bool {
Self::SUPPORTED_DESTINATIONS.contains(&pixel_destination)
}
}
+5 -2
View File
@@ -16,6 +16,7 @@
use crate::frame_format::{CustomFrameFormat, FrameFormat};
use std::fmt::Debug;
use thiserror::Error;
use crate::pixel_destination::PixelDestination;
use crate::types::Backends;
pub type NokhwaResult<T> = Result<T, NokhwaError>;
@@ -68,8 +69,10 @@ pub enum NokhwaError {
DecoderUnsupportedFrameFormat(FrameFormat),
#[error("The destination frame format from {0} to {1} is not supported.")]
DecoderUnsupportedCustomFrameFormatDestination(CustomFrameFormat, FrameFormat),
#[error("Unsupported pixel configuration {0} with width {1}b.")]
DecoderUnsupportedDestinationPixelFormat(&'static str, u32),
#[error("Unknown pixel configuration {0} with width {1}b.")]
DecoderUnknownDestinationPixelFormat(&'static str, u32),
#[error("Unsupported pixel configuration {0}.")]
DecoderUnsupportedDestinationPixelFormat(PixelDestination),
#[error("Bad decoder configuration: {0}")]
DecoderInvalidConfiguration(String),
#[error("Failed to initialize decoder: {0}")]
+1
View File
@@ -35,3 +35,4 @@ pub mod stream;
pub mod traits;
pub mod types;
pub mod utils;
pub mod pixel_destination;
+67
View File
@@ -0,0 +1,67 @@
use std::fmt::{Display, Formatter};
use image::Pixel;
use crate::image::NonFloatScalarWidth;
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)]
pub enum PixelDestination {
Rgb8,
Rgba8,
Rgb16,
Rgba16,
Bgr8,
Bgra8,
Bgr16,
Bgra16,
Luma8,
LumaA8,
Luma16,
LumaA16,
}
impl PixelDestination {
pub fn get_by_pixel<P>() -> Option<Self>
where
P: Pixel,
<P as Pixel>::Subpixel: NonFloatScalarWidth,
{
match P::COLOR_MODEL {
"RGB" => match P::Subpixel::WIDTH_BYTES {
1 => Some(PixelDestination::Rgb8),
2 => Some(PixelDestination::Rgb16),
_ => None,
},
"RGBA" => match P::Subpixel::WIDTH_BYTES {
1 => Some(PixelDestination::Rgba8),
2 => Some(PixelDestination::Rgba16),
_ => None,
},
"BGR" => match P::Subpixel::WIDTH_BYTES {
1 => Some(PixelDestination::Bgr8),
2 => Some(PixelDestination::Bgr16),
_ => None,
},
"BGRA" => match P::Subpixel::WIDTH_BYTES {
1 => Some(PixelDestination::Bgra8),
2 => Some(PixelDestination::Bgra16),
_ => None,
},
"Y" => match P::Subpixel::WIDTH_BYTES {
1 => Some(PixelDestination::Luma8),
2 => Some(PixelDestination::Luma16),
_ => None,
},
"YA" => match P::Subpixel::WIDTH_BYTES {
1 => Some(PixelDestination::LumaA8),
2 => Some(PixelDestination::LumaA16),
_ => None,
}
_ => None,
}
}
}
impl Display for PixelDestination {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
}
}
+1 -2
View File
@@ -1,7 +1,6 @@
use crate::camera::Camera;
use crate::error::NokhwaResult;
use crate::types::{Backends, CameraIndex, CameraInformation, QueriedCamera};
use std::fmt::{Display, Formatter};
use crate::types::{Backends, CameraIndex, QueriedCamera};
pub trait PlatformTrait {
-1
View File
@@ -8,7 +8,6 @@ use serde::{Deserialize, Serialize};
use std::num::NonZeroI32;
use std::ops::{Div, Rem};
use std::{
borrow::Borrow,
cmp::Ordering,
fmt::{Debug, Display, Formatter},
hash::Hash,