Skip to content
File

Blob: firmware/vendor/str0m/src/packet/payload.rs

rust106 lines
1use crate::format::Vp9PacketizerMode;
2use crate::format::{Codec, CodecSpec};
3use crate::media::ToPayload;
4use crate::rtp::vla::VideoLayersAllocation;
5use crate::rtp_::Frequency;
6use crate::streams::{RtpWrite, StreamTx};
7 
8use super::PacketError;
9use super::{CodecPacketizer, Packetizer};
10 
11#[derive(Debug)]
12pub struct Payloader {
13 pack: CodecPacketizer,
14 clock_rate: Frequency,
15 allow_talkspurt_marker: bool,
16}
17 
18impl Payloader {
19 pub(crate) fn new(spec: CodecSpec, vp9_mode: Vp9PacketizerMode) -> Self {
20 let mut pack = CodecPacketizer::new(spec.codec, vp9_mode);
21 
22 // Enable DONL for H.265 when sprop-max-don-diff > 0 (RFC 7798 §7.1)
23 if let CodecPacketizer::H265(ref mut h265) = pack {
24 if spec.format.sprop_max_don_diff.unwrap_or(0) > 0 {
25 h265.with_donl(true);
26 }
27 }
28 
29 // Enable DONL for H.266 when sprop-max-don-diff > 0 (RFC 9328 §7.2)
30 if let CodecPacketizer::H266(ref mut h266) = pack {
31 if spec.format.sprop_max_don_diff.unwrap_or(0) > 0 {
32 h266.with_donl(true);
33 }
34 }
35 
36 Payloader {
37 pack,
38 clock_rate: spec.rtp_clock_rate(),
39 allow_talkspurt_marker: spec.codec != Codec::CN,
40 }
41 }
42 
43 pub(crate) fn push_sample(
44 &mut self,
45 to_payload: ToPayload,
46 mtu: usize,
47 is_audio: bool,
48 stream: &mut StreamTx,
49 ) -> Result<(), PacketError> {
50 let ToPayload {
51 pt,
52 wallclock,
53 rtp_time,
54 data,
55 start_of_talk_spurt,
56 ext_vals,
57 ..
58 } = to_payload;
59 
60 let chunks = self.pack.packetize(mtu, data.as_ref())?;
61 let len = chunks.len();
62 
63 for (idx, data) in chunks.into_iter().enumerate() {
64 let last = idx == len - 1;
65 let first = idx == 0;
66 
67 let previous_data = stream.last_packet();
68 let marker = self.pack.is_marker(data.as_slice(), previous_data, last)
69 || (is_audio && self.allow_talkspurt_marker && start_of_talk_spurt);
70 
71 let seq_no = stream.next_seq_no();
72 
73 // TODO: delegate to self.pack to decide whether this packet is nackable.
74 let nackable = !is_audio;
75 
76 let mut pkt_ext_vals = ext_vals.clone();
77 
78 if !first {
79 pkt_ext_vals.abs_capture_time = None;
80 pkt_ext_vals.user_values.remove::<VideoLayersAllocation>();
81 }
82 
83 if !last {
84 pkt_ext_vals.video_orientation = None;
85 pkt_ext_vals.video_content_type = None;
86 pkt_ext_vals.video_timing = None;
87 }
88 
89 stream.write_rtp(
90 RtpWrite::new(
91 pt,
92 seq_no,
93 rtp_time.rebase(self.clock_rate).numer() as u32,
94 wallclock,
95 data,
96 )
97 .marker(marker)
98 .ext_vals(pkt_ext_vals)
99 .nackable(nackable),
100 );
101 }
102 
103 Ok(())
104 }
105}