Skip to content

Commit

Permalink
Port C code changes to Rust
Browse files Browse the repository at this point in the history
  • Loading branch information
Frank Bossen committed Mar 23, 2024
1 parent ccbdd92 commit b806651
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 86 deletions.
5 changes: 5 additions & 0 deletions src/getbits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,9 @@ impl<'a> GetBits<'a> {
pub const fn pos(&self) -> usize {
self.index * u8::BITS as usize - self.bits_left as usize
}

#[inline]
pub const fn has_pending_bits(&self) -> bool {
self.state != 0 || self.bits_left != 0
}
}
62 changes: 5 additions & 57 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ use crate::include::dav1d::dav1d::Dav1dSettings;
use crate::include::dav1d::dav1d::Rav1dDecodeFrameType;
use crate::include::dav1d::dav1d::Rav1dInloopFilterType;
use crate::include::dav1d::dav1d::Rav1dSettings;
use crate::include::dav1d::headers::DRav1d;
use crate::include::dav1d::headers::Dav1dSequenceHeader;
use crate::include::dav1d::headers::Rav1dFilmGrainData;
use crate::include::dav1d::headers::Rav1dSequenceHeader;
use crate::include::dav1d::picture::Dav1dPicture;
use crate::include::dav1d::picture::Rav1dPicture;
use crate::src::cdf::rav1d_cdf_thread_unref;
Expand All @@ -25,7 +23,6 @@ use crate::src::error::Dav1dResult;
use crate::src::error::Rav1dError::EGeneric;
use crate::src::error::Rav1dError::EAGAIN;
use crate::src::error::Rav1dError::EINVAL;
use crate::src::error::Rav1dError::ENOENT;
use crate::src::error::Rav1dError::ENOMEM;
use crate::src::error::Rav1dResult;
use crate::src::fg_apply;
Expand All @@ -37,13 +34,13 @@ use crate::src::internal::Rav1dTaskContext;
use crate::src::internal::Rav1dTaskContext_task_thread;
use crate::src::internal::TaskThreadData;
use crate::src::log::Rav1dLog as _;
use crate::src::mem::freep;
use crate::src::mem::rav1d_alloc_aligned;
use crate::src::mem::rav1d_free_aligned;
use crate::src::mem::rav1d_freep_aligned;
use crate::src::mem::rav1d_mem_pool_end;
use crate::src::mem::rav1d_mem_pool_init;
use crate::src::obu::rav1d_parse_obus;
use crate::src::obu::rav1d_parse_sequence_header;
use crate::src::picture::dav1d_default_picture_alloc;
use crate::src::picture::dav1d_default_picture_release;
use crate::src::picture::rav1d_picture_alloc_copy;
Expand Down Expand Up @@ -398,57 +395,6 @@ pub unsafe extern "C" fn dav1d_open(
.into()
}

unsafe extern "C" fn dummy_free(data: *const u8, user_data: *mut c_void) {
if !(!data.is_null() && user_data.is_null()) {
unreachable!();
}
}

pub(crate) unsafe fn rav1d_parse_sequence_header(
ptr: *const u8,
sz: usize,
) -> Rav1dResult<DRav1d<Rav1dSequenceHeader, Dav1dSequenceHeader>> {
let s = Rav1dSettings {
n_threads: 1,
logger: None,
..Default::default()
};
let mut c: *mut Rav1dContext = 0 as *mut Rav1dContext;
rav1d_open(&mut c, &s)?;
|| -> Rav1dResult<DRav1d<Rav1dSequenceHeader, Dav1dSequenceHeader>> {
let Rav1dData {
mut data,
m: mut props,
} = match NonNull::new(ptr.cast_mut()) {
None => Default::default(),
Some(ptr) => Rav1dData::wrap(
slice::from_raw_parts(ptr.as_ptr(), sz).into(),
Some(dummy_free),
ptr::null_mut(),
)?,
};
if let Some(data) = &mut data {
while !data.is_empty() {
let len = rav1d_parse_obus(&mut *c, data, &mut props, true)?;
data.slice_in_place(len..);
}
}

if (*c).seq_hdr.is_none() {
return Err(ENOENT);
}

(*c).seq_hdr
.take()
.and_then(Arc::into_inner)
.map(Ok)
.unwrap()
}()
.inspect_err(|_| {
rav1d_close(&mut c);
})
}

#[no_mangle]
pub unsafe extern "C" fn dav1d_parse_sequence_header(
out: *mut Dav1dSequenceHeader,
Expand All @@ -457,7 +403,9 @@ pub unsafe extern "C" fn dav1d_parse_sequence_header(
) -> Dav1dResult {
(|| {
validate_input!((!out.is_null(), EINVAL))?;
let seq_hdr = rav1d_parse_sequence_header(ptr, sz)?;
validate_input!((!ptr.is_null(), EINVAL))?;
validate_input!((sz > 0, EINVAL))?;
let seq_hdr = rav1d_parse_sequence_header(slice::from_raw_parts(ptr, sz))?;
out.write(seq_hdr.dav1d);
Ok(())
})()
Expand Down Expand Up @@ -607,7 +555,7 @@ unsafe fn gen_picture(c: &mut Rav1dContext) -> Rav1dResult {
} = mem::take(&mut c.in_0);
let Some(mut r#in) = r#in else { return Ok(()) };
while !r#in.is_empty() {
let len = rav1d_parse_obus(c, &r#in, &props, false);
let len = rav1d_parse_obus(c, &r#in, &props);
if let Ok(len) = len {
r#in.slice_in_place(len..);
}
Expand Down
100 changes: 71 additions & 29 deletions src/obu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::include::dav1d::common::Rav1dDataProps;
use crate::include::dav1d::data::Rav1dData;
use crate::include::dav1d::dav1d::Rav1dDecodeFrameType;
use crate::include::dav1d::headers::DRav1d;
use crate::include::dav1d::headers::Dav1dSequenceHeader;
use crate::include::dav1d::headers::Rav1dAdaptiveBoolean;
use crate::include::dav1d::headers::Rav1dChromaSamplePosition;
use crate::include::dav1d::headers::Rav1dColorPrimaries;
Expand Down Expand Up @@ -59,6 +60,7 @@ use crate::src::cdf::rav1d_cdf_thread_unref;
use crate::src::decode::rav1d_submit_frame;
use crate::src::env::get_poc_diff;
use crate::src::error::Rav1dError::EINVAL;
use crate::src::error::Rav1dError::ENOENT;
use crate::src::error::Rav1dError::ERANGE;
use crate::src::error::Rav1dResult;
use crate::src::getbits::GetBits;
Expand Down Expand Up @@ -130,7 +132,10 @@ impl Debug {
}
}

fn parse_seq_hdr(c: &mut Rav1dContext, gb: &mut GetBits) -> Rav1dResult<Rav1dSequenceHeader> {
fn parse_seq_hdr(
gb: &mut GetBits,
strict_std_compliance: bool,
) -> Rav1dResult<Rav1dSequenceHeader> {
let debug = Debug::new(false, "SEQHDR", gb);

let profile = Rav1dProfile::from_repr(gb.get_bits(3) as usize).ok_or(EINVAL)?;
Expand Down Expand Up @@ -182,7 +187,7 @@ fn parse_seq_hdr(c: &mut Rav1dContext, gb: &mut GetBits) -> Rav1dResult<Rav1dSeq
if timing_info_present != 0 {
num_units_in_tick = gb.get_bits(32) as c_int;
time_scale = gb.get_bits(32) as c_int;
if c.strict_std_compliance && (num_units_in_tick == 0 || time_scale == 0) {
if strict_std_compliance && (num_units_in_tick == 0 || time_scale == 0) {
return Err(EINVAL);
}
equal_picture_interval = gb.get_bit() as c_int;
Expand All @@ -201,7 +206,7 @@ fn parse_seq_hdr(c: &mut Rav1dContext, gb: &mut GetBits) -> Rav1dResult<Rav1dSeq
if decoder_model_info_present != 0 {
encoder_decoder_buffer_delay_length = gb.get_bits(5) as c_int + 1;
num_units_in_decoding_tick = gb.get_bits(32) as c_int;
if c.strict_std_compliance && num_units_in_decoding_tick == 0 {
if strict_std_compliance && num_units_in_decoding_tick == 0 {
return Err(EINVAL);
}
buffer_removal_delay_length = gb.get_bits(5) as c_int + 1;
Expand Down Expand Up @@ -263,19 +268,6 @@ fn parse_seq_hdr(c: &mut Rav1dContext, gb: &mut GetBits) -> Rav1dResult<Rav1dSeq
debug.post(gb, "operating-points");
}

let op_idx = if c.operating_point < num_operating_points {
c.operating_point
} else {
0
};
c.operating_point_idc = operating_points[op_idx as usize].idc as c_uint;
let spatial_mask = c.operating_point_idc >> 8;
c.max_spatial_id = if spatial_mask != 0 {
ulog2(spatial_mask) != 0
} else {
false
};

let width_n_bits = gb.get_bits(4) as c_int + 1;
let height_n_bits = gb.get_bits(4) as c_int + 1;
let max_width = gb.get_bits(width_n_bits) as c_int + 1;
Expand Down Expand Up @@ -468,7 +460,7 @@ fn parse_seq_hdr(c: &mut Rav1dContext, gb: &mut GetBits) -> Rav1dResult<Rav1dSeq
Rav1dChromaSamplePosition::Unknown
};
}
if c.strict_std_compliance
if strict_std_compliance
&& mtrx == Rav1dMatrixCoefficients::IDENTITY
&& layout != Rav1dPixelLayout::I444
{
Expand Down Expand Up @@ -549,6 +541,50 @@ fn parse_seq_hdr(c: &mut Rav1dContext, gb: &mut GetBits) -> Rav1dResult<Rav1dSeq
})
}

pub(crate) unsafe fn rav1d_parse_sequence_header(
mut data: &[u8],
) -> Rav1dResult<DRav1d<Rav1dSequenceHeader, Dav1dSequenceHeader>> {
let mut res = Err(ENOENT);

while !data.is_empty() {
let mut gb = GetBits::new(data);

gb.get_bit(); // obu_forbidden_bit
let r#type = Rav1dObuType::from_repr(gb.get_bits(4) as usize);
let has_extension = gb.get_bit();
let has_length_field = gb.get_bit();
gb.get_bits(1 + has_extension as i32 * 8); // reserved

// obu length field
let obu_end = if has_length_field {
let len = gb.get_uleb128() as usize;
if len > data.len() {
return Err(EINVAL);
}
gb.pos() / u8::BITS as usize + len
} else {
data.len()
};

if r#type == Some(Rav1dObuType::SeqHdr) {
res = Ok(parse_seq_hdr(&mut gb, false)?);
if gb.pos() > obu_end * u8::BITS as usize {
return Err(EINVAL);
}
gb.bytealign();
}

if gb.has_error() != 0 {
return Err(EINVAL);
}
assert_eq!(gb.has_pending_bits(), false);

data = &data[obu_end..]
}

res.map(DRav1d::from_rav1d)
}

unsafe fn parse_frame_size(
c: &Rav1dContext,
seqhdr: &Rav1dSequenceHeader,
Expand Down Expand Up @@ -2102,7 +2138,6 @@ unsafe fn parse_obus(
c: &mut Rav1dContext,
r#in: &CArc<[u8]>,
props: &Rav1dDataProps,
global: bool,
) -> Rav1dResult<usize> {
unsafe fn skip(c: &mut Rav1dContext, len: usize, init_byte_pos: usize) -> usize {
// update refs with only the headers in case we skip the frame
Expand Down Expand Up @@ -2225,12 +2260,26 @@ unsafe fn parse_obus(

match r#type {
Some(Rav1dObuType::SeqHdr) => {
let seq_hdr = parse_seq_hdr(c, &mut gb).inspect_err(|_| {
let seq_hdr = parse_seq_hdr(&mut gb, c.strict_std_compliance).inspect_err(|_| {
writeln!(c.logger, "Error parsing sequence header");
})?;
if check_for_overrun(c, &mut gb, init_bit_pos, len) != 0 {
return Err(EINVAL);
}

let op_idx = if c.operating_point < seq_hdr.num_operating_points {
c.operating_point
} else {
0
};
c.operating_point_idc = seq_hdr.operating_points[op_idx as usize].idc as c_uint;
let spatial_mask = c.operating_point_idc >> 8;
c.max_spatial_id = if spatial_mask != 0 {
ulog2(spatial_mask) != 0
} else {
false
};

// If we have read a sequence header which is different from the old one,
// this is a new video sequence and can't use any previous state.
// Free that state.
Expand Down Expand Up @@ -2270,8 +2319,6 @@ unsafe fn parse_obus(
c.seq_hdr = Some(Arc::new(DRav1d::from_rav1d(seq_hdr))); // TODO(kkysen) fallible allocation
}
Some(Rav1dObuType::RedundantFrameHdr) if c.frame_hdr.is_some() => {}
Some(Rav1dObuType::RedundantFrameHdr | Rav1dObuType::Frame | Rav1dObuType::FrameHdr)
if global => {}
Some(Rav1dObuType::RedundantFrameHdr | Rav1dObuType::Frame | Rav1dObuType::FrameHdr) => {
c.frame_hdr = None;
// TODO(kkysen) C originally re-used this allocation,
Expand Down Expand Up @@ -2323,15 +2370,11 @@ unsafe fn parse_obus(
// There's no trailing bit at the end to skip,
// but we do need to align to the next byte.
gb.bytealign();
if !global {
parse_tile_grp(c, r#in, props, &mut gb, init_bit_pos, init_byte_pos, len)?;
}
parse_tile_grp(c, r#in, props, &mut gb, init_bit_pos, init_byte_pos, len)?;
}
}
Some(Rav1dObuType::TileGrp) => {
if !global {
parse_tile_grp(c, r#in, props, &mut gb, init_bit_pos, init_byte_pos, len)?;
}
parse_tile_grp(c, r#in, props, &mut gb, init_bit_pos, init_byte_pos, len)?;
}
Some(Rav1dObuType::Metadata) => {
let debug = Debug::new(false, "OBU", &gb);
Expand Down Expand Up @@ -2631,9 +2674,8 @@ pub(crate) unsafe fn rav1d_parse_obus(
c: &mut Rav1dContext,
r#in: &CArc<[u8]>,
props: &Rav1dDataProps,
global: bool,
) -> Rav1dResult<usize> {
parse_obus(c, r#in, props, global).inspect_err(|_| {
parse_obus(c, r#in, props).inspect_err(|_| {
*c.cached_error_props.get_mut().unwrap() = props.clone();
writeln!(c.logger, "Error parsing OBU data");
})
Expand Down

0 comments on commit b806651

Please sign in to comment.