use crate::error::OxiResult;
use crate::types::{CodecId, MediaType, Rational, Timestamp};
#[derive(Clone, Debug)]
pub struct StreamInfo {
pub index: u32,
pub media_type: MediaType,
pub codec_id: CodecId,
pub timebase: Rational,
pub duration: Option<i64>,
pub extra_data: Vec<u8>,
pub video: Option<VideoStreamInfo>,
pub audio: Option<AudioStreamInfo>,
}
#[derive(Clone, Debug)]
pub struct VideoStreamInfo {
pub width: u32,
pub height: u32,
pub frame_rate: Option<Rational>,
pub pixel_aspect_ratio: Option<Rational>,
}
#[derive(Clone, Debug)]
pub struct AudioStreamInfo {
pub sample_rate: u32,
pub channels: u16,
pub bits_per_sample: Option<u16>,
}
#[derive(Clone, Debug)]
pub struct Packet {
pub stream_index: u32,
pub timestamp: Timestamp,
pub data: Vec<u8>,
pub is_keyframe: bool,
}
impl Packet {
#[must_use]
pub fn new(stream_index: u32, timestamp: Timestamp, data: Vec<u8>, is_keyframe: bool) -> Self {
Self {
stream_index,
timestamp,
data,
is_keyframe,
}
}
}
#[derive(Clone, Debug, Default)]
pub struct ContainerInfo {
pub format_name: String,
pub duration: Option<f64>,
pub file_size: Option<u64>,
pub bit_rate: Option<u64>,
pub seekable: bool,
}
pub trait Demuxer {
fn container_info(&self) -> &ContainerInfo;
fn stream_count(&self) -> usize;
fn stream_info(&self, index: usize) -> &StreamInfo;
fn streams(&self) -> Vec<&StreamInfo>;
fn read_packet(&mut self) -> OxiResult<Option<Packet>>;
fn seek(&mut self, timestamp: f64, stream_index: Option<u32>) -> OxiResult<()>;
fn is_seekable(&self) -> bool {
self.container_info().seekable
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stream_info() {
let info = StreamInfo {
index: 0,
media_type: MediaType::Video,
codec_id: CodecId::Av1,
timebase: Rational::new(1, 1000),
duration: Some(60000),
extra_data: vec![],
video: Some(VideoStreamInfo {
width: 1920,
height: 1080,
frame_rate: Some(Rational::new(30, 1)),
pixel_aspect_ratio: None,
}),
audio: None,
};
assert_eq!(info.media_type, MediaType::Video);
assert_eq!(info.codec_id, CodecId::Av1);
let video = info.video.as_ref().expect("should have value");
assert_eq!(video.width, 1920);
assert_eq!(video.height, 1080);
}
#[test]
fn test_packet_new() {
let timestamp = Timestamp::new(1000, Rational::new(1, 1000));
let packet = Packet::new(0, timestamp, vec![0u8; 1024], true);
assert_eq!(packet.stream_index, 0);
assert!(packet.is_keyframe);
assert_eq!(packet.data.len(), 1024);
}
#[test]
fn test_container_info_default() {
let info = ContainerInfo::default();
assert!(info.format_name.is_empty());
assert!(info.duration.is_none());
assert!(!info.seekable);
}
}