Skip to main content

xberg_libheif/
track.rs

1use std::ptr;
2
3use four_cc::FourCC;
4use libheif_sys as lh;
5
6use crate::decoder::get_decoding_options_ptr;
7use crate::{ColorSpace, DecodingOptions, HeifError, Image, Result};
8
9pub type TrackType = FourCC;
10
11pub mod track_types {
12    use super::{FourCC, TrackType};
13
14    pub const VIDEO: TrackType = FourCC(*b"vide");
15    pub const IMAGE_SEQUENCE: TrackType = FourCC(*b"pict");
16    pub const AUXILIARY: TrackType = FourCC(*b"auxv");
17    pub const METADATA: TrackType = FourCC(*b"meta");
18}
19
20#[derive(Default, Copy, Clone, PartialEq, Eq)]
21pub struct ImageResolution {
22    pub width: u16,
23    pub height: u16,
24}
25
26pub struct Track {
27    pub(crate) inner: *mut lh::heif_track,
28}
29
30#[allow(unsafe_code)]
31impl Track {
32    #[inline]
33    pub(crate) fn from_heif_track(track: *mut lh::heif_track) -> Track {
34        Track { inner: track }
35    }
36
37    /// Get the ID of the track.
38    ///
39    /// The track ID will never be 0.
40    #[allow(unsafe_code)]
41    pub fn id(&self) -> u32 {
42        unsafe { lh::heif_track_get_id(self.inner) }
43    }
44
45    /// Get the four-cc track handler type.
46    ///
47    /// Typical codes are "vide" for video sequences, "pict" for image sequences,
48    /// "meta" for metadata tracks.
49    /// These are defined in [`track_types`] module, but files may also contain other types.
50    #[allow(unsafe_code)]
51    pub fn handler_type(&self) -> TrackType {
52        let c_track_type = unsafe { lh::heif_track_get_track_handler_type(self.inner) };
53        TrackType::from(c_track_type as u32)
54    }
55
56    #[cfg(feature = "v1_21")]
57    #[allow(unsafe_code)]
58    pub fn has_alpha_channel(&self) -> bool {
59        unsafe { lh::heif_track_has_alpha_channel(self.inner) != 0 }
60    }
61
62    /// Get the timescale (clock ticks per second) for this track.
63    ///
64    /// Note that this can be different from the timescale used at sequence level.
65    #[allow(unsafe_code)]
66    pub fn timescale(&self) -> u32 {
67        unsafe { lh::heif_track_get_timescale(self.inner) }
68    }
69
70    /// Get the image resolution of the track.
71    ///
72    /// If the track is no visual track, an error is returned.
73    #[allow(unsafe_code)]
74    pub fn image_resolution(&self) -> Result<ImageResolution> {
75        let mut res = ImageResolution::default();
76
77        let err = unsafe { lh::heif_track_get_image_resolution(self.inner, &mut res.width, &mut res.height) };
78
79        HeifError::from_heif_error(err)?;
80        Ok(res)
81    }
82
83    /// Decode the next image in the sequence track.
84    ///
85    /// If there is no more image in the sequence,
86    /// error with code [HeifErrorCode::EndOfSequence](crate::HeifErrorCode::EndOfSequence)
87    /// will be returned.
88    /// The parameters `color_space` and `decoding_options` are similar to
89    /// [LibHeif::decode()](crate::LibHeif::decode).
90    /// If you want to let `libheif` decide the output colorspace and chroma,
91    /// set `color_space` parameter to [ColorSpace::Undefined].
92    /// Usually, `libheif` will return the image in the input colorspace,
93    /// but it may also modify it for example when it has to rotate the image.
94    /// If you want to get the image in a specific colorspace/chroma format,
95    /// you can specify this and `libheif` will convert the image to match this format.
96    #[allow(unsafe_code)]
97    pub fn decode_next_image(
98        &self,
99        color_space: ColorSpace,
100        decoding_options: Option<DecodingOptions>,
101    ) -> Result<Image> {
102        let mut c_image: *mut lh::heif_image = ptr::null_mut();
103        let err = unsafe {
104            lh::heif_track_decode_next_image(
105                self.inner,
106                &mut c_image,
107                color_space.heif_color_space(),
108                color_space.heif_chroma(),
109                get_decoding_options_ptr(&decoding_options),
110            )
111        };
112        HeifError::from_heif_error(err)?;
113        Ok(Image::from_heif_image(c_image))
114    }
115}
116
117#[allow(unsafe_code)]
118impl Drop for Track {
119    #[allow(unsafe_code)]
120    fn drop(&mut self) {
121        unsafe { lh::heif_track_release(self.inner) };
122    }
123}