#![deny(missing_docs)]
use crate::api::color::*;
use crate::api::config::*;
use crate::api::internal::*;
use crate::api::util::*;
use bitstream_io::*;
use crate::encoder::*;
use crate::frame::*;
use crate::util::Pixel;
use std::fmt;
use std::io;
use std::sync::Arc;
pub struct Context<T: Pixel> {
pub(crate) inner: ContextInner<T>,
pub(crate) config: EncoderConfig,
pub(crate) pool: Arc<crate::rayon::ThreadPool>,
pub(crate) is_flushing: bool,
}
impl<T: Pixel> Context<T> {
#[inline]
pub fn new_frame(&self) -> Frame<T> {
Frame::new(
self.config.width,
self.config.height,
self.config.chroma_sampling,
)
}
#[inline]
pub fn send_frame<F>(&mut self, frame: F) -> Result<(), EncoderStatus>
where
F: IntoFrame<T>,
{
let (frame, params) = frame.into();
if frame.is_none() {
if self.is_flushing {
return Ok(());
}
self.inner.limit = Some(self.inner.frame_count);
self.is_flushing = true;
} else if self.is_flushing {
return Err(EncoderStatus::EnoughData);
} else if self.inner.frame_count == std::i32::MAX as u64 - 1 {
self.inner.limit = Some(self.inner.frame_count);
self.is_flushing = true;
}
let inner = &mut self.inner;
let pool = &mut self.pool;
pool.install(|| inner.send_frame(frame, params))
}
#[inline]
pub fn twopass_out(&mut self) -> Option<&[u8]> {
let params = self
.inner
.rc_state
.get_twopass_out_params(&self.inner, self.inner.output_frameno);
self.inner.rc_state.twopass_out(params)
}
#[inline]
pub fn twopass_bytes_needed(&mut self) -> usize {
self.inner.rc_state.twopass_in(None).unwrap_or(0)
}
#[inline]
pub fn twopass_in(&mut self, buf: &[u8]) -> Result<usize, EncoderStatus> {
self.inner.rc_state.twopass_in(Some(buf)).or(Err(EncoderStatus::Failure))
}
#[inline]
pub fn receive_packet(&mut self) -> Result<Packet<T>, EncoderStatus> {
let inner = &mut self.inner;
let pool = &mut self.pool;
pool.install(|| inner.receive_packet())
}
#[inline]
pub fn flush(&mut self) {
self.send_frame(None).unwrap();
}
#[inline]
pub fn container_sequence_header(&self) -> Vec<u8> {
fn sequence_header_inner(seq: &Sequence) -> io::Result<Vec<u8>> {
let mut buf = Vec::new();
{
let mut bw = BitWriter::endian(&mut buf, BigEndian);
bw.write_bit(true)?; bw.write(7, 1)?; bw.write(3, seq.profile)?;
bw.write(5, 31)?; bw.write_bit(false)?; bw.write_bit(seq.bit_depth > 8)?; bw.write_bit(seq.bit_depth == 12)?; bw.write_bit(seq.bit_depth == 1)?; bw.write_bit(seq.chroma_sampling != ChromaSampling::Cs444)?; bw.write_bit(seq.chroma_sampling == ChromaSampling::Cs420)?; bw.write(2, 0)?; bw.write(3, 0)?; bw.write_bit(false)?;
bw.write(4, 0)?; }
Ok(buf)
}
let seq = Sequence::new(&self.config);
sequence_header_inner(&seq).unwrap()
}
}
pub enum RcData {
Summary(Box<[u8]>),
Frame(Box<[u8]>),
}
impl<T: Pixel> Context<T> {
pub fn rc_summary_size(&self) -> usize {
crate::rate::TWOPASS_HEADER_SZ
}
pub fn rc_receive_pass_data(&mut self) -> Option<RcData> {
if self.inner.done_processing() && self.inner.rc_state.pass1_data_retrieved
{
let data = self.inner.rc_state.emit_summary();
Some(RcData::Summary(data.to_vec().into_boxed_slice()))
} else if self.inner.rc_state.pass1_data_retrieved {
None
} else if let Some(data) = self.inner.rc_state.emit_frame_data() {
Some(RcData::Frame(data.to_vec().into_boxed_slice()))
} else {
unreachable!(
"The encoder received more frames than its internal limit allows"
)
}
}
pub fn rc_second_pass_data_required(&self) -> usize {
if self.inner.done_processing() {
0
} else {
self.inner.rc_state.twopass_in_frames_needed() as usize
}
}
pub fn rc_send_pass_data(
&mut self, data: &[u8],
) -> Result<(), EncoderStatus> {
self
.inner
.rc_state
.parse_frame_data_packet(data)
.map_err(|_| EncoderStatus::Failure)
}
}
impl<T: Pixel> fmt::Debug for Context<T> {
fn fmt(
&self, f: &mut fmt::Formatter<'_>,
) -> std::result::Result<(), fmt::Error> {
write!(
f,
"{{ \
config: {:?}, \
is_flushing: {}, \
}}",
self.config, self.is_flushing,
)
}
}