1use std::{fmt, marker::PhantomData, mem, ptr, slice};
4
5use crate::ffi;
6use glib::translate::{from_glib, mut_override, FromGlibPtrFull, IntoGlib};
7
8pub enum Readable {}
9pub enum Writable {}
10
11pub struct RTPBuffer<'a, T> {
15 rtp_buffer: ffi::GstRTPBuffer,
16 phantom: PhantomData<&'a T>,
17}
18
19unsafe impl<T> Send for RTPBuffer<'_, T> {}
20unsafe impl<T> Sync for RTPBuffer<'_, T> {}
21
22impl<T> fmt::Debug for RTPBuffer<'_, T> {
23 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24 f.debug_struct("RTPBuffer")
25 .field("rtp_buffer", &self.rtp_buffer)
26 .finish()
27 }
28}
29
30impl<'a> RTPBuffer<'a, Readable> {
31 #[inline]
32 pub fn from_buffer_readable(
33 buffer: &'a gst::BufferRef,
34 ) -> Result<RTPBuffer<'a, Readable>, glib::BoolError> {
35 skip_assert_initialized!();
36 unsafe {
37 let mut rtp_buffer = mem::MaybeUninit::zeroed();
38 let res: bool = from_glib(ffi::gst_rtp_buffer_map(
39 mut_override(buffer.as_ptr()),
40 gst::ffi::GST_MAP_READ,
41 rtp_buffer.as_mut_ptr(),
42 ));
43
44 if res {
45 Ok(RTPBuffer {
46 rtp_buffer: rtp_buffer.assume_init(),
47 phantom: PhantomData,
48 })
49 } else {
50 Err(glib::bool_error!("Failed to map RTP buffer readable"))
51 }
52 }
53 }
54
55 #[inline]
56 pub unsafe fn from_glib_borrow<'b>(
57 rtp_buffer: *mut ffi::GstRTPBuffer,
58 ) -> glib::translate::Borrowed<RTPBuffer<'b, Readable>> {
59 glib::translate::Borrowed::new(RTPBuffer {
60 rtp_buffer: *rtp_buffer,
61 phantom: PhantomData,
62 })
63 }
64}
65
66impl<'a> RTPBuffer<'a, Writable> {
67 #[inline]
68 pub fn from_buffer_writable(
69 buffer: &'a mut gst::BufferRef,
70 ) -> Result<RTPBuffer<'a, Writable>, glib::BoolError> {
71 skip_assert_initialized!();
72 unsafe {
73 let mut rtp_buffer = mem::MaybeUninit::zeroed();
74 let res: bool = from_glib(ffi::gst_rtp_buffer_map(
75 buffer.as_mut_ptr(),
76 gst::ffi::GST_MAP_READWRITE,
77 rtp_buffer.as_mut_ptr(),
78 ));
79
80 if res {
81 Ok(RTPBuffer {
82 rtp_buffer: rtp_buffer.assume_init(),
83 phantom: PhantomData,
84 })
85 } else {
86 Err(glib::bool_error!("Failed to map RTP buffer writable"))
87 }
88 }
89 }
90
91 #[doc(alias = "gst_rtp_buffer_set_seq")]
92 pub fn set_seq(&mut self, seq: u16) {
93 unsafe {
94 ffi::gst_rtp_buffer_set_seq(&mut self.rtp_buffer, seq);
95 }
96 }
97
98 #[doc(alias = "gst_rtp_buffer_set_marker")]
99 pub fn set_marker(&mut self, m: bool) {
100 unsafe {
101 ffi::gst_rtp_buffer_set_marker(&mut self.rtp_buffer, m.into_glib());
102 }
103 }
104
105 #[doc(alias = "gst_rtp_buffer_set_payload_type")]
106 pub fn set_payload_type(&mut self, pt: u8) {
107 unsafe {
108 ffi::gst_rtp_buffer_set_payload_type(&mut self.rtp_buffer, pt);
109 }
110 }
111
112 #[doc(alias = "gst_rtp_buffer_set_ssrc")]
113 pub fn set_ssrc(&mut self, ssrc: u32) {
114 unsafe { ffi::gst_rtp_buffer_set_ssrc(&mut self.rtp_buffer, ssrc) }
115 }
116
117 #[doc(alias = "gst_rtp_buffer_set_csrc")]
118 pub fn set_csrc(&mut self, idx: u8, ssrc: u32) {
119 unsafe { ffi::gst_rtp_buffer_set_csrc(&mut self.rtp_buffer, idx, ssrc) }
120 }
121
122 #[doc(alias = "gst_rtp_buffer_set_timestamp")]
123 pub fn set_timestamp(&mut self, rtptime: u32) {
124 unsafe {
125 ffi::gst_rtp_buffer_set_timestamp(&mut self.rtp_buffer, rtptime);
126 }
127 }
128
129 #[doc(alias = "gst_rtp_buffer_set_extension")]
130 pub fn set_extension(&mut self, extension: bool) {
131 unsafe { ffi::gst_rtp_buffer_set_extension(&mut self.rtp_buffer, extension.into_glib()) }
132 }
133
134 #[doc(alias = "gst_rtp_buffer_add_extension_onebyte_header")]
135 #[allow(clippy::manual_range_contains)]
136 pub fn add_extension_onebyte_header(
137 &mut self,
138 id: u8,
139 data: &[u8],
140 ) -> Result<(), glib::BoolError> {
141 assert!(
142 id >= 1 && id <= 14,
143 "id should be between 1 and 14 (inclusive)"
144 );
145 assert!(
146 !data.is_empty() && data.len() <= 16,
147 "data size should be between 1 and 16 (inclusive"
148 );
149 unsafe {
150 let result: bool = from_glib(ffi::gst_rtp_buffer_add_extension_onebyte_header(
151 &mut self.rtp_buffer,
152 id,
153 data.as_ptr() as glib::ffi::gconstpointer,
154 data.len() as u32,
155 ));
156 if result {
157 Ok(())
158 } else {
159 Err(glib::bool_error!("Failed to add onebyte header extension"))
160 }
161 }
162 }
163
164 #[doc(alias = "gst_rtp_buffer_add_extension_twobytes_header")]
165 pub fn add_extension_twobytes_header(
166 &mut self,
167 appbits: u8,
168 id: u8,
169 data: &[u8],
170 ) -> Result<(), glib::BoolError> {
171 assert_eq!(
172 appbits & 0xF0,
173 0,
174 "appbits must use only 4 bits (max value is 15)"
175 );
176 assert!(data.len() < 256, "data size should be smaller than 256");
177 unsafe {
178 let result: bool = from_glib(ffi::gst_rtp_buffer_add_extension_twobytes_header(
179 &mut self.rtp_buffer,
180 appbits,
181 id,
182 data.as_ptr() as glib::ffi::gconstpointer,
183 data.len() as u32,
184 ));
185 if result {
186 Ok(())
187 } else {
188 Err(glib::bool_error!("Failed to add twobytes header extension"))
189 }
190 }
191 }
192
193 #[cfg(feature = "v1_20")]
194 #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
195 #[doc(alias = "gst_rtp_buffer_remove_extension_data")]
196 pub fn remove_extension_data(&mut self) {
197 unsafe {
198 ffi::gst_rtp_buffer_remove_extension_data(&mut self.rtp_buffer);
199 }
200 }
201
202 #[doc(alias = "gst_rtp_buffer_set_padding")]
203 pub fn set_padding(&mut self, padding: bool) {
204 unsafe { ffi::gst_rtp_buffer_set_padding(&mut self.rtp_buffer, padding.into_glib()) }
205 }
206}
207
208impl<T> RTPBuffer<'_, T> {
209 #[doc(alias = "get_seq")]
210 #[doc(alias = "gst_rtp_buffer_get_seq")]
211 pub fn seq(&self) -> u16 {
212 unsafe { ffi::gst_rtp_buffer_get_seq(glib::translate::mut_override(&self.rtp_buffer)) }
213 }
214
215 #[doc(alias = "get_payload_type")]
216 #[doc(alias = "gst_rtp_buffer_get_payload_type")]
217 pub fn payload_type(&self) -> u8 {
218 unsafe {
219 ffi::gst_rtp_buffer_get_payload_type(glib::translate::mut_override(&self.rtp_buffer))
220 }
221 }
222
223 #[doc(alias = "get_ssrc")]
224 #[doc(alias = "gst_rtp_buffer_get_ssrc")]
225 pub fn ssrc(&self) -> u32 {
226 unsafe { ffi::gst_rtp_buffer_get_ssrc(glib::translate::mut_override(&self.rtp_buffer)) }
227 }
228
229 #[doc(alias = "get_timestamp")]
230 #[doc(alias = "gst_rtp_buffer_get_timestamp")]
231 pub fn timestamp(&self) -> u32 {
232 unsafe {
233 ffi::gst_rtp_buffer_get_timestamp(glib::translate::mut_override(&self.rtp_buffer))
234 }
235 }
236
237 #[doc(alias = "get_csrc")]
238 #[doc(alias = "gst_rtp_buffer_get_csrc")]
239 pub fn csrc(&self, idx: u8) -> Option<u32> {
240 if idx < self.csrc_count() {
241 unsafe {
242 Some(ffi::gst_rtp_buffer_get_csrc(
243 glib::translate::mut_override(&self.rtp_buffer),
244 idx,
245 ))
246 }
247 } else {
248 None
249 }
250 }
251
252 #[doc(alias = "get_csrc_count")]
253 #[doc(alias = "gst_rtp_buffer_get_csrc_count")]
254 pub fn csrc_count(&self) -> u8 {
255 unsafe {
256 ffi::gst_rtp_buffer_get_csrc_count(glib::translate::mut_override(&self.rtp_buffer))
257 }
258 }
259
260 #[doc(alias = "get_marker")]
261 pub fn is_marker(&self) -> bool {
262 unsafe {
263 from_glib(ffi::gst_rtp_buffer_get_marker(
264 glib::translate::mut_override(&self.rtp_buffer),
265 ))
266 }
267 }
268
269 #[doc(alias = "get_payload_size")]
270 pub fn payload_size(&self) -> u32 {
271 unsafe {
272 ffi::gst_rtp_buffer_get_payload_len(glib::translate::mut_override(&self.rtp_buffer))
273 }
274 }
275
276 #[doc(alias = "get_payload")]
277 #[doc(alias = "gst_rtp_buffer_get_payload")]
278 pub fn payload(&self) -> Result<&[u8], glib::error::BoolError> {
279 let size = self.payload_size();
280 if size == 0 {
281 return Ok(&[]);
282 }
283 unsafe {
284 let pointer =
285 ffi::gst_rtp_buffer_get_payload(glib::translate::mut_override(&self.rtp_buffer));
286 if pointer.is_null() {
287 Err(glib::bool_error!("Failed to get payload data"))
288 } else {
289 Ok(slice::from_raw_parts(pointer as *const u8, size as usize))
290 }
291 }
292 }
293
294 #[doc(alias = "get_payload")]
295 #[doc(alias = "gst_rtp_buffer_get_payload")]
296 pub fn payload_mut(&mut self) -> Result<&mut [u8], glib::error::BoolError> {
297 let size = self.payload_size();
298 if size == 0 {
299 return Ok(&mut []);
300 }
301 unsafe {
302 let pointer = ffi::gst_rtp_buffer_get_payload(&mut self.rtp_buffer);
303 if pointer.is_null() {
304 Err(glib::bool_error!("Failed to get payload data"))
305 } else {
306 Ok(slice::from_raw_parts_mut(pointer as *mut u8, size as usize))
307 }
308 }
309 }
310
311 #[doc(alias = "get_payload_buffer")]
312 #[doc(alias = "gst_rtp_buffer_get_payload_buffer")]
313 pub fn payload_buffer(&self) -> Result<gst::Buffer, glib::BoolError> {
314 unsafe {
315 Option::<_>::from_glib_full(ffi::gst_rtp_buffer_get_payload_buffer(
316 glib::translate::mut_override(&self.rtp_buffer),
317 ))
318 .ok_or_else(|| glib::bool_error!("Failed to get payload buffer"))
319 }
320 }
321
322 #[inline]
323 pub fn buffer(&self) -> &gst::BufferRef {
324 unsafe {
325 let ptr = self.rtp_buffer.buffer;
326
327 debug_assert!(!ptr.is_null());
328
329 gst::BufferRef::from_ptr(ptr)
330 }
331 }
332
333 #[doc(alias = "get_extension")]
334 pub fn is_extension(&self) -> bool {
335 unsafe {
336 from_glib(ffi::gst_rtp_buffer_get_extension(
337 glib::translate::mut_override(&self.rtp_buffer),
338 ))
339 }
340 }
341
342 #[doc(alias = "get_extension_bytes")]
343 #[doc(alias = "gst_rtp_buffer_get_extension_bytes")]
344 pub fn extension_bytes(&self) -> Option<(u16, glib::Bytes)> {
345 unsafe {
346 let mut bits: u16 = 0;
347 Option::<glib::Bytes>::from_glib_full(ffi::gst_rtp_buffer_get_extension_bytes(
348 glib::translate::mut_override(&self.rtp_buffer),
349 &mut bits,
350 ))
351 .map(|bytes| (bits, bytes))
352 }
353 }
354
355 #[doc(alias = "get_extension_onebyte_header")]
356 #[doc(alias = "gst_rtp_buffer_get_extension_onebyte_header")]
357 pub fn extension_onebyte_header(&self, id: u8, nth: u32) -> Option<&[u8]> {
358 unsafe {
359 let mut data = ptr::null_mut();
360 let data_ptr = &mut data as *mut *mut u8 as *mut u8;
362 let mut size: u32 = 0;
363 let result: bool = from_glib(ffi::gst_rtp_buffer_get_extension_onebyte_header(
364 glib::translate::mut_override(&self.rtp_buffer),
365 id,
366 nth,
367 data_ptr,
368 &mut size,
369 ));
370 if result {
371 if size == 0 {
372 Some(&[])
373 } else {
374 Some(slice::from_raw_parts(data as *const u8, size as usize))
375 }
376 } else {
377 None
378 }
379 }
380 }
381
382 #[doc(alias = "get_extension_twobytes_header")]
383 #[doc(alias = "gst_rtp_buffer_get_extension_twobytes_header")]
384 pub fn extension_twobytes_header(&self, id: u8, nth: u32) -> Option<(u8, &[u8])> {
385 unsafe {
386 let mut data = ptr::null_mut();
387 let data_ptr = &mut data as *mut *mut u8 as *mut u8;
389 let mut size: u32 = 0;
390 let mut appbits = 0;
391 let result: bool = from_glib(ffi::gst_rtp_buffer_get_extension_twobytes_header(
392 glib::translate::mut_override(&self.rtp_buffer),
393 &mut appbits,
394 id,
395 nth,
396 data_ptr,
397 &mut size,
398 ));
399 if result {
400 if size == 0 {
401 Some((appbits, &[]))
402 } else {
403 Some((
404 appbits,
405 slice::from_raw_parts(data as *const u8, size as usize),
406 ))
407 }
408 } else {
409 None
410 }
411 }
412 }
413
414 #[doc(alias = "get_padding")]
415 #[doc(alias = "gst_rtp_buffer_get_padding")]
416 pub fn has_padding(&self) -> bool {
417 unsafe {
418 from_glib(ffi::gst_rtp_buffer_get_padding(
419 glib::translate::mut_override(&self.rtp_buffer),
420 ))
421 }
422 }
423
424 #[inline]
425 pub fn as_ptr(&self) -> *const ffi::GstRTPBuffer {
426 &self.rtp_buffer as *const ffi::GstRTPBuffer
427 }
428
429 #[inline]
430 pub fn as_mut_ptr(&self) -> *mut ffi::GstRTPBuffer {
431 &self.rtp_buffer as *const ffi::GstRTPBuffer as *mut ffi::GstRTPBuffer
432 }
433}
434
435impl<T> Drop for RTPBuffer<'_, T> {
436 #[inline]
437 fn drop(&mut self) {
438 unsafe {
439 ffi::gst_rtp_buffer_unmap(&mut self.rtp_buffer);
440 }
441 }
442}
443
444pub trait RTPBufferExt {
445 fn new_rtp_with_sizes(
446 payload_len: u32,
447 pad_len: u8,
448 csrc_count: u8,
449 ) -> Result<gst::Buffer, glib::BoolError>;
450}
451
452impl RTPBufferExt for gst::Buffer {
453 fn new_rtp_with_sizes(
454 payload_len: u32,
455 pad_len: u8,
456 csrc_count: u8,
457 ) -> Result<gst::Buffer, glib::BoolError> {
458 assert_initialized_main_thread!();
459 unsafe {
460 Option::<_>::from_glib_full(ffi::gst_rtp_buffer_new_allocate(
461 payload_len,
462 pad_len,
463 csrc_count,
464 ))
465 .ok_or_else(|| glib::bool_error!("Failed to allocate new RTP buffer"))
466 }
467 }
468}
469
470#[doc(alias = "gst_rtp_buffer_compare_seqnum")]
471pub fn compare_seqnum(seqnum1: u16, seqnum2: u16) -> i32 {
472 skip_assert_initialized!();
473 unsafe { ffi::gst_rtp_buffer_compare_seqnum(seqnum1, seqnum2) }
474}
475
476#[doc(alias = "gst_rtp_buffer_calc_header_len")]
477pub fn calc_header_len(csrc_count: u8) -> u32 {
478 skip_assert_initialized!();
479 unsafe { ffi::gst_rtp_buffer_calc_header_len(csrc_count) }
480}
481
482#[doc(alias = "gst_rtp_buffer_calc_packet_len")]
483pub fn calc_packet_len(payload_len: u32, pad_len: u8, csrc_count: u8) -> u32 {
484 skip_assert_initialized!();
485 unsafe { ffi::gst_rtp_buffer_calc_packet_len(payload_len, pad_len, csrc_count) }
486}
487
488#[doc(alias = "gst_rtp_buffer_calc_payload_len")]
489pub fn calc_payload_len(packet_len: u32, pad_len: u8, csrc_count: u8) -> u32 {
490 skip_assert_initialized!();
491 unsafe { ffi::gst_rtp_buffer_calc_payload_len(packet_len, pad_len, csrc_count) }
492}
493
494#[doc(alias = "gst_rtp_buffer_ext_timestamp")]
495pub fn ext_timestamp(exttimestamp: &mut u64, timestamp: u32) -> u64 {
496 skip_assert_initialized!();
497 unsafe { ffi::gst_rtp_buffer_ext_timestamp(exttimestamp, timestamp) }
498}
499
500#[cfg(test)]
501mod tests {
502 use super::*;
503
504 #[test]
505 fn test_map() {
506 gst::init().unwrap();
507
508 let csrc_count = 2;
509 let payload_size = 16;
510 let mut buffer = gst::Buffer::new_rtp_with_sizes(payload_size, 4, csrc_count).unwrap();
511 {
512 let buffer = buffer.get_mut().unwrap();
513 let mut rtp_buffer = RTPBuffer::from_buffer_writable(buffer).unwrap();
514
515 rtp_buffer.set_seq(42);
516 assert_eq!(rtp_buffer.seq(), 42);
517
518 rtp_buffer.set_marker(true);
519 assert!(rtp_buffer.is_marker());
520
521 rtp_buffer.set_payload_type(43);
522 assert_eq!(rtp_buffer.payload_type(), 43);
523
524 rtp_buffer.set_timestamp(44);
525 assert_eq!(rtp_buffer.timestamp(), 44);
526
527 rtp_buffer.set_ssrc(45);
528 assert_eq!(rtp_buffer.ssrc(), 45);
529
530 assert_eq!(rtp_buffer.payload_size(), payload_size);
531 let payload = rtp_buffer.payload();
532 assert!(payload.is_ok());
533 let payload = payload.unwrap();
534 assert_eq!(payload.len(), payload_size as usize);
535
536 assert_eq!(rtp_buffer.csrc_count(), csrc_count);
537 rtp_buffer.set_csrc(0, 12);
538 rtp_buffer.set_csrc(1, 15);
539 assert_eq!(rtp_buffer.csrc(0).unwrap(), 12);
540 assert_eq!(rtp_buffer.csrc(1).unwrap(), 15);
541 assert!(rtp_buffer.csrc(2).is_none());
542
543 rtp_buffer.set_extension(true);
544 assert!(rtp_buffer.is_extension());
545
546 assert_eq!(rtp_buffer.extension_bytes(), None);
547 }
548 }
549
550 #[test]
551 fn test_empty_payload() {
552 gst::init().unwrap();
553
554 let csrc_count = 0;
555 let payload_size = 0;
556 let buffer = gst::Buffer::new_rtp_with_sizes(payload_size, 4, csrc_count).unwrap();
557 let rtp_buffer = RTPBuffer::from_buffer_readable(&buffer).unwrap();
558
559 assert_eq!(rtp_buffer.payload_size(), payload_size);
560 let payload = rtp_buffer.payload();
561 assert!(payload.is_ok());
562 assert_eq!(payload.unwrap().len(), payload_size as usize);
563 }
564
565 #[test]
566 fn test_mut_payload() {
567 gst::init().unwrap();
568
569 let csrc_count = 2;
570 let payload_size = 8;
571 let mut buffer = gst::Buffer::new_rtp_with_sizes(payload_size, 4, csrc_count).unwrap();
572 {
573 let buffer = buffer.get_mut().unwrap();
574 let mut rtp_buffer = RTPBuffer::from_buffer_writable(buffer).unwrap();
575
576 let payload = rtp_buffer.payload_mut();
577 assert!(payload.is_ok());
578
579 let payload = payload.unwrap();
580 payload[3] = 42;
581 }
582
583 let rtp_buffer = RTPBuffer::from_buffer_readable(&buffer).unwrap();
584 let payload = rtp_buffer.payload();
585
586 assert!(payload.is_ok());
587 assert_eq!(payload.unwrap()[3], 42);
588 }
589
590 #[test]
591 fn test_extension_header_onebyte() {
592 gst::init().unwrap();
593
594 let extension_data: [u8; 4] = [100, 101, 102, 103];
595 let mut buffer = gst::Buffer::new_rtp_with_sizes(16, 4, 0).unwrap();
596 {
597 let buffer = buffer.get_mut().unwrap();
598 let mut rtp_buffer = RTPBuffer::from_buffer_writable(buffer).unwrap();
599
600 assert_eq!(rtp_buffer.extension_bytes(), None);
601
602 let result = rtp_buffer.add_extension_onebyte_header(1, &extension_data);
603 assert!(result.is_ok());
604 }
605
606 let rtp_buffer = RTPBuffer::from_buffer_readable(&buffer).unwrap();
607 let bytes_option = rtp_buffer.extension_bytes();
608 assert!(bytes_option.is_some());
609 let (bits, bytes) = bytes_option.unwrap();
610 assert_eq!(bits, 0xbede);
612 assert_eq!(bytes[0] >> 4, 1);
619 assert_eq!(bytes[0] & 0xF, 3);
620 for i in 0..extension_data.len() {
621 assert_eq!(bytes[i + 1], extension_data[i]);
622 }
623
624 let result = rtp_buffer.extension_onebyte_header(2, 0);
625 assert!(result.is_none());
626
627 let result = rtp_buffer.extension_onebyte_header(1, 0);
628 assert!(result.is_some());
629 assert_eq!(result.unwrap(), &extension_data);
630 }
631
632 #[test]
633 fn test_extension_header_twobytes() {
634 gst::init().unwrap();
635
636 let extension_data: [u8; 4] = [100, 101, 102, 103];
637 let appbits = 5;
638 let id = 1;
639
640 let mut buffer = gst::Buffer::new_rtp_with_sizes(16, 4, 0).unwrap();
641 {
642 let buffer = buffer.get_mut().unwrap();
643 let mut rtp_buffer = RTPBuffer::from_buffer_writable(buffer).unwrap();
644
645 assert_eq!(rtp_buffer.extension_bytes(), None);
646
647 let result = rtp_buffer.add_extension_twobytes_header(appbits, id, &extension_data);
648 assert!(result.is_ok());
649 }
650
651 let rtp_buffer = RTPBuffer::from_buffer_readable(&buffer).unwrap();
652
653 let bytes_option = rtp_buffer.extension_bytes();
654 assert!(bytes_option.is_some());
655 let (bits, bytes) = bytes_option.unwrap();
656 assert_eq!(bits, 0x1000 | appbits as u16);
659 assert_eq!(bytes[0], id);
666 assert_eq!(bytes[1], extension_data.len() as u8);
667 for i in 0..extension_data.len() {
668 assert_eq!(bytes[i + 2], extension_data[i]);
669 }
670
671 let result = rtp_buffer.extension_twobytes_header(2, 0);
672 assert!(result.is_none());
673
674 let result = rtp_buffer.extension_twobytes_header(id, 0);
675 assert!(result.is_some());
676 let (extracted_appbits, data) = result.unwrap();
677 assert_eq!(appbits, extracted_appbits);
678 assert_eq!(data, &extension_data);
679 }
680
681 #[test]
682 fn test_padding() {
683 gst::init().unwrap();
684
685 let csrc_count = 2;
686 let payload_size = 16;
687 let mut buffer = gst::Buffer::new_rtp_with_sizes(payload_size, 4, csrc_count).unwrap();
688 {
689 let rtp_buffer = RTPBuffer::from_buffer_readable(&buffer).unwrap();
690 assert!(rtp_buffer.has_padding());
691 }
692 {
693 let buffer = buffer.get_mut().unwrap();
694 let mut rtp_buffer = RTPBuffer::from_buffer_writable(buffer).unwrap();
695
696 rtp_buffer.set_padding(false);
697 }
698
699 {
700 let rtp_buffer = RTPBuffer::from_buffer_readable(&buffer).unwrap();
701 assert!(!rtp_buffer.has_padding());
702 }
703 }
704
705 #[test]
706 fn test_calc_functions() {
707 let res = super::calc_header_len(0);
708 assert_eq!(res, 12);
709 let res = super::calc_packet_len(100, 10, 2);
710 assert_eq!(res, 130);
711 let res = super::calc_payload_len(100, 5, 4);
712 assert_eq!(res, 67);
713 }
714}