use bytes::Bytes;
use super::{DecodedSurface, VideoCodec};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct VideoTimestamp {
pub value: i64,
pub timescale: i32,
}
impl VideoTimestamp {
pub const RTP_VIDEO_TIMESCALE: i32 = 90_000;
pub const fn new(value: i64, timescale: i32) -> Option<Self> {
if timescale > 0 {
Some(Self { value, timescale })
} else {
None
}
}
pub const fn from_rtp(value: u32) -> Self {
Self {
value: value as i64,
timescale: Self::RTP_VIDEO_TIMESCALE,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EncodedAccessUnit {
pub codec: VideoCodec,
pub data: Bytes,
pub timestamp: VideoTimestamp,
pub keyframe: bool,
pub sequence_number: Option<u16>,
pub damaged: bool,
}
impl EncodedAccessUnit {
pub fn new(
codec: VideoCodec,
data: impl Into<Bytes>,
timestamp: VideoTimestamp,
keyframe: bool,
) -> Self {
Self {
codec,
data: data.into(),
timestamp,
keyframe,
sequence_number: None,
damaged: false,
}
}
pub const fn can_resynchronize(&self) -> bool {
self.keyframe && !self.damaged
}
}
#[cfg(test)]
mod tests {
use super::{EncodedAccessUnit, VideoTimestamp};
use crate::VideoCodec;
#[test]
fn only_clean_keyframes_can_resynchronize_a_decoder() {
let mut frame = EncodedAccessUnit::new(
VideoCodec::H264,
vec![0, 0, 0, 1, 0x65],
VideoTimestamp::from_rtp(90_000),
true,
);
assert!(frame.can_resynchronize());
frame.damaged = true;
assert!(!frame.can_resynchronize());
frame.damaged = false;
frame.keyframe = false;
assert!(!frame.can_resynchronize());
}
}
impl From<openipc_core::DepacketizedFrame> for EncodedAccessUnit {
fn from(value: openipc_core::DepacketizedFrame) -> Self {
Self {
codec: value.codec.into(),
data: Bytes::from(value.data),
timestamp: VideoTimestamp::from_rtp(value.timestamp),
keyframe: value.is_keyframe,
sequence_number: Some(value.sequence_number),
damaged: value.damaged,
}
}
}
#[derive(Debug)]
pub struct DecodedFrame<S> {
pub surface: S,
pub timestamp: VideoTimestamp,
pub duration: Option<VideoTimestamp>,
}
impl<S: DecodedSurface> DecodedFrame<S> {
pub fn dimensions(&self) -> super::FrameDimensions {
self.surface.dimensions()
}
}