#![deny(missing_docs)]
use burn_core::tensor::{backend::Backend, Int, Tensor};
use j2k::{BatchGroupInfo, IndexedBatchError, J2kDecodeWarning, Rect};
#[cfg(any(
feature = "cpu",
feature = "cuda",
all(feature = "metal", target_os = "macos")
))]
mod batch_contract;
#[cfg(any(feature = "cuda", all(feature = "metal", target_os = "macos"), test))]
mod completion;
#[cfg(feature = "cpu")]
pub mod cpu;
#[cfg(feature = "cuda")]
pub mod cuda;
#[cfg(feature = "metal")]
pub mod metal;
#[cfg(feature = "cpu")]
pub use cpu::CpuBurnDecoder;
#[cfg(feature = "cuda")]
pub use cuda::{CudaBurnDecoder, SubmittedCudaBurnBatch};
#[cfg(feature = "metal")]
pub use metal::{MetalBurnDecoder, SubmittedMetalBurnBatch};
#[derive(Debug)]
pub enum BurnBatchTensor<B: Backend> {
U8(Tensor<B, 4, Int>),
U16(Tensor<B, 4, Int>),
I16(Tensor<B, 4, Int>),
}
impl<B: Backend> BurnBatchTensor<B> {
#[must_use]
pub const fn tensor(&self) -> &Tensor<B, 4, Int> {
match self {
Self::U8(tensor) | Self::U16(tensor) | Self::I16(tensor) => tensor,
}
}
#[must_use]
pub fn into_tensor(self) -> Tensor<B, 4, Int> {
match self {
Self::U8(tensor) | Self::U16(tensor) | Self::I16(tensor) => tensor,
}
}
}
#[derive(Debug)]
pub struct BurnBatchGroup<B: Backend> {
pub tensor: BurnBatchTensor<B>,
pub info: BatchGroupInfo,
pub source_indices: Vec<usize>,
pub decoded_rects: Vec<Rect>,
pub warnings: Vec<Vec<J2kDecodeWarning>>,
}
#[derive(Debug, thiserror::Error)]
#[error("Burn batch group containing source indices {source_indices:?} failed: {source}")]
pub struct BurnBatchGroupError {
source_indices: Vec<usize>,
#[source]
source: BurnDecodeError,
}
impl BurnBatchGroupError {
#[cfg(any(feature = "cuda", all(feature = "metal", target_os = "macos"), test))]
pub(crate) fn new(source_indices: Vec<usize>, source: BurnDecodeError) -> Self {
Self {
source_indices,
source,
}
}
#[must_use]
pub fn source_indices(&self) -> &[usize] {
&self.source_indices
}
#[must_use]
pub const fn source(&self) -> &BurnDecodeError {
&self.source
}
#[must_use]
pub fn into_parts(self) -> (Vec<usize>, BurnDecodeError) {
(self.source_indices, self.source)
}
}
#[derive(Debug)]
pub struct BurnBatchDecode<B: Backend> {
pub groups: Vec<BurnBatchGroup<B>>,
pub errors: Vec<IndexedBatchError>,
pub group_errors: Vec<BurnBatchGroupError>,
}
#[derive(Debug, thiserror::Error)]
pub enum BurnDecodeError {
#[error("JPEG 2000 batch infrastructure failed: {0}")]
Infrastructure(#[from] j2k::BatchInfrastructureError),
#[error("Burn backend does not support exact codec dtype {dtype:?}")]
UnsupportedDType {
dtype: burn_core::tensor::DType,
},
#[error("codec batch sample owner did not match its declared sample type")]
SampleTypeMismatch,
#[error("Burn tensor shape overflow")]
SizeOverflow,
#[error("unsupported codec batch layout or sample type")]
UnsupportedCodecContract,
#[cfg(feature = "cuda")]
#[error(transparent)]
Cuda(#[from] j2k_cuda::CudaBatchError),
#[cfg(feature = "metal")]
#[error(transparent)]
Metal(#[from] j2k_metal::Error),
#[error("{backend} tensor interop failed: {message}")]
AcceleratorInterop {
backend: &'static str,
message: String,
},
}