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