use crate::api::color::*;
use crate::api::config::EncoderConfig;
use crate::api::context::RcData;
use crate::api::util::*;
use crate::encoder::*;
use crate::frame::*;
use crate::util::Pixel;
use bitstream_io::{BigEndian, BitWrite, BitWriter};
use crossbeam::channel::{Receiver, Sender};
use thiserror::Error;
use std::io;
use std::sync::Arc;
#[derive(PartialEq, Eq, Clone, Copy, Error)]
#[error("sending on a disconnected channel")]
pub struct SendError<T>(pub T);
#[derive(PartialEq, Eq, Clone, Copy, Error)]
pub enum TrySendError<T> {
#[error("sending on a full channel")]
Full(T),
#[error("sending on a disconnected channel")]
Disconnected(T),
}
#[derive(PartialEq, Eq, Clone, Copy, Debug, Error)]
#[error("receiving on an empty and disconnected channel")]
pub struct RecvError;
#[derive(PartialEq, Eq, Clone, Copy, Debug, Error)]
pub enum TryRecvError {
#[error("receiving on an empty channel")]
Empty,
#[error("receiving on an empty and disconnected channel")]
Disconnected,
}
impl<T> SendError<T> {
fn from(value: crossbeam::channel::SendError<T>) -> Self {
Self(value.0)
}
}
impl<T> TrySendError<T> {
fn from(value: crossbeam::channel::TrySendError<T>) -> Self {
use crossbeam::channel::TrySendError::*;
match value {
Full(v) => TrySendError::Full(v),
Disconnected(v) => TrySendError::Disconnected(v),
}
}
}
impl RecvError {
fn from(_: crossbeam::channel::RecvError) -> Self {
RecvError
}
}
impl TryRecvError {
fn from(value: crossbeam::channel::TryRecvError) -> Self {
use crossbeam::channel::TryRecvError::*;
match value {
Empty => TryRecvError::Empty,
Disconnected => TryRecvError::Disconnected,
}
}
}
pub struct RcDataSender {
pub(crate) sender: Sender<RcData>,
pub(crate) limit: u64,
pub(crate) count: u64,
}
impl RcDataSender {
pub(crate) fn new(limit: u64, sender: Sender<RcData>) -> RcDataSender {
Self { sender, limit, count: 0 }
}
pub fn try_send(
&mut self, data: RcData,
) -> Result<(), TrySendError<RcData>> {
if self.limit <= self.count {
Err(TrySendError::Full(data))
} else {
let r = self.sender.try_send(data).map_err(TrySendError::from);
if r.is_ok() {
self.count += 1;
}
r
}
}
pub fn send(&mut self, data: RcData) -> Result<(), SendError<RcData>> {
if self.limit <= self.count {
Err(SendError(data))
} else {
let r = self.sender.send(data).map_err(SendError::from);
if r.is_ok() {
self.count += 1;
}
r
}
}
pub fn len(&self) -> usize {
self.sender.len()
}
pub fn is_empty(&self) -> bool {
self.sender.is_empty()
}
}
pub struct RcDataReceiver(pub(crate) Receiver<RcData>);
impl RcDataReceiver {
pub fn try_recv(&self) -> Result<RcData, TryRecvError> {
self.0.try_recv().map_err(TryRecvError::from)
}
pub fn recv(&self) -> Result<RcData, RecvError> {
self.0.recv().map_err(RecvError::from)
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn iter<'a>(&'a self) -> impl Iterator<Item = RcData> + 'a {
self.0.iter()
}
pub const fn summary_size(&self) -> usize {
crate::rate::TWOPASS_HEADER_SZ
}
}
pub type PassDataChannel = (RcDataSender, RcDataReceiver);
pub type FrameInput<T> = (Option<Arc<Frame<T>>>, Option<FrameParameters>);
pub struct FrameSender<T: Pixel> {
sender: Sender<FrameInput<T>>,
config: Arc<EncoderConfig>,
limit: u64,
count: u64,
}
impl<T: Pixel> FrameSender<T> {
pub(crate) fn new(
limit: u64, sender: Sender<FrameInput<T>>, config: Arc<EncoderConfig>,
) -> FrameSender<T> {
Self { sender, config, limit, count: 0 }
}
pub fn try_send<F: IntoFrame<T>>(
&mut self, frame: F,
) -> Result<(), TrySendError<FrameInput<T>>> {
if self.limit <= self.count {
Err(TrySendError::Full(frame.into()))
} else {
let r = self.sender.try_send(frame.into()).map_err(TrySendError::from);
if r.is_ok() {
self.count += 1;
}
r
}
}
pub fn send<F: IntoFrame<T>>(
&mut self, frame: F,
) -> Result<(), SendError<FrameInput<T>>> {
if self.limit <= self.count {
Err(SendError(frame.into()))
} else {
let r = self.sender.send(frame.into()).map_err(SendError::from);
if r.is_ok() {
self.count += 1;
}
r
}
}
pub fn len(&self) -> usize {
self.sender.len()
}
pub fn is_empty(&self) -> bool {
self.sender.is_empty()
}
}
impl<T: Pixel> FrameSender<T> {
#[inline]
pub fn new_frame(&self) -> Frame<T> {
Frame::new(
self.config.width,
self.config.height,
self.config.chroma_sampling,
)
}
}
pub struct PacketReceiver<T: Pixel> {
pub(crate) receiver: Receiver<Packet<T>>,
pub(crate) config: Arc<EncoderConfig>,
}
impl<T: Pixel> PacketReceiver<T> {
pub fn try_recv(&self) -> Result<Packet<T>, TryRecvError> {
self.receiver.try_recv().map_err(TryRecvError::from)
}
pub fn recv(&self) -> Result<Packet<T>, RecvError> {
self.receiver.recv().map_err(RecvError::from)
}
pub fn len(&self) -> usize {
self.receiver.len()
}
pub fn is_empty(&self) -> bool {
self.receiver.is_empty()
}
pub fn iter<'a>(&'a self) -> impl Iterator<Item = Packet<T>> + 'a {
self.receiver.iter()
}
}
impl<T: Pixel> PacketReceiver<T> {
#[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, u8>(1)?; bw.write::<3, u8>(seq.profile)?;
bw.write::<5, u8>(31)?; bw.write_bit(false)?; bw.write_bit(seq.bit_depth > 8)?; bw.write_bit(seq.bit_depth == 12)?; bw.write_bit(seq.chroma_sampling == ChromaSampling::Cs400)?; bw.write_bit(seq.chroma_sampling != ChromaSampling::Cs444)?; bw.write_bit(seq.chroma_sampling == ChromaSampling::Cs420)?; bw.write::<2, u8>(0)?; bw.write::<3, u8>(0)?; bw.write_bit(false)?;
bw.write::<4, u8>(0)?; }
Ok(buf)
}
let seq = Sequence::new(&self.config);
sequence_header_inner(&seq).unwrap()
}
}
pub type VideoDataChannel<T> = (FrameSender<T>, PacketReceiver<T>);