spectrusty_core/clock/
ops.rs1use core::cmp::{Ord, PartialEq, PartialOrd};
9use core::convert::TryInto;
10use core::fmt::Debug;
11use core::ops::{Add, Sub, AddAssign, SubAssign};
12
13use crate::video::VideoFrame;
14use super::{VFrameTsCounter, VFrameTs, VideoTs, FTs, Ts};
15
16pub trait TimestampOps: Copy
20 + PartialEq
21 + Eq
22 + PartialOrd
23 + Ord
24 + Debug
25 + Add<FTs, Output=Self>
26 + Sub<FTs, Output=Self>
27 + AddAssign<FTs>
28 + SubAssign<FTs>
29{
30 fn from_tstates(ts: FTs) -> Self;
35 fn into_tstates(self) -> FTs;
40 fn max_value() -> Self;
42 fn min_value() -> Self;
44 fn diff_from(self, ts_from: Self) -> FTs;
49 fn saturating_add(self, other: Self) -> Self;
53 fn saturating_sub(self, other: Self) -> Self;
57}
58
59impl TimestampOps for FTs {
60 #[inline(always)]
61 fn from_tstates(ts: FTs) -> Self {
62 ts
63 }
64 #[inline(always)]
65 fn into_tstates(self) -> FTs {
66 self
67 }
68 #[inline(always)]
69 fn max_value() -> Self {
70 FTs::max_value()
71 }
72 #[inline(always)]
73 fn min_value() -> Self {
74 FTs::min_value()
75 }
76 #[inline(always)]
77 fn diff_from(self, ts_from: Self) -> FTs {
78 self - ts_from
79 }
80 #[inline(always)]
81 fn saturating_add(self, other: Self) -> Self {
82 self.saturating_add(other)
83 }
84 #[inline(always)]
85 fn saturating_sub(self, other: Self) -> Self {
86 self.saturating_sub(other)
87 }
88}
89
90impl <V: VideoFrame> TimestampOps for VFrameTs<V> {
91 #[inline]
92 fn from_tstates(ts: FTs) -> Self {
93 VFrameTs::from_tstates(ts)
94 }
95 #[inline]
96 fn into_tstates(self) -> FTs {
97 VFrameTs::into_tstates(self)
98 }
99 #[inline(always)]
100 fn max_value() -> Self {
101 VFrameTs::max_value()
102 }
103 #[inline(always)]
104 fn min_value() -> Self {
105 VFrameTs::min_value()
106 }
107 #[inline]
108 fn diff_from(self, vts_from: Self) -> FTs {
109 (self.vc as FTs - vts_from.vc as FTs) * V::HTS_COUNT as FTs +
110 (self.hc as FTs - vts_from.hc as FTs)
111 }
112 fn saturating_add(self, other: Self) -> Self {
115 let VideoTs { vc, hc } = self.ts;
116 let vc = vc.saturating_add(other.vc);
117 let hc = hc + other.hc;
118 VFrameTs::new(vc, hc).saturating_normalized()
119 }
120 fn saturating_sub(self, other: Self) -> Self {
123 let VideoTs { vc, hc } = self.ts;
124 let vc = vc.saturating_sub(other.vc);
125 let hc = hc - other.hc;
126 VFrameTs::new(vc, hc).saturating_normalized()
127 }
128}
129
130impl<V: VideoFrame> Add<FTs> for VFrameTs<V> {
131 type Output = Self;
132 #[inline]
137 #[allow(clippy::suspicious_arithmetic_impl)]
138 fn add(self, delta: FTs) -> Self {
139 let VideoTs { vc, hc } = self.ts;
140 let dvc: Ts = (delta / V::HTS_COUNT as FTs).try_into().expect("absolute delta FTs is too large");
141 let dhc = (delta % V::HTS_COUNT as FTs) as Ts;
142 VFrameTs::new(vc + dvc, hc + dhc).normalized()
143 }
144}
145
146impl<V: VideoFrame> AddAssign<FTs> for VFrameTs<V> {
147 #[inline(always)]
148 fn add_assign(&mut self, delta: FTs) {
149 *self = *self + delta
150 }
151}
152
153impl<V: VideoFrame> Sub<FTs> for VFrameTs<V> {
154 type Output = Self;
155 #[inline]
160 #[allow(clippy::suspicious_arithmetic_impl)]
161 fn sub(self, delta: FTs) -> Self {
162 let VideoTs { vc, hc } = self.ts;
163 let dvc: Ts = (delta / V::HTS_COUNT as FTs).try_into().expect("delta too large");
164 let dhc = (delta % V::HTS_COUNT as FTs) as Ts;
165 VFrameTs::new(vc - dvc, hc - dhc).normalized()
166 }
167}
168
169impl<V: VideoFrame> SubAssign<FTs> for VFrameTs<V> {
170 #[inline(always)]
171 fn sub_assign(&mut self, delta: FTs) {
172 *self = *self - delta
173 }
174}
175
176impl<V: VideoFrame> Add<u32> for VFrameTs<V> {
177 type Output = Self;
178 #[inline]
183 #[allow(clippy::suspicious_arithmetic_impl)]
184 fn add(self, delta: u32) -> Self {
185 let VideoTs { vc, hc } = self.ts;
186 let dvc = (delta / V::HTS_COUNT as u32).try_into().expect("delta too large");
187 let dhc = (delta % V::HTS_COUNT as u32) as Ts;
188 let vc = vc.checked_add(dvc).expect("delta too large");
189 VFrameTs::new(vc, hc + dhc).normalized()
190 }
191}
192
193impl<V: VideoFrame> AddAssign<u32> for VFrameTs<V> {
194 #[inline(always)]
195 fn add_assign(&mut self, delta: u32) {
196 *self = *self + delta
197 }
198}
199
200impl<V: VideoFrame> Sub<u32> for VFrameTs<V> {
201 type Output = Self;
202 #[inline]
207 #[allow(clippy::suspicious_arithmetic_impl)]
208 fn sub(self, delta: u32) -> Self {
209 let VideoTs { vc, hc } = self.ts;
210 let dvc = (delta / V::HTS_COUNT as u32).try_into().expect("delta too large");
211 let dhc = (delta % V::HTS_COUNT as u32) as Ts;
212 let vc = vc.checked_sub(dvc).expect("delta too large");
213 VFrameTs::new(vc, hc - dhc).normalized()
214 }
215}
216
217impl<V: VideoFrame> SubAssign<u32> for VFrameTs<V> {
218 #[inline(always)]
219 fn sub_assign(&mut self, delta: u32) {
220 *self = *self - delta
221 }
222}
223
224impl<V: VideoFrame, C> AddAssign<u32> for VFrameTsCounter<V, C> {
225 fn add_assign(&mut self, delta: u32) {
226 self.vts += delta;
227 }
228}
229
230impl<V: VideoFrame, C> SubAssign<u32> for VFrameTsCounter<V, C> {
231 fn sub_assign(&mut self, delta: u32) {
232 self.vts -= delta;
233 }
234}