use crate::hevc::CompressionContext;
use std::ops::{Deref, DerefMut};
use std::sync::Mutex;
pub(crate) struct CoderScratch {
pub(crate) cc: CompressionContext,
pub(crate) rec_y: Vec<u16>,
pub(crate) rec_cb: Vec<u16>,
pub(crate) rec_cr: Vec<u16>,
pub(crate) cu_depth: Vec<u8>,
pub(crate) mode_map: Vec<u8>,
pub(crate) edge_v: Vec<bool>,
pub(crate) edge_h: Vec<bool>,
pub(crate) qp_map: Vec<u8>,
pub(crate) sao_original: Vec<u16>,
pub(crate) sao_apply: Vec<u16>,
pub(crate) conv_y: Vec<u16>,
pub(crate) conv_cb: Vec<u16>,
pub(crate) conv_cr: Vec<u16>,
pub(crate) stage: Vec<u16>,
pub(crate) stage2: Vec<u16>,
}
impl CoderScratch {
fn new() -> Box<Self> {
Box::new(Self {
cc: CompressionContext::new(),
rec_y: Vec::new(),
rec_cb: Vec::new(),
rec_cr: Vec::new(),
cu_depth: Vec::new(),
mode_map: Vec::new(),
edge_v: Vec::new(),
edge_h: Vec::new(),
qp_map: Vec::new(),
sao_original: Vec::new(),
sao_apply: Vec::new(),
conv_y: Vec::new(),
conv_cb: Vec::new(),
conv_cr: Vec::new(),
stage: Vec::new(),
stage2: Vec::new(),
})
}
}
static STASH: Mutex<Vec<Box<CoderScratch>>> = Mutex::new(Vec::new());
pub(crate) struct ScratchLease(Option<Box<CoderScratch>>);
pub(crate) fn lease() -> ScratchLease {
let recycled = STASH.lock().unwrap().pop();
ScratchLease(Some(recycled.unwrap_or_else(CoderScratch::new)))
}
impl Deref for ScratchLease {
type Target = CoderScratch;
fn deref(&self) -> &CoderScratch {
self.0.as_deref().expect("lease is populated until drop")
}
}
impl DerefMut for ScratchLease {
fn deref_mut(&mut self) -> &mut CoderScratch {
self.0.as_deref_mut().expect("lease is populated until drop")
}
}
impl Drop for ScratchLease {
fn drop(&mut self) {
if let Some(scratch) = self.0.take() {
STASH.lock().unwrap().push(scratch);
}
}
}
#[inline]
pub(crate) fn fill_resize<T: Copy>(out: &mut Vec<T>, len: usize, value: T) {
out.clear();
out.resize(len, value);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn lease_recycles_the_same_workspace() {
let first = {
let mut lease = lease();
lease.rec_y.resize(4096, 7);
lease.rec_y.as_ptr() as usize
};
let lease = lease();
assert!(lease.rec_y.capacity() >= 4096 || lease.rec_y.as_ptr() as usize != first);
}
#[test]
fn fill_resize_overwrites_previous_contents() {
let mut v = vec![9u8; 16];
fill_resize(&mut v, 8, 3);
assert_eq!(v, vec![3u8; 8]);
fill_resize(&mut v, 12, 0);
assert_eq!(v, vec![0u8; 12]);
}
}