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