use crate::api::*;
use crate::context::*;
use crate::ec::*;
use crate::lrf::*;
use crate::partition::*;
use crate::tiling::MAX_TILE_WIDTH;
use crate::util::Fixed;
use crate::util::Pixel;
use crate::DeblockState;
use crate::FrameInvariants;
use crate::FrameState;
use crate::SegmentationState;
use crate::Sequence;
use arrayvec::ArrayVec;
use bitstream_io::{BigEndian, BitWrite, BitWriter, LittleEndian};
use std::io;
pub const PRIMARY_REF_NONE: u32 = 7;
pub const ALL_REF_FRAMES_MASK: u32 = (1 << REF_FRAMES) - 1;
const PRIMARY_REF_BITS: u32 = 3;
#[allow(unused)]
const OP_POINTS_IDC_BITS: usize = 12;
#[allow(unused)]
const LEVEL_MAJOR_MIN: usize = 2;
#[allow(unused)]
const LEVEL_MAJOR_BITS: usize = 3;
#[allow(unused)]
const LEVEL_MINOR_BITS: usize = 2;
#[allow(unused)]
const LEVEL_BITS: usize = LEVEL_MAJOR_BITS + LEVEL_MINOR_BITS;
#[allow(dead_code, non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReferenceMode {
SINGLE = 0,
COMPOUND = 1,
SELECT = 2,
}
#[allow(non_camel_case_types)]
#[allow(unused)]
pub enum ObuType {
OBU_SEQUENCE_HEADER = 1,
OBU_TEMPORAL_DELIMITER = 2,
OBU_FRAME_HEADER = 3,
OBU_TILE_GROUP = 4,
OBU_METADATA = 5,
OBU_FRAME = 6,
OBU_REDUNDANT_FRAME_HEADER = 7,
OBU_TILE_LIST = 8,
OBU_PADDING = 15,
}
#[derive(Clone, Copy)]
#[allow(non_camel_case_types)]
#[allow(unused)]
pub enum ObuMetaType {
OBU_META_HDR_CLL = 1,
OBU_META_HDR_MDCV = 2,
OBU_META_SCALABILITY = 3,
OBU_META_ITUT_T35 = 4,
OBU_META_TIMECODE = 5,
}
impl ObuMetaType {
const fn size(self) -> u64 {
use self::ObuMetaType::*;
match self {
OBU_META_HDR_CLL => 4,
OBU_META_HDR_MDCV => 24,
_ => 0,
}
}
}
pub trait ULEB128Writer {
fn write_uleb128(&mut self, payload: u64) -> io::Result<()>;
}
impl<W: io::Write> ULEB128Writer for BitWriter<W, BigEndian> {
fn write_uleb128(&mut self, payload: u64) -> io::Result<()> {
let mut coded_value: ArrayVec<u8, 8> = ArrayVec::new();
let mut value = payload as u32;
loop {
let mut byte = (value & 0x7f) as u8;
value >>= 7u8;
if value != 0 {
byte |= 0x80;
}
coded_value.push(byte);
if value == 0 {
break;
}
}
for byte in coded_value {
self.write(8, byte)?;
}
Ok(())
}
}
pub trait LEWriter {
fn write_le(&mut self, bytes: u32, payload: u64) -> io::Result<()>;
}
impl<W: io::Write> LEWriter for BitWriter<W, BigEndian> {
fn write_le(&mut self, bytes: u32, value: u64) -> io::Result<()> {
let mut data = Vec::new();
let mut bwle = BitWriter::endian(&mut data, LittleEndian);
bwle.write(bytes * 8, value)?;
self.write_bytes(&data)
}
}
pub trait UncompressedHeader {
fn write_obu_header(
&mut self, obu_type: ObuType, obu_extension: u32,
) -> io::Result<()>;
fn write_sequence_metadata_obu(
&mut self, obu_meta_type: ObuMetaType, seq: &Sequence,
) -> io::Result<()>;
fn write_sequence_header_obu<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()>;
fn write_frame_header_obu<T: Pixel>(
&mut self, fi: &FrameInvariants<T>, fs: &FrameState<T>,
inter_cfg: &InterConfig,
) -> io::Result<()>;
fn write_sequence_header<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()>;
fn write_color_config(&mut self, seq: &Sequence) -> io::Result<()>;
fn write_t35_metadata_obu(&mut self, t35: &T35) -> io::Result<()>;
fn write_max_frame_size<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()>;
fn write_frame_size<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()>;
fn write_render_size<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()>;
fn write_frame_size_with_refs<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()>;
fn write_deblock_filter_a<T: Pixel>(
&mut self, fi: &FrameInvariants<T>, deblock: &DeblockState,
) -> io::Result<()>;
fn write_deblock_filter_b<T: Pixel>(
&mut self, fi: &FrameInvariants<T>, deblock: &DeblockState,
) -> io::Result<()>;
fn write_frame_cdef<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()>;
fn write_frame_lrf<T: Pixel>(
&mut self, fi: &FrameInvariants<T>, rs: &RestorationState,
) -> io::Result<()>;
fn write_segment_data<T: Pixel>(
&mut self, fi: &FrameInvariants<T>, segmentation: &SegmentationState,
) -> io::Result<()>;
fn write_delta_q(&mut self, delta_q: i8) -> io::Result<()>;
}
impl<W: io::Write> UncompressedHeader for BitWriter<W, BigEndian> {
fn write_obu_header(
&mut self, obu_type: ObuType, obu_extension: u32,
) -> io::Result<()> {
self.write_bit(false)?; self.write(4, obu_type as u32)?;
self.write_bit(obu_extension != 0)?;
self.write_bit(true)?; self.write_bit(false)?; if obu_extension != 0 {
unimplemented!();
}
Ok(())
}
fn write_sequence_metadata_obu(
&mut self, obu_meta_type: ObuMetaType, seq: &Sequence,
) -> io::Result<()> {
self.write_obu_header(ObuType::OBU_METADATA, 0)?;
self.write_uleb128(obu_meta_type.size() + 2)?;
self.write_uleb128(obu_meta_type as u64)?;
match obu_meta_type {
ObuMetaType::OBU_META_HDR_CLL => {
let cll = seq.content_light.unwrap();
self.write(16, cll.max_content_light_level)?;
self.write(16, cll.max_frame_average_light_level)?;
}
ObuMetaType::OBU_META_HDR_MDCV => {
let mdcv = seq.mastering_display.unwrap();
for i in 0..3 {
self.write(16, mdcv.primaries[i].x)?;
self.write(16, mdcv.primaries[i].y)?;
}
self.write(16, mdcv.white_point.x)?;
self.write(16, mdcv.white_point.y)?;
self.write(32, mdcv.max_luminance)?;
self.write(32, mdcv.min_luminance)?;
}
_ => {}
}
self.write_bit(true)?;
self.byte_align()?;
Ok(())
}
fn write_t35_metadata_obu(&mut self, t35: &T35) -> io::Result<()> {
self.write_obu_header(ObuType::OBU_METADATA, 0)?;
self.write_uleb128(
t35.data.len() as u64 + if t35.country_code == 0xFF { 4 } else { 3 },
)?;
self.write_uleb128(ObuMetaType::OBU_META_ITUT_T35 as u64)?;
self.write(8, t35.country_code)?;
if t35.country_code == 0xFF {
self.write(8, t35.country_code_extension_byte)?;
}
self.write_bytes(&t35.data)?;
self.write_bit(true)?;
self.byte_align()?;
Ok(())
}
fn write_sequence_header_obu<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()> {
assert!(
!fi.sequence.reduced_still_picture_hdr || fi.sequence.still_picture
);
self.write(3, fi.sequence.profile)?; self.write_bit(fi.sequence.still_picture)?; self.write_bit(fi.sequence.reduced_still_picture_hdr)?; assert!(fi.sequence.level_idx[0] <= 31);
if fi.sequence.reduced_still_picture_hdr {
assert!(!fi.sequence.timing_info_present);
assert!(!fi.sequence.decoder_model_info_present_flag);
assert_eq!(fi.sequence.operating_points_cnt_minus_1, 0);
assert_eq!(fi.sequence.operating_point_idc[0], 0);
self.write(5, fi.sequence.level_idx[0])?; assert_eq!(fi.sequence.tier[0], 0);
} else {
self.write_bit(fi.sequence.timing_info_present)?; if fi.sequence.timing_info_present {
self.write(32, fi.sequence.time_base.num)?;
self.write(32, fi.sequence.time_base.den)?;
self.write_bit(true)?; self.write_bit(true)?; self.write_bit(false)?; }
self.write_bit(false)?; self.write(5, 0)?; self.write(12, 0)?; self.write(5, fi.sequence.level_idx[0])?; if fi.sequence.level_idx[0] > 7 {
self.write(1, 0)?; }
}
self.write_sequence_header(fi)?;
self.write_color_config(&fi.sequence)?;
self.write_bit(fi.sequence.film_grain_params_present)?;
Ok(())
}
fn write_sequence_header<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()> {
self.write_max_frame_size(fi)?;
let seq = &fi.sequence;
if seq.reduced_still_picture_hdr {
assert!(!seq.frame_id_numbers_present_flag);
} else {
self.write_bit(seq.frame_id_numbers_present_flag)?;
}
if seq.frame_id_numbers_present_flag {
self.write(4, seq.delta_frame_id_length - 2)?;
self.write(3, seq.frame_id_length - seq.delta_frame_id_length - 1)?;
}
self.write_bit(seq.use_128x128_superblock)?;
self.write_bit(seq.enable_filter_intra)?;
self.write_bit(seq.enable_intra_edge_filter)?;
if seq.reduced_still_picture_hdr {
assert!(!seq.enable_interintra_compound);
assert!(!seq.enable_masked_compound);
assert!(!seq.enable_warped_motion);
assert!(!seq.enable_dual_filter);
assert!(!seq.enable_order_hint);
assert!(!seq.enable_jnt_comp);
assert!(!seq.enable_ref_frame_mvs);
assert!(seq.force_screen_content_tools == 2);
assert!(seq.force_integer_mv == 2);
} else {
self.write_bit(seq.enable_interintra_compound)?;
self.write_bit(seq.enable_masked_compound)?;
self.write_bit(seq.enable_warped_motion)?;
self.write_bit(seq.enable_dual_filter)?;
self.write_bit(seq.enable_order_hint)?;
if seq.enable_order_hint {
self.write_bit(seq.enable_jnt_comp)?;
self.write_bit(seq.enable_ref_frame_mvs)?;
}
if seq.force_screen_content_tools == 2 {
self.write_bit(true)?;
} else {
self.write_bit(false)?;
self.write_bit(seq.force_screen_content_tools != 0)?;
}
if seq.force_screen_content_tools > 0 {
if seq.force_integer_mv == 2 {
self.write_bit(true)?;
} else {
self.write_bit(false)?;
self.write_bit(seq.force_integer_mv != 0)?;
}
} else {
assert!(seq.force_integer_mv == 2);
}
if seq.enable_order_hint {
self.write(3, seq.order_hint_bits_minus_1)?;
}
}
self.write_bit(seq.enable_superres)?;
self.write_bit(seq.enable_cdef)?;
self.write_bit(seq.enable_restoration)?;
Ok(())
}
fn write_color_config(&mut self, seq: &Sequence) -> io::Result<()> {
let high_bitdepth = seq.bit_depth > 8;
self.write_bit(high_bitdepth)?;
if seq.profile == 2 && high_bitdepth {
self.write_bit(seq.bit_depth == 12)?; }
let monochrome = seq.chroma_sampling == ChromaSampling::Cs400;
if seq.profile == 1 {
assert!(!monochrome);
} else {
self.write_bit(monochrome)?; }
self.write_bit(seq.color_description.is_some())?;
let mut srgb_triple = false;
if let Some(color_description) = seq.color_description {
self.write(8, color_description.color_primaries as u8)?;
self.write(8, color_description.transfer_characteristics as u8)?;
self.write(8, color_description.matrix_coefficients as u8)?;
srgb_triple = color_description.is_srgb_triple();
}
if monochrome || !srgb_triple {
self.write_bit(seq.pixel_range == PixelRange::Full)?; }
if monochrome {
return Ok(());
} else if srgb_triple {
assert!(seq.pixel_range == PixelRange::Full);
assert!(seq.chroma_sampling == ChromaSampling::Cs444);
} else {
if seq.profile == 0 {
assert!(seq.chroma_sampling == ChromaSampling::Cs420);
} else if seq.profile == 1 {
assert!(seq.chroma_sampling == ChromaSampling::Cs444);
} else if seq.bit_depth == 12 {
let subsampling_x = seq.chroma_sampling != ChromaSampling::Cs444;
let subsampling_y = seq.chroma_sampling == ChromaSampling::Cs420;
self.write_bit(subsampling_x)?;
if subsampling_x {
self.write_bit(subsampling_y)?;
}
} else {
assert!(seq.chroma_sampling == ChromaSampling::Cs422);
}
if seq.chroma_sampling == ChromaSampling::Cs420 {
self.write(2, seq.chroma_sample_position as u32)?;
}
}
self.write_bit(true)?; Ok(())
}
#[allow(unused)]
fn write_frame_header_obu<T: Pixel>(
&mut self, fi: &FrameInvariants<T>, fs: &FrameState<T>,
inter_cfg: &InterConfig,
) -> io::Result<()> {
if fi.sequence.reduced_still_picture_hdr {
assert!(!fi.is_show_existing_frame());
assert!(fi.frame_type == FrameType::KEY);
assert!(fi.show_frame);
assert!(!fi.showable_frame);
} else {
self.write_bit(fi.is_show_existing_frame())?;
if fi.is_show_existing_frame() {
self.write(3, fi.frame_to_show_map_idx)?;
self.write_bit(true)?; self.byte_align()?;
return Ok(());
}
self.write(2, fi.frame_type as u32)?;
self.write_bit(fi.show_frame)?; if fi.show_frame {
} else {
self.write_bit(fi.showable_frame)?;
}
if fi.error_resilient {
assert!(fi.primary_ref_frame == PRIMARY_REF_NONE);
}
if fi.frame_type == FrameType::SWITCH {
assert!(fi.error_resilient);
} else if !(fi.frame_type == FrameType::KEY && fi.show_frame) {
self.write_bit(fi.error_resilient)?; }
}
self.write_bit(fi.disable_cdf_update)?;
if fi.sequence.force_screen_content_tools == 2 {
self.write_bit(fi.allow_screen_content_tools != 0)?;
} else {
assert!(
fi.allow_screen_content_tools
== fi.sequence.force_screen_content_tools
);
}
if fi.allow_screen_content_tools > 0 {
if fi.sequence.force_integer_mv == 2 {
self.write_bit(fi.force_integer_mv != 0)?;
} else {
assert!(fi.force_integer_mv == fi.sequence.force_integer_mv);
}
}
assert!(
fi.force_integer_mv
== u32::from(fi.frame_type == FrameType::KEY || fi.intra_only)
);
if fi.sequence.frame_id_numbers_present_flag {
unimplemented!();
}
if fi.frame_type != FrameType::SWITCH
&& !fi.sequence.reduced_still_picture_hdr
{
self.write_bit(fi.frame_size_override_flag)?; }
if fi.sequence.enable_order_hint {
let n = fi.sequence.order_hint_bits_minus_1 + 1;
let mask = (1 << n) - 1;
self.write(n, fi.order_hint & mask)?;
}
if !fi.error_resilient && !fi.intra_only {
self.write(PRIMARY_REF_BITS, fi.primary_ref_frame)?;
}
if fi.sequence.decoder_model_info_present_flag {
unimplemented!();
}
if fi.frame_type == FrameType::KEY {
if !fi.show_frame {
unimplemented!();
self.write(REF_FRAMES as u32, fi.refresh_frame_flags)?;
} else {
assert!(fi.refresh_frame_flags == ALL_REF_FRAMES_MASK);
}
} else if fi.frame_type == FrameType::SWITCH {
assert!(fi.refresh_frame_flags == ALL_REF_FRAMES_MASK);
} else {
if fi.intra_only {
assert!(fi.refresh_frame_flags != ALL_REF_FRAMES_MASK);
} else {
}
self.write(REF_FRAMES as u32, fi.refresh_frame_flags)?;
};
if (!fi.intra_only || fi.refresh_frame_flags != ALL_REF_FRAMES_MASK) {
if (fi.error_resilient && fi.sequence.enable_order_hint) {
for i in 0..REF_FRAMES {
let n = fi.sequence.order_hint_bits_minus_1 + 1;
let mask = (1 << n) - 1;
if let Some(ref rec) = fi.rec_buffer.frames[i] {
let ref_hint = rec.order_hint;
self.write(n, ref_hint & mask)?;
} else {
self.write(n, 0)?;
}
}
}
}
if fi.intra_only {
self.write_frame_size(fi)?;
self.write_render_size(fi)?;
if fi.allow_screen_content_tools != 0 {
self.write_bit(fi.allow_intrabc)?;
}
}
let frame_refs_short_signaling = false;
if fi.frame_type == FrameType::KEY || fi.intra_only {
} else {
if fi.sequence.enable_order_hint {
self.write_bit(frame_refs_short_signaling)?;
if frame_refs_short_signaling {
unimplemented!();
}
}
for i in 0..INTER_REFS_PER_FRAME {
if !frame_refs_short_signaling {
self.write(REF_FRAMES_LOG2 as u32, fi.ref_frames[i])?;
}
if fi.sequence.frame_id_numbers_present_flag {
unimplemented!();
}
}
if !fi.error_resilient && fi.frame_size_override_flag {
self.write_frame_size_with_refs(fi)?;
} else {
self.write_frame_size(fi)?;
self.write_render_size(fi)?;
}
if fi.force_integer_mv == 0 {
self.write_bit(fi.allow_high_precision_mv);
}
self.write_bit(fi.is_filter_switchable)?;
if !fi.is_filter_switchable {
self.write(2, fi.default_filter as u8)?;
}
self.write_bit(fi.is_motion_mode_switchable)?;
if (!fi.error_resilient && fi.sequence.enable_ref_frame_mvs) {
self.write_bit(fi.use_ref_frame_mvs)?;
}
}
if fi.sequence.reduced_still_picture_hdr || fi.disable_cdf_update {
assert!(fi.disable_frame_end_update_cdf);
} else {
self.write_bit(fi.disable_frame_end_update_cdf)?;
}
let ti = &fi.sequence.tiling;
if fi.sb_width.align_power_of_two_and_shift(ti.tile_cols_log2)
== ti.tile_width_sb
&& fi.sb_height.align_power_of_two_and_shift(ti.tile_rows_log2)
== ti.tile_height_sb
{
self.write_bit(true)?; let cols_ones = ti.tile_cols_log2 - ti.min_tile_cols_log2;
for _ in 0..cols_ones {
self.write_bit(true);
}
if ti.tile_cols_log2 < ti.max_tile_cols_log2 {
self.write_bit(false);
}
let rows_ones = ti.tile_rows_log2 - ti.min_tile_rows_log2;
for _ in 0..rows_ones {
self.write_bit(true);
}
if ti.tile_rows_log2 < ti.max_tile_rows_log2 {
self.write_bit(false);
}
} else {
self.write_bit(false)?; let mut sofar = 0;
let mut widest_tile_sb = 0;
for _ in 0..ti.cols {
let max = (MAX_TILE_WIDTH
>> if fi.sequence.use_128x128_superblock { 7 } else { 6 })
.min(fi.sb_width - sofar) as u16;
let this_sb_width = ti.tile_width_sb.min(fi.sb_width - sofar);
self.write_quniform(max, (this_sb_width - 1) as u16);
sofar += this_sb_width;
widest_tile_sb = widest_tile_sb.max(this_sb_width);
}
let max_tile_area_sb = if ti.min_tiles_log2 > 0 {
(fi.sb_height * fi.sb_width) >> (ti.min_tiles_log2 + 1)
} else {
fi.sb_height * fi.sb_width
};
let max_tile_height_sb = (max_tile_area_sb / widest_tile_sb).max(1);
sofar = 0;
for i in 0..ti.rows {
let max = max_tile_height_sb.min(fi.sb_height - sofar) as u16;
let this_sb_height = ti.tile_height_sb.min(fi.sb_height - sofar);
self.write_quniform(max, (this_sb_height - 1) as u16);
sofar += this_sb_height;
}
}
let tiles_log2 = ti.tile_cols_log2 + ti.tile_rows_log2;
if tiles_log2 > 0 {
self.write(tiles_log2 as u32, fs.context_update_tile_id as u32)?;
self.write(2, fs.max_tile_size_bytes - 1);
}
assert!(fi.base_q_idx > 0);
self.write(8, fi.base_q_idx)?; self.write_delta_q(fi.dc_delta_q[0])?;
if fi.sequence.chroma_sampling != ChromaSampling::Cs400 {
assert!(fi.ac_delta_q[0] == 0);
let diff_uv_delta = fi.dc_delta_q[1] != fi.dc_delta_q[2]
|| fi.ac_delta_q[1] != fi.ac_delta_q[2];
self.write_bit(diff_uv_delta)?;
self.write_delta_q(fi.dc_delta_q[1])?;
self.write_delta_q(fi.ac_delta_q[1])?;
if diff_uv_delta {
self.write_delta_q(fi.dc_delta_q[2])?;
self.write_delta_q(fi.ac_delta_q[2])?;
}
}
self.write_bit(false)?; self.write_segment_data(fi, &fs.segmentation)?;
self.write_bit(false)?; self.write_deblock_filter_a(fi, &fs.deblock)?;
self.write_deblock_filter_b(fi, &fs.deblock)?;
self.write_frame_cdef(fi)?;
self.write_frame_lrf(fi, &fs.restoration)?;
self.write_bit(fi.tx_mode_select)?; let mut reference_select = false;
if !fi.intra_only {
reference_select = fi.reference_mode != ReferenceMode::SINGLE;
self.write_bit(reference_select)?;
}
let skip_mode_allowed =
fi.sequence.get_skip_mode_allowed(fi, inter_cfg, reference_select);
if skip_mode_allowed {
self.write_bit(false)?; }
if fi.intra_only || fi.error_resilient || !fi.sequence.enable_warped_motion
{
} else {
self.write_bit(fi.allow_warped_motion)?; }
self.write_bit(fi.use_reduced_tx_set)?; if !fi.intra_only {
for i in 0..7 {
let mode = fi.globalmv_transformation_type[i];
self.write_bit(mode != GlobalMVMode::IDENTITY)?;
if mode != GlobalMVMode::IDENTITY {
self.write_bit(mode == GlobalMVMode::ROTZOOM)?;
if mode != GlobalMVMode::ROTZOOM {
self.write_bit(mode == GlobalMVMode::TRANSLATION)?;
}
}
match mode {
GlobalMVMode::IDENTITY => { }
GlobalMVMode::TRANSLATION => {
let mv_x = 0;
let mv_x_ref = 0;
let mv_y = 0;
let mv_y_ref = 0;
let bits = 12 - 6 + 3 - !fi.allow_high_precision_mv as u8;
let bits_diff = 12 - 3 + fi.allow_high_precision_mv as u8;
BCodeWriter::write_s_refsubexpfin(
self,
(1 << bits) + 1,
3,
mv_x_ref >> bits_diff,
mv_x >> bits_diff,
)?;
BCodeWriter::write_s_refsubexpfin(
self,
(1 << bits) + 1,
3,
mv_y_ref >> bits_diff,
mv_y >> bits_diff,
)?;
}
GlobalMVMode::ROTZOOM => unimplemented!(),
GlobalMVMode::AFFINE => unimplemented!(),
};
}
}
if fi.sequence.film_grain_params_present {
if let Some(grain_params) = fi.film_grain_params() {
self.write_bit(true)?;
self.write(16, grain_params.random_seed)?;
if fi.frame_type == FrameType::INTER {
self.write_bit(true)?;
}
self.write(4, grain_params.scaling_points_y.len() as u8)?;
for point in &grain_params.scaling_points_y {
self.write(8, point[0])?;
self.write(8, point[1])?;
}
let chroma_scaling_from_luma =
if fi.sequence.chroma_sampling != ChromaSampling::Cs400 {
self.write_bit(grain_params.chroma_scaling_from_luma)?;
grain_params.chroma_scaling_from_luma
} else {
false
};
if !(fi.sequence.chroma_sampling == ChromaSampling::Cs400
|| chroma_scaling_from_luma
|| (fi.sequence.chroma_sampling == ChromaSampling::Cs420
&& grain_params.scaling_points_y.is_empty()))
{
self.write(4, grain_params.scaling_points_cb.len() as u8)?;
for point in &grain_params.scaling_points_cb {
self.write(8, point[0])?;
self.write(8, point[1])?;
}
self.write(4, grain_params.scaling_points_cr.len() as u8)?;
for point in &grain_params.scaling_points_cr {
self.write(8, point[0])?;
self.write(8, point[1])?;
}
}
self.write(2, grain_params.scaling_shift - 8)?;
self.write(2, grain_params.ar_coeff_lag)?;
let mut num_pos_luma =
(2 * grain_params.ar_coeff_lag * (grain_params.ar_coeff_lag + 1))
as usize;
let mut num_pos_chroma;
if !grain_params.scaling_points_y.is_empty() {
num_pos_chroma = num_pos_luma + 1;
for i in 0..num_pos_luma {
self.write(8, grain_params.ar_coeffs_y[i] as i16 + 128)?;
}
} else {
num_pos_chroma = num_pos_luma;
}
if chroma_scaling_from_luma
|| !grain_params.scaling_points_cb.is_empty()
{
for i in 0..num_pos_chroma {
self.write(8, grain_params.ar_coeffs_cb[i] as i16 + 128)?;
}
}
if chroma_scaling_from_luma
|| !grain_params.scaling_points_cr.is_empty()
{
for i in 0..num_pos_chroma {
self.write(8, grain_params.ar_coeffs_cr[i] as i16 + 128)?;
}
}
self.write(2, grain_params.ar_coeff_shift - 6)?;
self.write(2, grain_params.grain_scale_shift)?;
if !grain_params.scaling_points_cb.is_empty() {
self.write(8, grain_params.cb_mult)?;
self.write(8, grain_params.cb_luma_mult)?;
self.write(9, grain_params.cb_offset)?;
}
if !grain_params.scaling_points_cr.is_empty() {
self.write(8, grain_params.cr_mult)?;
self.write(8, grain_params.cr_luma_mult)?;
self.write(9, grain_params.cr_offset)?;
}
self.write_bit(grain_params.overlap_flag)?;
self.write_bit(fi.sequence.pixel_range == PixelRange::Limited)?;
} else {
self.write_bit(false)?;
}
}
if fi.large_scale_tile {
unimplemented!();
}
self.byte_align()?;
Ok(())
}
fn write_max_frame_size<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()> {
let width = fi.width - 1;
let height = fi.height - 1;
let width_bits = log_in_base_2(width as u32) as u32 + 1;
let height_bits = log_in_base_2(height as u32) as u32 + 1;
assert!(width_bits <= 16);
assert!(height_bits <= 16);
self.write(4, width_bits - 1)?;
self.write(4, height_bits - 1)?;
self.write(width_bits, width as u16)?;
self.write(height_bits, height as u16)?;
Ok(())
}
fn write_frame_size<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()> {
if fi.frame_size_override_flag {
let width = fi.width - 1;
let height = fi.height - 1;
let width_bits = log_in_base_2(width as u32) as u32 + 1;
let height_bits = log_in_base_2(height as u32) as u32 + 1;
assert!(width_bits <= 16);
assert!(height_bits <= 16);
self.write(width_bits, width as u16)?;
self.write(height_bits, height as u16)?;
}
if fi.sequence.enable_superres {
unimplemented!();
}
Ok(())
}
fn write_render_size<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()> {
self.write_bit(fi.render_and_frame_size_different)?;
if fi.render_and_frame_size_different {
self.write(16, fi.render_width - 1)?;
self.write(16, fi.render_height - 1)?;
}
Ok(())
}
fn write_frame_size_with_refs<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()> {
let mut found_ref = false;
for i in 0..INTER_REFS_PER_FRAME {
if let Some(ref rec) = fi.rec_buffer.frames[fi.ref_frames[i] as usize] {
if rec.width == fi.width as u32
&& rec.height == fi.height as u32
&& rec.render_width == fi.render_width
&& rec.render_height == fi.render_height
{
self.write_bit(true)?;
found_ref = true;
break;
} else {
self.write_bit(false)?;
}
} else {
self.write_bit(false)?;
}
}
if !found_ref {
self.write_frame_size(fi)?;
self.write_render_size(fi)?;
} else if fi.sequence.enable_superres {
unimplemented!();
}
Ok(())
}
fn write_deblock_filter_a<T: Pixel>(
&mut self, fi: &FrameInvariants<T>, deblock: &DeblockState,
) -> io::Result<()> {
if fi.delta_q_present {
if !fi.allow_intrabc {
self.write_bit(deblock.block_deltas_enabled)?;
}
if deblock.block_deltas_enabled {
self.write(2, deblock.block_delta_shift)?;
self.write_bit(deblock.block_delta_multi)?;
}
}
Ok(())
}
fn write_deblock_filter_b<T: Pixel>(
&mut self, fi: &FrameInvariants<T>, deblock: &DeblockState,
) -> io::Result<()> {
let planes = if fi.sequence.chroma_sampling == ChromaSampling::Cs400 {
1
} else {
MAX_PLANES
};
assert!(deblock.levels[0] < 64);
self.write(6, deblock.levels[0])?; assert!(deblock.levels[1] < 64);
self.write(6, deblock.levels[1])?; if planes > 1 && (deblock.levels[0] > 0 || deblock.levels[1] > 0) {
assert!(deblock.levels[2] < 64);
self.write(6, deblock.levels[2])?; assert!(deblock.levels[3] < 64);
self.write(6, deblock.levels[3])?; }
self.write(3, deblock.sharpness)?; self.write_bit(deblock.deltas_enabled)?; if deblock.deltas_enabled {
self.write_bit(deblock.delta_updates_enabled)?; if deblock.delta_updates_enabled {
let prev_ref_deltas = if fi.primary_ref_frame == PRIMARY_REF_NONE {
[1, 0, 0, 0, 0, -1, -1, -1]
} else {
fi.rec_buffer.deblock
[fi.ref_frames[fi.primary_ref_frame as usize] as usize]
.ref_deltas
};
for i in 0..REF_FRAMES {
let update = deblock.ref_deltas[i] != prev_ref_deltas[i];
self.write_bit(update)?;
if update {
self.write_signed(7, deblock.ref_deltas[i])?;
}
}
let prev_mode_deltas = if fi.primary_ref_frame == PRIMARY_REF_NONE {
[0, 0]
} else {
fi.rec_buffer.deblock
[fi.ref_frames[fi.primary_ref_frame as usize] as usize]
.mode_deltas
};
for i in 0..2 {
let update = deblock.mode_deltas[i] != prev_mode_deltas[i];
self.write_bit(update)?;
if update {
self.write_signed(7, deblock.mode_deltas[i])?;
}
}
}
}
Ok(())
}
fn write_frame_cdef<T: Pixel>(
&mut self, fi: &FrameInvariants<T>,
) -> io::Result<()> {
if fi.sequence.enable_cdef && !fi.allow_intrabc {
assert!(fi.cdef_damping >= 3);
assert!(fi.cdef_damping <= 6);
self.write(2, fi.cdef_damping - 3)?;
assert!(fi.cdef_bits < 4);
self.write(2, fi.cdef_bits)?; for i in 0..(1 << fi.cdef_bits) {
assert!(fi.cdef_y_strengths[i] < 64);
assert!(fi.cdef_uv_strengths[i] < 64);
self.write(6, fi.cdef_y_strengths[i])?; if fi.sequence.chroma_sampling != ChromaSampling::Cs400 {
self.write(6, fi.cdef_uv_strengths[i])?; }
}
}
Ok(())
}
fn write_frame_lrf<T: Pixel>(
&mut self, fi: &FrameInvariants<T>, rs: &RestorationState,
) -> io::Result<()> {
if fi.sequence.enable_restoration && !fi.allow_intrabc {
let planes = if fi.sequence.chroma_sampling == ChromaSampling::Cs400 {
1
} else {
MAX_PLANES
};
let mut use_lrf = false;
let mut use_chroma_lrf = false;
for i in 0..planes {
self.write(2, rs.planes[i].cfg.lrf_type)?; if rs.planes[i].cfg.lrf_type != RESTORE_NONE {
use_lrf = true;
if i > 0 {
use_chroma_lrf = true;
}
}
}
if use_lrf {
if !fi.sequence.use_128x128_superblock {
self.write(1, u8::from(rs.planes[0].cfg.unit_size > 64))?;
}
if rs.planes[0].cfg.unit_size > 64 {
self.write(1, u8::from(rs.planes[0].cfg.unit_size > 128))?;
}
if use_chroma_lrf
&& fi.sequence.chroma_sampling == ChromaSampling::Cs420
{
self.write(
1,
u8::from(rs.planes[0].cfg.unit_size > rs.planes[1].cfg.unit_size),
)?;
}
}
}
Ok(())
}
fn write_segment_data<T: Pixel>(
&mut self, fi: &FrameInvariants<T>, segmentation: &SegmentationState,
) -> io::Result<()> {
assert_eq!(fi.enable_segmentation, segmentation.enabled);
self.write_bit(fi.enable_segmentation)?;
if segmentation.enabled {
if fi.primary_ref_frame == PRIMARY_REF_NONE {
assert!(segmentation.update_map);
assert!(segmentation.update_data);
} else {
self.write_bit(segmentation.update_map)?;
if segmentation.update_map {
self.write_bit(false)?; }
self.write_bit(segmentation.update_data)?;
}
if segmentation.update_data {
for i in 0..8 {
for j in 0..SegLvl::SEG_LVL_MAX as usize {
self.write_bit(segmentation.features[i][j])?;
if segmentation.features[i][j] {
let bits = seg_feature_bits[j];
let data = segmentation.data[i][j];
if seg_feature_is_signed[j] {
self.write_signed(bits + 1, data)?;
} else {
self.write(bits, data)?;
}
}
}
}
}
}
Ok(())
}
fn write_delta_q(&mut self, delta_q: i8) -> io::Result<()> {
self.write_bit(delta_q != 0)?;
if delta_q != 0 {
assert!((-63..=63).contains(&delta_q));
self.write_signed(6 + 1, delta_q)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::ULEB128Writer;
use bitstream_io::{BigEndian, BitWriter};
use nom::error::Error;
use nom::IResult;
use quickcheck::quickcheck;
fn leb128(mut input: &[u8]) -> IResult<&[u8], u64, Error<&[u8]>> {
use nom::bytes::complete::take;
let mut value = 0u64;
for i in 0..8u8 {
let result = take(1usize)(input)?;
input = result.0;
let leb128_byte = result.1[0];
value |= u64::from(leb128_byte & 0x7f) << (i * 7);
if (leb128_byte & 0x80) == 0 {
break;
}
}
Ok((input, value))
}
quickcheck! {
fn validate_leb128_write(val: u32) -> bool {
let mut buf1 = Vec::new();
let mut bw1 = BitWriter::endian(&mut buf1, BigEndian);
bw1.write_uleb128(val as u64).unwrap();
let result = leb128(&buf1).unwrap();
u64::from(val) == result.1 && result.0.is_empty()
}
}
}