diff --git a/include/dav1d/picture.rs b/include/dav1d/picture.rs index cc2104470..91e0e8cc3 100644 --- a/include/dav1d/picture.rs +++ b/include/dav1d/picture.rs @@ -17,7 +17,6 @@ use crate::src::c_arc::RawArc; use crate::src::error::Dav1dResult; use crate::src::error::Rav1dError; use crate::src::error::Rav1dError::EINVAL; -use crate::src::error::Rav1dResult; use crate::src::r#ref::Rav1dRef; use libc::ptrdiff_t; use libc::uintptr_t; @@ -30,6 +29,7 @@ use std::sync::Arc; pub(crate) const RAV1D_PICTURE_ALIGNMENT: usize = 64; pub const DAV1D_PICTURE_ALIGNMENT: usize = RAV1D_PICTURE_ALIGNMENT; +#[derive(Default)] #[repr(C)] pub struct Dav1dPictureParameters { pub w: c_int, @@ -72,11 +72,12 @@ impl From for Dav1dPictureParameters { } } +#[derive(Default)] #[repr(C)] pub struct Dav1dPicture { pub seq_hdr: Option>, pub frame_hdr: Option>, - pub data: [*mut c_void; 3], + pub data: [Option>; 3], pub stride: [ptrdiff_t; 2], pub p: Dav1dPictureParameters, pub m: Dav1dDataProps, @@ -90,24 +91,43 @@ pub struct Dav1dPicture { pub mastering_display_ref: Option>, // opaque, so we can change this pub itut_t35_ref: Option>>, // opaque, so we can change this pub reserved_ref: [uintptr_t; 4], - pub r#ref: *mut Dav1dRef, - pub allocator_data: *mut c_void, + pub r#ref: Option>, + pub allocator_data: Option>, } #[derive(Clone)] +pub(crate) struct Rav1dPictureData { + pub data: [*mut c_void; 3], + pub allocator_data: Option>, +} + +impl Default for Rav1dPictureData { + fn default() -> Self { + Self { + data: [ptr::null_mut(); 3], + allocator_data: Default::default(), + } + } +} + +// TODO(kkysen) Eventually the [`impl Default`] might not be needed. +// It's needed currently for a [`mem::take`] that simulates a move, +// but once everything is Rusty, we may not need to clear the `dst` anymore. +// This also applies to the `#[derive(Default)]` +// on [`Rav1dPictureParameters`] and [`Rav1dPixelLayout`]. +#[derive(Clone, Default)] #[repr(C)] pub(crate) struct Rav1dPicture { pub seq_hdr: Option>>, pub frame_hdr: Option>>, - pub data: [*mut c_void; 3], + pub data: Rav1dPictureData, pub stride: [ptrdiff_t; 2], pub p: Rav1dPictureParameters, pub m: Rav1dDataProps, pub content_light: Option>, pub mastering_display: Option>, pub itut_t35: Option>>, - pub r#ref: *mut Rav1dRef, - pub allocator_data: *mut c_void, + pub r#ref: Option>, } impl From for Rav1dPicture { @@ -139,7 +159,10 @@ impl From for Rav1dPicture { // We don't `.update_rav1d()` [`Rav1dFrameHeader`] because it's meant to be read-only. // Safety: `raw` came from [`RawArc::from_arc`]. frame_hdr: frame_hdr_ref.map(|raw| unsafe { raw.into_arc() }), - data, + data: Rav1dPictureData { + data: data.map(|data| data.map_or_else(ptr::null_mut, NonNull::as_ptr)), + allocator_data, + }, stride, p: p.into(), m: m.into(), @@ -151,7 +174,6 @@ impl From for Rav1dPicture { // Safety: `raw` came from [`RawArc::from_arc`]. itut_t35: itut_t35_ref.map(|raw| unsafe { raw.into_arc() }), r#ref, - allocator_data, } } } @@ -161,7 +183,11 @@ impl From for Dav1dPicture { let Rav1dPicture { seq_hdr, frame_hdr, - data, + data: + Rav1dPictureData { + data, + allocator_data, + }, stride, p, m, @@ -169,14 +195,13 @@ impl From for Dav1dPicture { mastering_display, itut_t35, r#ref, - allocator_data, } = value; Self { // [`DRav1d::from_rav1d`] is called right after [`parse_seq_hdr`]. seq_hdr: seq_hdr.as_ref().map(|arc| (&arc.as_ref().dav1d).into()), // [`DRav1d::from_rav1d`] is called in [`parse_frame_hdr`]. frame_hdr: frame_hdr.as_ref().map(|arc| (&arc.as_ref().dav1d).into()), - data, + data: data.map(NonNull::new), stride, p: p.into(), m: m.into(), @@ -197,29 +222,6 @@ impl From for Dav1dPicture { } } -// TODO(kkysen) Eventually the [`impl Default`] might not be needed. -// It's needed currently for a [`mem::take`] that simulates a move, -// but once everything is Rusty, we may not need to clear the `dst` anymore. -// This also applies to the `#[derive(Default)]` -// on [`Rav1dPictureParameters`] and [`Rav1dPixelLayout`]. -impl Default for Rav1dPicture { - fn default() -> Self { - Self { - seq_hdr: None, - frame_hdr: None, - data: [ptr::null_mut(); 3], - stride: Default::default(), - p: Default::default(), - m: Default::default(), - content_light: None, - mastering_display: None, - itut_t35: None, - r#ref: ptr::null_mut(), - allocator_data: ptr::null_mut(), - } - } -} - #[derive(Clone)] #[repr(C)] pub struct Dav1dPicAllocator { @@ -248,6 +250,14 @@ pub struct Dav1dPicAllocator { /// with a custom pointer that will be passed to /// [`release_picture_callback`]. /// + /// The only fields of `pic` that will be already set are: + /// * [`Dav1dPicture::p`] + /// * [`Dav1dPicture::seq_hdr`] + /// * [`Dav1dPicture::frame_hdr`] + /// + /// This is not a change from the original `DAV1D_API`, + /// just a clarification of it. + /// /// * `cookie`: Custom pointer passed to all calls. /// /// *Note*: No fields other than [`data`], [`stride`] and [`allocator_data`] @@ -279,6 +289,23 @@ pub struct Dav1dPicAllocator { /// # Args /// /// * `pic`: The picture that was filled by [`alloc_picture_callback`]. + /// + /// The only fields of `pic` that will be set are + /// the ones allocated by [`Self::alloc_picture_callback`]: + /// * [`Dav1dPicture::data`] + /// * [`Dav1dPicture::allocator_data`] + /// + /// NOTE: This is a slight change from the original `DAV1D_API`, which was underspecified. + /// However, all known uses of this API follow this already: + /// * `libdav1d`: [`dav1d_default_picture_release`](https://code.videolan.org/videolan/dav1d/-/blob/16ed8e8b99f2fcfffe016e929d3626e15267ad3e/src/picture.c#L85-87) + /// * `dav1d`: [`picture_release`](https://code.videolan.org/videolan/dav1d/-/blob/16ed8e8b99f2fcfffe016e929d3626e15267ad3e/tools/dav1d.c#L180-182) + /// * `dav1dplay`: [`placebo_release_pic`](https://code.videolan.org/videolan/dav1d/-/blob/16ed8e8b99f2fcfffe016e929d3626e15267ad3e/examples/dp_renderer_placebo.c#L375-383) + /// * `libplacebo`: [`pl_release_dav1dpicture`](https://github.com/haasn/libplacebo/blob/34e019bfedaa5a64f268d8f9263db352c0a8f67f/src/include/libplacebo/utils/dav1d_internal.h#L594-L607) + /// * `ffmpeg`: [`libdav1d_picture_release`](https://github.com/FFmpeg/FFmpeg/blob/00b288da73f45acb78b74bcc40f73c7ba1fff7cb/libavcodec/libdav1d.c#L124-L129) + /// + /// Making this API safe without this slight tightening of the API + /// [is very difficult](https://github.com/memorysafety/rav1d/pull/685#discussion_r1458171639). + /// /// * `cookie`: Custom pointer passed to all calls. /// /// [`dav1d_get_picture`]: crate::src::lib::dav1d_get_picture @@ -343,18 +370,3 @@ impl From for Dav1dPicAllocator { } } } - -impl Rav1dPicAllocator { - pub unsafe fn alloc_picture(&self, p: *mut Rav1dPicture) -> Rav1dResult { - let mut p_c = p.read().into(); - let result = (self.alloc_picture_callback)(&mut p_c, self.cookie); - p.write(p_c.into()); - result.try_into().unwrap() - } - - pub unsafe fn release_picture(&self, p: *mut Rav1dPicture) { - let mut p_c = p.read().into(); - (self.release_picture_callback)(&mut p_c, self.cookie); - p.write(p_c.into()); - } -} diff --git a/src/decode.rs b/src/decode.rs index e7dadf832..67f87cac9 100644 --- a/src/decode.rs +++ b/src/decode.rs @@ -4674,8 +4674,8 @@ pub(crate) unsafe fn rav1d_decode_frame_init(f: &mut Rav1dFrameContext) -> Rav1d // what they point at, as long as the pointers are valid. let has_chroma = (f.cur.p.layout != Rav1dPixelLayout::I400) as usize; f.lf.mask_ptr = f.lf.mask; - f.lf.p = array::from_fn(|i| f.cur.data[has_chroma * i].cast()); - f.lf.sr_p = array::from_fn(|i| f.sr_cur.p.data[has_chroma * i].cast()); + f.lf.p = array::from_fn(|i| f.cur.data.data[has_chroma * i].cast()); + f.lf.sr_p = array::from_fn(|i| f.sr_cur.p.data.data[has_chroma * i].cast()); Ok(()) } @@ -4849,7 +4849,7 @@ unsafe fn rav1d_decode_frame_main(f: &mut Rav1dFrameContext) -> Rav1dResult { pub(crate) unsafe fn rav1d_decode_frame_exit(f: &mut Rav1dFrameContext, retval: Rav1dResult) { let c = &*f.c; - if !f.sr_cur.p.data[0].is_null() { + if !f.sr_cur.p.data.data[0].is_null() { f.task_thread.error = AtomicI32::new(0); } if c.n_fc > 1 && retval.is_err() && !f.frame_thread.cf.is_null() { @@ -4953,7 +4953,8 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { pthread_cond_wait(&mut f.task_thread.cond, &mut c.task_thread.lock); } let out_delayed = &mut *c.frame_thread.out_delayed.offset(next as isize); - if !out_delayed.p.data[0].is_null() || f.task_thread.error.load(Ordering::SeqCst) != 0 { + if !out_delayed.p.data.data[0].is_null() || f.task_thread.error.load(Ordering::SeqCst) != 0 + { let first = c.task_thread.first.load(Ordering::SeqCst); if first + 1 < c.n_fc { c.task_thread.first.fetch_add(1, Ordering::SeqCst); @@ -4976,7 +4977,7 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { c.cached_error = error; c.cached_error_props = out_delayed.p.m.clone(); rav1d_thread_picture_unref(out_delayed); - } else if !out_delayed.p.data[0].is_null() { + } else if !out_delayed.p.data.data[0].is_null() { let progress = out_delayed.progress.as_ref().unwrap()[1].load(Ordering::Relaxed); if (out_delayed.visible || c.output_invisible_frames) && progress != FRAME_ERROR { rav1d_thread_picture_ref(&mut c.out, out_delayed); @@ -5091,14 +5092,14 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { if frame_hdr.frame_type.is_inter_or_switch() { if frame_hdr.primary_ref_frame != RAV1D_PRIMARY_REF_NONE { let pri_ref = frame_hdr.refidx[frame_hdr.primary_ref_frame as usize] as usize; - if c.refs[pri_ref].p.p.data[0].is_null() { + if c.refs[pri_ref].p.p.data.data[0].is_null() { on_error(f, c, out_delayed); return Err(EINVAL); } } for i in 0..7 { let refidx = frame_hdr.refidx[i] as usize; - if c.refs[refidx].p.p.data[0].is_null() + if c.refs[refidx].p.p.data.data[0].is_null() || (frame_hdr.size.width[0] * 2) < c.refs[refidx].p.p.p.w || (frame_hdr.size.height * 2) < c.refs[refidx].p.p.p.h || frame_hdr.size.width[0] > c.refs[refidx].p.p.p.w * 16 diff --git a/src/fg_apply.rs b/src/fg_apply.rs index 39f87c700..922e64286 100644 --- a/src/fg_apply.rs +++ b/src/fg_apply.rs @@ -119,16 +119,16 @@ pub(crate) unsafe fn rav1d_prep_grain( let sz = out.p.h as isize * stride; if sz < 0 { memcpy( - (out.data[0] as *mut u8) + (out.data.data[0] as *mut u8) .offset(sz as isize) .offset(-(stride as isize)) as *mut c_void, - (r#in.data[0] as *mut u8) + (r#in.data.data[0] as *mut u8) .offset(sz as isize) .offset(-(stride as isize)) as *const c_void, -sz as usize, ); } else { - memcpy(out.data[0], r#in.data[0], sz as usize); + memcpy(out.data.data[0], r#in.data.data[0], sz as usize); } } @@ -140,10 +140,10 @@ pub(crate) unsafe fn rav1d_prep_grain( if sz < 0 { if data.num_uv_points[0] == 0 { memcpy( - (out.data[1] as *mut u8) + (out.data.data[1] as *mut u8) .offset(sz as isize) .offset(-(stride as isize)) as *mut c_void, - (r#in.data[1] as *mut u8) + (r#in.data.data[1] as *mut u8) .offset(sz as isize) .offset(-(stride as isize)) as *const c_void, -sz as usize, @@ -151,10 +151,10 @@ pub(crate) unsafe fn rav1d_prep_grain( } if data.num_uv_points[1] == 0 { memcpy( - (out.data[2] as *mut u8) + (out.data.data[2] as *mut u8) .offset(sz as isize) .offset(-(stride as isize)) as *mut c_void, - (r#in.data[2] as *mut u8) + (r#in.data.data[2] as *mut u8) .offset(sz as isize) .offset(-(stride as isize)) as *const c_void, -sz as usize, @@ -162,10 +162,10 @@ pub(crate) unsafe fn rav1d_prep_grain( } } else { if data.num_uv_points[0] == 0 { - memcpy(out.data[1], r#in.data[1], sz as usize); + memcpy(out.data.data[1], r#in.data.data[1], sz as usize); } if data.num_uv_points[1] == 0 { - memcpy(out.data[2], r#in.data[2], sz as usize); + memcpy(out.data.data[2], r#in.data.data[2], sz as usize); } } } @@ -188,7 +188,7 @@ pub(crate) unsafe fn rav1d_apply_grain_row( let ss_x = (r#in.p.layout != Rav1dPixelLayout::I444) as usize; let cpw = out.p.w as usize + ss_x >> ss_x; let is_id = seq_hdr.mtrx == RAV1D_MC_IDENTITY; - let luma_src = (r#in.data[0] as *mut BD::Pixel) + let luma_src = (r#in.data.data[0] as *mut BD::Pixel) .offset(((row * 32) as isize * BD::pxstride(r#in.stride[0] as usize) as isize) as isize); let bitdepth_max = (1 << out.p.bpc) - 1; let bd = BD::from_c(bitdepth_max); @@ -196,7 +196,7 @@ pub(crate) unsafe fn rav1d_apply_grain_row( if data.num_y_points != 0 { let bh = cmp::min(out.p.h as usize - row * 32, 32); dsp.fgy_32x32xn.call( - (out.data[0] as *mut BD::Pixel).offset( + (out.data.data[0] as *mut BD::Pixel).offset( ((row * 32) as isize * BD::pxstride(out.stride[0] as usize) as isize) as isize, ), luma_src.cast(), @@ -230,8 +230,8 @@ pub(crate) unsafe fn rav1d_apply_grain_row( if data.chroma_scaling_from_luma { for pl in 0..2 { dsp.fguv_32x32xn[r#in.p.layout.try_into().unwrap()].call( - (out.data[1 + pl] as *mut BD::Pixel).offset(uv_off as isize), - (r#in.data[1 + pl] as *const BD::Pixel).offset(uv_off as isize), + (out.data.data[1 + pl] as *mut BD::Pixel).offset(uv_off as isize), + (r#in.data.data[1 + pl] as *const BD::Pixel).offset(uv_off as isize), r#in.stride[1], data, cpw, @@ -250,8 +250,8 @@ pub(crate) unsafe fn rav1d_apply_grain_row( for pl in 0..2 { if data.num_uv_points[pl] != 0 { dsp.fguv_32x32xn[r#in.p.layout.try_into().unwrap()].call( - (out.data[1 + pl] as *mut BD::Pixel).offset(uv_off as isize), - (r#in.data[1 + pl] as *const BD::Pixel).offset(uv_off as isize), + (out.data.data[1 + pl] as *mut BD::Pixel).offset(uv_off as isize), + (r#in.data.data[1 + pl] as *const BD::Pixel).offset(uv_off as isize), r#in.stride[1], data_c, cpw, diff --git a/src/lib.rs b/src/lib.rs index 3c0e598d0..ca39c9ab6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -568,7 +568,7 @@ unsafe fn output_image(c: &mut Rav1dContext, out: &mut Rav1dPicture) -> Rav1dRes } rav1d_thread_picture_unref(r#in); - if !c.all_layers && c.max_spatial_id && !(c.out.p.data[0]).is_null() { + if !c.all_layers && c.max_spatial_id && !(c.out.p.data.data[0]).is_null() { rav1d_thread_picture_move_ref(r#in, &mut c.out); } res @@ -579,7 +579,7 @@ unsafe fn output_picture_ready(c: &mut Rav1dContext, drain: bool) -> bool { return true; } if !c.all_layers && c.max_spatial_id { - if !c.out.p.data[0].is_null() && !c.cache.p.data[0].is_null() { + if !c.out.p.data.data[0].is_null() && !c.cache.p.data.data[0].is_null() { if c.max_spatial_id == (c.cache.p.frame_hdr.as_ref().unwrap().spatial_id != 0) || c.out.flags.contains(PictureFlags::NEW_TEMPORAL_UNIT) { @@ -589,17 +589,17 @@ unsafe fn output_picture_ready(c: &mut Rav1dContext, drain: bool) -> bool { rav1d_thread_picture_move_ref(&mut c.cache, &mut c.out); return false; } else { - if !c.cache.p.data[0].is_null() && drain { + if !c.cache.p.data.data[0].is_null() && drain { return true; } else { - if !c.out.p.data[0].is_null() { + if !c.out.p.data.data[0].is_null() { rav1d_thread_picture_move_ref(&mut c.cache, &mut c.out); return false; } } } } - !c.out.p.data[0].is_null() + !c.out.p.data.data[0].is_null() } unsafe fn drain_picture(c: &mut Rav1dContext, out: &mut Rav1dPicture) -> Rav1dResult { @@ -618,7 +618,7 @@ unsafe fn drain_picture(c: &mut Rav1dContext, out: &mut Rav1dPicture) -> Rav1dRe } let out_delayed: *mut Rav1dThreadPicture = &mut *(c.frame_thread.out_delayed).offset(next as isize) as *mut Rav1dThreadPicture; - if !((*out_delayed).p.data[0]).is_null() + if !((*out_delayed).p.data.data[0]).is_null() || (*f).task_thread.error.load(Ordering::SeqCst) != 0 { let first: c_uint = c.task_thread.first.load(Ordering::SeqCst); @@ -653,7 +653,7 @@ unsafe fn drain_picture(c: &mut Rav1dContext, out: &mut Rav1dPicture) -> Rav1dRe rav1d_thread_picture_unref(out_delayed); return error; } - if !((*out_delayed).p.data[0]).is_null() { + if !((*out_delayed).p.data.data[0]).is_null() { let progress = (*out_delayed).progress.as_ref().unwrap()[1].load(Ordering::Relaxed); if ((*out_delayed).visible || c.output_invisible_frames) && progress != FRAME_ERROR { rav1d_thread_picture_ref(&mut c.out, out_delayed); diff --git a/src/obu.rs b/src/obu.rs index 5ff4aa249..bf90105f1 100644 --- a/src/obu.rs +++ b/src/obu.rs @@ -2495,7 +2495,7 @@ unsafe fn parse_obus( } _ => {} } - if c.refs[frame_hdr.existing_frame_idx as usize].p.p.data[0].is_null() { + if c.refs[frame_hdr.existing_frame_idx as usize].p.p.data.data[0].is_null() { return Err(EINVAL); } if c.strict_std_compliance && !c.refs[frame_hdr.existing_frame_idx as usize].p.showable @@ -2533,7 +2533,7 @@ unsafe fn parse_obus( ); } let out_delayed = &mut *c.frame_thread.out_delayed.offset(next as isize); - if !(*out_delayed).p.data[0].is_null() + if !(*out_delayed).p.data.data[0].is_null() || (*f).task_thread.error.load(Ordering::SeqCst) != 0 { let first = c.task_thread.first.load(Ordering::SeqCst); @@ -2558,7 +2558,7 @@ unsafe fn parse_obus( (*f).task_thread.retval = Ok(()); c.cached_error_props = (*out_delayed).p.m.clone(); rav1d_thread_picture_unref(out_delayed); - } else if !((*out_delayed).p.data[0]).is_null() { + } else if !((*out_delayed).p.data.data[0]).is_null() { let progress = (*out_delayed).progress.as_ref().unwrap()[1].load(Ordering::Relaxed); if ((*out_delayed).visible || c.output_invisible_frames) diff --git a/src/picture.rs b/src/picture.rs index 820703532..54fdb3d2b 100644 --- a/src/picture.rs +++ b/src/picture.rs @@ -14,6 +14,7 @@ use crate::include::dav1d::headers::Rav1dSequenceHeader; use crate::include::dav1d::picture::Dav1dPicture; use crate::include::dav1d::picture::Rav1dPicAllocator; use crate::include::dav1d::picture::Rav1dPicture; +use crate::include::dav1d::picture::Rav1dPictureData; use crate::include::dav1d::picture::Rav1dPictureParameters; use crate::include::dav1d::picture::RAV1D_PICTURE_ALIGNMENT; use crate::src::error::Dav1dResult; @@ -34,14 +35,12 @@ use crate::src::r#ref::rav1d_ref_wrap; use atomig::Atom; use atomig::AtomLogic; use bitflags::bitflags; -use libc::free; -use libc::malloc; use libc::ptrdiff_t; use std::ffi::c_int; use std::ffi::c_void; -use std::io; use std::mem; use std::ptr; +use std::ptr::NonNull; use std::slice; use std::sync::atomic::AtomicU32; use std::sync::atomic::Ordering; @@ -121,7 +120,6 @@ pub unsafe extern "C" fn dav1d_default_picture_alloc( if buf.is_null() { return Rav1dResult::<()>::Err(ENOMEM).into(); } - p.allocator_data = buf as *mut c_void; let data = slice::from_raw_parts_mut((*buf).data as *mut u8, pic_size); let (data0, data12) = data.split_at_mut(y_sz); @@ -129,7 +127,11 @@ pub unsafe extern "C" fn dav1d_default_picture_alloc( // Note that `data[1]` and `data[2]` // were previously null instead of an empty slice when `!has_chroma`, // but this way is simpler and more uniform, especially when we move to slices. - p.data = [data0, data1, data2].map(|data| data.as_mut_ptr().cast()); + let data = [data0, data1, data2].map(|data| data.as_mut_ptr().cast()); + p.data = Rav1dPictureData { + data, + allocator_data: NonNull::new(buf.cast()), + }; p_c.write(p.into()); Rav1dResult::Ok(()).into() } @@ -137,7 +139,8 @@ pub unsafe extern "C" fn dav1d_default_picture_alloc( pub unsafe extern "C" fn dav1d_default_picture_release(p: *mut Dav1dPicture, cookie: *mut c_void) { rav1d_mem_pool_push( cookie as *mut Rav1dMemPool, - (*p).allocator_data as *mut Rav1dMemPoolBuffer, + (*p).allocator_data + .map_or_else(ptr::null_mut, |data| data.as_ptr()) as *mut Rav1dMemPoolBuffer, ); } @@ -153,8 +156,72 @@ impl Default for Rav1dPicAllocator { unsafe extern "C" fn free_buffer(_data: *const u8, user_data: *mut c_void) { let pic_ctx: *mut pic_ctx_context = user_data as *mut pic_ctx_context; - (*pic_ctx).allocator.release_picture(&mut (*pic_ctx).pic); - free(pic_ctx as *mut c_void); + let pic_ctx = Box::from_raw(pic_ctx); + let data = &pic_ctx.pic.data; + pic_ctx + .allocator + .dealloc_picture_data(data.data, data.allocator_data); +} + +impl Rav1dPicAllocator { + pub fn alloc_picture_data( + &self, + w: c_int, + h: c_int, + seq_hdr: Arc>, + frame_hdr: Option>>, + ) -> Rav1dResult { + let pic = Rav1dPicture { + p: Rav1dPictureParameters { + w, + h, + layout: seq_hdr.layout, + bpc: 8 + 2 * seq_hdr.hbd, + }, + seq_hdr: Some(seq_hdr), + frame_hdr, + ..Default::default() + }; + let mut pic_c = pic.to::(); + // Safety: `pic_c` is a valid `Dav1dPicture` with `data`, `stride`, `allocator_data` unset. + let result = unsafe { (self.alloc_picture_callback)(&mut pic_c, self.cookie) }; + result.try_to::().unwrap()?; + let mut pic = pic_c.to::(); + + let pic_ctx = Box::new(pic_ctx_context { + allocator: self.clone(), + pic: pic.clone(), + }); + // Safety: TODO(kkysen) Will be replaced by an `Arc` shortly. + pic.r#ref = NonNull::new(unsafe { + rav1d_ref_wrap( + pic.data.data[0] as *const u8, + Some(free_buffer), + Box::into_raw(pic_ctx).cast(), + ) + }); + assert!(pic.r#ref.is_some()); // TODO(kkysen) Will be removed soon anyways. + + Ok(pic) + } + + pub fn dealloc_picture_data( + &self, + data: [*mut c_void; 3], + allocator_data: Option>, + ) { + let data = data.map(NonNull::new); + let mut pic_c = Dav1dPicture { + data, + allocator_data, + ..Default::default() + }; + // Safety: `pic_c` contains the same `data` and `allocator_data` + // that `Self::alloc_picture_data` set, which now get deallocated here. + unsafe { + (self.release_picture_callback)(&mut pic_c, self.cookie); + } + } } unsafe fn picture_alloc_with_edges( @@ -171,50 +238,14 @@ unsafe fn picture_alloc_with_edges( props: Rav1dDataProps, p_allocator: &Rav1dPicAllocator, ) -> Rav1dResult { - if !p.data[0].is_null() { + if !p.data.data[0].is_null() { writeln!(logger, "Picture already allocated!",); return Err(EGeneric); } assert!(bpc > 0 && bpc <= 16); - let pic_ctx: *mut pic_ctx_context = - malloc(::core::mem::size_of::()) as *mut pic_ctx_context; - if pic_ctx.is_null() { - return Err(ENOMEM); - } - p.p = Rav1dPictureParameters { - w, - h, - layout: seq_hdr.as_ref().unwrap().layout, - bpc, - }; - p.seq_hdr = seq_hdr; - p.frame_hdr = frame_hdr; - p.m = Default::default(); - let res = p_allocator.alloc_picture(p); - if res.is_err() { - free(pic_ctx as *mut c_void); - return res; - } - pic_ctx.write(pic_ctx_context { - allocator: p_allocator.clone(), - pic: p.clone(), - }); - p.r#ref = rav1d_ref_wrap( - p.data[0] as *const u8, - Some(free_buffer), - pic_ctx as *mut c_void, - ); - if p.r#ref.is_null() { - p_allocator.release_picture(p); - free(pic_ctx as *mut c_void); - writeln!( - logger, - "Failed to wrap picture: {}", - io::Error::last_os_error(), - ); - return Err(ENOMEM); - } - rav1d_picture_copy_props(p, content_light, mastering_display, itut_t35, props); + let mut pic = p_allocator.alloc_picture_data(w, h, seq_hdr.unwrap(), frame_hdr)?; + rav1d_picture_copy_props(&mut pic, content_light, mastering_display, itut_t35, props); + *p = pic; Ok(()) } @@ -276,7 +307,8 @@ pub(crate) unsafe fn rav1d_picture_alloc_copy( w: c_int, src: &Rav1dPicture, ) -> Rav1dResult { - let pic_ctx: *mut pic_ctx_context = (*(*src).r#ref).user_data as *mut pic_ctx_context; + let pic_ctx: *mut pic_ctx_context = + (*src).r#ref.unwrap().as_mut().user_data as *mut pic_ctx_context; picture_alloc_with_edges( &c.logger, dst, @@ -294,24 +326,24 @@ pub(crate) unsafe fn rav1d_picture_alloc_copy( } pub(crate) unsafe fn rav1d_picture_ref(dst: &mut Rav1dPicture, src: &Rav1dPicture) { - if validate_input!(dst.data[0].is_null()).is_err() { + if validate_input!(dst.data.data[0].is_null()).is_err() { return; } - if !src.r#ref.is_null() { - if validate_input!(!src.data[0].is_null()).is_err() { + if let Some(r#ref) = src.r#ref { + if validate_input!(!src.data.data[0].is_null()).is_err() { return; } - rav1d_ref_inc(src.r#ref); + rav1d_ref_inc(r#ref.as_ptr()); } *dst = src.clone(); } pub(crate) unsafe fn rav1d_picture_move_ref(dst: &mut Rav1dPicture, src: &mut Rav1dPicture) { - if validate_input!(dst.data[0].is_null()).is_err() { + if validate_input!(dst.data.data[0].is_null()).is_err() { return; } - if !src.r#ref.is_null() { - if validate_input!(!src.data[0].is_null()).is_err() { + if src.r#ref.is_some() { + if validate_input!(!src.data.data[0].is_null()).is_err() { return; } } @@ -337,17 +369,12 @@ pub(crate) unsafe fn rav1d_thread_picture_move_ref( } pub(crate) unsafe fn rav1d_picture_unref_internal(p: &mut Rav1dPicture) { - let Rav1dPicture { - m: _, - data, - mut r#ref, - .. - } = mem::take(p); - if !r#ref.is_null() { - if validate_input!(!data[0].is_null()).is_err() { + let Rav1dPicture { data, r#ref, .. } = mem::take(p); + if let Some(r#ref) = r#ref { + if validate_input!(!data.data[0].is_null()).is_err() { return; } - rav1d_ref_dec(&mut r#ref); + rav1d_ref_dec(&mut r#ref.as_ptr()); } } diff --git a/src/recon.rs b/src/recon.rs index a4e0480a0..606cc8403 100644 --- a/src/recon.rs +++ b/src/recon.rs @@ -2094,7 +2094,7 @@ unsafe fn mc( let dy = by * v_mul + (mvy >> 3 + ss_ver); let w; let h; - if (*refp).p.data[0] != (*f).cur.data[0] { + if (*refp).p.data.data[0] != (*f).cur.data.data[0] { w = (*f).cur.p.w + ss_hor >> ss_hor; h = (*f).cur.p.h + ss_ver >> ss_ver; } else { @@ -2119,7 +2119,7 @@ unsafe fn mc( (192 as c_int as c_ulong) .wrapping_mul(::core::mem::size_of::() as c_ulong) as ptrdiff_t, - (*refp).p.data[pl as usize].cast(), + (*refp).p.data.data[pl as usize].cast(), ref_stride, ); r#ref = &mut *emu_edge_buf @@ -2129,7 +2129,7 @@ unsafe fn mc( .wrapping_mul(::core::mem::size_of::() as c_ulong) as ptrdiff_t; } else { - r#ref = ((*refp).p.data[pl as usize] as *mut BD::Pixel) + r#ref = ((*refp).p.data.data[pl as usize] as *mut BD::Pixel) .offset(BD::pxstride(ref_stride as usize) as isize * dy as isize) .offset(dx as isize); } @@ -2211,7 +2211,7 @@ unsafe fn mc( (320 as c_int as c_ulong) .wrapping_mul(::core::mem::size_of::() as c_ulong) as ptrdiff_t, - (*refp).p.data[pl as usize].cast(), + (*refp).p.data.data[pl as usize].cast(), ref_stride, ); r#ref = &mut *emu_edge_buf.offset((320 * 3 + 3) as isize) as *mut BD::Pixel; @@ -2222,7 +2222,7 @@ unsafe fn mc( printf(b"Emu\n\0" as *const u8 as *const c_char); } } else { - r#ref = ((*refp).p.data[pl as usize] as *mut BD::Pixel) + r#ref = ((*refp).p.data.data[pl as usize] as *mut BD::Pixel) .offset(BD::pxstride(ref_stride as usize) as isize * top as isize) .offset(left as isize); } @@ -2457,7 +2457,7 @@ unsafe fn warp_affine( (32 as c_int as c_ulong) .wrapping_mul(::core::mem::size_of::() as c_ulong) as ptrdiff_t, - (*refp).p.data[pl as usize].cast(), + (*refp).p.data.data[pl as usize].cast(), ref_stride, ); ref_ptr = &mut *emu_edge_buf.offset((32 * 3 + 3) as isize) as *mut BD::Pixel; @@ -2465,7 +2465,7 @@ unsafe fn warp_affine( .wrapping_mul(::core::mem::size_of::() as c_ulong) as ptrdiff_t; } else { - ref_ptr = ((*refp).p.data[pl as usize] as *mut BD::Pixel) + ref_ptr = ((*refp).p.data.data[pl as usize] as *mut BD::Pixel) .offset((BD::pxstride(ref_stride as usize) as isize * dy as isize) as isize) .offset(dx as isize); } @@ -2555,7 +2555,7 @@ pub(crate) unsafe fn rav1d_recon_b_intra( let mut init_x = 0; while init_x < w4 { if b.c2rust_unnamed.c2rust_unnamed.pal_sz[0] != 0 { - let dst: *mut BD::Pixel = ((*f).cur.data[0] as *mut BD::Pixel).offset( + let dst: *mut BD::Pixel = ((*f).cur.data.data[0] as *mut BD::Pixel).offset( (4 * (t.by as isize * BD::pxstride((*f).cur.stride[0] as usize) as isize + t.bx as isize)) as isize, ); @@ -2621,7 +2621,7 @@ pub(crate) unsafe fn rav1d_recon_b_intra( y = init_y; t.by += init_y; while y < sub_h4 { - let mut dst: *mut BD::Pixel = ((*f).cur.data[0] as *mut BD::Pixel).offset( + let mut dst: *mut BD::Pixel = ((*f).cur.data.data[0] as *mut BD::Pixel).offset( (4 * (t.by as isize * BD::pxstride((*f).cur.stride[0] as usize) as isize + t.bx as isize + init_x as isize)) as isize, @@ -2821,7 +2821,7 @@ pub(crate) unsafe fn rav1d_recon_b_intra( unreachable!(); } let ac = &mut t.scratch.c2rust_unnamed_0.ac; - let y_src: *mut BD::Pixel = ((*f).cur.data[0] as *mut BD::Pixel) + let y_src: *mut BD::Pixel = ((*f).cur.data.data[0] as *mut BD::Pixel) .offset((4 * (t.bx & !ss_hor)) as isize) .offset( ((4 * (t.by & !ss_ver)) as isize @@ -2832,8 +2832,8 @@ pub(crate) unsafe fn rav1d_recon_b_intra( * ((t.bx >> ss_hor) as isize + (t.by >> ss_ver) as isize * BD::pxstride(stride as usize) as isize); let uv_dst: [*mut BD::Pixel; 2] = [ - ((*f).cur.data[1] as *mut BD::Pixel).offset(uv_off as isize), - ((*f).cur.data[2] as *mut BD::Pixel).offset(uv_off as isize), + ((*f).cur.data.data[1] as *mut BD::Pixel).offset(uv_off as isize), + ((*f).cur.data.data[2] as *mut BD::Pixel).offset(uv_off as isize), ]; let furthest_r = (cw4 << ss_hor) + (*t_dim).w as c_int - 1 & !((*t_dim).w as c_int - 1); @@ -2942,7 +2942,7 @@ pub(crate) unsafe fn rav1d_recon_b_intra( as *mut u8; } (*(*f).dsp).ipred.pal_pred.call::( - ((*f).cur.data[1] as *mut BD::Pixel).offset(uv_dstoff as isize), + ((*f).cur.data.data[1] as *mut BD::Pixel).offset(uv_dstoff as isize), (*f).cur.stride[1], (*pal.offset(1)).as_ptr(), pal_idx, @@ -2950,7 +2950,7 @@ pub(crate) unsafe fn rav1d_recon_b_intra( cbh4 * 4, ); (*(*f).dsp).ipred.pal_pred.call::( - ((*f).cur.data[2] as *mut BD::Pixel).offset(uv_dstoff as isize), + ((*f).cur.data.data[2] as *mut BD::Pixel).offset(uv_dstoff as isize), (*f).cur.stride[1], (*pal.offset(2)).as_ptr(), pal_idx, @@ -2959,14 +2959,14 @@ pub(crate) unsafe fn rav1d_recon_b_intra( ); if DEBUG_BLOCK_INFO(&*f, t) && 0 != 0 { hex_dump::( - ((*f).cur.data[1] as *mut BD::Pixel).offset(uv_dstoff as isize), + ((*f).cur.data.data[1] as *mut BD::Pixel).offset(uv_dstoff as isize), BD::pxstride((*f).cur.stride[1] as usize), cbw4 as usize * 4, cbh4 as usize * 4, "u-pal-pred", ); hex_dump::( - ((*f).cur.data[2] as *mut BD::Pixel).offset(uv_dstoff as isize), + ((*f).cur.data.data[2] as *mut BD::Pixel).offset(uv_dstoff as isize), BD::pxstride((*f).cur.stride[1] as usize), cbw4 as usize * 4, cbh4 as usize * 4, @@ -3003,7 +3003,7 @@ pub(crate) unsafe fn rav1d_recon_b_intra( t.by += init_y; while y < sub_ch4 { let mut dst: *mut BD::Pixel = - ((*f).cur.data[(1 + pl) as usize] as *mut BD::Pixel).offset( + ((*f).cur.data.data[(1 + pl) as usize] as *mut BD::Pixel).offset( (4 * ((t.by >> ss_ver) as isize * BD::pxstride(stride as usize) as isize + (t.bx + init_x >> ss_hor) as isize)) @@ -3280,7 +3280,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( let mut res; let cbh4 = bh4 + ss_ver >> ss_ver; let cbw4 = bw4 + ss_hor >> ss_hor; - let mut dst: *mut BD::Pixel = ((*f).cur.data[0] as *mut BD::Pixel).offset( + let mut dst: *mut BD::Pixel = ((*f).cur.data.data[0] as *mut BD::Pixel).offset( (4 * (t.by as isize * BD::pxstride((*f).cur.stride[0] as usize) as isize + t.bx as isize)) as isize, ); @@ -3319,7 +3319,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( while pl < 3 { res = mc::( t, - ((*f).cur.data[pl as usize] as *mut BD::Pixel).offset(uvdstoff as isize), + ((*f).cur.data.data[pl as usize] as *mut BD::Pixel).offset(uvdstoff as isize), 0 as *mut i16, (*f).cur.stride[1], bw4 << (bw4 == ss_hor) as c_int, @@ -3544,7 +3544,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( while pl < 2 { res = mc::( t, - ((*f).cur.data[(1 + pl) as usize] as *mut BD::Pixel) + ((*f).cur.data.data[(1 + pl) as usize] as *mut BD::Pixel) .offset(uvdstoff as isize), 0 as *mut i16, (*f).cur.stride[1], @@ -3601,7 +3601,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( while pl < 2 { res = mc::( t, - ((*f).cur.data[(1 + pl) as usize] as *mut BD::Pixel) + ((*f).cur.data.data[(1 + pl) as usize] as *mut BD::Pixel) .offset(uvdstoff as isize) .offset(v_off as isize), 0 as *mut i16, @@ -3647,7 +3647,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( while pl < 2 { res = mc::( t, - ((*f).cur.data[(1 + pl) as usize] as *mut BD::Pixel) + ((*f).cur.data.data[(1 + pl) as usize] as *mut BD::Pixel) .offset(uvdstoff as isize) .offset(h_off as isize), 0 as *mut i16, @@ -3697,7 +3697,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( while pl < 2 { res = mc::( t, - ((*f).cur.data[(1 + pl) as usize] as *mut BD::Pixel) + ((*f).cur.data.data[(1 + pl) as usize] as *mut BD::Pixel) .offset(uvdstoff as isize) .offset(h_off as isize) .offset(v_off as isize), @@ -3738,7 +3738,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( while pl < 2 { res = warp_affine::( t, - ((*f).cur.data[(1 + pl) as usize] as *mut BD::Pixel) + ((*f).cur.data.data[(1 + pl) as usize] as *mut BD::Pixel) .offset(uvdstoff as isize), 0 as *mut i16, (*f).cur.stride[1], @@ -3763,7 +3763,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( while pl < 2 { res = mc::( t, - ((*f).cur.data[(1 + pl) as usize] as *mut BD::Pixel) + ((*f).cur.data.data[(1 + pl) as usize] as *mut BD::Pixel) .offset(uvdstoff as isize), 0 as *mut i16, (*f).cur.stride[1], @@ -3789,7 +3789,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( { res = obmc::( t, - ((*f).cur.data[(1 + pl) as usize] as *mut BD::Pixel) + ((*f).cur.data.data[(1 + pl) as usize] as *mut BD::Pixel) .offset(uvdstoff as isize), (*f).cur.stride[1], b_dim, @@ -3855,7 +3855,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( .interintra_mode as c_int }) as IntraPredMode; let mut angle = 0; - let uvdst: *mut BD::Pixel = ((*f).cur.data[(1 + pl) as usize] + let uvdst: *mut BD::Pixel = ((*f).cur.data.data[(1 + pl) as usize] as *mut BD::Pixel) .offset(uvdstoff as isize); let mut top_sb_edge: *const BD::Pixel = 0 as *const BD::Pixel; @@ -4152,8 +4152,9 @@ pub(crate) unsafe fn rav1d_recon_b_inter( } i += 1; } - let uvdst: *mut BD::Pixel = - ((*f).cur.data[(1 + pl) as usize] as *mut BD::Pixel).offset(uvdstoff as isize); + let uvdst: *mut BD::Pixel = ((*f).cur.data.data[(1 + pl) as usize] + as *mut BD::Pixel) + .offset(uvdstoff as isize); match b.c2rust_unnamed.c2rust_unnamed_0.comp_type as c_int { 2 => { ((*dsp).mc.avg)( @@ -4221,7 +4222,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( ); if has_chroma != 0 { hex_dump::( - &mut *(*((*f).cur.data).as_ptr().offset(1) as *mut BD::Pixel) + &mut *(*((*f).cur.data.data).as_ptr().offset(1) as *mut BD::Pixel) .offset(uvdstoff as isize), (*f).cur.stride[1] as usize, cbw4 as usize * 4, @@ -4229,7 +4230,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( "u-pred", ); hex_dump::( - &mut *(*((*f).cur.data).as_ptr().offset(2) as *mut BD::Pixel) + &mut *(*((*f).cur.data.data).as_ptr().offset(2) as *mut BD::Pixel) .offset(uvdstoff as isize), (*f).cur.stride[1] as usize, cbw4 as usize * 4, @@ -4320,7 +4321,7 @@ pub(crate) unsafe fn rav1d_recon_b_inter( if has_chroma != 0 { let mut pl = 0; while pl < 2 { - let mut uvdst: *mut BD::Pixel = ((*f).cur.data[(1 + pl) as usize] + let mut uvdst: *mut BD::Pixel = ((*f).cur.data.data[(1 + pl) as usize] as *mut BD::Pixel) .offset(uvdstoff as isize) .offset( @@ -4672,7 +4673,7 @@ pub(crate) unsafe fn rav1d_backup_ipred_edge(t: &mut Rav1dTaskCont let sby = t.by >> (*f).sb_shift; let sby_off = (*f).sb128w * 128 * sby; let x_off = (*ts).tiling.col_start; - let y: *const BD::Pixel = ((*f).cur.data[0] as *const BD::Pixel) + let y: *const BD::Pixel = ((*f).cur.data.data[0] as *const BD::Pixel) .offset((x_off * 4) as isize) .offset( (((t.by + (*f).sb_step) * 4 - 1) as isize @@ -4708,7 +4709,7 @@ pub(crate) unsafe fn rav1d_backup_ipred_edge(t: &mut Rav1dTaskCont .unwrap(), )[(sby_off + (x_off * 4 >> ss_hor)).try_into().unwrap()..], &slice::from_raw_parts( - (*f).cur.data[pl as usize].cast(), + (*f).cur.data.data[pl as usize].cast(), (uv_off + (4 * ((*ts).tiling.col_end - x_off) >> ss_hor) as isize) .try_into() .unwrap(), diff --git a/src/thread_task.rs b/src/thread_task.rs index bfbda38a8..8a4142839 100644 --- a/src/thread_task.rs +++ b/src/thread_task.rs @@ -1281,7 +1281,7 @@ pub unsafe extern "C" fn rav1d_worker_task(data: *mut c_void) -> *mut c_void { }; // Note that `progress.is_some() == c.n_fc > 1`. let progress = &**f.sr_cur.progress.as_ref().unwrap(); - if !(f.sr_cur.p.data[0]).is_null() { + if !(f.sr_cur.p.data.data[0]).is_null() { progress[0].store(if error_0 != 0 { FRAME_ERROR } else { y }, Ordering::SeqCst); } f.frame_thread.entropy_progress.store( @@ -1331,7 +1331,7 @@ pub unsafe extern "C" fn rav1d_worker_task(data: *mut c_void) -> *mut c_void { // Note that `progress.is_some() == c.n_fc > 1`. if let Some(progress) = &f.sr_cur.progress { // upon flush, this can be free'ed already - if !(f.sr_cur.p.data[0]).is_null() { + if !(f.sr_cur.p.data.data[0]).is_null() { progress[1].store( if error_0 != 0 { FRAME_ERROR } else { y_0 }, Ordering::SeqCst, diff --git a/tests/seek_stress.rs b/tests/seek_stress.rs index a002b4f3d..3f5ade523 100644 --- a/tests/seek_stress.rs +++ b/tests/seek_stress.rs @@ -42,7 +42,6 @@ use rav1d::include::dav1d::common::Dav1dUserData; use rav1d::include::dav1d::data::Dav1dData; use rav1d::include::dav1d::dav1d::Dav1dContext; use rav1d::include::dav1d::dav1d::Dav1dLogger; -use rav1d::include::dav1d::dav1d::Dav1dRef; use rav1d::include::dav1d::dav1d::Dav1dSettings; use rav1d::include::dav1d::dav1d::DAV1D_DECODEFRAMETYPE_ALL; use rav1d::include::dav1d::dav1d::DAV1D_INLOOPFILTER_NONE; @@ -57,7 +56,6 @@ use rav1d::include::dav1d::headers::DAV1D_OFF; use rav1d::include::dav1d::headers::DAV1D_PIXEL_LAYOUT_I400; use rav1d::include::dav1d::picture::Dav1dPicAllocator; use rav1d::include::dav1d::picture::Dav1dPicture; -use rav1d::include::dav1d::picture::Dav1dPictureParameters; use rav1d::src::lib::dav1d_close; use rav1d::src::lib::dav1d_flush; use rav1d::src::lib::dav1d_get_picture; @@ -144,40 +142,7 @@ unsafe fn decode_rand( fps: c_double, ) -> c_int { let mut res = 0; - let mut p: Dav1dPicture = Dav1dPicture { - seq_hdr: None, - frame_hdr: None, - data: [0 as *mut c_void; 3], - stride: [0; 2], - p: Dav1dPictureParameters { - w: 0, - h: 0, - layout: DAV1D_PIXEL_LAYOUT_I400, - bpc: 0, - }, - m: Dav1dDataProps { - timestamp: 0, - duration: 0, - offset: 0, - size: 0, - user_data: Dav1dUserData { - data: None, - r#ref: None, - }, - }, - content_light: None, - mastering_display: None, - itut_t35: None, - reserved: [0; 4], - frame_hdr_ref: None, - seq_hdr_ref: None, - content_light_ref: None, - mastering_display_ref: None, - itut_t35_ref: None, - reserved_ref: [0; 4], - r#ref: 0 as *mut Dav1dRef, - allocator_data: 0 as *mut c_void, - }; + let mut p = Default::default(); let num_frames: c_int = xor128_rand() % (fps * 5 as c_double) as c_int; let mut i = 0; while i < num_frames { @@ -199,40 +164,7 @@ unsafe fn decode_all( data: *mut Dav1dData, ) -> c_int { let mut res: c_int; - let mut p: Dav1dPicture = Dav1dPicture { - seq_hdr: None, - frame_hdr: None, - data: [0 as *mut c_void; 3], - stride: [0; 2], - p: Dav1dPictureParameters { - w: 0, - h: 0, - layout: DAV1D_PIXEL_LAYOUT_I400, - bpc: 0, - }, - m: Dav1dDataProps { - timestamp: 0, - duration: 0, - offset: 0, - size: 0, - user_data: Dav1dUserData { - data: None, - r#ref: None, - }, - }, - content_light: None, - mastering_display: None, - itut_t35: None, - reserved: [0; 4], - frame_hdr_ref: None, - seq_hdr_ref: None, - content_light_ref: None, - mastering_display_ref: None, - itut_t35_ref: None, - reserved_ref: [0; 4], - r#ref: 0 as *mut Dav1dRef, - allocator_data: 0 as *mut c_void, - }; + let mut p = Default::default(); loop { res = decode_frame(&mut p, c, data); if res != 0 { diff --git a/tools/dav1d.rs b/tools/dav1d.rs index 462f81aaf..f94894908 100644 --- a/tools/dav1d.rs +++ b/tools/dav1d.rs @@ -59,7 +59,6 @@ use rav1d::include::dav1d::common::Dav1dUserData; use rav1d::include::dav1d::data::Dav1dData; use rav1d::include::dav1d::dav1d::Dav1dContext; use rav1d::include::dav1d::dav1d::Dav1dLogger; -use rav1d::include::dav1d::dav1d::Dav1dRef; use rav1d::include::dav1d::dav1d::Dav1dSettings; use rav1d::include::dav1d::dav1d::DAV1D_DECODEFRAMETYPE_ALL; use rav1d::include::dav1d::dav1d::DAV1D_INLOOPFILTER_NONE; @@ -76,7 +75,6 @@ use rav1d::include::dav1d::headers::DAV1D_PIXEL_LAYOUT_I420; use rav1d::include::dav1d::headers::DAV1D_PIXEL_LAYOUT_I444; use rav1d::include::dav1d::picture::Dav1dPicAllocator; use rav1d::include::dav1d::picture::Dav1dPicture; -use rav1d::include::dav1d::picture::Dav1dPictureParameters; use rav1d::include::dav1d::picture::DAV1D_PICTURE_ALIGNMENT; use rav1d::src::lib::dav1d_close; use rav1d::src::lib::dav1d_data_unref; @@ -92,6 +90,7 @@ use std::ffi::c_int; use std::ffi::c_uint; use std::ffi::c_ulonglong; use std::ffi::c_void; +use std::ptr::NonNull; unsafe fn get_time_nanos() -> u64 { let mut ts: libc::timespec = libc::timespec { @@ -238,29 +237,36 @@ unsafe extern "C" fn picture_alloc(p: *mut Dav1dPicture, _: *mut c_void) -> Dav1 if buf.is_null() { return Dav1dResult(-12); } - (*p).allocator_data = buf as *mut c_void; + (*p).allocator_data = NonNull::new(buf.cast()); let align_m1: ptrdiff_t = (DAV1D_PICTURE_ALIGNMENT - 1) as ptrdiff_t; let data: *mut u8 = (buf as ptrdiff_t + align_m1 & !align_m1) as *mut u8; - (*p).data[0] = data.offset(y_sz as isize).offset(-(y_stride as isize)) as *mut c_void; - (*p).data[1] = (if has_chroma != 0 { - data.offset(y_sz as isize) - .offset(uv_sz.wrapping_mul(1) as isize) - .offset(-(uv_stride as isize)) - } else { - 0 as *mut u8 - }) as *mut c_void; - (*p).data[2] = (if has_chroma != 0 { - data.offset(y_sz as isize) - .offset(uv_sz.wrapping_mul(2) as isize) - .offset(-(uv_stride as isize)) - } else { - 0 as *mut u8 - }) as *mut c_void; + (*p).data[0] = + NonNull::new(data.offset(y_sz as isize).offset(-(y_stride as isize)) as *mut c_void); + (*p).data[1] = NonNull::new( + (if has_chroma != 0 { + data.offset(y_sz as isize) + .offset(uv_sz.wrapping_mul(1) as isize) + .offset(-(uv_stride as isize)) + } else { + 0 as *mut u8 + }) as *mut c_void, + ); + (*p).data[2] = NonNull::new( + (if has_chroma != 0 { + data.offset(y_sz as isize) + .offset(uv_sz.wrapping_mul(2) as isize) + .offset(-(uv_stride as isize)) + } else { + 0 as *mut u8 + }) as *mut c_void, + ); Dav1dResult(0) } unsafe extern "C" fn picture_release(p: *mut Dav1dPicture, _: *mut c_void) { - free((*p).allocator_data); + if let Some(data) = (*p).allocator_data { + free(data.as_ptr()); + } } unsafe fn main_0(argc: c_int, argv: *const *mut c_char) -> c_int { @@ -302,40 +308,7 @@ unsafe fn main_0(argc: c_int, argv: *const *mut c_char) -> c_int { }; let mut in_0: *mut DemuxerContext = 0 as *mut DemuxerContext; let mut out: *mut MuxerContext = 0 as *mut MuxerContext; - let mut p: Dav1dPicture = Dav1dPicture { - seq_hdr: None, - frame_hdr: None, - data: [0 as *mut c_void; 3], - stride: [0; 2], - p: Dav1dPictureParameters { - w: 0, - h: 0, - layout: DAV1D_PIXEL_LAYOUT_I400, - bpc: 0, - }, - m: Dav1dDataProps { - timestamp: 0, - duration: 0, - offset: 0, - size: 0, - user_data: Dav1dUserData { - data: None, - r#ref: None, - }, - }, - content_light: None, - mastering_display: None, - itut_t35: None, - reserved: [0; 4], - frame_hdr_ref: None, - seq_hdr_ref: None, - content_light_ref: None, - mastering_display_ref: None, - itut_t35_ref: None, - reserved_ref: [0; 4], - r#ref: 0 as *mut Dav1dRef, - allocator_data: 0 as *mut c_void, - }; + let mut p = Default::default(); let mut c: *mut Dav1dContext = 0 as *mut Dav1dContext; let mut data: Dav1dData = Dav1dData { data: None, diff --git a/tools/output/md5.rs b/tools/output/md5.rs index 0e719fda5..2367f1bcb 100644 --- a/tools/output/md5.rs +++ b/tools/output/md5.rs @@ -21,6 +21,8 @@ use std::ffi::c_int; use std::ffi::c_uint; use std::ffi::c_ulong; use std::ffi::c_void; +use std::ptr; +use std::ptr::NonNull; #[repr(C)] pub struct MuxerPriv { @@ -540,7 +542,7 @@ unsafe extern "C" fn md5_write(md5: *mut MD5Context, p: *mut Dav1dPicture) -> c_ let hbd = ((*p).p.bpc > 8) as c_int; let w = (*p).p.w; let h = (*p).p.h; - let mut yptr: *mut u8 = (*p).data[0] as *mut u8; + let mut yptr: *mut u8 = (*p).data[0].map_or_else(ptr::null_mut, NonNull::as_ptr) as *mut u8; let mut y = 0; while y < h { md5_update(md5, yptr, (w << hbd) as c_uint); @@ -556,7 +558,8 @@ unsafe extern "C" fn md5_write(md5: *mut MD5Context, p: *mut Dav1dPicture) -> c_ let ch = h + ss_ver >> ss_ver; let mut pl = 1; while pl <= 2 { - let mut uvptr: *mut u8 = (*p).data[pl as usize] as *mut u8; + let mut uvptr: *mut u8 = + (*p).data[pl as usize].map_or_else(ptr::null_mut, NonNull::as_ptr) as *mut u8; let mut y_0 = 0; while y_0 < ch { md5_update(md5, uvptr, (cw << hbd) as c_uint); diff --git a/tools/output/y4m2.rs b/tools/output/y4m2.rs index abc30fdfd..e3392b2f6 100644 --- a/tools/output/y4m2.rs +++ b/tools/output/y4m2.rs @@ -19,6 +19,8 @@ use std::ffi::c_int; use std::ffi::c_uint; use std::ffi::c_ulong; use std::ffi::c_void; +use std::ptr; +use std::ptr::NonNull; #[repr(C)] pub struct MuxerPriv { @@ -157,7 +159,7 @@ unsafe extern "C" fn y4m2_write(c: *mut Y4m2OutputContext, p: *mut Dav1dPicture) fprintf((*c).f, b"FRAME\n\0" as *const u8 as *const c_char); let mut ptr: *mut u8; let hbd = ((*p).p.bpc > 8) as c_int; - ptr = (*p).data[0] as *mut u8; + ptr = (*p).data[0].map_or_else(ptr::null_mut, NonNull::as_ptr) as *mut u8; let mut y = 0; loop { if !(y < (*p).p.h) { @@ -186,7 +188,8 @@ unsafe extern "C" fn y4m2_write(c: *mut Y4m2OutputContext, p: *mut Dav1dPicture) current_block = 13797916685926291137; break; } - ptr = (*p).data[pl as usize] as *mut u8; + ptr = (*p).data[pl as usize].map_or_else(ptr::null_mut, NonNull::as_ptr) + as *mut u8; let mut y_0 = 0; while y_0 < ch { if fwrite(ptr as *const c_void, (cw << hbd) as usize, 1, (*c).f) != 1 { diff --git a/tools/output/yuv.rs b/tools/output/yuv.rs index 21a09ca6d..4b1cd25c2 100644 --- a/tools/output/yuv.rs +++ b/tools/output/yuv.rs @@ -18,6 +18,8 @@ use std::ffi::c_int; use std::ffi::c_uint; use std::ffi::c_ulong; use std::ffi::c_void; +use std::ptr; +use std::ptr::NonNull; #[repr(C)] pub struct MuxerPriv { @@ -71,7 +73,7 @@ unsafe extern "C" fn yuv_write(c: *mut YuvOutputContext, p: *mut Dav1dPicture) - let mut current_block: u64; let mut ptr: *mut u8; let hbd = ((*p).p.bpc > 8) as c_int; - ptr = (*p).data[0] as *mut u8; + ptr = (*p).data[0].map_or_else(ptr::null_mut, NonNull::as_ptr) as *mut u8; let mut y = 0; loop { if !(y < (*p).p.h) { @@ -100,7 +102,8 @@ unsafe extern "C" fn yuv_write(c: *mut YuvOutputContext, p: *mut Dav1dPicture) - current_block = 7976072742316086414; break; } - ptr = (*p).data[pl as usize] as *mut u8; + ptr = (*p).data[pl as usize].map_or_else(ptr::null_mut, NonNull::as_ptr) + as *mut u8; let mut y_0 = 0; while y_0 < ch { if fwrite(ptr as *const c_void, (cw << hbd) as usize, 1, (*c).f) != 1 {