openipc_video/api/
frame.rs1use bytes::Bytes;
2
3use super::{DecodedSurface, VideoCodec};
4
5#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
7pub struct VideoTimestamp {
8 pub value: i64,
10 pub timescale: i32,
12}
13
14impl VideoTimestamp {
15 pub const RTP_VIDEO_TIMESCALE: i32 = 90_000;
17
18 pub const fn new(value: i64, timescale: i32) -> Option<Self> {
20 if timescale > 0 {
21 Some(Self { value, timescale })
22 } else {
23 None
24 }
25 }
26
27 pub const fn from_rtp(value: u32) -> Self {
29 Self {
30 value: value as i64,
31 timescale: Self::RTP_VIDEO_TIMESCALE,
32 }
33 }
34}
35
36#[derive(Debug, Clone, PartialEq, Eq)]
38pub struct EncodedAccessUnit {
39 pub codec: VideoCodec,
41 pub data: Bytes,
43 pub timestamp: VideoTimestamp,
45 pub keyframe: bool,
47 pub sequence_number: Option<u16>,
49 pub damaged: bool,
51}
52
53impl EncodedAccessUnit {
54 pub fn new(
56 codec: VideoCodec,
57 data: impl Into<Bytes>,
58 timestamp: VideoTimestamp,
59 keyframe: bool,
60 ) -> Self {
61 Self {
62 codec,
63 data: data.into(),
64 timestamp,
65 keyframe,
66 sequence_number: None,
67 damaged: false,
68 }
69 }
70
71 pub const fn can_resynchronize(&self) -> bool {
73 self.keyframe && !self.damaged
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::{EncodedAccessUnit, VideoTimestamp};
80 use crate::VideoCodec;
81
82 #[test]
83 fn only_clean_keyframes_can_resynchronize_a_decoder() {
84 let mut frame = EncodedAccessUnit::new(
85 VideoCodec::H264,
86 vec![0, 0, 0, 1, 0x65],
87 VideoTimestamp::from_rtp(90_000),
88 true,
89 );
90 assert!(frame.can_resynchronize());
91 frame.damaged = true;
92 assert!(!frame.can_resynchronize());
93 frame.damaged = false;
94 frame.keyframe = false;
95 assert!(!frame.can_resynchronize());
96 }
97}
98
99impl From<openipc_core::DepacketizedFrame> for EncodedAccessUnit {
100 fn from(value: openipc_core::DepacketizedFrame) -> Self {
101 Self {
102 codec: value.codec.into(),
103 data: Bytes::from(value.data),
104 timestamp: VideoTimestamp::from_rtp(value.timestamp),
105 keyframe: value.is_keyframe,
106 sequence_number: Some(value.sequence_number),
107 damaged: value.damaged,
108 }
109 }
110}
111
112#[derive(Debug)]
114pub struct DecodedFrame<S> {
115 pub surface: S,
117 pub timestamp: VideoTimestamp,
119 pub duration: Option<VideoTimestamp>,
121}
122
123impl<S: DecodedSurface> DecodedFrame<S> {
124 pub fn dimensions(&self) -> super::FrameDimensions {
126 self.surface.dimensions()
127 }
128}