xref: /webrtc/rtp/src/codecs/h264/h264_test.rs (revision 013c11db)
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