diff --git a/src/decode.rs b/src/decode.rs index 551b1cf4e..6ac164509 100644 --- a/src/decode.rs +++ b/src/decode.rs @@ -3888,7 +3888,7 @@ pub(crate) unsafe fn rav1d_decode_tile_sbrow( ); } - if frame_hdr.frame_type.is_inter_or_switch() && c.n_fc > 1 { + if frame_hdr.frame_type.is_inter_or_switch() && c.fc.len() > 1 { let sby = t.b.y - ts.tiling.row_start >> f.sb_shift; *f.lowest_pixel_mem.index_mut(ts.lowest_pixel + sby as usize) = [[i32::MIN; 2]; 7]; } @@ -4096,7 +4096,7 @@ pub(crate) unsafe fn rav1d_decode_frame_init( let n_ts = frame_hdr.tiling.cols * frame_hdr.tiling.rows; if n_ts != f.n_ts { - if c.n_fc > 1 { + if c.fc.len() > 1 { // TODO: Fallible allocation f.frame_thread.tile_start_off.resize(n_ts as usize, 0); } @@ -4109,7 +4109,7 @@ pub(crate) unsafe fn rav1d_decode_frame_init( f.n_ts = n_ts; } - let a_sz = f.sb128w * frame_hdr.tiling.rows * (1 + (c.n_fc > 1 && c.tc.len() > 1) as c_int); + let a_sz = f.sb128w * frame_hdr.tiling.rows * (1 + (c.fc.len() > 1 && c.tc.len() > 1) as c_int); // TODO: Fallible allocation f.a.resize_with(a_sz as usize, Default::default); @@ -4117,7 +4117,7 @@ pub(crate) unsafe fn rav1d_decode_frame_init( let size_mul = &ss_size_mul[f.cur.p.layout]; let seq_hdr = &***f.seq_hdr.as_ref().unwrap(); let hbd = (seq_hdr.hbd != 0) as c_int; - if c.n_fc > 1 { + if c.fc.len() > 1 { let mut tile_idx = 0; let sb_step4 = f.sb_step as u32 * 4; for tile_row in 0..frame_hdr.tiling.rows { @@ -4284,7 +4284,7 @@ pub(crate) unsafe fn rav1d_decode_frame_init( // index this from the level type and can thus over-read by up to 3 bytes. f.lf.level .resize(num_sb128 as usize * 32 * 32 + 1, [0u8; 4]); // TODO: Fallible allocation - if c.n_fc > 1 { + if c.fc.len() > 1 { // TODO: Fallible allocation f.frame_thread .b @@ -4346,7 +4346,7 @@ pub(crate) unsafe fn rav1d_decode_frame_init( &f.refrefpoc, &f.ref_mvs, c.tc.len() as u32, - c.n_fc, + c.fc.len() as u32, )?; } @@ -4421,7 +4421,7 @@ pub(crate) unsafe fn rav1d_decode_frame_init_cdf( rav1d_cdf_thread_copy(&mut f.out_cdf.cdf_write(), in_cdf); } - let uses_2pass = c.n_fc > 1; + let uses_2pass = c.fc.len() > 1; let tiling = &frame_hdr.tiling; @@ -4588,7 +4588,7 @@ pub(crate) unsafe fn rav1d_decode_frame_exit( task_thread.error.store(0, Ordering::Relaxed); } let cf = f.frame_thread.cf.get_mut(); - if c.n_fc > 1 && retval.is_err() && !cf.is_empty() { + if c.fc.len() > 1 && retval.is_err() && !cf.is_empty() { cf.fill_with(Default::default); } // TODO(kkysen) use array::zip when stable @@ -4624,7 +4624,7 @@ pub(crate) unsafe fn rav1d_decode_frame_exit( } pub(crate) unsafe fn rav1d_decode_frame(c: &Rav1dContext, fc: &Rav1dFrameContext) -> Rav1dResult { - assert!(c.n_fc == 1); + assert!(c.fc.len() == 1); // if.tc.len() > 1 (but n_fc == 1), we could run init/exit in the task // threads also. Not sure it makes a measurable difference. let mut res = rav1d_decode_frame_init(c, fc); @@ -4678,22 +4678,19 @@ fn get_upscale_x0(in_w: c_int, out_w: c_int, step: c_int) -> c_int { pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { // wait for c->out_delayed[next] and move into c->out if visible - let (fc, out, _task_thread_lock) = if c.n_fc > 1 { + let (fc, out, _task_thread_lock) = if c.fc.len() > 1 { let mut task_thread_lock = c.task_thread.delayed_fg.lock().unwrap(); let next = c.frame_thread.next; - c.frame_thread.next += 1; - if c.frame_thread.next == c.n_fc { - c.frame_thread.next = 0; - } + c.frame_thread.next = (c.frame_thread.next + 1) % c.fc.len() as u32; - let fc = &(*c.fc.offset(next as isize)); + let fc = &c.fc[next as usize]; while !fc.task_thread.finished.load(Ordering::SeqCst) { task_thread_lock = fc.task_thread.cond.wait(task_thread_lock).unwrap(); } let out_delayed = &mut c.frame_thread.out_delayed[next as usize]; if out_delayed.p.data.is_some() || fc.task_thread.error.load(Ordering::SeqCst) != 0 { let first = c.task_thread.first.load(Ordering::SeqCst); - if first + 1 < c.n_fc { + if first as usize + 1 < c.fc.len() { c.task_thread.first.fetch_add(1, Ordering::SeqCst); } else { c.task_thread.first.store(0, Ordering::SeqCst); @@ -4706,7 +4703,7 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { ); // `cur` is not actually mutated from multiple threads concurrently let cur = c.task_thread.cur.load(Ordering::Relaxed); - if cur != 0 && cur < c.n_fc { + if cur != 0 && (cur as usize) < c.fc.len() { c.task_thread.cur.fetch_sub(1, Ordering::Relaxed); } } @@ -4725,7 +4722,7 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { } (fc, out_delayed as *mut _, Some(task_thread_lock)) } else { - (&(*c.fc), &mut c.out as *mut _, None) + (&c.fc[0], &mut c.out as *mut _, None) }; let mut f = fc.data.try_write().unwrap(); @@ -4830,7 +4827,7 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { *fc.in_cdf.try_write().unwrap() = c.cdf[pri_ref].clone(); } if frame_hdr.refresh_context != 0 { - let res = rav1d_cdf_thread_alloc(c, (c.n_fc > 1) as c_int); + let res = rav1d_cdf_thread_alloc(c, (c.fc.len() > 1) as c_int); match res { Err(e) => { on_error(fc, &mut f, c, out); @@ -4885,7 +4882,7 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { } // move f->cur into output queue - if c.n_fc == 1 { + if c.fc.len() == 1 { if frame_hdr.show_frame != 0 || c.output_invisible_frames { c.out = f.sr_cur.clone(); c.event_flags |= f.sr_cur.flags.into(); @@ -4906,7 +4903,7 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { f.b4_stride = (f.bw + 31 & !31) as ptrdiff_t; f.bitdepth_max = (1 << f.cur.p.bpc) - 1; fc.task_thread.error.store(0, Ordering::Relaxed); - let uses_2pass = (c.n_fc > 1) as c_int; + let uses_2pass = (c.fc.len() > 1) as c_int; let cols = frame_hdr.tiling.cols; let rows = frame_hdr.tiling.rows; fc.task_thread @@ -5017,10 +5014,9 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { c.refs[i].refpoc = f.refpoc; } } - let index = f.index; drop(f); - if c.n_fc == 1 { + if c.fc.len() == 1 { let res = rav1d_decode_frame(c, &fc); if res.is_err() { let _ = mem::take(&mut c.out); @@ -5039,7 +5035,7 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { return res; } } else { - rav1d_task_frame_init(c, fc, index); + rav1d_task_frame_init(c, fc); } Ok(()) diff --git a/src/internal.rs b/src/internal.rs index 883204a8a..d45455115 100644 --- a/src/internal.rs +++ b/src/internal.rs @@ -250,9 +250,22 @@ pub(crate) struct TaskThreadData_delayed_fg { pub grain: BitDepthUnion, } +impl Default for TaskThreadData_delayed_fg { + fn default() -> Self { + Self { + exec: 0, + in_0: std::ptr::null(), + out: std::ptr::null_mut(), + type_0: Default::default(), + grain: Default::default(), + } + } +} + // TODO(SJC): Remove when TaskThreadData_delayed_fg is thread-safe unsafe impl Send for TaskThreadData_delayed_fg {} +#[derive(Default)] #[repr(C)] pub(crate) struct TaskThreadData { pub cond: Condvar, @@ -313,8 +326,7 @@ impl Rav1dContextTaskThread { #[repr(C)] pub struct Rav1dContext { - pub(crate) fc: *mut Rav1dFrameContext, - pub(crate) n_fc: c_uint, + pub(crate) fc: Box<[Rav1dFrameContext]>, /// Worker thread join handles and communication, or main thread task /// context if single-threaded @@ -369,6 +381,15 @@ pub struct Rav1dContext { pub(crate) picture_pool: *mut Rav1dMemPool, } +impl Rav1dContext { + /// Iterates over all frame contexts in the `fc` buffer, starting at a given + /// index. The iterator wraps around to the start of the buffer. so all + /// contexts will be included. + pub(crate) fn fc_iter(&self, start: usize) -> impl Iterator { + self.fc.iter().skip(start).chain(self.fc.iter().take(start)) + } +} + // TODO(SJC): Remove when Rav1dContext is thread-safe unsafe impl Send for Rav1dContext {} // TODO(SJC): Remove when Rav1dContext is thread-safe @@ -785,6 +806,26 @@ pub(crate) struct Rav1dFrameContext_task_thread { pub pending_tasks: Mutex, } +impl Default for Rav1dFrameContext_task_thread { + fn default() -> Self { + Self { + lock: Default::default(), + cond: Default::default(), + ttd: Default::default(), + tasks: Default::default(), + init_done: Default::default(), + done: Default::default(), + retval: Mutex::new(Ok(())), + finished: Default::default(), + update_set: Default::default(), + error: Default::default(), + task_counter: Default::default(), + pending_tasks_merge: Default::default(), + pending_tasks: Default::default(), + } + } +} + impl Rav1dFrameContext_task_thread { pub unsafe fn tasks(&self) -> *mut Rav1dTasks { self.tasks.get() @@ -800,6 +841,9 @@ pub(crate) struct Rav1dFrameContext_frame_thread_progress { } pub(crate) struct Rav1dFrameContext { + /// Index in [`Rav1dContext::fc`] + pub index: usize, + pub data: RwLock, pub in_cdf: RwLock, pub task_thread: Rav1dFrameContext_task_thread, @@ -807,6 +851,16 @@ pub(crate) struct Rav1dFrameContext { } impl Rav1dFrameContext { + pub(crate) unsafe fn zeroed(index: usize) -> Self { + Self { + index, + data: RwLock::new(unsafe { Rav1dFrameData::zeroed() }), + in_cdf: Default::default(), + task_thread: Default::default(), + frame_thread_progress: Default::default(), + } + } + pub fn in_cdf<'a>(&'a self) -> RwLockReadGuard<'a, CdfThreadContext> { self.in_cdf.try_read().unwrap() } @@ -824,9 +878,6 @@ impl Rav1dFrameContext { #[repr(C)] pub(crate) struct Rav1dFrameData { - /// Index in [`Rav1dContext::fc`] - pub index: usize, - pub seq_hdr: Option>>, pub frame_hdr: Option>>, pub refp: [Rav1dThreadPicture; 7], @@ -881,9 +932,13 @@ pub(crate) struct Rav1dFrameData { impl Rav1dFrameData { pub unsafe fn zeroed() -> Self { let mut data: MaybeUninit = MaybeUninit::zeroed(); + addr_of_mut!((*data.as_mut_ptr()).refp).write(Default::default()); + addr_of_mut!((*data.as_mut_ptr()).cur).write(Default::default()); + addr_of_mut!((*data.as_mut_ptr()).sr_cur).write(Default::default()); addr_of_mut!((*data.as_mut_ptr()).out_cdf).write(Default::default()); addr_of_mut!((*data.as_mut_ptr()).tiles).write(vec![]); addr_of_mut!((*data.as_mut_ptr()).a).write(vec![]); + addr_of_mut!((*data.as_mut_ptr()).rf).write(Default::default()); addr_of_mut!((*data.as_mut_ptr()).lowest_pixel_mem).write(Default::default()); addr_of_mut!((*data.as_mut_ptr()).frame_thread).write(Default::default()); addr_of_mut!((*data.as_mut_ptr()).lf).write(Default::default()); diff --git a/src/lib.rs b/src/lib.rs index 07a87252a..46134267a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,6 @@ use crate::src::internal::Rav1dContextTaskThread; use crate::src::internal::Rav1dContextTaskType; use crate::src::internal::Rav1dDSPContext; use crate::src::internal::Rav1dFrameContext; -use crate::src::internal::Rav1dFrameData; use crate::src::internal::Rav1dTaskContext; use crate::src::internal::Rav1dTaskContext_task_thread; use crate::src::internal::TaskThreadData; @@ -52,12 +51,10 @@ use crate::src::picture::PictureFlags; use crate::src::picture::Rav1dThreadPicture; use crate::src::refmvs::rav1d_refmvs_clear; use crate::src::refmvs::rav1d_refmvs_dsp_init; -use crate::src::refmvs::rav1d_refmvs_init; use crate::src::thread_task::rav1d_task_delayed_fg; use crate::src::thread_task::rav1d_worker_task; use crate::src::thread_task::FRAME_ERROR; use libc::memset; -use std::cell::UnsafeCell; use std::cmp; use std::ffi::c_char; use std::ffi::c_int; @@ -78,7 +75,6 @@ use std::sync::Arc; use std::sync::Condvar; use std::sync::Mutex; use std::sync::Once; -use std::sync::RwLock; use std::thread; use to_method::To as _; @@ -246,23 +242,12 @@ pub(crate) unsafe fn rav1d_open(c_out: &mut *mut Rav1dContext, s: &Rav1dSettings } (*c).flush = AtomicI32::new(0); let NumThreads { n_tc, n_fc } = get_num_threads(s); - (*c).n_fc = n_fc as c_uint; - (*c).fc = rav1d_alloc_aligned( - ::core::mem::size_of::().wrapping_mul((*c).n_fc as usize), - 32 as c_int as usize, - ) as *mut Rav1dFrameContext; - if ((*c).fc).is_null() { - return error(c, c_out); - } - memset( - (*c).fc as *mut c_void, - 0 as c_int, - ::core::mem::size_of::().wrapping_mul((*c).n_fc as usize), - ); + // TODO fallible allocation + (*c).fc = (0..n_fc).map(|i| Rav1dFrameContext::zeroed(i)).collect(); let ttd = TaskThreadData { cond: Condvar::new(), first: AtomicU32::new(0), - cur: AtomicU32::new((*c).n_fc), + cur: AtomicU32::new(n_fc as u32), reset_task_cur: AtomicU32::new(u32::MAX), cond_signaled: AtomicI32::new(0), delayed_fg_progress: [AtomicI32::new(0), AtomicI32::new(0)], @@ -271,8 +256,8 @@ pub(crate) unsafe fn rav1d_open(c_out: &mut *mut Rav1dContext, s: &Rav1dSettings }; (&mut (*c).task_thread as *mut Arc).write(Arc::new(ttd)); addr_of_mut!((*c).tiles).write(Default::default()); - ptr::addr_of_mut!((*c).frame_thread.out_delayed).write(if (*c).n_fc > 1 { - (0..(*c).n_fc).map(|_| Default::default()).collect() + ptr::addr_of_mut!((*c).frame_thread.out_delayed).write(if n_fc > 1 { + (0..n_fc).map(|_| Default::default()).collect() } else { Box::new([]) }); @@ -280,28 +265,11 @@ pub(crate) unsafe fn rav1d_open(c_out: &mut *mut Rav1dContext, s: &Rav1dSettings addr_of_mut!((*c).out).write(Default::default()); addr_of_mut!((*c).cache).write(Default::default()); addr_of_mut!((*c).refs).write(Default::default()); - for n in 0..n_fc { - let fc = &mut *((*c).fc).offset(n as isize); - addr_of_mut!(fc.data).write(RwLock::new(Rav1dFrameData::zeroed())); + for fc in (*c).fc.iter_mut() { + fc.task_thread.finished = AtomicBool::new(true); + fc.task_thread.ttd = Arc::clone(&(*c).task_thread); let f = fc.data.get_mut().unwrap(); - f.index = n; - addr_of_mut!(fc.in_cdf).write(RwLock::new(Default::default())); - addr_of_mut!(fc.task_thread.tasks).write(UnsafeCell::new(Default::default())); - addr_of_mut!(fc.task_thread.retval).write(Mutex::new(Ok(()))); - addr_of_mut!(fc.task_thread.update_set).write(AtomicBool::new(false)); - addr_of_mut!(fc.task_thread.finished).write(AtomicBool::new(true)); - addr_of_mut!(fc.task_thread.ttd).write(Arc::clone(&(*c).task_thread)); - addr_of_mut!(fc.frame_thread_progress).write(Default::default()); - if n_tc > 1 { - fc.task_thread.lock = Mutex::new(()); - fc.task_thread.cond = Condvar::new(); - fc.task_thread.pending_tasks = Default::default(); - } f.lf.last_sharpness = -(1 as c_int); - rav1d_refmvs_init(&mut f.rf); - addr_of_mut!(f.refp).write(Default::default()); - addr_of_mut!(f.cur).write(Default::default()); - addr_of_mut!(f.sr_cur).write(Default::default()); } (*c).tc = (0..n_tc) .map(|n| { @@ -437,7 +405,7 @@ unsafe fn drain_picture(c: &mut Rav1dContext, out: &mut Rav1dPicture) -> Rav1dRe let mut drained = 0; loop { let next: c_uint = c.frame_thread.next; - let fc = &(*(c.fc).offset(next as isize)); + let fc = &c.fc[next as usize]; let mut task_thread_lock = c.task_thread.delayed_fg.lock().unwrap(); while !fc.task_thread.finished.load(Ordering::SeqCst) { task_thread_lock = fc.task_thread.cond.wait(task_thread_lock).unwrap(); @@ -445,7 +413,7 @@ unsafe fn drain_picture(c: &mut Rav1dContext, out: &mut Rav1dPicture) -> Rav1dRe let out_delayed = &mut c.frame_thread.out_delayed[next as usize]; if out_delayed.p.data.is_some() || fc.task_thread.error.load(Ordering::SeqCst) != 0 { let first: c_uint = c.task_thread.first.load(Ordering::SeqCst); - if first.wrapping_add(1 as c_uint) < c.n_fc { + if (first.wrapping_add(1 as c_uint) as usize) < c.fc.len() { c.task_thread.first.fetch_add(1, Ordering::SeqCst); } else { c.task_thread.first.store(0, Ordering::SeqCst); @@ -457,7 +425,7 @@ unsafe fn drain_picture(c: &mut Rav1dContext, out: &mut Rav1dPicture) -> Rav1dRe Ordering::SeqCst, ); if c.task_thread.cur.load(Ordering::Relaxed) != 0 - && c.task_thread.cur.load(Ordering::Relaxed) < c.n_fc + && (c.task_thread.cur.load(Ordering::Relaxed) as usize) < c.fc.len() { c.task_thread.cur.fetch_sub(1, Ordering::Relaxed); } @@ -466,7 +434,7 @@ unsafe fn drain_picture(c: &mut Rav1dContext, out: &mut Rav1dPicture) -> Rav1dRe break; } c.frame_thread.next = (c.frame_thread.next).wrapping_add(1); - if c.frame_thread.next == c.n_fc { + if c.frame_thread.next as usize == c.fc.len() { c.frame_thread.next = 0 as c_int as c_uint; } drop(task_thread_lock); @@ -488,7 +456,7 @@ unsafe fn drain_picture(c: &mut Rav1dContext, out: &mut Rav1dPicture) -> Rav1dRe } } drain_count = drain_count.wrapping_add(1); - if !(drain_count < c.n_fc) { + if !((drain_count as usize) < c.fc.len()) { break; } } @@ -569,10 +537,10 @@ pub(crate) unsafe fn rav1d_get_picture( let drain = mem::replace(&mut c.drain, 1); gen_picture(c)?; mem::replace(&mut c.cached_error, Ok(()))?; - if output_picture_ready(c, c.n_fc == 1) { + if output_picture_ready(c, c.fc.len() == 1) { return output_image(c, out); } - if c.n_fc > 1 && drain != 0 { + if c.fc.len() > 1 && drain != 0 { return drain_picture(c, out); } Err(EAGAIN) @@ -688,7 +656,7 @@ pub(crate) unsafe fn rav1d_flush(c: *mut Rav1dContext) { let _ = mem::take(&mut (*c).mastering_display); let _ = mem::take(&mut (*c).itut_t35); let _ = mem::take(&mut (*c).cached_error_props); - if (*c).n_fc == 1 as c_uint && (*c).tc.len() == 1 { + if (*c).fc.len() == 1 && (*c).tc.len() == 1 { return; } (*c).flush.store(1, Ordering::SeqCst); @@ -699,45 +667,31 @@ pub(crate) unsafe fn rav1d_flush(c: *mut Rav1dContext) { task_thread_lock = tc.thread_data.cond.wait(task_thread_lock).unwrap(); } } - let mut i_1: c_uint = 0 as c_int as c_uint; - while i_1 < (*c).n_fc { - let tasks = &mut *(*((*c).fc).offset(i_1 as isize)).task_thread.tasks(); + for fc in (*c).fc.iter_mut() { + let tasks = &mut *fc.task_thread.tasks(); tasks.head = None; tasks.tail = None; tasks.cur_prev = None; - *(*((*c).fc).offset(i_1 as isize)) - .task_thread - .pending_tasks - .get_mut() - .unwrap() = Default::default(); - *&mut (*((*c).fc).offset(i_1 as isize)) - .task_thread - .pending_tasks_merge = AtomicI32::new(0); - i_1 = i_1.wrapping_add(1); + *fc.task_thread.pending_tasks.get_mut().unwrap() = Default::default(); + fc.task_thread.pending_tasks_merge = AtomicI32::new(0); } (*c).task_thread.first.store(0, Ordering::SeqCst); - (*c).task_thread.cur.store((*c).n_fc, Ordering::SeqCst); + (*c).task_thread + .cur + .store((*c).fc.len() as u32, Ordering::SeqCst); (*c).task_thread .reset_task_cur .store(u32::MAX, Ordering::SeqCst); (*c).task_thread.cond_signaled.store(0, Ordering::SeqCst); } - if (*c).n_fc > 1 as c_uint { - let mut n: c_uint = 0 as c_int as c_uint; - let mut next: c_uint = (*c).frame_thread.next; - while n < (*c).n_fc { - if next == (*c).n_fc { - next = 0 as c_int as c_uint; - } - let fc = &(*((*c).fc).offset(next as isize)); + if (*c).fc.len() > 1 { + for fc in (*c).fc_iter((*c).frame_thread.next as usize) { rav1d_decode_frame_exit(&*c, fc, Err(EGeneric)); *fc.task_thread.retval.try_lock().unwrap() = Ok(()); - let out_delayed = &mut (*c).frame_thread.out_delayed[next as usize]; + let out_delayed = &mut (*c).frame_thread.out_delayed[fc.index]; if out_delayed.p.frame_hdr.is_some() { let _ = mem::take(out_delayed); } - n = n.wrapping_add(1); - next = next.wrapping_add(1); } (*c).frame_thread.next = 0 as c_int as c_uint; } @@ -797,11 +751,10 @@ impl Drop for Rav1dContext { } } } - let mut n_1: c_uint = 0 as c_int as c_uint; - while !(self.fc).is_null() && n_1 < self.n_fc { - let fc = &mut (*(self.fc).offset(n_1 as isize)); + let fc_len = self.fc.len(); + for fc in self.fc.iter_mut() { let f = fc.data.get_mut().unwrap(); - if self.n_fc > 1 as c_uint { + if fc_len > 1 { let _ = mem::take(&mut f.lowest_pixel_mem); // TODO: remove when context is owned } if self.tc.len() > 1 { @@ -825,12 +778,10 @@ impl Drop for Rav1dContext { rav1d_refmvs_clear(&mut f.rf); let _ = mem::take(&mut f.lf.cdef_line_buf); // TODO: remove when context is owned let _ = mem::take(&mut f.lf.lr_line_buf); // TODO: remove when context is owned - n_1 = n_1.wrapping_add(1); } - rav1d_free_aligned(self.fc as *mut c_void); - if self.n_fc > 1 as c_uint && !self.frame_thread.out_delayed.is_empty() { - let mut n_2: c_uint = 0 as c_int as c_uint; - while n_2 < self.n_fc { + if self.fc.len() > 1 && !self.frame_thread.out_delayed.is_empty() { + let mut n_2 = 0; + while n_2 < self.fc.len() { if self.frame_thread.out_delayed[n_2 as usize] .p .frame_hdr diff --git a/src/obu.rs b/src/obu.rs index 2474a71fd..af8c9c65f 100644 --- a/src/obu.rs +++ b/src/obu.rs @@ -2522,7 +2522,7 @@ unsafe fn parse_obus( { return Err(EINVAL); } - if c.n_fc == 1 { + if c.fc.len() == 1 { c.out = c.refs[frame_hdr.existing_frame_idx as usize].p.clone(); rav1d_picture_copy_props( &mut (*c).out.p, @@ -2537,12 +2537,9 @@ unsafe fn parse_obus( let mut task_thread_lock = c.task_thread.delayed_fg.lock().unwrap(); // Need to append this to the frame output queue. let next = c.frame_thread.next; - c.frame_thread.next += 1; - if c.frame_thread.next == c.n_fc { - c.frame_thread.next = 0; - } + c.frame_thread.next = (c.frame_thread.next + 1) % c.fc.len() as u32; - let fc = &(*c.fc.offset(next as isize)); + let fc = &c.fc[next as usize]; while !fc.task_thread.finished.load(Ordering::SeqCst) { task_thread_lock = fc.task_thread.cond.wait(task_thread_lock).unwrap(); } @@ -2550,7 +2547,7 @@ unsafe fn parse_obus( if out_delayed.p.data.is_some() || fc.task_thread.error.load(Ordering::SeqCst) != 0 { let first = c.task_thread.first.load(Ordering::SeqCst); - if first + 1 < c.n_fc { + if first as usize + 1 < c.fc.len() { c.task_thread.first.fetch_add(1, Ordering::SeqCst); } else { c.task_thread.first.store(0, Ordering::SeqCst); @@ -2562,7 +2559,7 @@ unsafe fn parse_obus( Ordering::SeqCst, ); if c.task_thread.cur.load(Ordering::Relaxed) != 0 - && c.task_thread.cur.load(Ordering::Relaxed) < c.n_fc + && (c.task_thread.cur.load(Ordering::Relaxed) as usize) < c.fc.len() { c.task_thread.cur.fetch_sub(1, Ordering::Relaxed); } diff --git a/src/picture.rs b/src/picture.rs index 172121239..46e1b1ceb 100644 --- a/src/picture.rs +++ b/src/picture.rs @@ -247,7 +247,7 @@ pub(crate) unsafe fn rav1d_thread_picture_alloc( itut_t35: Arc>>, ) -> Rav1dResult { let p = &mut f.sr_cur; - let have_frame_mt = c.n_fc > 1; + let have_frame_mt = c.fc.len() > 1; let frame_hdr = &***f.frame_hdr.as_ref().unwrap(); picture_alloc_with_edges( &c.logger, diff --git a/src/refmvs.rs b/src/refmvs.rs index e28426c7a..6b18a8bbd 100644 --- a/src/refmvs.rs +++ b/src/refmvs.rs @@ -204,6 +204,7 @@ pub(crate) struct refmvs_frame<'a> { pub n_frame_threads: c_int, } +#[derive(Default)] pub(crate) struct RefMvsFrame { pub iw4: c_int, pub ih4: c_int, @@ -1708,13 +1709,6 @@ pub(crate) fn rav1d_refmvs_init_frame( Ok(()) } -pub(crate) fn rav1d_refmvs_init(rf: &mut RefMvsFrame) { - rf.r = Default::default(); - rf.r_stride = 0; - rf.rp_proj = Default::default(); - rf.rp_stride = 0; -} - pub(crate) fn rav1d_refmvs_clear(rf: &mut RefMvsFrame) { let _ = mem::take(&mut rf.r); let _ = mem::take(&mut rf.rp_proj); diff --git a/src/thread_task.rs b/src/thread_task.rs index 95bd7ea10..c15371868 100644 --- a/src/thread_task.rs +++ b/src/thread_task.rs @@ -58,14 +58,9 @@ pub const TILE_ERROR: i32 = i32::MAX - 1; /// this special case. #[inline] unsafe fn reset_task_cur(c: &Rav1dContext, ttd: &TaskThreadData, mut frame_idx: c_uint) -> c_int { - unsafe fn curr_found(c: &Rav1dContext, ttd: &TaskThreadData, first: u32) -> c_int { - let mut i: c_uint = ttd.cur.load(Ordering::Relaxed); - while i < c.n_fc { - (*(*(c.fc).offset(first.wrapping_add(i).wrapping_rem(c.n_fc) as isize)) - .task_thread - .tasks()) - .cur_prev = None; - i = i + 1; + unsafe fn curr_found(c: &Rav1dContext, ttd: &TaskThreadData, first: usize) -> c_int { + for i in ttd.cur.load(Ordering::Relaxed) as usize..c.fc.len() { + (*c.fc[(first + i) % c.fc.len()].task_thread.tasks()).cur_prev = None; } return 1; } @@ -80,7 +75,7 @@ unsafe fn reset_task_cur(c: &Rav1dContext, ttd: &TaskThreadData, mut frame_idx: reset_frame_idx = u32::MAX; } if ttd.cur.load(Ordering::Relaxed) == 0 - && ((*(*(c.fc).offset(first as isize)).task_thread.tasks()).cur_prev).is_none() + && ((*c.fc[first as usize].task_thread.tasks()).cur_prev).is_none() { return 0 as c_int; } @@ -91,7 +86,7 @@ unsafe fn reset_task_cur(c: &Rav1dContext, ttd: &TaskThreadData, mut frame_idx: } ttd.cur .store(reset_frame_idx.wrapping_sub(first), Ordering::Relaxed); - return curr_found(c, ttd, first); + return curr_found(c, ttd, first as usize); } } else { if frame_idx == u32::MAX { @@ -99,23 +94,19 @@ unsafe fn reset_task_cur(c: &Rav1dContext, ttd: &TaskThreadData, mut frame_idx: } } if frame_idx < first { - frame_idx = frame_idx.wrapping_add(c.n_fc); + frame_idx += c.fc.len() as c_uint; } min_frame_idx = cmp::min(reset_frame_idx, frame_idx); cur_frame_idx = first.wrapping_add(ttd.cur.load(Ordering::Relaxed)); - if ttd.cur.load(Ordering::Relaxed) < c.n_fc && cur_frame_idx < min_frame_idx { + if (ttd.cur.load(Ordering::Relaxed) as usize) < c.fc.len() && cur_frame_idx < min_frame_idx { return 0 as c_int; } ttd.cur .store(min_frame_idx.wrapping_sub(first), Ordering::Relaxed); - while ttd.cur.load(Ordering::Relaxed) < c.n_fc { - if (*(*(c.fc).offset( - first - .wrapping_add(ttd.cur.load(Ordering::Relaxed)) - .wrapping_rem(c.n_fc) as isize, - )) - .task_thread - .tasks()) + while (ttd.cur.load(Ordering::Relaxed) as usize) < c.fc.len() { + if (*c.fc[((first + ttd.cur.load(Ordering::Relaxed)) as usize) % c.fc.len()] + .task_thread + .tasks()) .head .is_some() { @@ -123,7 +114,7 @@ unsafe fn reset_task_cur(c: &Rav1dContext, ttd: &TaskThreadData, mut frame_idx: } ttd.cur.fetch_add(1, Ordering::Relaxed); } - return curr_found(c, ttd, first); + return curr_found(c, ttd, first as usize); } #[inline] @@ -300,10 +291,8 @@ unsafe fn merge_pending_frame(c: &Rav1dContext, f: &Rav1dFrameContext) -> c_int #[inline] unsafe fn merge_pending(c: &Rav1dContext) -> c_int { let mut res = 0; - let mut i: c_uint = 0 as c_int as c_uint; - while i < c.n_fc { - res |= merge_pending_frame(c, &mut *(c.fc).offset(i as isize)); - i = i.wrapping_add(1); + for fc in c.fc.iter() { + res |= merge_pending_frame(c, fc); } return res; } @@ -322,7 +311,7 @@ unsafe fn create_filter_sbrow( let has_resize = (frame_hdr.size.width[0] != frame_hdr.size.width[1]) as c_int; let has_lr = f.lf.restore_planes; let tasks = &mut *fc.task_thread.tasks(); - let uses_2pass = (c.n_fc > 1 as c_uint) as c_int; + let uses_2pass = (c.fc.len() > 1) as c_int; let num_tasks = (f.sbh * (1 + uses_2pass)) as usize; tasks.grow_tasks(num_tasks); let task_idx = Rav1dTaskIndex::Task((f.sbh * (pass & 1)) as usize); @@ -354,7 +343,7 @@ unsafe fn create_filter_sbrow( } else { TaskType::ReconstructionProgress }; - t.frame_idx = f.index as c_uint; + t.frame_idx = fc.index as c_uint; Ok(task_idx) } @@ -366,7 +355,7 @@ pub(crate) unsafe fn rav1d_task_create_tile_sbrow( _cond_signal: c_int, ) -> Rav1dResult { let tasks = &mut *fc.task_thread.tasks(); - let uses_2pass = (c.n_fc > 1 as c_uint) as c_int; + let uses_2pass = (c.fc.len() > 1) as c_int; let frame_hdr = &***f.frame_hdr.as_ref().unwrap(); let num_tasks = frame_hdr.tiling.cols * frame_hdr.tiling.rows; if pass < 2 { @@ -398,7 +387,7 @@ pub(crate) unsafe fn rav1d_task_create_tile_sbrow( } else { TaskType::TileEntropy }; - t.frame_idx = f.index as c_uint; + t.frame_idx = fc.index as c_uint; if let Some(prev_t) = prev_t { tasks[prev_t].next = Some(t_idx); } @@ -428,13 +417,13 @@ pub(crate) unsafe fn rav1d_task_create_tile_sbrow( Ok(()) } -pub(crate) unsafe fn rav1d_task_frame_init(c: &Rav1dContext, fc: &Rav1dFrameContext, index: usize) { +pub(crate) unsafe fn rav1d_task_frame_init(c: &Rav1dContext, fc: &Rav1dFrameContext) { fc.task_thread.init_done.store(0, Ordering::SeqCst); let tasks = fc.task_thread.tasks(); let t_idx = Rav1dTaskIndex::Init; let t = &mut (*tasks)[t_idx]; t.type_0 = TaskType::Init; - t.frame_idx = index as c_uint; + t.frame_idx = fc.index as c_uint; t.sby = 0 as c_int; t.deblock_progress = 0 as c_int; t.recon_progress = t.deblock_progress; @@ -563,7 +552,7 @@ unsafe fn check_tile( #[inline] unsafe fn get_frame_progress(fc: &Rav1dFrameContext, f: &Rav1dFrameData) -> c_int { - // Note that `progress.is_some() == c.n_fc > 1`. + // Note that `progress.is_some() == c.fc.len() > 1`. let frame_prog = f .sr_cur .progress @@ -766,11 +755,9 @@ pub unsafe fn rav1d_worker_task(c: &Rav1dContext, task_thread: Arc 1 as c_uint) as c_int, + (c.fc.len() > 1) as c_int, ) == 0 { break 'found (fc, t_idx, prev_t); @@ -968,7 +951,7 @@ pub unsafe fn rav1d_worker_task(c: &Rav1dContext, task_thread: Arc { - if !(c.n_fc > 1 as c_uint) { + if !(c.fc.len() > 1) { unreachable!(); } let res = rav1d_decode_frame_init(c, fc); @@ -994,7 +977,7 @@ pub unsafe fn rav1d_worker_task(c: &Rav1dContext, task_thread: Arc { - if !(c.n_fc > 1 as c_uint) { + if !(c.fc.len() > 1) { unreachable!(); } let mut res_0 = Err(EINVAL); @@ -1017,7 +1000,7 @@ pub unsafe fn rav1d_worker_task(c: &Rav1dContext, task_thread: Arc 1 as c_uint) { + if !(c.fc.len() > 1) { unreachable!(); } let mut p_0 = 1; @@ -1041,7 +1024,7 @@ pub unsafe fn rav1d_worker_task(c: &Rav1dContext, task_thread: Arc 1`. + // Note that `progress.is_some() == c.fc.len() > 1`. let progress = &**f.sr_cur.progress.as_ref().unwrap(); progress[(p_0 - 1) as usize] .store(FRAME_ERROR, Ordering::SeqCst); @@ -1085,7 +1068,7 @@ pub unsafe fn rav1d_worker_task(c: &Rav1dContext, task_thread: Arc 1 as c_uint) as c_int; + let uses_2pass = (c.fc.len() > 1) as c_int; tc.frame_thread.pass = if uses_2pass == 0 { 0 as c_int } else { @@ -1106,7 +1089,7 @@ pub unsafe fn rav1d_worker_task(c: &Rav1dContext, task_thread: Arc 1 as c_uint) as c_int; + let uses_2pass_0 = (c.fc.len() > 1) as c_int; let sbh = f.sbh; let sbsz = f.sb_step * 4; if t.type_0 == TaskType::EntropyProgress { @@ -1303,7 +1286,7 @@ pub unsafe fn rav1d_worker_task(c: &Rav1dContext, task_thread: Arc 1`. + // Note that `progress.is_some() == c.fc.len() > 1`. let progress = &**f.sr_cur.progress.as_ref().unwrap(); if f.sr_cur.p.data.is_some() { progress[0].store(if error_0 != 0 { FRAME_ERROR } else { y }, Ordering::SeqCst); @@ -1356,7 +1339,7 @@ pub unsafe fn rav1d_worker_task(c: &Rav1dContext, task_thread: Arc 1`. + // Note that `progress.is_some() == c.fc.len() > 1`. if let Some(progress) = &f.sr_cur.progress { // upon flush, this can be free'ed already if f.sr_cur.p.data.is_some() {