Skip to main content

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