use std::fmt::Debug;
use std::io;
use scuffle_bytes_util::{BitReader, range_check};
use scuffle_expgolomb::BitReaderExpGolombExt;
#[derive(Debug, Clone, PartialEq)]
pub struct ShortTermRefPicSets {
pub num_delta_pocs: Vec<u64>,
pub num_positive_pics: Vec<u64>,
pub num_negative_pics: Vec<u64>,
pub delta_poc_s1: Vec<Vec<i64>>,
pub delta_poc_s0: Vec<Vec<i64>>,
pub used_by_curr_pic_s0: Vec<Vec<bool>>,
pub used_by_curr_pic_s1: Vec<Vec<bool>>,
}
impl ShortTermRefPicSets {
pub(crate) fn parse<R: io::Read>(
bit_reader: &mut BitReader<R>,
num_short_term_ref_pic_sets: usize,
nuh_layer_id: u8,
sps_max_dec_pic_buffering_minus1_at_sps_max_sub_layers_minus1: u64,
) -> io::Result<Self> {
let mut num_delta_pocs = Vec::with_capacity(num_short_term_ref_pic_sets);
let mut num_positive_pics = vec![0u64; num_short_term_ref_pic_sets];
let mut num_negative_pics = vec![0u64; num_short_term_ref_pic_sets];
let mut delta_poc_s1 = Vec::with_capacity(num_short_term_ref_pic_sets);
let mut delta_poc_s0 = Vec::with_capacity(num_short_term_ref_pic_sets);
let mut used_by_curr_pic_s0 = Vec::with_capacity(num_short_term_ref_pic_sets);
let mut used_by_curr_pic_s1 = Vec::with_capacity(num_short_term_ref_pic_sets);
for st_rps_idx in 0..num_short_term_ref_pic_sets {
let mut inter_ref_pic_set_prediction_flag = false;
if st_rps_idx != 0 {
inter_ref_pic_set_prediction_flag = bit_reader.read_bit()?;
}
if inter_ref_pic_set_prediction_flag {
let mut delta_idx_minus1 = 0;
if st_rps_idx == num_short_term_ref_pic_sets {
delta_idx_minus1 = bit_reader.read_exp_golomb()? as usize;
range_check!(delta_idx_minus1, 0, st_rps_idx - 1)?;
}
let ref_rps_idx = st_rps_idx - (delta_idx_minus1 + 1);
let delta_rps_sign = bit_reader.read_bit()?;
let abs_delta_rps_minus1 = bit_reader.read_exp_golomb()?;
range_check!(abs_delta_rps_minus1, 0, 2u64.pow(15) - 1)?;
let delta_rps = (1 - 2 * delta_rps_sign as i64) * (abs_delta_rps_minus1 + 1) as i64;
let len = num_delta_pocs[ref_rps_idx] as usize + 1;
let mut used_by_curr_pic_flag = vec![false; len];
let mut use_delta_flag = vec![true; len];
for j in 0..len {
used_by_curr_pic_flag[j] = bit_reader.read_bit()?;
if !used_by_curr_pic_flag[j] {
use_delta_flag[j] = bit_reader.read_bit()?;
}
}
delta_poc_s0.push(vec![0; len]);
delta_poc_s1.push(vec![0; len]);
used_by_curr_pic_s0.push(vec![false; len]);
used_by_curr_pic_s1.push(vec![false; len]);
let mut i = 0;
if let Some(start) = num_positive_pics[ref_rps_idx].checked_sub(1).map(|s| s as usize) {
for j in (0..=start).rev() {
let d_poc = delta_poc_s1[ref_rps_idx][j] + delta_rps;
if d_poc < 0 && use_delta_flag[num_negative_pics[ref_rps_idx] as usize + j] {
delta_poc_s0[st_rps_idx][i] = d_poc;
used_by_curr_pic_s0[st_rps_idx][i] =
used_by_curr_pic_flag[num_negative_pics[ref_rps_idx] as usize + j];
i += 1;
}
}
}
if delta_rps < 0 && use_delta_flag[num_delta_pocs[ref_rps_idx] as usize] {
delta_poc_s0[st_rps_idx][i] = delta_rps;
used_by_curr_pic_s0[st_rps_idx][i] = used_by_curr_pic_flag[num_delta_pocs[ref_rps_idx] as usize];
i += 1;
}
for j in 0..num_negative_pics[ref_rps_idx] as usize {
let d_poc = delta_poc_s0[ref_rps_idx][j] + delta_rps;
if d_poc < 0 && use_delta_flag[j] {
delta_poc_s0[st_rps_idx][i] = d_poc;
used_by_curr_pic_s0[st_rps_idx][i] = used_by_curr_pic_flag[j];
i += 1;
}
}
num_negative_pics[st_rps_idx] = i as u64;
range_check!(num_negative_pics[st_rps_idx], 0, 16)?;
i = 0;
if let Some(start) = num_negative_pics[ref_rps_idx].checked_sub(1).map(|s| s as usize) {
for j in (0..=start).rev() {
let d_poc = delta_poc_s0[ref_rps_idx][j] + delta_rps;
if d_poc > 0 && use_delta_flag[j] {
delta_poc_s1[st_rps_idx][i] = d_poc;
used_by_curr_pic_s1[st_rps_idx][i] = used_by_curr_pic_flag[j];
i += 1;
}
}
}
if delta_rps > 0 && use_delta_flag[num_delta_pocs[ref_rps_idx] as usize] {
delta_poc_s1[st_rps_idx][i] = delta_rps;
used_by_curr_pic_s1[st_rps_idx][i] = used_by_curr_pic_flag[num_delta_pocs[ref_rps_idx] as usize];
i += 1;
}
for j in 0..num_positive_pics[ref_rps_idx] as usize {
let d_poc = delta_poc_s1[ref_rps_idx][j] + delta_rps;
if d_poc > 0 && use_delta_flag[num_negative_pics[ref_rps_idx] as usize + j] {
delta_poc_s1[st_rps_idx][i] = d_poc;
used_by_curr_pic_s1[st_rps_idx][i] =
used_by_curr_pic_flag[num_negative_pics[ref_rps_idx] as usize + j];
i += 1;
}
}
num_positive_pics[st_rps_idx] = i as u64;
range_check!(num_negative_pics[st_rps_idx], 0, 16)?;
} else {
num_negative_pics[st_rps_idx] = bit_reader.read_exp_golomb()?;
num_positive_pics[st_rps_idx] = bit_reader.read_exp_golomb()?;
let upper_bound = if nuh_layer_id == 0 {
sps_max_dec_pic_buffering_minus1_at_sps_max_sub_layers_minus1
} else {
16
};
range_check!(num_negative_pics[st_rps_idx], 0, upper_bound)?;
let upper_bound = if nuh_layer_id == 0 {
sps_max_dec_pic_buffering_minus1_at_sps_max_sub_layers_minus1
.saturating_sub(num_negative_pics[st_rps_idx])
} else {
16
};
range_check!(num_positive_pics[st_rps_idx], 0, upper_bound)?;
delta_poc_s0.push(vec![0; num_negative_pics[st_rps_idx] as usize]);
used_by_curr_pic_s0.push(vec![false; num_negative_pics[st_rps_idx] as usize]);
for i in 0..num_negative_pics[st_rps_idx] as usize {
let delta_poc_s0_minus1 = bit_reader.read_exp_golomb()?;
range_check!(delta_poc_s0_minus1, 0, 2u64.pow(15) - 1)?;
if i == 0 {
delta_poc_s0[st_rps_idx][i] = -(delta_poc_s0_minus1 as i64 + 1);
} else {
delta_poc_s0[st_rps_idx][i] = delta_poc_s0[st_rps_idx][i - 1] - (delta_poc_s0_minus1 as i64 + 1);
}
let used_by_curr_pic_s0_flag = bit_reader.read_bit()?;
used_by_curr_pic_s0[st_rps_idx][i] = used_by_curr_pic_s0_flag;
}
delta_poc_s1.push(vec![0; num_positive_pics[st_rps_idx] as usize]);
used_by_curr_pic_s1.push(vec![false; num_positive_pics[st_rps_idx] as usize]);
for i in 0..num_positive_pics[st_rps_idx] as usize {
let delta_poc_s1_minus1 = bit_reader.read_exp_golomb()?;
range_check!(delta_poc_s1_minus1, 0, 2u64.pow(15) - 1)?;
if i == 0 {
delta_poc_s1[st_rps_idx][i] = delta_poc_s1_minus1 as i64 + 1;
} else {
delta_poc_s1[st_rps_idx][i] = delta_poc_s1[st_rps_idx][i - 1] + delta_poc_s1_minus1 as i64 + 1;
}
let used_by_curr_pic_s1_flag = bit_reader.read_bit()?;
used_by_curr_pic_s1[st_rps_idx][i] = used_by_curr_pic_s1_flag;
}
}
num_delta_pocs.push(num_negative_pics[st_rps_idx] + num_positive_pics[st_rps_idx]);
}
Ok(Self {
num_delta_pocs,
num_positive_pics,
num_negative_pics,
delta_poc_s1,
delta_poc_s0,
used_by_curr_pic_s0,
used_by_curr_pic_s1,
})
}
}