1use serde::{Deserialize, Serialize};
7
8#[derive(Serialize, Deserialize, Debug)]
9pub struct Root {
10 pub version: u16,
11
12 #[serde(rename = "streamingFormat")]
13 pub streaming_format: u16,
14
15 #[serde(rename = "streamingFormatVersion")]
16 pub streaming_format_version: String,
17
18 #[serde(rename = "supportsDeltaUpdates")]
19 pub streaming_delta_updates: bool,
20
21 #[serde(rename = "commonTrackFields")]
22 pub common_track_fields: CommonTrackFields,
23
24 pub tracks: Vec<Track>,
25}
26
27#[derive(Serialize, Deserialize, Debug, Default)]
28pub struct Track {
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub namespace: Option<String>,
31
32 pub name: String,
33
34 #[serde(rename = "initTrack", skip_serializing_if = "Option::is_none")]
35 pub init_track: Option<String>,
36
37 #[serde(rename = "initData", skip_serializing_if = "Option::is_none")]
38 pub init_data: Option<String>,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub packaging: Option<TrackPackaging>,
42
43 #[serde(rename = "renderGroup", skip_serializing_if = "Option::is_none")]
44 pub render_group: Option<u16>,
45
46 #[serde(rename = "altGroup", skip_serializing_if = "Option::is_none")]
47 pub alt_group: Option<u16>,
48
49 #[serde(rename = "selectionParams")]
50 pub selection_params: SelectionParam,
51
52 #[serde(rename = "temporalId", skip_serializing_if = "Option::is_none")]
53 pub temporal_id: Option<u32>,
54
55 #[serde(rename = "spatialId", skip_serializing_if = "Option::is_none")]
56 pub spatial_id: Option<u32>,
57
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub depends: Option<Vec<String>>,
60}
61
62impl Track {
63 #[allow(dead_code)] fn with_common(&mut self, common: &CommonTrackFields) {
65 if self.namespace.is_none() {
66 self.namespace.clone_from(&common.namespace);
67 }
68 if self.packaging.is_none() {
69 self.packaging.clone_from(&common.packaging);
70 }
71 if self.render_group.is_none() {
72 self.render_group = common.render_group;
73 }
74 if self.alt_group.is_none() {
75 self.alt_group = common.alt_group;
76 }
77 }
78}
79
80#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Default)]
81pub enum TrackPackaging {
82 #[serde(rename = "cmaf")]
83 #[default]
84 Cmaf,
85
86 #[serde(rename = "loc")]
87 Loc,
88}
89
90#[derive(Serialize, Deserialize, Debug, Default)]
91pub struct SelectionParam {
92 pub codec: Option<String>,
93
94 #[serde(rename = "mimeType")]
95 #[serde(skip_serializing_if = "Option::is_none")]
96 pub mime_type: Option<String>,
97
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub framerate: Option<u64>,
100
101 #[serde(skip_serializing_if = "Option::is_none")]
102 pub bitrate: Option<u32>,
103
104 #[serde(skip_serializing_if = "Option::is_none")]
105 pub width: Option<u32>,
106
107 #[serde(skip_serializing_if = "Option::is_none")]
108 pub height: Option<u32>,
109
110 #[serde(skip_serializing_if = "Option::is_none")]
111 pub samplerate: Option<u32>,
112
113 #[serde(rename = "channelConfig", skip_serializing_if = "Option::is_none")]
114 pub channel_config: Option<String>,
115
116 #[serde(rename = "displayWidth", skip_serializing_if = "Option::is_none")]
117 pub display_width: Option<u16>,
118
119 #[serde(rename = "displayHeight", skip_serializing_if = "Option::is_none")]
120 pub display_height: Option<u16>,
121
122 #[serde(rename = "lang", skip_serializing_if = "Option::is_none")]
123 pub language: Option<String>,
124}
125
126#[derive(Serialize, Deserialize, Debug, Default)]
127pub struct CommonTrackFields {
128 #[serde(skip_serializing_if = "Option::is_none")]
129 pub namespace: Option<String>,
130
131 #[serde(skip_serializing_if = "Option::is_none")]
132 pub packaging: Option<TrackPackaging>,
133
134 #[serde(rename = "renderGroup", skip_serializing_if = "Option::is_none")]
135 pub render_group: Option<u16>,
136
137 #[serde(rename = "altGroup", skip_serializing_if = "Option::is_none")]
138 pub alt_group: Option<u16>,
139}
140
141impl CommonTrackFields {
142 pub fn from_tracks(tracks: &mut [Track]) -> Self {
144 if tracks.is_empty() {
145 return Default::default();
146 }
147
148 let mut common = Self {
150 namespace: tracks[0].namespace.clone(),
151 packaging: tracks[0].packaging.clone(),
152 render_group: tracks[0].render_group,
153 alt_group: tracks[0].alt_group,
154 };
155
156 for track in &mut tracks[1..] {
158 if track.namespace != common.namespace {
159 common.namespace = None;
160 }
161 if track.packaging != common.packaging {
162 common.packaging = None;
163 }
164 if track.render_group != common.render_group {
165 common.render_group = None
166 }
167 if track.alt_group != common.alt_group {
168 common.alt_group = None;
169 }
170 }
171
172 for track in tracks {
174 if common.namespace.is_some() {
175 track.namespace = None;
176 }
177 if track.packaging.is_some() {
178 track.packaging = None;
179 }
180 if track.render_group.is_some() {
181 track.render_group = None;
182 }
183 if track.alt_group.is_some() {
184 track.alt_group = None;
185 }
186 }
187
188 common
189 }
190}