From 0d6cbc55aa277a50df8863fa43cf8fce48dc877c Mon Sep 17 00:00:00 2001 From: Stephen Crane Date: Tue, 23 Apr 2024 18:53:09 -0700 Subject: [PATCH] `Rav1dContext`: Make frame contexts a boxed slice Replaces the C allocation and `fc` array pointer of `Rav1dFrameContext` structures with a Rust boxed slice. --- src/decode.rs | 45 +++++++++++------------- src/internal.rs | 61 +++++++++++++++++++++++++++++--- src/lib.rs | 88 +++++++++++++++------------------------------- src/obu.rs | 13 +++---- src/picture.rs | 2 +- src/thread_task.rs | 88 ++++++++++++++++++++-------------------------- 6 files changed, 150 insertions(+), 147 deletions(-) diff --git a/src/decode.rs b/src/decode.rs index 0ea0a2f5d..92c07280b 100644 --- a/src/decode.rs +++ b/src/decode.rs @@ -3886,7 +3886,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]; } @@ -4094,7 +4094,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); } @@ -4107,7 +4107,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); @@ -4115,7 +4115,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 { @@ -4282,7 +4282,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 @@ -4344,7 +4344,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, )?; } @@ -4419,7 +4419,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; @@ -4586,7 +4586,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 @@ -4622,7 +4622,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); @@ -4674,15 +4674,12 @@ 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).wrapping_rem(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(); } @@ -4690,7 +4687,7 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { if !out_delayed.p.data.data[0].is_null() || 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); @@ -4703,7 +4700,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); } } @@ -4722,7 +4719,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(); @@ -4827,7 +4824,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); @@ -4884,7 +4881,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 { rav1d_thread_picture_ref(&mut c.out, &mut f.sr_cur); c.event_flags |= f.sr_cur.flags.into(); @@ -4905,7 +4902,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,7 +5014,7 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { } } - if c.n_fc == 1 { + if c.fc.len() == 1 { drop(f); let res = rav1d_decode_frame(c, &fc); if res.is_err() { @@ -5037,8 +5034,8 @@ pub unsafe fn rav1d_submit_frame(c: &mut Rav1dContext) -> Rav1dResult { return res; } } else { - let index = f.index; - let fc = &mut (*c.fc.offset(index as isize)); + let index = fc.index; + let fc = &c.fc[index as usize]; rav1d_task_frame_init(c, fc, index); } diff --git a/src/internal.rs b/src/internal.rs index df2368b1f..f3f908618 100644 --- a/src/internal.rs +++ b/src/internal.rs @@ -249,9 +249,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, @@ -312,8 +325,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 @@ -367,6 +379,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 @@ -783,6 +804,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() @@ -798,6 +839,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, @@ -805,6 +849,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: RwLock::new(CdfThreadContext::default()), + task_thread: Rav1dFrameContext_task_thread::default(), + frame_thread_progress: Rav1dFrameContext_frame_thread_progress::default(), + } + } + pub fn in_cdf<'a>(&'a self) -> RwLockReadGuard<'a, CdfThreadContext> { self.in_cdf.try_read().unwrap() } @@ -822,9 +876,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], diff --git a/src/lib.rs b/src/lib.rs index 0c66848a0..0e2f6d8ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -249,23 +249,11 @@ 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), - ); + (*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)], @@ -274,8 +262,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([]) }); @@ -284,10 +272,9 @@ pub(crate) unsafe fn rav1d_open(c_out: &mut *mut Rav1dContext, s: &Rav1dSettings 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); + let fc = &mut (*c).fc[n]; addr_of_mut!(fc.data).write(RwLock::new(Rav1dFrameData::zeroed())); 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(()))); @@ -439,7 +426,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(); @@ -448,7 +435,7 @@ unsafe fn drain_picture(c: &mut Rav1dContext, out: &mut Rav1dPicture) -> Rav1dRe if !out_delayed.p.data.data[0].is_null() || 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); @@ -460,7 +447,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); } @@ -469,7 +456,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); @@ -491,7 +478,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; } } @@ -572,10 +559,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) @@ -691,7 +678,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); @@ -702,45 +689,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() { rav1d_thread_picture_unref(out_delayed); } - n = n.wrapping_add(1); - next = next.wrapping_add(1); } (*c).frame_thread.next = 0 as c_int as c_uint; } @@ -800,11 +773,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 { @@ -828,12 +800,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 233576c2f..a5007594d 100644 --- a/src/obu.rs +++ b/src/obu.rs @@ -2519,7 +2519,7 @@ unsafe fn parse_obus( { return Err(EINVAL); } - if c.n_fc == 1 { + if c.fc.len() == 1 { rav1d_thread_picture_ref( &mut c.out, &mut c.refs[frame_hdr.existing_frame_idx as usize].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).wrapping_rem(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(); } @@ -2551,7 +2548,7 @@ unsafe fn parse_obus( || 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); @@ -2563,7 +2560,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 36d56007a..a87eb4800 100644 --- a/src/picture.rs +++ b/src/picture.rs @@ -268,7 +268,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/thread_task.rs b/src/thread_task.rs index f9ed5c4df..2a4fc975d 100644 --- a/src/thread_task.rs +++ b/src/thread_task.rs @@ -56,14 +56,12 @@ 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)) + 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).wrapping_rem(c.fc.len())] .task_thread .tasks()) .cur_prev = None; - i = i + 1; } return 1; } @@ -78,7 +76,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; } @@ -89,7 +87,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 { @@ -97,23 +95,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).wrapping_rem(c.fc.len())] + .task_thread + .tasks()) .head .is_some() { @@ -121,7 +115,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] @@ -298,10 +292,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; } @@ -320,7 +312,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); @@ -352,7 +344,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) } @@ -364,7 +356,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 { @@ -396,7 +388,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); } @@ -561,7 +553,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 @@ -764,11 +756,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); @@ -966,7 +954,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); @@ -992,7 +980,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); @@ -1015,7 +1003,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; @@ -1039,7 +1027,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); @@ -1083,7 +1071,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 { @@ -1104,7 +1092,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 { @@ -1298,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.data[0]).is_null() { progress[0].store(if error_0 != 0 { FRAME_ERROR } else { y }, Ordering::SeqCst); @@ -1351,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.data[0]).is_null() {