sentryshot_util 0.1.2

Port of FFmpeg's utils
Documentation
// SPDX-License-Identifier: MPL-2.0+

mod common;
mod frame;
mod imgutils;
pub mod pixfmt;

pub use common::ceil_rshift;
pub use frame::{Frame, NUM_DATA_POINTERS};
pub use imgutils::{image_fill_max_pixsteps, ImageCopyToBufferError, ResetBufferError};

use sentryshot_padded_bytes::PaddedBytes;
use std::{convert::TryFrom, os::raw::c_uint};
use thiserror::Error;

// Clip a signed integer value into the 0-255 range.
#[must_use]
#[allow(
    clippy::cast_possible_truncation,
    clippy::cast_sign_loss,
    clippy::as_conversions
)]
pub fn clip_u8(a: i32) -> u8 {
    if (a & (!0xff)) == 0 {
        a as u8
    } else {
        ((!a) >> 31) as u8
    }
    //if (a&(~0xFF)) return (~a)>>31;
    //else           return a;
}

pub struct Packet<'a> {
    data: &'a PaddedBytes,
    pts: i64,
}

impl<'a> Packet<'a> {
    #[must_use]
    pub fn new(data: &'a PaddedBytes) -> Self {
        Self { data, pts: 0 }
    }
    #[must_use]
    pub fn with_pts(mut self, pts: i64) -> Self {
        self.pts = pts;
        self
    }

    #[must_use]
    pub fn data(&self) -> &PaddedBytes {
        self.data
    }
    #[must_use]
    pub fn pts(&self) -> i64 {
        self.pts
    }
}

/// Visual content value range.
///
/// These values are based on definitions that can be found in multiple
/// specifications, such as ITU-T BT.709 (3.4 - Quantization of RGB, luminance
/// and colour-difference signals), ITU-T BT.2020 (Table 5 - Digital
/// Representation) as well as ITU-T BT.2100 (Table 9 - Digital 10- and 12-bit
/// integer representation). At the time of writing, the BT.2100 one is
/// recommended, as it also defines the full range representation.
///
/// Common definitions:
///   - For RGB and luma planes such as Y in `YCbCr` and I in `ICtCp`,
///     'E' is the original value in range of 0.0 to 1.0.
///   - For chroma planes such as Cb,Cr and Ct,Cp, 'E' is the original
///     value in range of -0.5 to 0.5.
///   - 'n' is the output bit depth.
///   - For additional definitions such as rounding and clipping to valid n
///     bit unsigned integer range, please refer to BT.2100 (Table 9).
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum ColorRange {
    UNSPECIFIED, // 0.

    /// Narrow or limited range content.
    ///
    /// - For luma planes:
    ///       (219 * E + 16) * 2^(n-8)
    ///
    ///   F.ex. the range of 16-235 for 8 bits
    ///
    /// - For chroma planes:
    ///       (224 * E + 128) * 2^(n-8)
    ///
    ///   F.ex. the range of 16-240 for 8 bits
    MPEG, // 1.

    /// Full range content.
    ///
    /// - For RGB and luma planes:
    ///       (2^n - 1) * E
    ///
    ///   F.ex. the range of 0-255 for 8 bits
    ///
    /// - For chroma planes:
    ///       (2^n - 1) * E + 2^(n - 1)
    ///
    ///   F.ex. the range of 1-255 for 8 bits
    JPEG, // = 2,

          // NB // Not part of ABI
}

impl std::fmt::Debug for ColorRange {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let name = match self {
            ColorRange::UNSPECIFIED => "unspecified",
            ColorRange::MPEG => "mpeg",
            ColorRange::JPEG => "jpeg",
        };
        write!(f, "{name}")
    }
}

impl std::fmt::Display for ColorRange {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{self:?}")
    }
}

#[derive(Debug, Error)]
#[error("invalid color range: {0}")]
pub struct InvalidColorRange(c_uint);

impl TryFrom<c_uint> for ColorRange {
    type Error = InvalidColorRange;

    fn try_from(value: c_uint) -> Result<Self, Self::Error> {
        match value {
            0 => Ok(ColorRange::UNSPECIFIED),
            1 => Ok(ColorRange::MPEG),
            2 => Ok(ColorRange::JPEG),
            _ => Err(InvalidColorRange(value)),
        }
    }
}