rtmp_rs/registry/
frame.rs

1//! Broadcast frame types for stream routing
2//!
3//! This module defines the key types for identifying streams and the frames
4//! that are broadcast to subscribers.
5
6use bytes::Bytes;
7
8use crate::media::flv::{FlvTag, FlvTagType};
9
10/// Unique identifier for a stream (app + stream name)
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12pub struct StreamKey {
13    /// Application name (e.g., "live")
14    pub app: String,
15    /// Stream name/key (e.g., "stream_key_123")
16    pub name: String,
17}
18
19impl StreamKey {
20    /// Create a new stream key
21    pub fn new(app: impl Into<String>, name: impl Into<String>) -> Self {
22        Self {
23            app: app.into(),
24            name: name.into(),
25        }
26    }
27}
28
29impl std::fmt::Display for StreamKey {
30    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31        write!(f, "{}/{}", self.app, self.name)
32    }
33}
34
35/// Type of broadcast frame
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum FrameType {
38    /// Video frame
39    Video,
40    /// Audio frame
41    Audio,
42    /// Metadata (onMetaData)
43    Metadata,
44}
45
46/// A frame to be broadcast to subscribers
47///
48/// This is designed to be cheap to clone due to `Bytes` reference counting.
49#[derive(Debug, Clone)]
50pub struct BroadcastFrame {
51    /// Type of frame
52    pub frame_type: FrameType,
53    /// Timestamp in milliseconds
54    pub timestamp: u32,
55    /// Frame data (zero-copy via reference counting)
56    pub data: Bytes,
57    /// Whether this is a keyframe (video only)
58    pub is_keyframe: bool,
59    /// Whether this is a sequence header
60    pub is_header: bool,
61}
62
63impl BroadcastFrame {
64    /// Create a video frame
65    pub fn video(timestamp: u32, data: Bytes, is_keyframe: bool, is_header: bool) -> Self {
66        Self {
67            frame_type: FrameType::Video,
68            timestamp,
69            data,
70            is_keyframe,
71            is_header,
72        }
73    }
74
75    /// Create an audio frame
76    pub fn audio(timestamp: u32, data: Bytes, is_header: bool) -> Self {
77        Self {
78            frame_type: FrameType::Audio,
79            timestamp,
80            data,
81            is_keyframe: false,
82            is_header,
83        }
84    }
85
86    /// Create a metadata frame
87    pub fn metadata(data: Bytes) -> Self {
88        Self {
89            frame_type: FrameType::Metadata,
90            timestamp: 0,
91            data,
92            is_keyframe: false,
93            is_header: false,
94        }
95    }
96
97    /// Convert from FLV tag
98    pub fn from_flv_tag(tag: &FlvTag) -> Self {
99        match tag.tag_type {
100            FlvTagType::Video => {
101                let is_keyframe = tag.is_keyframe();
102                let is_header = tag.is_avc_sequence_header();
103                Self::video(tag.timestamp, tag.data.clone(), is_keyframe, is_header)
104            }
105            FlvTagType::Audio => {
106                let is_header = tag.is_aac_sequence_header();
107                Self::audio(tag.timestamp, tag.data.clone(), is_header)
108            }
109            FlvTagType::Script => Self::metadata(tag.data.clone()),
110        }
111    }
112}