oximedia_codec/rate_control/
buffer.rs1#![allow(clippy::cast_lossless)]
9#![allow(clippy::cast_precision_loss)]
10#![allow(clippy::cast_possible_truncation)]
11#![allow(clippy::cast_sign_loss)]
12#![forbid(unsafe_code)]
13
14#[derive(Clone, Debug)]
20pub struct RateBuffer {
21 capacity: u64,
23 level: u64,
25 initial_fullness: f32,
27}
28
29impl RateBuffer {
30 #[must_use]
37 pub fn new(capacity: u64, initial_fullness: f32) -> Self {
38 let fullness = initial_fullness.clamp(0.0, 1.0);
39 let level = (capacity as f64 * fullness as f64) as u64;
40 Self {
41 capacity,
42 level,
43 initial_fullness: fullness,
44 }
45 }
46
47 pub fn add_bits(&mut self, bits: u64) -> u64 {
51 let new_level = self.level.saturating_add(bits);
52 if new_level > self.capacity {
53 let overflow = new_level - self.capacity;
54 self.level = self.capacity;
55 overflow
56 } else {
57 self.level = new_level;
58 0
59 }
60 }
61
62 pub fn remove_bits(&mut self, bits: u64) -> u64 {
66 if bits > self.level {
67 let underflow = bits - self.level;
68 self.level = 0;
69 underflow
70 } else {
71 self.level -= bits;
72 0
73 }
74 }
75
76 #[must_use]
78 pub fn level(&self) -> u64 {
79 self.level
80 }
81
82 #[must_use]
84 pub fn capacity(&self) -> u64 {
85 self.capacity
86 }
87
88 #[must_use]
90 pub fn fullness(&self) -> f32 {
91 if self.capacity == 0 {
92 return 0.0;
93 }
94 self.level as f32 / self.capacity as f32
95 }
96
97 #[must_use]
99 pub fn available_space(&self) -> u64 {
100 self.capacity.saturating_sub(self.level)
101 }
102
103 #[must_use]
105 pub fn is_empty(&self) -> bool {
106 self.level == 0
107 }
108
109 #[must_use]
111 pub fn is_full(&self) -> bool {
112 self.level >= self.capacity
113 }
114
115 pub fn reset(&mut self) {
117 self.level = (self.capacity as f64 * self.initial_fullness as f64) as u64;
118 }
119
120 pub fn set_level(&mut self, level: u64) {
122 self.level = level.min(self.capacity);
123 }
124}
125
126impl Default for RateBuffer {
127 fn default() -> Self {
128 Self::new(5_000_000, 0.5)
129 }
130}
131
132#[derive(Clone, Debug)]
137pub struct BufferModel {
138 cpb_size: u64,
140 cpb_level: u64,
142 bitrate: u64,
144 framerate: f64,
146 initial_delay: f64,
148 time_since_removal: f64,
150 overflow_count: u64,
152 underflow_count: u64,
154}
155
156impl BufferModel {
157 #[must_use]
159 pub fn new(cpb_size: u64, bitrate: u64, framerate: f64, initial_delay: f64) -> Self {
160 let initial_level = (bitrate as f64 * initial_delay) as u64;
162
163 Self {
164 cpb_size,
165 cpb_level: initial_level.min(cpb_size),
166 bitrate,
167 framerate,
168 initial_delay,
169 time_since_removal: 0.0,
170 overflow_count: 0,
171 underflow_count: 0,
172 }
173 }
174
175 pub fn fill_for_frame(&mut self) {
177 let frame_duration = 1.0 / self.framerate;
178 let bits_to_add = (self.bitrate as f64 * frame_duration) as u64;
179
180 let new_level = self.cpb_level.saturating_add(bits_to_add);
181 if new_level > self.cpb_size {
182 self.overflow_count += 1;
183 self.cpb_level = self.cpb_size;
184 } else {
185 self.cpb_level = new_level;
186 }
187
188 self.time_since_removal += frame_duration;
189 }
190
191 pub fn remove_frame_bits(&mut self, bits: u64) {
193 if bits > self.cpb_level {
194 self.underflow_count += 1;
195 self.cpb_level = 0;
196 } else {
197 self.cpb_level -= bits;
198 }
199 self.time_since_removal = 0.0;
200 }
201
202 pub fn encode_frame(&mut self, bits: u64) {
206 self.fill_for_frame();
207 self.remove_frame_bits(bits);
208 }
209
210 #[must_use]
212 pub fn max_frame_bits(&self) -> u64 {
213 let frame_duration = 1.0 / self.framerate;
215 let bits_added = (self.bitrate as f64 * frame_duration) as u64;
216
217 self.cpb_level.saturating_add(bits_added).min(self.cpb_size)
219 }
220
221 #[must_use]
223 pub fn min_frame_bits(&self) -> u64 {
224 let frame_duration = 1.0 / self.framerate;
226 let bits_added = (self.bitrate as f64 * frame_duration) as u64;
227 let future_level = self.cpb_level.saturating_add(bits_added);
228
229 future_level.saturating_sub(self.cpb_size)
231 }
232
233 #[must_use]
235 pub fn is_healthy(&self) -> bool {
236 let fullness = self.fullness();
237 (0.2..=0.8).contains(&fullness)
238 }
239
240 #[must_use]
242 pub fn fullness(&self) -> f32 {
243 if self.cpb_size == 0 {
244 return 0.0;
245 }
246 self.cpb_level as f32 / self.cpb_size as f32
247 }
248
249 #[must_use]
251 pub fn level(&self) -> u64 {
252 self.cpb_level
253 }
254
255 #[must_use]
257 pub fn cpb_size(&self) -> u64 {
258 self.cpb_size
259 }
260
261 #[must_use]
263 pub fn overflow_count(&self) -> u64 {
264 self.overflow_count
265 }
266
267 #[must_use]
269 pub fn underflow_count(&self) -> u64 {
270 self.underflow_count
271 }
272
273 pub fn reset(&mut self) {
275 let initial_level = (self.bitrate as f64 * self.initial_delay) as u64;
276 self.cpb_level = initial_level.min(self.cpb_size);
277 self.time_since_removal = 0.0;
278 self.overflow_count = 0;
279 self.underflow_count = 0;
280 }
281}
282
283impl Default for BufferModel {
284 fn default() -> Self {
285 Self::new(5_000_000, 5_000_000, 30.0, 0.5)
286 }
287}
288
289#[derive(Clone, Debug)]
291pub struct VbvParams {
292 pub max_buffer_size: u64,
294 pub max_bitrate: u64,
296 pub initial_delay: f64,
298 pub enabled: bool,
300}
301
302impl VbvParams {
303 #[must_use]
305 pub fn from_bitrate(bitrate: u64) -> Self {
306 Self {
307 max_buffer_size: bitrate * 2, max_bitrate: bitrate,
309 initial_delay: 0.5,
310 enabled: true,
311 }
312 }
313
314 #[must_use]
316 pub fn for_streaming(bitrate: u64, buffer_seconds: f64) -> Self {
317 Self {
318 max_buffer_size: (bitrate as f64 * buffer_seconds) as u64,
319 max_bitrate: bitrate,
320 initial_delay: buffer_seconds / 2.0,
321 enabled: true,
322 }
323 }
324
325 #[must_use]
327 pub fn disabled() -> Self {
328 Self {
329 max_buffer_size: u64::MAX,
330 max_bitrate: u64::MAX,
331 initial_delay: 0.0,
332 enabled: false,
333 }
334 }
335}
336
337impl Default for VbvParams {
338 fn default() -> Self {
339 Self::from_bitrate(5_000_000)
340 }
341}
342
343#[cfg(test)]
344mod tests {
345 use super::*;
346
347 #[test]
348 fn test_rate_buffer_creation() {
349 let buffer = RateBuffer::new(1_000_000, 0.5);
350 assert_eq!(buffer.capacity(), 1_000_000);
351 assert_eq!(buffer.level(), 500_000);
352 assert!((buffer.fullness() - 0.5).abs() < f32::EPSILON);
353 }
354
355 #[test]
356 fn test_rate_buffer_add_bits() {
357 let mut buffer = RateBuffer::new(1_000_000, 0.0);
358 assert_eq!(buffer.level(), 0);
359
360 buffer.add_bits(500_000);
361 assert_eq!(buffer.level(), 500_000);
362
363 let overflow = buffer.add_bits(600_000);
365 assert_eq!(overflow, 100_000);
366 assert_eq!(buffer.level(), 1_000_000);
367 assert!(buffer.is_full());
368 }
369
370 #[test]
371 fn test_rate_buffer_remove_bits() {
372 let mut buffer = RateBuffer::new(1_000_000, 0.5);
373
374 buffer.remove_bits(200_000);
375 assert_eq!(buffer.level(), 300_000);
376
377 let underflow = buffer.remove_bits(400_000);
379 assert_eq!(underflow, 100_000);
380 assert_eq!(buffer.level(), 0);
381 assert!(buffer.is_empty());
382 }
383
384 #[test]
385 fn test_rate_buffer_available_space() {
386 let buffer = RateBuffer::new(1_000_000, 0.5);
387 assert_eq!(buffer.available_space(), 500_000);
388 }
389
390 #[test]
391 fn test_rate_buffer_reset() {
392 let mut buffer = RateBuffer::new(1_000_000, 0.5);
393 buffer.add_bits(500_000);
394 buffer.reset();
395 assert_eq!(buffer.level(), 500_000);
396 }
397
398 #[test]
399 fn test_buffer_model_creation() {
400 let model = BufferModel::new(5_000_000, 5_000_000, 30.0, 0.5);
401 assert_eq!(model.cpb_size(), 5_000_000);
402 assert_eq!(model.level(), 2_500_000);
404 }
405
406 #[test]
407 fn test_buffer_model_encode_frame() {
408 let mut model = BufferModel::new(5_000_000, 5_000_000, 30.0, 0.5);
409 let initial_level = model.level();
410
411 let target_bits = 5_000_000 / 30; model.encode_frame(target_bits);
414
415 let diff = (model.level() as i64 - initial_level as i64).abs();
417 assert!(diff < 100); }
419
420 #[test]
421 fn test_buffer_model_max_min_bits() {
422 let model = BufferModel::new(5_000_000, 5_000_000, 30.0, 0.5);
423
424 let max_bits = model.max_frame_bits();
425 let min_bits = model.min_frame_bits();
426
427 assert!(max_bits > 0);
428 assert!(max_bits >= min_bits);
429 }
430
431 #[test]
432 fn test_buffer_model_overflow() {
433 let mut model = BufferModel::new(1_000_000, 5_000_000, 30.0, 0.9);
434
435 for _ in 0..60 {
437 model.fill_for_frame();
438 model.remove_frame_bits(1000); }
440
441 assert!(model.overflow_count() > 0);
442 }
443
444 #[test]
445 fn test_buffer_model_underflow() {
446 let mut model = BufferModel::new(1_000_000, 5_000_000, 30.0, 0.1);
447
448 model.remove_frame_bits(500_000);
450
451 assert!(model.underflow_count() > 0 || model.level() == 0);
452 }
453
454 #[test]
455 fn test_vbv_params() {
456 let vbv = VbvParams::from_bitrate(5_000_000);
457 assert!(vbv.enabled);
458 assert_eq!(vbv.max_bitrate, 5_000_000);
459 assert_eq!(vbv.max_buffer_size, 10_000_000);
460
461 let vbv = VbvParams::for_streaming(5_000_000, 2.0);
462 assert_eq!(vbv.max_buffer_size, 10_000_000);
463 assert!((vbv.initial_delay - 1.0).abs() < f64::EPSILON);
464
465 let vbv = VbvParams::disabled();
466 assert!(!vbv.enabled);
467 }
468}