Skip to main content

oxideav_tiff/
registry.rs

1//! `oxideav-core` integration layer for `oxideav-tiff`.
2//!
3//! Gated behind the default-on `registry` feature so image-library
4//! consumers can depend on `oxideav-tiff` with `default-features = false`
5//! and skip the `oxideav-core` dependency entirely.
6//!
7//! The module exposes:
8//! * [`register`] / [`register_codecs`] / [`register_containers`] — the
9//!   `CodecRegistry` / `ContainerRegistry` entry points the umbrella
10//!   `oxideav` crate calls during framework initialisation.
11//! * The `From<TiffError> for oxideav_core::Error` and
12//!   `From<TiffImage> for oxideav_core::Frame` conversions used by the
13//!   [`TiffDecoder`] trait impl below.
14
15use oxideav_core::{
16    frame::VideoPlane, CodecCapabilities, CodecId, CodecInfo, CodecParameters, CodecRegistry,
17    ContainerRegistry, Decoder, Error, Frame, Packet, PixelFormat, Result, VideoFrame,
18};
19
20use crate::container;
21use crate::decoder::decode_tiff;
22use crate::error::TiffError;
23use crate::image::{TiffImage, TiffPixelFormat};
24use crate::CODEC_ID_STR;
25
26impl From<TiffError> for Error {
27    fn from(e: TiffError) -> Self {
28        match e {
29            TiffError::InvalidData(s) => Error::InvalidData(s),
30            TiffError::Unsupported(s) => Error::Unsupported(s),
31        }
32    }
33}
34
35impl From<TiffPixelFormat> for PixelFormat {
36    fn from(p: TiffPixelFormat) -> Self {
37        match p {
38            TiffPixelFormat::Gray8 => PixelFormat::Gray8,
39            TiffPixelFormat::Gray16Le => PixelFormat::Gray16Le,
40            TiffPixelFormat::Rgb24 => PixelFormat::Rgb24,
41            TiffPixelFormat::Rgb48Le => PixelFormat::Rgb48Le,
42        }
43    }
44}
45
46impl From<TiffImage> for VideoFrame {
47    fn from(img: TiffImage) -> Self {
48        let planes = img
49            .planes
50            .into_iter()
51            .map(|p| VideoPlane {
52                stride: p.stride,
53                data: p.data,
54            })
55            .collect();
56        VideoFrame { pts: None, planes }
57    }
58}
59
60impl From<TiffImage> for Frame {
61    fn from(img: TiffImage) -> Self {
62        Frame::Video(img.into())
63    }
64}
65
66/// Register the TIFF codec (decoder) into the supplied [`CodecRegistry`].
67pub fn register_codecs(reg: &mut CodecRegistry) {
68    let caps = CodecCapabilities::video("tiff_sw")
69        .with_intra_only(true)
70        .with_lossless(true)
71        .with_max_size(65535, 65535)
72        .with_pixel_formats(vec![
73            PixelFormat::Rgb24,
74            PixelFormat::Rgb48Le,
75            PixelFormat::Gray8,
76            PixelFormat::Gray16Le,
77        ]);
78    reg.register(
79        CodecInfo::new(CodecId::new(CODEC_ID_STR))
80            .capabilities(caps)
81            .decoder(make_decoder),
82    );
83}
84
85/// Register the TIFF container demuxer + extension + probe.
86pub fn register_containers(reg: &mut ContainerRegistry) {
87    container::register(reg);
88}
89
90/// Combined registration for callers that just want everything wired
91/// up in one call.
92pub fn register(codecs: &mut CodecRegistry, containers: &mut ContainerRegistry) {
93    register_codecs(codecs);
94    register_containers(containers);
95}
96
97/// Factory registered with the codec registry.
98pub fn make_decoder(_params: &CodecParameters) -> Result<Box<dyn Decoder>> {
99    Ok(Box::new(TiffDecoder {
100        codec_id: CodecId::new(CODEC_ID_STR),
101        pending: None,
102        eof: false,
103    }))
104}
105
106struct TiffDecoder {
107    codec_id: CodecId,
108    pending: Option<VideoFrame>,
109    eof: bool,
110}
111
112impl Decoder for TiffDecoder {
113    fn codec_id(&self) -> &CodecId {
114        &self.codec_id
115    }
116    fn send_packet(&mut self, packet: &Packet) -> Result<()> {
117        let d = decode_tiff(&packet.data)?;
118        self.pending = Some(d.frame.into());
119        Ok(())
120    }
121    fn receive_frame(&mut self) -> Result<Frame> {
122        match self.pending.take() {
123            Some(f) => Ok(Frame::Video(f)),
124            None => {
125                if self.eof {
126                    Err(Error::Eof)
127                } else {
128                    Err(Error::NeedMore)
129                }
130            }
131        }
132    }
133    fn flush(&mut self) -> Result<()> {
134        self.eof = true;
135        Ok(())
136    }
137}