1 // Silence warning on `for i in 0..vec.len() { … }`:
2 #![allow(clippy::needless_range_loop)]
3
4 use super::*;
5
6 #[test]
test_h264_payload() -> Result<()>7 fn test_h264_payload() -> Result<()> {
8 let empty = Bytes::from_static(&[]);
9 let small_payload = Bytes::from_static(&[0x90, 0x90, 0x90]);
10 let multiple_payload = Bytes::from_static(&[0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x01, 0x90]);
11 let large_payload = Bytes::from_static(&[
12 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11,
13 0x12, 0x13, 0x14, 0x15,
14 ]);
15 let large_payload_packetized = vec![
16 Bytes::from_static(&[0x1c, 0x80, 0x01, 0x02, 0x03]),
17 Bytes::from_static(&[0x1c, 0x00, 0x04, 0x05, 0x06]),
18 Bytes::from_static(&[0x1c, 0x00, 0x07, 0x08, 0x09]),
19 Bytes::from_static(&[0x1c, 0x00, 0x10, 0x11, 0x12]),
20 Bytes::from_static(&[0x1c, 0x40, 0x13, 0x14, 0x15]),
21 ];
22
23 let mut pck = H264Payloader::default();
24
25 // Positive MTU, empty payload
26 let result = pck.payload(1, &empty)?;
27 assert!(result.is_empty(), "Generated payload should be empty");
28
29 // 0 MTU, small payload
30 let result = pck.payload(0, &small_payload)?;
31 assert_eq!(result.len(), 0, "Generated payload should be empty");
32
33 // Positive MTU, small payload
34 let result = pck.payload(1, &small_payload)?;
35 assert_eq!(result.len(), 0, "Generated payload should be empty");
36
37 // Positive MTU, small payload
38 let result = pck.payload(5, &small_payload)?;
39 assert_eq!(result.len(), 1, "Generated payload should be the 1");
40 assert_eq!(
41 result[0].len(),
42 small_payload.len(),
43 "Generated payload should be the same size as original payload size"
44 );
45
46 // Multiple NALU in a single payload
47 let result = pck.payload(5, &multiple_payload)?;
48 assert_eq!(result.len(), 2, "2 nal units should be broken out");
49 for i in 0..2 {
50 assert_eq!(
51 result[i].len(),
52 1,
53 "Payload {} of 2 is packed incorrectly",
54 i + 1,
55 );
56 }
57
58 // Large Payload split across multiple RTP Packets
59 let result = pck.payload(5, &large_payload)?;
60 assert_eq!(
61 result, large_payload_packetized,
62 "FU-A packetization failed"
63 );
64
65 // Nalu type 9 or 12
66 let small_payload2 = Bytes::from_static(&[0x09, 0x00, 0x00]);
67 let result = pck.payload(5, &small_payload2)?;
68 assert_eq!(result.len(), 0, "Generated payload should be empty");
69
70 Ok(())
71 }
72
73 #[test]
test_h264_packet_unmarshal() -> Result<()>74 fn test_h264_packet_unmarshal() -> Result<()> {
75 let single_payload = Bytes::from_static(&[0x90, 0x90, 0x90]);
76 let single_payload_unmarshaled =
77 Bytes::from_static(&[0x00, 0x00, 0x00, 0x01, 0x90, 0x90, 0x90]);
78 let single_payload_unmarshaled_avc =
79 Bytes::from_static(&[0x00, 0x00, 0x00, 0x03, 0x90, 0x90, 0x90]);
80
81 let large_payload = Bytes::from_static(&[
82 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
83 0x11, 0x12, 0x13, 0x14, 0x15,
84 ]);
85 let large_payload_avc = Bytes::from_static(&[
86 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
87 0x11, 0x12, 0x13, 0x14, 0x15,
88 ]);
89 let large_payload_packetized = vec![
90 Bytes::from_static(&[0x1c, 0x80, 0x01, 0x02, 0x03]),
91 Bytes::from_static(&[0x1c, 0x00, 0x04, 0x05, 0x06]),
92 Bytes::from_static(&[0x1c, 0x00, 0x07, 0x08, 0x09]),
93 Bytes::from_static(&[0x1c, 0x00, 0x10, 0x11, 0x12]),
94 Bytes::from_static(&[0x1c, 0x40, 0x13, 0x14, 0x15]),
95 ];
96
97 let single_payload_multi_nalu = Bytes::from_static(&[
98 0x78, 0x00, 0x0f, 0x67, 0x42, 0xc0, 0x1f, 0x1a, 0x32, 0x35, 0x01, 0x40, 0x7a, 0x40, 0x3c,
99 0x22, 0x11, 0xa8, 0x00, 0x05, 0x68, 0x1a, 0x34, 0xe3, 0xc8,
100 ]);
101 let single_payload_multi_nalu_unmarshaled = Bytes::from_static(&[
102 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1f, 0x1a, 0x32, 0x35, 0x01, 0x40, 0x7a, 0x40,
103 0x3c, 0x22, 0x11, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x68, 0x1a, 0x34, 0xe3, 0xc8,
104 ]);
105 let single_payload_multi_nalu_unmarshaled_avc = Bytes::from_static(&[
106 0x00, 0x00, 0x00, 0x0f, 0x67, 0x42, 0xc0, 0x1f, 0x1a, 0x32, 0x35, 0x01, 0x40, 0x7a, 0x40,
107 0x3c, 0x22, 0x11, 0xa8, 0x00, 0x00, 0x00, 0x05, 0x68, 0x1a, 0x34, 0xe3, 0xc8,
108 ]);
109
110 let incomplete_single_payload_multi_nalu = Bytes::from_static(&[
111 0x78, 0x00, 0x0f, 0x67, 0x42, 0xc0, 0x1f, 0x1a, 0x32, 0x35, 0x01, 0x40, 0x7a, 0x40, 0x3c,
112 0x22, 0x11,
113 ]);
114
115 let mut pkt = H264Packet::default();
116 let mut avc_pkt = H264Packet {
117 is_avc: true,
118 ..Default::default()
119 };
120
121 let data = Bytes::from_static(&[]);
122 let result = pkt.depacketize(&data);
123 assert!(result.is_err(), "Unmarshal did not fail on nil payload");
124
125 let data = Bytes::from_static(&[0x00, 0x00]);
126 let result = pkt.depacketize(&data);
127 assert!(
128 result.is_err(),
129 "Unmarshal accepted a packet that is too small for a payload and header"
130 );
131
132 let data = Bytes::from_static(&[0xFF, 0x00, 0x00]);
133 let result = pkt.depacketize(&data);
134 assert!(
135 result.is_err(),
136 "Unmarshal accepted a packet with a NALU Type we don't handle"
137 );
138
139 let result = pkt.depacketize(&incomplete_single_payload_multi_nalu);
140 assert!(
141 result.is_err(),
142 "Unmarshal accepted a STAP-A packet with insufficient data"
143 );
144
145 let payload = pkt.depacketize(&single_payload)?;
146 assert_eq!(
147 payload, single_payload_unmarshaled,
148 "Unmarshaling a single payload shouldn't modify the payload"
149 );
150
151 let payload = avc_pkt.depacketize(&single_payload)?;
152 assert_eq!(
153 payload, single_payload_unmarshaled_avc,
154 "Unmarshaling a single payload into avc stream shouldn't modify the payload"
155 );
156
157 let mut large_payload_result = BytesMut::new();
158 for p in &large_payload_packetized {
159 let payload = pkt.depacketize(p)?;
160 large_payload_result.put(&*payload.clone());
161 }
162 assert_eq!(
163 large_payload_result.freeze(),
164 large_payload,
165 "Failed to unmarshal a large payload"
166 );
167
168 let mut large_payload_result_avc = BytesMut::new();
169 for p in &large_payload_packetized {
170 let payload = avc_pkt.depacketize(p)?;
171 large_payload_result_avc.put(&*payload.clone());
172 }
173 assert_eq!(
174 large_payload_result_avc.freeze(),
175 large_payload_avc,
176 "Failed to unmarshal a large payload into avc stream"
177 );
178
179 let payload = pkt.depacketize(&single_payload_multi_nalu)?;
180 assert_eq!(
181 payload, single_payload_multi_nalu_unmarshaled,
182 "Failed to unmarshal a single packet with multiple NALUs"
183 );
184
185 let payload = avc_pkt.depacketize(&single_payload_multi_nalu)?;
186 assert_eq!(
187 payload, single_payload_multi_nalu_unmarshaled_avc,
188 "Failed to unmarshal a single packet with multiple NALUs into avc stream"
189 );
190
191 Ok(())
192 }
193
194 #[test]
test_h264_partition_head_checker_is_partition_head() -> Result<()>195 fn test_h264_partition_head_checker_is_partition_head() -> Result<()> {
196 let h264 = H264Packet::default();
197 let empty_nalu = Bytes::from_static(&[]);
198 assert!(
199 !h264.is_partition_head(&empty_nalu),
200 "empty nalu must not be a partition head"
201 );
202
203 let single_nalu = Bytes::from_static(&[1, 0]);
204 assert!(
205 h264.is_partition_head(&single_nalu),
206 "single nalu must be a partition head"
207 );
208
209 let stapa_nalu = Bytes::from_static(&[STAPA_NALU_TYPE, 0]);
210 assert!(
211 h264.is_partition_head(&stapa_nalu),
212 "stapa nalu must be a partition head"
213 );
214
215 let fua_start_nalu = Bytes::from_static(&[FUA_NALU_TYPE, FU_START_BITMASK]);
216 assert!(
217 h264.is_partition_head(&fua_start_nalu),
218 "fua start nalu must be a partition head"
219 );
220
221 let fua_end_nalu = Bytes::from_static(&[FUA_NALU_TYPE, FU_END_BITMASK]);
222 assert!(
223 !h264.is_partition_head(&fua_end_nalu),
224 "fua end nalu must not be a partition head"
225 );
226
227 let fub_start_nalu = Bytes::from_static(&[FUB_NALU_TYPE, FU_START_BITMASK]);
228 assert!(
229 h264.is_partition_head(&fub_start_nalu),
230 "fub start nalu must be a partition head"
231 );
232
233 let fub_end_nalu = Bytes::from_static(&[FUB_NALU_TYPE, FU_END_BITMASK]);
234 assert!(
235 !h264.is_partition_head(&fub_end_nalu),
236 "fub end nalu must not be a partition head"
237 );
238
239 Ok(())
240 }
241
242 #[test]
test_h264_payloader_payload_sps_and_pps_handling() -> Result<()>243 fn test_h264_payloader_payload_sps_and_pps_handling() -> Result<()> {
244 let mut pck = H264Payloader::default();
245 let expected = vec![
246 Bytes::from_static(&[
247 0x78, 0x00, 0x03, 0x07, 0x00, 0x01, 0x00, 0x03, 0x08, 0x02, 0x03,
248 ]),
249 Bytes::from_static(&[0x05, 0x04, 0x05]),
250 ];
251
252 // When packetizing SPS and PPS are emitted with following NALU
253 let res = pck.payload(1500, &Bytes::from_static(&[0x07, 0x00, 0x01]))?;
254 assert!(res.is_empty(), "Generated payload should be empty");
255
256 let res = pck.payload(1500, &Bytes::from_static(&[0x08, 0x02, 0x03]))?;
257 assert!(res.is_empty(), "Generated payload should be empty");
258
259 let actual = pck.payload(1500, &Bytes::from_static(&[0x05, 0x04, 0x05]))?;
260 assert_eq!(actual, expected, "SPS and PPS aren't packed together");
261
262 Ok(())
263 }
264