videocall_codecs/frame.rs
1/*
2 * Copyright 2025 Security Union LLC
3 *
4 * Licensed under either of
5 *
6 * * Apache License, Version 2.0
7 * (http://www.apache.org/licenses/LICENSE-2.0)
8 * * MIT license
9 * (http://opensource.org/licenses/MIT)
10 *
11 * at your option.
12 *
13 * Unless you explicitly state otherwise, any contribution intentionally
14 * submitted for inclusion in the work by you, as defined in the Apache-2.0
15 * license, shall be dual licensed as above, without any additional terms or
16 * conditions.
17 */
18
19//! Contains the fundamental data structures for video frames.
20
21use serde::{Deserialize, Serialize};
22
23/// The type of a video frame, indicating its dependency on other frames.
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
25pub enum FrameType {
26 /// A KeyFrame (or I-frame) can be decoded independently of any other frame.
27 KeyFrame,
28 /// A DeltaFrame (or P-frame) can only be decoded if the preceding frame has been decoded.
29 DeltaFrame,
30}
31
32/// The codec used to encode a video frame.
33/// Names include profile/level details for scalability.
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
35pub enum FrameCodec {
36 /// Unknown/unspecified codec - skip decoding.
37 #[default]
38 Unspecified,
39 /// VP8 codec - no profile variants.
40 Vp8,
41 /// VP9 Profile 0, Level 1.0, 8-bit (vp09.00.10.08).
42 Vp9Profile0Level10Bit8,
43}
44
45impl FrameCodec {
46 /// Returns the WebCodecs codec string for this codec, or None for Unspecified.
47 pub fn as_webcodecs_str(&self) -> Option<&'static str> {
48 match self {
49 FrameCodec::Unspecified => None,
50 FrameCodec::Vp8 => Some("vp8"),
51 FrameCodec::Vp9Profile0Level10Bit8 => Some("vp09.00.10.08"),
52 }
53 }
54
55 /// Returns true if this is a known, decodable codec.
56 pub fn is_known(&self) -> bool {
57 !matches!(self, FrameCodec::Unspecified)
58 }
59}
60
61/// Represents a raw, encoded video frame as it arrives from the network.
62/// In our simulation, this is the unit that comes from a QUIC stream.
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct VideoFrame {
65 /// The sequence number of the frame. Must be contiguous.
66 pub sequence_number: u64,
67 /// The type of the frame (KeyFrame or DeltaFrame).
68 pub frame_type: FrameType,
69 /// The codec used to encode this frame.
70 #[serde(default)]
71 pub codec: FrameCodec,
72 /// The encoded video data.
73 pub data: Vec<u8>,
74 /// The timestamp of the frame.
75 pub timestamp: f64,
76}
77
78/// A wrapper for a `VideoFrame` that includes metadata used by the jitter buffer.
79/// This is the object that is stored and managed within the buffer itself.
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct FrameBuffer {
82 /// The underlying video frame data and properties.
83 pub frame: VideoFrame,
84 /// The system time when this frame was received by the jitter buffer.
85 pub arrival_time_ms: u128,
86}
87
88impl FrameBuffer {
89 /// Creates a new, empty `FrameBuffer` ready to be populated.
90 /// In a real system with object pooling, this would be reused.
91 pub fn new(frame: VideoFrame, arrival_time_ms: u128) -> Self {
92 Self {
93 frame,
94 arrival_time_ms,
95 }
96 }
97
98 pub fn sequence_number(&self) -> u64 {
99 self.frame.sequence_number
100 }
101
102 pub fn is_keyframe(&self) -> bool {
103 self.frame.frame_type == FrameType::KeyFrame
104 }
105}