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