Skip to content
File

Blob: firmware/vendor/str0m/src/rtp/vla.rs

rust1166 lines
1use std::collections::VecDeque;
2 
3use super::{ExtensionSerializer, ExtensionValues};
4 
5#[allow(dead_code)]
6/// URI for the Video Layers Allocation RTP Header Extension
7pub const URI: &str = "http://www.webrtc.org/experiments/rtp-hdrext/video-layers-allocation00";
8 
9/// Top-level "allocation" for the Video Layers Allocation RTP Header Extension
10/// Contains allocations for many simulcast streams, which contain many spatial layers.
11/// In practice, there are either many simulcast streams with 1 spatial layer each (simulcast)
12/// or 1 simulcast stream with many spatial layers (SVC)
13/// or 1 simulcast stream with 1 spatial layer (only temporal layers used).
14/// But theoretically, you could have 5 simulcast streams with 4 spatial layers each.
15#[derive(Debug, Clone, Eq, PartialEq)]
16pub struct VideoLayersAllocation {
17 /// The index of the current simulcast stream.
18 /// AKA RTP stream index
19 /// Set to 0 when everything is inactive (the special case of the header extension being just 0).
20 /// Erroneously called "RID" in the spec.
21 pub current_simulcast_stream_index: u8,
22 
23 /// AKA RTP streams
24 /// Max size of this Vec: 5
25 pub simulcast_streams: Vec<SimulcastStreamAllocation>,
26}
27 
28/// An allocation for a simulcast stream, which may contain up to 4 allocations for spatial layers.
29/// There may be up to 5 of these per top-level allocation.
30#[derive(Debug, Clone, Eq, PartialEq)]
31pub struct SimulcastStreamAllocation {
32 /// May contains many spatial layers, or none.
33 /// Max size of this Vec: 4
34 pub spatial_layers: Vec<SpatialLayerAllocation>,
35}
36 
37/// An allocation for a spatial layer, which may contain up to 5 allocations for temporal layers.
38/// There may be up to 4 per simulcast stream.
39/// Also contains an optional resolution and framerate.
40#[derive(Debug, Clone, Eq, PartialEq)]
41pub struct SpatialLayerAllocation {
42 /// Contains many temporal layers, or none.
43 /// If empty, the spatial layer is not active.
44 /// Max size of this Vec: 5
45 pub temporal_layers: Vec<TemporalLayerAllocation>,
46 /// Contains an optional resolution and framerate
47 pub resolution_and_framerate: Option<ResolutionAndFramerate>,
48}
49 
50/// An allocation for a temporal layer. There may be up to 5 per spatial layer.
51#[derive(Debug, Clone, Eq, PartialEq)]
52pub struct TemporalLayerAllocation {
53 /// Cumulative bitrate for this temporal layer and all below it within a spatial layer.
54 pub cumulative_kbps: u64,
55}
56 
57/// A resolution and a frame rate, tied together because that's how it's formed in
58/// the header extension. Either they are both there or neither are there.
59#[derive(Debug, Clone, Eq, PartialEq)]
60pub struct ResolutionAndFramerate {
61 /// Width in number of pixels
62 pub width: u16,
63 /// Height in number of pixels
64 pub height: u16,
65 /// Framerate in frames per second
66 pub framerate: u8,
67}
68 
69impl VideoLayersAllocation {
70 #[allow(dead_code)]
71 fn parse(buf: &[u8]) -> Option<Self> {
72 // First byte
73 let (&b0, after_b0) = buf.split_first()?;
74 if b0 == 0u8 && after_b0.is_empty() {
75 // Special case when everything is inactive.
76 return Some(VideoLayersAllocation {
77 current_simulcast_stream_index: 0,
78 simulcast_streams: vec![],
79 });
80 }
81 let current_simulcast_stream_index = read_bits(b0, 0..2);
82 // Maximum of 5 simulcast streams
83 let simulcast_stream_count = read_bits(b0, 2..4) + 1;
84 let shared_spatial_layer_bitmask = read_bits(b0, 4..8);
85 
86 // Spatial layer bitmasks, which can be either "shared" or not.
87 // If shared, each simulcast stream as the same spatial layers active.
88 // If not, each simulcast stream has its own 4 bits indicating which spatial layers are active.
89 // So, a maximum of 4 spatial layers per simulcast stream.
90 let (spatial_layer_active_bits, after_spatial_layer_bitmasks) =
91 if shared_spatial_layer_bitmask > 0 {
92 let shared_spatial_layer_active_bits =
93 read_lower_4bits_ignoring_leading_zeros(shared_spatial_layer_bitmask);
94 let spatial_layer_active_bits =
95 vec![shared_spatial_layer_active_bits; simulcast_stream_count as usize];
96 let after_spatial_layer_bitmasks = after_b0;
97 (spatial_layer_active_bits, after_spatial_layer_bitmasks)
98 } else {
99 // 4 bits per simulcast stream
100 let (spatial_layer_bitmasks, after_spatial_layer_bitmasks) =
101 split_at(after_b0, div_round_up(simulcast_stream_count as usize, 2))?;
102 let spatial_layer_actives = spatial_layer_bitmasks
103 .iter()
104 .flat_map(|&byte| split_byte_in2(byte))
105 .take(simulcast_stream_count as usize)
106 .map(read_lower_4bits_ignoring_leading_zeros)
107 .collect();
108 (spatial_layer_actives, after_spatial_layer_bitmasks)
109 };
110 // The number of active bits that are set across all simulcast streams,
111 // which is the number of active spatial layers across all simulcast streams.
112 // A maximum of 5x4 = 20 spatial layers across all simulcast streams.
113 let total_active_spatial_layer_count = spatial_layer_active_bits
114 .iter()
115 .flatten()
116 .filter(|&&active| active)
117 .count();
118 
119 // Temporal layer counts
120 // 2 bits per spatial layer
121 // A maximum of 5 temporal layers per spatial layer.
122 // For a maximum of 5x4x5 = 100 temporal layers across all spatial layers
123 // across all simulcast streams.
124 let (temporal_layer_counts, after_temporal_layer_counts) = split_at(
125 after_spatial_layer_bitmasks,
126 div_round_up(total_active_spatial_layer_count, 4),
127 )?;
128 // Max size of this VecDeque: 20
129 let mut temporal_layer_counts: VecDeque<u8> = temporal_layer_counts
130 .iter()
131 .flat_map(|&byte| split_byte_in4(byte))
132 .map(|count_minus_1| count_minus_1 + 1)
133 .take(total_active_spatial_layer_count)
134 .collect();
135 let total_temporal_layer_count = temporal_layer_counts.iter().sum();
136 
137 // Temporal layer bitrates
138 let mut next_temporal_layer_bitrate = after_temporal_layer_counts;
139 // Max size of this VecDeque: 100
140 let mut temporal_layer_cumulative_bitrates: VecDeque<u64> = (0..total_temporal_layer_count)
141 .map(|_temporal_layer_index| {
142 let (bitrate, after_temporal_layer_bitrate) =
143 parse_leb_u63(next_temporal_layer_bitrate);
144 next_temporal_layer_bitrate = after_temporal_layer_bitrate;
145 bitrate
146 })
147 .collect();
148 // libwebrtc fails to parse at a value of 1_000_000 kbps. We are a little more forgiving,
149 // but since we limit the LEB parse at 63 bits, we should be at least that strict.
150 if temporal_layer_cumulative_bitrates
151 .iter()
152 .any(|&kbps| kbps > (1u64 << 63))
153 {
154 return None;
155 }
156 
157 // (Optional) resolutions and framerates
158 let mut next_resolution_and_framerate = next_temporal_layer_bitrate;
159 let mut resolutions_and_framerates =
160 (0..total_active_spatial_layer_count).filter_map(|_| {
161 let (resolution_and_framerate, after_resolution_and_framerate) =
162 split_at(next_resolution_and_framerate, 5)?;
163 next_resolution_and_framerate = after_resolution_and_framerate;
164 Some(ResolutionAndFramerate {
165 width: u16::from_be_bytes(resolution_and_framerate[0..2].try_into().unwrap())
166 + 1,
167 height: u16::from_be_bytes(resolution_and_framerate[2..4].try_into().unwrap())
168 + 1,
169 framerate: resolution_and_framerate[4],
170 })
171 });
172 
173 let simulcast_streams = spatial_layer_active_bits
174 .into_iter()
175 .map(|spatial_layer_actives| {
176 let spatial_layers = spatial_layer_actives
177 .into_iter()
178 .filter_map(|spatial_layer_active| {
179 let (temporal_layers, resolution_and_framerate) = if spatial_layer_active {
180 let temporal_layer_count = temporal_layer_counts.pop_front()?;
181 let temporal_layers = (0..temporal_layer_count)
182 .filter_map(|_temporal_layer_index| {
183 Some(TemporalLayerAllocation {
184 cumulative_kbps: temporal_layer_cumulative_bitrates
185 .pop_front()?,
186 })
187 })
188 .collect();
189 let resolution_and_framerate = resolutions_and_framerates.next();
190 (temporal_layers, resolution_and_framerate)
191 } else {
192 (vec![], None)
193 };
194 Some(SpatialLayerAllocation {
195 temporal_layers,
196 resolution_and_framerate,
197 })
198 })
199 .collect();
200 SimulcastStreamAllocation { spatial_layers }
201 })
202 .collect();
203 Some(VideoLayersAllocation {
204 current_simulcast_stream_index,
205 simulcast_streams,
206 })
207 }
208}
209 
210/// Serializer of the Video Layers Allocation Header Extension
211#[derive(Debug)]
212pub struct Serializer;
213 
214impl ExtensionSerializer for Serializer {
215 // +-+-+-+-+-+-+-+-+
216 // |RID| NS| sl_bm |
217 // +-+-+-+-+-+-+-+-+
218 // Spatial layer bitmask |sl0_bm |sl1_bm |
219 // up to 2 bytes |---------------|
220 // when sl_bm == 0 |sl2_bm |sl3_bm |
221 // +-+-+-+-+-+-+-+-+
222 // Number of temporal layers |#tl|#tl|#tl|#tl|
223 // per spatial layer | | | | |
224 // +-+-+-+-+-+-+-+-+
225 // Target bitrate in kpbs | |
226 // per temporal layer : ... :
227 // leb128 encoded | |
228 // +-+-+-+-+-+-+-+-+
229 // Resolution and framerate | |
230 // 5 bytes per spatial layer + width-1 for +
231 // (optional) | rid=0, sid=0 |
232 // +---------------+
233 // | |
234 // + height-1 for +
235 // | rid=0, sid=0 |
236 // +---------------+
237 // | max framerate |
238 // +-+-+-+-+-+-+-+-+
239 // : ... :
240 // +-+-+-+-+-+-+-+-+
241 
242 fn write_to(&self, buf: &mut [u8], ev: &ExtensionValues) -> usize {
243 if let Some(vla) = ev.user_values.get::<VideoLayersAllocation>() {
244 let mut index = 0;
245 
246 buf[index] = 0;
247 
248 if vla.current_simulcast_stream_index == 0 && vla.simulcast_streams.is_empty() {
249 return index + 1;
250 }
251 
252 // RID: RTP stream index this allocation is sent on, numbered from 0. 2 bits.
253 buf[index] |= (vla.current_simulcast_stream_index & 0b11) << 6;
254 // NS: Number of RTP streams minus one. 2 bits, thus allowing up-to 4 RTP streams.
255 buf[index] |= ((vla.simulcast_streams.len() - 1) as u8 & 0b11) << 4;
256 
257 // sl_bm: BitMask of the active Spatial Layers when same for all RTP streams or 0 otherwise.
258 // 4 bits, thus allows up to 4 spatial layers per RTP streams.
259 let total_spatial_layers = vla.simulcast_streams.len();
260 let spatial_layers = vla.simulcast_streams.iter().enumerate().fold(
261 [0u8; 4],
262 |mut spatial_layers, (stream_index, stream)| {
263 let sl_bm = stream.spatial_layers.iter().enumerate().fold(
264 0u8,
265 |is_active, (layer_id, l)| {
266 is_active | if l.temporal_layers.is_empty() { 0 } else { 1 } << layer_id
267 },
268 );
269 
270 spatial_layers[stream_index] = sl_bm;
271 spatial_layers
272 },
273 );
274 
275 let shared_spatial_layer_bitmask = spatial_layers[..total_spatial_layers]
276 .iter()
277 .all(|i| *i == spatial_layers[0]);
278 
279 if shared_spatial_layer_bitmask {
280 buf[index] |= spatial_layers[0] & 0b1111;
281 } else {
282 // slX_bm: BitMask of the active Spatial Layers for RTP stream with index=X.
283 // When NS < 2, takes one byte, otherwise uses two bytes. Zero-padded to byte alignment.
284 for (stream_index, sl_bm) in
285 spatial_layers[..total_spatial_layers].iter().enumerate()
286 {
287 let shift = if stream_index % 2 == 0 { 4 } else { 0 };
288 if shift == 4 {
289 index += 1;
290 buf[index] = 0;
291 }
292 buf[index + (stream_index / 2)] |= (sl_bm & 0b1111) << shift;
293 }
294 
295 // When writing 1 or 3 entries, skip the remaining nibble to be byte aligned
296 if total_spatial_layers % 2 != 0 {
297 buf[index] |= 0b1111;
298 }
299 }
300 
301 index += 1;
302 
303 // #tl: 2-bit value of number of temporal layers-1, thus allowing up-to 4 temporal layers.
304 // Values are stored in ascending order of spatial id. Zero-padded to byte alignment.
305 let mut tl_index = 0;
306 let mut wrote_temporal_layer_count = false;
307 for s in &vla.simulcast_streams {
308 for spatial in &s.spatial_layers {
309 if !spatial.temporal_layers.is_empty() {
310 wrote_temporal_layer_count = true;
311 let temporal_layer_count_minus_one =
312 (spatial.temporal_layers.len() - 1) as u8;
313 if tl_index % 4 == 0 {
314 if tl_index > 0 {
315 index += 1;
316 }
317 buf[index] = 0;
318 }
319 
320 buf[index] |= temporal_layer_count_minus_one << (6 - (tl_index % 4) * 2);
321 tl_index += 1;
322 }
323 }
324 }
325 
326 if wrote_temporal_layer_count {
327 index += 1;
328 } else {
329 buf[index] = 0;
330 index += 1;
331 return index;
332 }
333 
334 for s in &vla.simulcast_streams {
335 for spatial in &s.spatial_layers {
336 for temporal in &spatial.temporal_layers {
337 index += encode_leb_u63(temporal.cumulative_kbps, &mut buf[index..]);
338 }
339 }
340 }
341 
342 for s in &vla.simulcast_streams {
343 for spatial in &s.spatial_layers {
344 if let Some(r) = &spatial.resolution_and_framerate {
345 let width = (r.width - 1).to_be_bytes();
346 let height = (r.height - 1).to_be_bytes();
347 let framerate = r.framerate;
348 buf[index..index + 2].copy_from_slice(&width[..]);
349 index += 2;
350 buf[index..index + 2].copy_from_slice(&height[..]);
351 index += 2;
352 buf[index] = framerate;
353 index += 1;
354 }
355 }
356 }
357 
358 return index;
359 }
360 0
361 }
362 
363 fn parse_value(&self, buf: &[u8], ev: &mut ExtensionValues) -> bool {
364 let Some(vla) = VideoLayersAllocation::parse(buf) else {
365 return false;
366 };
367 ev.user_values.set(vla);
368 true
369 }
370 
371 fn is_video(&self) -> bool {
372 true
373 }
374 
375 fn is_audio(&self) -> bool {
376 false
377 }
378 
379 fn requires_two_byte_form(&self, _ev: &ExtensionValues) -> bool {
380 true
381 }
382}
383 
384// See https://en.wikipedia.org/wiki/LEB128
385// Reads out at most 9 bytes (63 bits) unsigned
386// returns (value, rest)
387// libwebrtc reads out all 64 bits, but then fails the parse if the value
388// is over 1_000_000 anyway, so reading 63 bits should be enough as long as
389// we throw away the parse if it's above 1_000_000.
390#[allow(dead_code)]
391fn parse_leb_u63(bytes: &[u8]) -> (u64, &[u8]) {
392 let mut result = 0;
393 for (index, &byte) in bytes.iter().enumerate() {
394 let is_last = !read_bit(byte, 0);
395 let chunk = read_bits(byte, 1..8);
396 result |= (chunk as u64) << (7 * index);
397 if is_last || index == 8 {
398 return (result, &bytes[(index + 1)..]);
399 }
400 }
401 (0, bytes)
402}
403 
404/// Encodes leb128
405pub fn encode_leb_u63(mut value: u64, buf: &mut [u8]) -> usize {
406 let mut index = 0;
407 loop {
408 if value < 0x80 {
409 buf[index] = value as u8;
410 index += 1;
411 break;
412 } else {
413 buf[index] = ((value & 0x7f) | 0x80) as u8;
414 value >>= 7;
415 index += 1;
416 }
417 }
418 
419 index
420}
421 
422// If successful, the size of the left will be mid,
423// and the size of the right while be buf.len()-mid.
424#[allow(dead_code)]
425fn split_at(buf: &[u8], mid: usize) -> Option<(&[u8], &[u8])> {
426 if mid > buf.len() {
427 return None;
428 }
429 Some(buf.split_at(mid))
430}
431 
432#[allow(dead_code)]
433fn div_round_up(top: usize, bottom: usize) -> usize {
434 if top == 0 {
435 0
436 } else {
437 ((top - 1) / bottom) + 1
438 }
439}
440 
441// Into 2 chunks of 4 bits
442#[allow(dead_code)]
443fn split_byte_in2(byte: u8) -> [u8; 2] {
444 [read_bits(byte, 0..4), read_bits(byte, 4..8)]
445}
446 
447// Into 4 chunks of 2 bits
448#[allow(dead_code)]
449fn split_byte_in4(byte: u8) -> [u8; 4] {
450 [
451 read_bits(byte, 0..2),
452 read_bits(byte, 2..4),
453 read_bits(byte, 4..6),
454 read_bits(byte, 6..8),
455 ]
456}
457 
458// Ignore top 4 bits and leading zeros. Then split into a Vec<bool>ca
459fn read_lower_4bits_ignoring_leading_zeros(bits: u8) -> Vec<bool> {
460 let mut count = 0;
461 let mut bools: Vec<bool> = (0..=3u8)
462 .map(|index| {
463 let bit = read_bit(bits, 7 - index);
464 if bit {
465 count = index + 1;
466 }
467 bit
468 })
469 .collect();
470 bools.truncate(count as usize);
471 bools
472}
473 
474#[allow(dead_code)]
475fn read_bit(bits: u8, index: u8) -> bool {
476 read_bits(bits, index..(index + 1)) > 0
477}
478 
479#[allow(dead_code)]
480fn read_bits(bits: u8, range: std::ops::Range<u8>) -> u8 {
481 assert!(range.end <= 8);
482 (bits >> (8 - range.end)) & (0b1111_1111 >> (8 - range.len()))
483}
484 
485#[cfg(test)]
486mod test {
487 use super::*;
488 
489 fn serialize(vla: Option<&VideoLayersAllocation>) -> Vec<u8> {
490 let Some(vla) = vla else { return Vec::new() };
491 let mut buf: [u8; 100] = [0u8; 100];
492 let mut ext_values: ExtensionValues = Default::default();
493 ext_values.user_values.set(vla.clone());
494 
495 let actual_size = Serializer {}.write_to(&mut buf, &ext_values);
496 
497 buf[..actual_size].to_vec()
498 }
499 
500 fn assert_ser_deser(bytes: &[u8], vla: Option<VideoLayersAllocation>) {
501 let vla_deserialized = VideoLayersAllocation::parse(bytes);
502 let vla_serialized = serialize(vla.as_ref());
503 
504 assert_eq!(vla, vla_deserialized);
505 assert_eq!(bytes, vla_serialized);
506 }
507 
508 #[test]
509 fn test_read_bits() {
510 assert_eq!(read_bits(0b1100_0000, 0..2), 0b0000_0011);
511 assert_eq!(read_bits(0b1001_0101, 0..2), 0b0000_0010);
512 assert_eq!(read_bits(0b0110_1010, 0..2), 0b0000_0001);
513 assert_eq!(read_bits(0b0011_1111, 0..2), 0b0000_0000);
514 assert_eq!(read_bits(0b0011_0000, 2..4), 0b0000_0011);
515 assert_eq!(read_bits(0b0110_0101, 2..4), 0b0000_0010);
516 assert_eq!(read_bits(0b1001_1010, 2..4), 0b0000_0001);
517 assert_eq!(read_bits(0b1100_1111, 2..4), 0b0000_0000);
518 }
519 
520 #[test]
521 fn test_parse_leb_u63() {
522 let (value, rest) = parse_leb_u63(&[0b0000_0000, 5]);
523 assert_eq!(0, value);
524 assert_eq!(&[5], rest);
525 
526 let (value, rest) = parse_leb_u63(&[0b0000_0001, 5]);
527 assert_eq!(1, value);
528 assert_eq!(&[5], rest);
529 
530 let (value, rest) = parse_leb_u63(&[0b1000_0000, 0b0000_0001, 5]);
531 assert_eq!(128, value);
532 assert_eq!(&[5], rest);
533 
534 let (value, rest) = parse_leb_u63(&[0b1000_0000, 0b1000_0000, 0b0000_0001, 5]);
535 assert_eq!(16384, value);
536 assert_eq!(&[5], rest);
537 
538 let (value, rest) = parse_leb_u63(&[0b1000_0000, 0b1000_0000, 0b1000_0000, 0b0000_0001, 5]);
539 assert_eq!(2097152, value);
540 assert_eq!(&[5], rest);
541 
542 let (value, rest) = parse_leb_u63(&[
543 0b1000_0000,
544 0b1000_0000,
545 0b1000_0000,
546 0b1000_0000,
547 0b1000_0000,
548 0b1000_0000,
549 0b1000_0000,
550 0b1000_0000,
551 0b0000_0001,
552 5,
553 ]);
554 assert_eq!(72057594037927936, value);
555 assert_eq!(&[5], rest);
556 
557 // Too many bytes, so stop early.
558 let (value, rest) = parse_leb_u63(&[
559 0b1000_0000,
560 0b1000_0000,
561 0b1000_0000,
562 0b1000_0000,
563 0b1000_0000,
564 0b1000_0000,
565 0b1000_0000,
566 0b1000_0000,
567 0b1000_0001,
568 5,
569 ]);
570 assert_eq!(72057594037927936, value);
571 assert_eq!(&[5], rest);
572 }
573 
574 #[test]
575 fn test_parse_vla_empty_buffer() {
576 assert_ser_deser(&[], None);
577 }
578 
579 #[test]
580 fn test_parse_vla_empty() {
581 assert_ser_deser(
582 &[0b0000_0000],
583 Some(VideoLayersAllocation {
584 current_simulcast_stream_index: 0,
585 simulcast_streams: vec![],
586 }),
587 );
588 }
589 
590 #[test]
591 fn test_res() {
592 let vla = VideoLayersAllocation::parse(&[
593 17, 111, 7, 0, 15, 92, 4, 255, 2, 207, 30, 7, 127, 4, 55, 30,
594 ]);
595 assert!(vla.is_some())
596 }
597 
598 #[test]
599 fn test_parse_vla_missing_spatial_layer_bitmasks() {
600 assert_eq!(VideoLayersAllocation::parse(&[0b0110_0000]), None);
601 }
602 
603 #[test]
604 fn test_parse_vla_1_simulcast_stream_with_no_active_layers() {
605 assert_ser_deser(
606 &[
607 0b0100_0000,
608 // 1 bitmask
609 0b0000_0000,
610 ],
611 Some(VideoLayersAllocation {
612 current_simulcast_stream_index: 1,
613 simulcast_streams: vec![SimulcastStreamAllocation {
614 spatial_layers: vec![],
615 }],
616 }),
617 );
618 }
619 
620 #[test]
621 fn test_parse_vla_3_simulcast_streams_with_no_active_layers() {
622 assert_eq!(
623 VideoLayersAllocation::parse(&[
624 0b0110_0000,
625 // 3 active spatial layer bitmasks, 4 bits each
626 0b0000_0000,
627 0b0000_1111,
628 ]),
629 Some(VideoLayersAllocation {
630 current_simulcast_stream_index: 1,
631 simulcast_streams: vec![
632 SimulcastStreamAllocation {
633 spatial_layers: vec![],
634 },
635 SimulcastStreamAllocation {
636 spatial_layers: vec![],
637 },
638 SimulcastStreamAllocation {
639 spatial_layers: vec![],
640 },
641 ],
642 }),
643 );
644 }
645 
646 #[test]
647 fn test_parse_vla_3_simulcast_streams_with_1_active_spatial_layers_and_2_temporal_layers() {
648 assert_ser_deser(
649 &[
650 0b0110_0001,
651 // 3 temporal layer counts (minus 1), 2 bits each
652 0b0101_0100,
653 // 6 temporal layer bitrates
654 0b0000_0001,
655 0b0000_0010,
656 0b0000_0100,
657 0b0000_1000,
658 0b0001_0000,
659 0b0010_0000,
660 ],
661 Some(VideoLayersAllocation {
662 current_simulcast_stream_index: 1,
663 simulcast_streams: vec![
664 SimulcastStreamAllocation {
665 spatial_layers: vec![SpatialLayerAllocation {
666 temporal_layers: vec![
667 TemporalLayerAllocation { cumulative_kbps: 1 },
668 TemporalLayerAllocation { cumulative_kbps: 2 },
669 ],
670 resolution_and_framerate: None,
671 }],
672 },
673 SimulcastStreamAllocation {
674 spatial_layers: vec![SpatialLayerAllocation {
675 temporal_layers: vec![
676 TemporalLayerAllocation { cumulative_kbps: 4 },
677 TemporalLayerAllocation { cumulative_kbps: 8 },
678 ],
679 resolution_and_framerate: None,
680 }],
681 },
682 SimulcastStreamAllocation {
683 spatial_layers: vec![SpatialLayerAllocation {
684 temporal_layers: vec![
685 TemporalLayerAllocation {
686 cumulative_kbps: 16,
687 },
688 TemporalLayerAllocation {
689 cumulative_kbps: 32,
690 },
691 ],
692 resolution_and_framerate: None,
693 }],
694 },
695 ],
696 }),
697 );
698 }
699 
700 #[test]
701 fn test_parse_vla_3_sim_1_spatial_2_temporal_with_resolutions() {
702 assert_ser_deser(
703 &[
704 0b0110_0001,
705 // 3 temporal layer counts (minus 1), 2 bits each
706 0b0101_0100,
707 // 6 temporal layer bitrates
708 100,
709 101,
710 110,
711 111,
712 120,
713 121,
714 // 3 resolutions + framerates (5 bytes each)
715 // 320x180x15
716 1,
717 63,
718 0,
719 179,
720 15,
721 // 640x360x30
722 2,
723 127,
724 1,
725 103,
726 30,
727 // 1280x720x60
728 4,
729 255,
730 2,
731 207,
732 60,
733 ],
734 Some(VideoLayersAllocation {
735 current_simulcast_stream_index: 1,
736 simulcast_streams: vec![
737 SimulcastStreamAllocation {
738 spatial_layers: vec![SpatialLayerAllocation {
739 temporal_layers: vec![
740 TemporalLayerAllocation {
741 cumulative_kbps: 100,
742 },
743 TemporalLayerAllocation {
744 cumulative_kbps: 101,
745 },
746 ],
747 resolution_and_framerate: Some(ResolutionAndFramerate {
748 width: 320,
749 height: 180,
750 framerate: 15,
751 }),
752 }],
753 },
754 SimulcastStreamAllocation {
755 spatial_layers: vec![SpatialLayerAllocation {
756 temporal_layers: vec![
757 TemporalLayerAllocation {
758 cumulative_kbps: 110,
759 },
760 TemporalLayerAllocation {
761 cumulative_kbps: 111,
762 },
763 ],
764 resolution_and_framerate: Some(ResolutionAndFramerate {
765 width: 640,
766 height: 360,
767 framerate: 30,
768 }),
769 }],
770 },
771 SimulcastStreamAllocation {
772 spatial_layers: vec![SpatialLayerAllocation {
773 temporal_layers: vec![
774 TemporalLayerAllocation {
775 cumulative_kbps: 120,
776 },
777 TemporalLayerAllocation {
778 cumulative_kbps: 121,
779 },
780 ],
781 resolution_and_framerate: Some(ResolutionAndFramerate {
782 width: 1280,
783 height: 720,
784 framerate: 60,
785 }),
786 }],
787 },
788 ],
789 }),
790 );
791 }
792 
793 #[test]
794 fn test_parse_vla_3_simulcast_streams_with_differing_active_spatial_layers_with_resolutions() {
795 assert_ser_deser(
796 &[
797 0b0010_0000,
798 // 3 active spatial layer bitmasks, 4 bits each; only the base layer is active
799 0b0001_0000,
800 0b0000_1111,
801 // 1 temporal layer counts (minus 1), 2 bits each
802 0b0100_0000,
803 // 2 temporal layer bitrates
804 100,
805 101,
806 // 1 resolutions + framerates (5 bytes)
807 // 320x180x15
808 1,
809 63,
810 0,
811 179,
812 15,
813 ],
814 Some(VideoLayersAllocation {
815 current_simulcast_stream_index: 0,
816 simulcast_streams: vec![
817 SimulcastStreamAllocation {
818 spatial_layers: vec![SpatialLayerAllocation {
819 temporal_layers: vec![
820 TemporalLayerAllocation {
821 cumulative_kbps: 100,
822 },
823 TemporalLayerAllocation {
824 cumulative_kbps: 101,
825 },
826 ],
827 resolution_and_framerate: Some(ResolutionAndFramerate {
828 width: 320,
829 height: 180,
830 framerate: 15,
831 }),
832 }],
833 },
834 SimulcastStreamAllocation {
835 spatial_layers: vec![],
836 },
837 SimulcastStreamAllocation {
838 spatial_layers: vec![],
839 },
840 ],
841 }),
842 );
843 }
844 
845 #[test]
846 fn test_parse_vla_1_simulcast_streams_with_3_spatial_layers() {
847 assert_ser_deser(
848 &[
849 0b0000_0111,
850 // 3 temporal layer counts (minus 1), 2 bits each
851 0b0101_0100,
852 // 6 temporal layer bitrates
853 100,
854 101,
855 110,
856 111,
857 120,
858 121,
859 ],
860 Some(VideoLayersAllocation {
861 current_simulcast_stream_index: 0,
862 simulcast_streams: vec![SimulcastStreamAllocation {
863 spatial_layers: vec![
864 SpatialLayerAllocation {
865 temporal_layers: vec![
866 TemporalLayerAllocation {
867 cumulative_kbps: 100,
868 },
869 TemporalLayerAllocation {
870 cumulative_kbps: 101,
871 },
872 ],
873 resolution_and_framerate: None,
874 },
875 SpatialLayerAllocation {
876 temporal_layers: vec![
877 TemporalLayerAllocation {
878 cumulative_kbps: 110,
879 },
880 TemporalLayerAllocation {
881 cumulative_kbps: 111,
882 },
883 ],
884 resolution_and_framerate: None,
885 },
886 SpatialLayerAllocation {
887 temporal_layers: vec![
888 TemporalLayerAllocation {
889 cumulative_kbps: 120,
890 },
891 TemporalLayerAllocation {
892 cumulative_kbps: 121,
893 },
894 ],
895 resolution_and_framerate: None,
896 },
897 ],
898 }],
899 }),
900 );
901 }
902 
903 #[test]
904 fn test_parse_vla_4_simulcast_streams_with_1_spatial_layer_each() {
905 assert_ser_deser(
906 &[
907 0b0011_0001,
908 // 4 temporal layer counts (minus 1), 2 bits each: all have 2 temporal layers
909 0b0101_0101,
910 // 8 temporal layer bitrates
911 // 100, 101, 110, 111 are single-byte LEB128
912 100,
913 101,
914 110,
915 111,
916 // 130 = LEB128 [0x82, 0x01], 131 = LEB128 [0x83, 0x01]
917 0x82,
918 0x01,
919 0x83,
920 0x01,
921 // 200 = LEB128 [0xC8, 0x01], 201 = LEB128 [0xC9, 0x01]
922 0xC8,
923 0x01,
924 0xC9,
925 0x01,
926 ],
927 Some(VideoLayersAllocation {
928 current_simulcast_stream_index: 0,
929 simulcast_streams: vec![
930 SimulcastStreamAllocation {
931 spatial_layers: vec![SpatialLayerAllocation {
932 temporal_layers: vec![
933 TemporalLayerAllocation {
934 cumulative_kbps: 100,
935 },
936 TemporalLayerAllocation {
937 cumulative_kbps: 101,
938 },
939 ],
940 resolution_and_framerate: None,
941 }],
942 },
943 SimulcastStreamAllocation {
944 spatial_layers: vec![SpatialLayerAllocation {
945 temporal_layers: vec![
946 TemporalLayerAllocation {
947 cumulative_kbps: 110,
948 },
949 TemporalLayerAllocation {
950 cumulative_kbps: 111,
951 },
952 ],
953 resolution_and_framerate: None,
954 }],
955 },
956 SimulcastStreamAllocation {
957 spatial_layers: vec![SpatialLayerAllocation {
958 temporal_layers: vec![
959 TemporalLayerAllocation {
960 cumulative_kbps: 130,
961 },
962 TemporalLayerAllocation {
963 cumulative_kbps: 131,
964 },
965 ],
966 resolution_and_framerate: None,
967 }],
968 },
969 SimulcastStreamAllocation {
970 spatial_layers: vec![SpatialLayerAllocation {
971 temporal_layers: vec![
972 TemporalLayerAllocation {
973 cumulative_kbps: 200,
974 },
975 TemporalLayerAllocation {
976 cumulative_kbps: 201,
977 },
978 ],
979 resolution_and_framerate: None,
980 }],
981 },
982 ],
983 }),
984 );
985 }
986 
987 #[test]
988 fn test_parse_vla_2_simulcast_streams_with_3_spatial_layers_each() {
989 assert_ser_deser(
990 &[
991 0b0001_0111,
992 // 6 temporal layer counts (minus 1), 2 bits each: all have 2 temporal layers
993 // First byte: 4 counts
994 0b0101_0101,
995 // Second byte: 2 counts + zero padding
996 0b0101_0000,
997 // 12 temporal layer bitrates
998 // Stream 1: 100, 101, 110, 111, 120, 121 are single-byte LEB128
999 100,
1000 101,
1001 110,
1002 111,
1003 120,
1004 121,
1005 // Stream 2: values >= 128, each needs 2-byte LEB128
1006 // 200 = [0xC8, 0x01], 201 = [0xC9, 0x01]
1007 0xC8,
1008 0x01,
1009 0xC9,
1010 0x01,
1011 // 210 = [0xD2, 0x01], 211 = [0xD3, 0x01]
1012 0xD2,
1013 0x01,
1014 0xD3,
1015 0x01,
1016 // 220 = [0xDC, 0x01], 221 = [0xDD, 0x01]
1017 0xDC,
1018 0x01,
1019 0xDD,
1020 0x01,
1021 ],
1022 Some(VideoLayersAllocation {
1023 current_simulcast_stream_index: 0,
1024 simulcast_streams: vec![
1025 SimulcastStreamAllocation {
1026 spatial_layers: vec![
1027 SpatialLayerAllocation {
1028 temporal_layers: vec![
1029 TemporalLayerAllocation {
1030 cumulative_kbps: 100,
1031 },
1032 TemporalLayerAllocation {
1033 cumulative_kbps: 101,
1034 },
1035 ],
1036 resolution_and_framerate: None,
1037 },
1038 SpatialLayerAllocation {
1039 temporal_layers: vec![
1040 TemporalLayerAllocation {
1041 cumulative_kbps: 110,
1042 },
1043 TemporalLayerAllocation {
1044 cumulative_kbps: 111,
1045 },
1046 ],
1047 resolution_and_framerate: None,
1048 },
1049 SpatialLayerAllocation {
1050 temporal_layers: vec![
1051 TemporalLayerAllocation {
1052 cumulative_kbps: 120,
1053 },
1054 TemporalLayerAllocation {
1055 cumulative_kbps: 121,
1056 },
1057 ],
1058 resolution_and_framerate: None,
1059 },
1060 ],
1061 },
1062 SimulcastStreamAllocation {
1063 spatial_layers: vec![
1064 SpatialLayerAllocation {
1065 temporal_layers: vec![
1066 TemporalLayerAllocation {
1067 cumulative_kbps: 200,
1068 },
1069 TemporalLayerAllocation {
1070 cumulative_kbps: 201,
1071 },
1072 ],
1073 resolution_and_framerate: None,
1074 },
1075 SpatialLayerAllocation {
1076 temporal_layers: vec![
1077 TemporalLayerAllocation {
1078 cumulative_kbps: 210,
1079 },
1080 TemporalLayerAllocation {
1081 cumulative_kbps: 211,
1082 },
1083 ],
1084 resolution_and_framerate: None,
1085 },
1086 SpatialLayerAllocation {
1087 temporal_layers: vec![
1088 TemporalLayerAllocation {
1089 cumulative_kbps: 220,
1090 },
1091 TemporalLayerAllocation {
1092 cumulative_kbps: 221,
1093 },
1094 ],
1095 resolution_and_framerate: None,
1096 },
1097 ],
1098 },
1099 ],
1100 }),
1101 );
1102 }
1103 
1104 #[test]
1105 fn test_parse_vla_1_simulcast_streams_with_4_spatial_layers_1_inactive() {
1106 assert_ser_deser(
1107 &[
1108 0b0000_1011,
1109 // 3 temporal layer counts (minus 1), 2 bits each
1110 0b0101_0100,
1111 // 6 temporal layer bitrates
1112 100,
1113 101,
1114 110,
1115 111,
1116 120,
1117 121,
1118 ],
1119 Some(VideoLayersAllocation {
1120 current_simulcast_stream_index: 0,
1121 simulcast_streams: vec![SimulcastStreamAllocation {
1122 spatial_layers: vec![
1123 SpatialLayerAllocation {
1124 temporal_layers: vec![
1125 TemporalLayerAllocation {
1126 cumulative_kbps: 100,
1127 },
1128 TemporalLayerAllocation {
1129 cumulative_kbps: 101,
1130 },
1131 ],
1132 resolution_and_framerate: None,
1133 },
1134 SpatialLayerAllocation {
1135 temporal_layers: vec![
1136 TemporalLayerAllocation {
1137 cumulative_kbps: 110,
1138 },
1139 TemporalLayerAllocation {
1140 cumulative_kbps: 111,
1141 },
1142 ],
1143 resolution_and_framerate: None,
1144 },
1145 SpatialLayerAllocation {
1146 temporal_layers: vec![],
1147 resolution_and_framerate: None,
1148 },
1149 SpatialLayerAllocation {
1150 temporal_layers: vec![
1151 TemporalLayerAllocation {
1152 cumulative_kbps: 120,
1153 },
1154 TemporalLayerAllocation {
1155 cumulative_kbps: 121,
1156 },
1157 ],
1158 resolution_and_framerate: None,
1159 },
1160 ],
1161 }],
1162 }),
1163 );
1164 }
1165}