#![forbid(unsafe_code)]
use crate::DecodeError;
use mediaway_sw::h264::BitReader;
use super::bits::s;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) struct QuantizationParams {
pub(super) base_q_idx: u8,
pub(super) lossless: bool,
}
fn read_delta_q(r: &mut BitReader<'_>) -> Result<i8, DecodeError> {
let map_err = |_| DecodeError::InvalidInput;
let delta_coded = r.read_bit().map_err(map_err)? != 0;
if !delta_coded {
return Ok(0);
}
let value = s(r, 4)?;
i8::try_from(value).map_err(|_| DecodeError::InvalidInput)
}
#[allow(
clippy::similar_names,
reason = "delta_q_uv_dc/delta_q_uv_ac are the VP9 spec's own quantization_params() names \
(§6.2.9) — a 1:1 spec mapping this crate relies on for review, same precedent as \
this crate's AV1 sibling's parse_quantization_params allow"
)]
pub(super) fn parse(r: &mut BitReader<'_>) -> Result<QuantizationParams, DecodeError> {
let map_err = |_| DecodeError::InvalidInput;
let base_q_idx = u8::try_from(r.read_bits(8).map_err(map_err)?).unwrap_or(0);
let delta_q_y_dc = read_delta_q(r)?;
let delta_q_uv_dc = read_delta_q(r)?;
let delta_q_uv_ac = read_delta_q(r)?;
let lossless = base_q_idx == 0 && delta_q_y_dc == 0 && delta_q_uv_dc == 0 && delta_q_uv_ac == 0;
Ok(QuantizationParams {
base_q_idx,
lossless,
})
}
#[cfg(test)]
#[path = "quantization_tests.rs"]
mod tests;