Skip to main content

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}