use crate::{
Received, Sent, Timebase, Timestamp,
adapter::{AudioAdapter, ImageAdapter, SubtitleAdapter, VideoAdapter},
demuxer::AttachmentPacket,
frame::{AudioFrame, ImageFrame, SubtitleFrame, VideoFrame},
packet::{AudioPacket, SubtitlePacket, VideoPacket},
};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ScaledOutputCapability {
Unsupported,
Supported,
}
impl ScaledOutputCapability {
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn is_supported(&self) -> bool {
matches!(self, Self::Supported)
}
}
pub trait VideoStreamDecoder {
type Adapter: VideoAdapter;
type Buffer: AsRef<[u8]>;
type Error;
fn send_packet(
&mut self,
packet: &VideoPacket<<Self::Adapter as VideoAdapter>::PacketExtra, Self::Buffer>,
) -> Result<Sent, Self::Error>;
fn receive_frame(
&mut self,
dst: &mut VideoFrame<
<Self::Adapter as VideoAdapter>::PixelFormat,
<Self::Adapter as VideoAdapter>::FrameExtra,
Self::Buffer,
>,
) -> Result<Received, Self::Error>;
fn send_eof(&mut self) -> Result<Sent, Self::Error>;
fn flush(&mut self) -> Result<(), Self::Error>;
fn scaled_output_capability(&self) -> ScaledOutputCapability {
ScaledOutputCapability::Unsupported
}
fn request_scaled_output(&mut self, size: (u32, u32)) -> ScaledOutputCapability {
let _ = size;
ScaledOutputCapability::Unsupported
}
}
pub trait VideoFrameSource {
type Adapter: VideoAdapter;
type Buffer: AsRef<[u8]>;
type ClipMeta;
type Error;
fn frame_count(&self) -> u64;
fn frame_rate(&self) -> Timebase;
fn duration(&self) -> Timestamp;
fn clip_meta(&self) -> &Self::ClipMeta;
fn decode_frame(
&mut self,
index: u64,
dst: &mut VideoFrame<
<Self::Adapter as VideoAdapter>::PixelFormat,
<Self::Adapter as VideoAdapter>::FrameExtra,
Self::Buffer,
>,
) -> Result<(), Self::Error>;
}
pub trait AudioStreamDecoder {
type Adapter: AudioAdapter;
type Buffer: AsRef<[u8]>;
type Error;
fn send_packet(
&mut self,
packet: &AudioPacket<<Self::Adapter as AudioAdapter>::PacketExtra, Self::Buffer>,
) -> Result<Sent, Self::Error>;
fn receive_frame(
&mut self,
dst: &mut AudioFrame<
<Self::Adapter as AudioAdapter>::SampleFormat,
<Self::Adapter as AudioAdapter>::ChannelLayout,
<Self::Adapter as AudioAdapter>::FrameExtra,
Self::Buffer,
>,
) -> Result<Received, Self::Error>;
fn send_eof(&mut self) -> Result<Sent, Self::Error>;
fn flush(&mut self) -> Result<(), Self::Error>;
}
pub trait AudioFrameSource {
type Adapter: AudioAdapter;
type Buffer: AsRef<[u8]>;
type ClipMeta;
type Error;
fn sample_count(&self) -> u64;
fn sample_rate(&self) -> u32;
fn channel_count(&self) -> u8;
fn clip_meta(&self) -> &Self::ClipMeta;
fn decode_block(
&mut self,
sample_offset: u64,
sample_count: u32,
dst: &mut AudioFrame<
<Self::Adapter as AudioAdapter>::SampleFormat,
<Self::Adapter as AudioAdapter>::ChannelLayout,
<Self::Adapter as AudioAdapter>::FrameExtra,
Self::Buffer,
>,
) -> Result<(), Self::Error>;
}
pub trait SubtitleDecoder {
type Adapter: SubtitleAdapter;
type Buffer: AsRef<[u8]>;
type Error;
fn send_packet(
&mut self,
packet: &SubtitlePacket<<Self::Adapter as SubtitleAdapter>::PacketExtra, Self::Buffer>,
) -> Result<Sent, Self::Error>;
fn receive_frame(
&mut self,
dst: &mut SubtitleFrame<<Self::Adapter as SubtitleAdapter>::FrameExtra, Self::Buffer>,
) -> Result<Received, Self::Error>;
fn send_eof(&mut self) -> Result<Sent, Self::Error>;
fn flush(&mut self) -> Result<(), Self::Error>;
}
pub trait ImageDecoder {
type Adapter: ImageAdapter;
type Buffer: AsRef<[u8]>;
type Error;
fn decode(
&mut self,
packet: &AttachmentPacket<<Self::Adapter as ImageAdapter>::PacketExtra, Self::Buffer>,
) -> Result<
ImageFrame<
<Self::Adapter as ImageAdapter>::PixelFormat,
<Self::Adapter as ImageAdapter>::FrameExtra,
Self::Buffer,
>,
Self::Error,
>;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Timebase;
use core::num::NonZeroI32;
pub(crate) struct VLoop;
impl VideoAdapter for VLoop {
type CodecId = u32;
type PixelFormat = u32;
type PacketExtra = ();
type FrameExtra = ();
}
pub(crate) struct LoopVideoStream;
#[derive(Debug)]
pub(crate) struct LoopError;
impl VideoStreamDecoder for LoopVideoStream {
type Adapter = VLoop;
type Buffer = &'static [u8];
type Error = LoopError;
fn send_packet(&mut self, _: &VideoPacket<(), &'static [u8]>) -> Result<Sent, LoopError> {
Ok(Sent::Accepted)
}
fn receive_frame(
&mut self,
_: &mut VideoFrame<u32, (), &'static [u8]>,
) -> Result<Received, LoopError> {
Ok(Received::NeedsInput)
}
fn send_eof(&mut self) -> Result<Sent, LoopError> {
Ok(Sent::Accepted)
}
fn flush(&mut self) -> Result<(), LoopError> {
Ok(())
}
}
pub(crate) struct LoopVideoSource;
impl VideoFrameSource for LoopVideoSource {
type Adapter = VLoop;
type Buffer = &'static [u8];
type ClipMeta = ();
type Error = LoopError;
fn frame_count(&self) -> u64 {
0
}
fn frame_rate(&self) -> Timebase {
Timebase::new(30, NonZeroI32::new(1).unwrap())
}
fn duration(&self) -> Timestamp {
Timestamp::new(0, self.frame_rate())
}
fn clip_meta(&self) -> &() {
&()
}
fn decode_frame(
&mut self,
_: u64,
_: &mut VideoFrame<u32, (), &'static [u8]>,
) -> Result<(), LoopError> {
Err(LoopError)
}
}
#[test]
fn video_traits_are_implementable() {
fn _stream<D: VideoStreamDecoder>() {}
fn _source<D: VideoFrameSource>() {}
_stream::<LoopVideoStream>();
_source::<LoopVideoSource>();
}
#[test]
fn scaled_output_defaults_to_unsupported_and_never_errors() {
let mut decoder = LoopVideoStream;
assert_eq!(
decoder.scaled_output_capability(),
ScaledOutputCapability::Unsupported
);
assert_eq!(
decoder.request_scaled_output((64, 64)),
ScaledOutputCapability::Unsupported
);
assert_eq!(
decoder.scaled_output_capability(),
ScaledOutputCapability::Unsupported
);
}
#[test]
fn scaled_output_capability_is_supported_predicate_agrees_with_the_variant() {
assert!(ScaledOutputCapability::Supported.is_supported());
assert!(!ScaledOutputCapability::Unsupported.is_supported());
}
pub(crate) struct ALoop;
impl AudioAdapter for ALoop {
type CodecId = u32;
type SampleFormat = u32;
type ChannelLayout = u32;
type PacketExtra = ();
type FrameExtra = ();
}
pub(crate) struct LoopAudioStream;
impl AudioStreamDecoder for LoopAudioStream {
type Adapter = ALoop;
type Buffer = &'static [u8];
type Error = LoopError;
fn send_packet(&mut self, _: &AudioPacket<(), &'static [u8]>) -> Result<Sent, LoopError> {
Ok(Sent::Accepted)
}
fn receive_frame(
&mut self,
_: &mut AudioFrame<u32, u32, (), &'static [u8]>,
) -> Result<Received, LoopError> {
Ok(Received::NeedsInput)
}
fn send_eof(&mut self) -> Result<Sent, LoopError> {
Ok(Sent::Accepted)
}
fn flush(&mut self) -> Result<(), LoopError> {
Ok(())
}
}
pub(crate) struct LoopAudioSource;
impl AudioFrameSource for LoopAudioSource {
type Adapter = ALoop;
type Buffer = &'static [u8];
type ClipMeta = ();
type Error = LoopError;
fn sample_count(&self) -> u64 {
0
}
fn sample_rate(&self) -> u32 {
48_000
}
fn channel_count(&self) -> u8 {
2
}
fn clip_meta(&self) -> &() {
&()
}
fn decode_block(
&mut self,
_: u64,
_: u32,
_: &mut AudioFrame<u32, u32, (), &'static [u8]>,
) -> Result<(), LoopError> {
Err(LoopError)
}
}
#[test]
fn audio_traits_are_implementable() {
fn _stream<D: AudioStreamDecoder>() {}
fn _source<D: AudioFrameSource>() {}
_stream::<LoopAudioStream>();
_source::<LoopAudioSource>();
}
pub(crate) struct SLoop;
impl SubtitleAdapter for SLoop {
type CodecId = u32;
type PacketExtra = ();
type FrameExtra = ();
}
pub(crate) struct LoopSubtitleStream;
impl SubtitleDecoder for LoopSubtitleStream {
type Adapter = SLoop;
type Buffer = &'static [u8];
type Error = LoopError;
fn send_packet(&mut self, _: &SubtitlePacket<(), &'static [u8]>) -> Result<Sent, LoopError> {
Ok(Sent::Accepted)
}
fn receive_frame(
&mut self,
_: &mut SubtitleFrame<(), &'static [u8]>,
) -> Result<Received, LoopError> {
Ok(Received::NeedsInput)
}
fn send_eof(&mut self) -> Result<Sent, LoopError> {
Ok(Sent::Accepted)
}
fn flush(&mut self) -> Result<(), LoopError> {
Ok(())
}
}
#[test]
fn subtitle_decoder_is_implementable() {
fn _decoder<D: SubtitleDecoder>() {}
_decoder::<LoopSubtitleStream>();
}
pub(crate) struct ILoop;
impl ImageAdapter for ILoop {
type CodecId = u32;
type PixelFormat = u32;
type PacketExtra = ();
type FrameExtra = ();
}
pub(crate) struct LoopImage;
impl ImageDecoder for LoopImage {
type Adapter = ILoop;
type Buffer = &'static [u8];
type Error = LoopError;
fn decode(
&mut self,
_: &AttachmentPacket<(), &'static [u8]>,
) -> Result<ImageFrame<u32, (), &'static [u8]>, LoopError> {
Err(LoopError)
}
}
#[test]
fn image_decoder_is_implementable() {
fn _decoder<D: ImageDecoder>() {}
_decoder::<LoopImage>();
}
#[test]
fn the_one_shot_seam_takes_a_packet_and_answers_a_frame() {
let mut decoder = LoopImage;
let packet: AttachmentPacket<(), &'static [u8]> = AttachmentPacket::new(&[][..], ());
assert!(decoder.decode(&packet).is_err());
}
}