rtc_rtp/codecs/av1/mod.rs
1use bytes::{BufMut, Bytes, BytesMut};
2
3use crate::codecs::av1::leb128::BytesMutExt;
4use crate::codecs::av1::obu::{obu_has_extension, parse_obus, OBU_HAS_SIZE_BIT};
5use crate::codecs::av1::packetizer::{
6 get_aggregation_header, packetize, AGGREGATION_HEADER_SIZE, MAX_NUM_OBUS_TO_OMIT_SIZE,
7};
8use crate::packetizer::Payloader;
9use shared::error::Result;
10
11#[cfg(test)]
12mod av1_test;
13mod leb128;
14mod obu;
15mod packetizer;
16
17#[derive(Default, Clone, Debug)]
18pub struct Av1Payloader {}
19
20impl Payloader for Av1Payloader {
21 /// Based on https://chromium.googlesource.com/external/webrtc/+/4e513346ec56c829b3a6010664998469fc237b35/modules/rtp_rtcp/source/rtp_packetizer_av1.cc
22 /// Reference: https://aomediacodec.github.io/av1-rtp-spec/#45-payload-structure
23 fn payload(&mut self, mtu: usize, payload: &Bytes) -> Result<Vec<Bytes>> {
24 // 0 1 2 3
25 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
26 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27 // |Z|Y|1 0|N|-|-|-| OBU element 1 size (leb128) | |
28 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
29 // | |
30 // : :
31 // : OBU element 1 data :
32 // : :
33 // | |
34 // | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 // | | |
36 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
37 // | |
38 // : :
39 // : OBU element 2 data :
40 // : :
41 // | |
42 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43
44 // Parse the payload into series of OBUs.
45 let obus = parse_obus(payload)?;
46
47 // Packetize the OBUs, possibly aggregating multiple OBUs into a single packet,
48 // or splitting a single OBU across multiple packets.
49 let packets_metadata = packetize(&obus, mtu);
50
51 let mut payloads = vec![];
52
53 // Split the payload into RTP packets according to the packetization scheme.
54 for packet_index in 0..packets_metadata.len() {
55 let packet = &packets_metadata[packet_index];
56 let mut obu_offset = packet.first_obu_offset;
57 let aggregation_header = get_aggregation_header(&obus, &packets_metadata, packet_index);
58
59 let mut out = BytesMut::with_capacity(AGGREGATION_HEADER_SIZE + packet.packet_size);
60 out.put_u8(aggregation_header);
61
62 // Store all OBU elements except the last one.
63 for i in 0..packet.num_obu_elements - 1 {
64 let obu = &obus[packet.first_obu_index + i];
65 let fragment_size = obu.size - obu_offset;
66 out.put_leb128(fragment_size as u32);
67 if obu_offset == 0 {
68 out.put_u8(obu.header & !OBU_HAS_SIZE_BIT);
69 }
70 if obu_offset <= 1 && obu_has_extension(obu.header) {
71 out.put_u8(obu.extension_header);
72 }
73 let payload_offset = if obu_offset > obu.header_size() {
74 obu_offset - obu.header_size()
75 } else {
76 0
77 };
78 let payload_size = obu.payload.len() - payload_offset;
79 out.put_slice(
80 obu.payload
81 .slice(payload_offset..payload_offset + payload_size)
82 .as_ref(),
83 );
84 // All obus are stored from the beginning, except, may be, the first one.
85 obu_offset = 0;
86 }
87
88 // Store the last OBU element.
89 let last_obu = &obus[packet.first_obu_index + packet.num_obu_elements - 1];
90 let mut fragment_size = packet.last_obu_size;
91 if packet.num_obu_elements > MAX_NUM_OBUS_TO_OMIT_SIZE {
92 out.put_leb128(fragment_size as u32);
93 }
94 if obu_offset == 0 && fragment_size > 0 {
95 out.put_u8(last_obu.header & !OBU_HAS_SIZE_BIT);
96 fragment_size -= 1;
97 }
98 if obu_offset <= 1 && obu_has_extension(last_obu.header) && fragment_size > 0 {
99 out.put_u8(last_obu.extension_header);
100 fragment_size -= 1;
101 }
102 let payload_offset = if obu_offset > last_obu.header_size() {
103 obu_offset - last_obu.header_size()
104 } else {
105 0
106 };
107 out.put_slice(
108 last_obu
109 .payload
110 .slice(payload_offset..payload_offset + fragment_size)
111 .as_ref(),
112 );
113
114 payloads.push(out.freeze());
115 }
116
117 Ok(payloads)
118 }
119
120 fn clone_to(&self) -> Box<dyn Payloader> {
121 Box::new(self.clone())
122 }
123}