1use std::{
4 cmp, fmt,
5 marker::PhantomData,
6 mem, ops,
7 ops::{Bound, ControlFlow, Range, RangeBounds},
8 ptr, slice,
9};
10
11use glib::translate::*;
12
13use crate::{
14 ffi, meta::*, BufferCursor, BufferFlags, BufferRefCursor, ClockTime, Memory, MemoryRef,
15};
16
17pub enum Readable {}
18pub enum Writable {}
19
20#[derive(Copy, Clone, Debug, PartialEq, Eq)]
21pub enum BufferMetaForeachAction {
22 Keep,
23 Remove,
24}
25
26mini_object_wrapper!(Buffer, BufferRef, ffi::GstBuffer, || {
27 ffi::gst_buffer_get_type()
28});
29
30pub struct BufferMap<'a, T> {
31 buffer: &'a BufferRef,
32 map_info: ffi::GstMapInfo,
33 phantom: PhantomData<T>,
34}
35
36pub struct MappedBuffer<T> {
37 buffer: Buffer,
38 map_info: ffi::GstMapInfo,
39 phantom: PhantomData<T>,
40}
41
42impl Buffer {
43 #[doc(alias = "gst_buffer_new")]
44 #[inline]
45 pub fn new() -> Self {
46 assert_initialized_main_thread!();
47
48 unsafe { from_glib_full(ffi::gst_buffer_new()) }
49 }
50
51 #[doc(alias = "gst_buffer_new_allocate")]
52 #[doc(alias = "gst_buffer_new_and_alloc")]
53 #[inline]
54 pub fn with_size(size: usize) -> Result<Self, glib::BoolError> {
55 assert_initialized_main_thread!();
56
57 unsafe {
58 Option::<_>::from_glib_full(ffi::gst_buffer_new_allocate(
59 ptr::null_mut(),
60 size,
61 ptr::null_mut(),
62 ))
63 .ok_or_else(|| glib::bool_error!("Failed to allocate buffer"))
64 }
65 }
66
67 #[doc(alias = "gst_buffer_new_wrapped")]
68 #[doc(alias = "gst_buffer_new_wrapped_full")]
69 #[inline]
70 pub fn from_mut_slice<T: AsMut<[u8]> + Send + 'static>(slice: T) -> Self {
71 assert_initialized_main_thread!();
72
73 let mem = Memory::from_mut_slice(slice);
74 let mut buffer = Buffer::new();
75 {
76 let buffer = buffer.get_mut().unwrap();
77 buffer.append_memory(mem);
78 buffer.unset_flags(BufferFlags::TAG_MEMORY);
79 }
80
81 buffer
82 }
83
84 #[doc(alias = "gst_buffer_new_wrapped")]
85 #[doc(alias = "gst_buffer_new_wrapped_full")]
86 #[inline]
87 pub fn from_slice<T: AsRef<[u8]> + Send + 'static>(slice: T) -> Self {
88 assert_initialized_main_thread!();
89
90 let mem = Memory::from_slice(slice);
91 let mut buffer = Buffer::new();
92 {
93 let buffer = buffer.get_mut().unwrap();
94 buffer.append_memory(mem);
95 buffer.unset_flags(BufferFlags::TAG_MEMORY);
96 }
97
98 buffer
99 }
100
101 #[doc(alias = "gst_buffer_map")]
102 #[inline]
103 pub fn into_mapped_buffer_readable(self) -> Result<MappedBuffer<Readable>, Self> {
104 unsafe {
105 let mut map_info = mem::MaybeUninit::uninit();
106 let res: bool = from_glib(ffi::gst_buffer_map(
107 self.as_mut_ptr(),
108 map_info.as_mut_ptr(),
109 ffi::GST_MAP_READ,
110 ));
111 if res {
112 Ok(MappedBuffer {
113 buffer: self,
114 map_info: map_info.assume_init(),
115 phantom: PhantomData,
116 })
117 } else {
118 Err(self)
119 }
120 }
121 }
122
123 #[doc(alias = "gst_buffer_map")]
124 #[inline]
125 pub fn into_mapped_buffer_writable(self) -> Result<MappedBuffer<Writable>, Self> {
126 unsafe {
127 let mut map_info = mem::MaybeUninit::uninit();
128 let res: bool = from_glib(ffi::gst_buffer_map(
129 self.as_mut_ptr(),
130 map_info.as_mut_ptr(),
131 ffi::GST_MAP_READWRITE,
132 ));
133 if res {
134 Ok(MappedBuffer {
135 buffer: self,
136 map_info: map_info.assume_init(),
137 phantom: PhantomData,
138 })
139 } else {
140 Err(self)
141 }
142 }
143 }
144
145 #[inline]
146 pub fn into_cursor_readable(self) -> BufferCursor<Readable> {
147 BufferCursor::new_readable(self)
148 }
149
150 #[inline]
151 pub fn into_cursor_writable(self) -> Result<BufferCursor<Writable>, glib::BoolError> {
152 BufferCursor::new_writable(self)
153 }
154
155 #[doc(alias = "gst_buffer_append")]
156 pub fn append(&mut self, other: Self) {
157 unsafe {
158 let ptr = ffi::gst_buffer_append(self.as_mut_ptr(), other.into_glib_ptr());
159 self.replace_ptr(ptr);
160 }
161 }
162}
163
164impl Default for Buffer {
165 fn default() -> Self {
166 Self::new()
167 }
168}
169
170impl BufferRef {
171 #[doc(alias = "gst_buffer_map")]
172 #[inline]
173 pub fn map_readable(&self) -> Result<BufferMap<Readable>, glib::BoolError> {
174 unsafe {
175 let mut map_info = mem::MaybeUninit::uninit();
176 let res =
177 ffi::gst_buffer_map(self.as_mut_ptr(), map_info.as_mut_ptr(), ffi::GST_MAP_READ);
178 if res == glib::ffi::GTRUE {
179 Ok(BufferMap {
180 buffer: self,
181 map_info: map_info.assume_init(),
182 phantom: PhantomData,
183 })
184 } else {
185 Err(glib::bool_error!("Failed to map buffer readable"))
186 }
187 }
188 }
189
190 #[doc(alias = "gst_buffer_map")]
191 #[inline]
192 pub fn map_writable(&mut self) -> Result<BufferMap<Writable>, glib::BoolError> {
193 unsafe {
194 let mut map_info = mem::MaybeUninit::uninit();
195 let res = ffi::gst_buffer_map(
196 self.as_mut_ptr(),
197 map_info.as_mut_ptr(),
198 ffi::GST_MAP_READWRITE,
199 );
200 if res == glib::ffi::GTRUE {
201 Ok(BufferMap {
202 buffer: self,
203 map_info: map_info.assume_init(),
204 phantom: PhantomData,
205 })
206 } else {
207 Err(glib::bool_error!("Failed to map buffer writable"))
208 }
209 }
210 }
211
212 fn memory_range_into_idx_len(
213 &self,
214 range: impl RangeBounds<usize>,
215 ) -> Result<(u32, i32), glib::BoolError> {
216 let n_memory = self.n_memory();
217 debug_assert!(n_memory <= u32::MAX as usize);
218
219 let start_idx = match range.start_bound() {
220 ops::Bound::Included(idx) if *idx >= n_memory => {
221 return Err(glib::bool_error!("Invalid range start"));
222 }
223 ops::Bound::Included(idx) => *idx,
224 ops::Bound::Excluded(idx) if idx.checked_add(1).map_or(true, |idx| idx >= n_memory) => {
225 return Err(glib::bool_error!("Invalid range start"));
226 }
227 ops::Bound::Excluded(idx) => *idx + 1,
228 ops::Bound::Unbounded => 0,
229 };
230
231 let end_idx = match range.end_bound() {
232 ops::Bound::Included(idx) if idx.checked_add(1).map_or(true, |idx| idx > n_memory) => {
233 return Err(glib::bool_error!("Invalid range end"));
234 }
235 ops::Bound::Included(idx) => *idx + 1,
236 ops::Bound::Excluded(idx) if *idx > n_memory => {
237 return Err(glib::bool_error!("Invalid range end"));
238 }
239 ops::Bound::Excluded(idx) => *idx,
240 ops::Bound::Unbounded => n_memory,
241 };
242
243 Ok((
244 start_idx as u32,
245 i32::try_from(end_idx - start_idx).map_err(|_| glib::bool_error!("Too large range"))?,
246 ))
247 }
248
249 #[doc(alias = "gst_buffer_map_range")]
250 #[inline]
251 pub fn map_range_readable(
252 &self,
253 range: impl RangeBounds<usize>,
254 ) -> Result<BufferMap<Readable>, glib::BoolError> {
255 let (idx, len) = self.memory_range_into_idx_len(range)?;
256 unsafe {
257 let mut map_info = mem::MaybeUninit::uninit();
258 let res = ffi::gst_buffer_map_range(
259 self.as_mut_ptr(),
260 idx,
261 len,
262 map_info.as_mut_ptr(),
263 ffi::GST_MAP_READ,
264 );
265 if res == glib::ffi::GTRUE {
266 Ok(BufferMap {
267 buffer: self,
268 map_info: map_info.assume_init(),
269 phantom: PhantomData,
270 })
271 } else {
272 Err(glib::bool_error!("Failed to map buffer readable"))
273 }
274 }
275 }
276
277 #[doc(alias = "gst_buffer_map_range")]
278 #[inline]
279 pub fn map_range_writable(
280 &mut self,
281 range: impl RangeBounds<usize>,
282 ) -> Result<BufferMap<Writable>, glib::BoolError> {
283 let (idx, len) = self.memory_range_into_idx_len(range)?;
284 unsafe {
285 let mut map_info = mem::MaybeUninit::uninit();
286 let res = ffi::gst_buffer_map_range(
287 self.as_mut_ptr(),
288 idx,
289 len,
290 map_info.as_mut_ptr(),
291 ffi::GST_MAP_READWRITE,
292 );
293 if res == glib::ffi::GTRUE {
294 Ok(BufferMap {
295 buffer: self,
296 map_info: map_info.assume_init(),
297 phantom: PhantomData,
298 })
299 } else {
300 Err(glib::bool_error!("Failed to map buffer writable"))
301 }
302 }
303 }
304
305 pub(crate) fn byte_range_into_offset_len(
306 &self,
307 range: impl RangeBounds<usize>,
308 ) -> Result<(usize, usize), glib::BoolError> {
309 let size = self.size();
310
311 let start_idx = match range.start_bound() {
312 ops::Bound::Included(idx) if *idx >= size => {
313 return Err(glib::bool_error!("Invalid range start"));
314 }
315 ops::Bound::Included(idx) => *idx,
316 ops::Bound::Excluded(idx) if idx.checked_add(1).map_or(true, |idx| idx >= size) => {
317 return Err(glib::bool_error!("Invalid range start"));
318 }
319 ops::Bound::Excluded(idx) => *idx + 1,
320 ops::Bound::Unbounded => 0,
321 };
322
323 let end_idx = match range.end_bound() {
324 ops::Bound::Included(idx) if idx.checked_add(1).map_or(true, |idx| idx > size) => {
325 return Err(glib::bool_error!("Invalid range end"));
326 }
327 ops::Bound::Included(idx) => *idx + 1,
328 ops::Bound::Excluded(idx) if *idx > size => {
329 return Err(glib::bool_error!("Invalid range end"));
330 }
331 ops::Bound::Excluded(idx) => *idx,
332 ops::Bound::Unbounded => size,
333 };
334
335 Ok((start_idx, end_idx - start_idx))
336 }
337
338 #[doc(alias = "gst_buffer_copy_region")]
339 pub fn copy_region(
340 &self,
341 flags: crate::BufferCopyFlags,
342 range: impl RangeBounds<usize>,
343 ) -> Result<Buffer, glib::BoolError> {
344 let (offset, size) = self.byte_range_into_offset_len(range)?;
345
346 unsafe {
347 Option::<_>::from_glib_full(ffi::gst_buffer_copy_region(
348 self.as_mut_ptr(),
349 flags.into_glib(),
350 offset,
351 size,
352 ))
353 .ok_or_else(|| glib::bool_error!("Failed to copy region of buffer"))
354 }
355 }
356
357 #[doc(alias = "gst_buffer_copy_into")]
358 pub fn copy_into(
359 &self,
360 dest: &mut BufferRef,
361 flags: crate::BufferCopyFlags,
362 range: impl RangeBounds<usize>,
363 ) -> Result<(), glib::BoolError> {
364 let (offset, size) = self.byte_range_into_offset_len(range)?;
365
366 unsafe {
367 glib::result_from_gboolean!(
368 ffi::gst_buffer_copy_into(
369 dest.as_mut_ptr(),
370 self.as_mut_ptr(),
371 flags.into_glib(),
372 offset,
373 size,
374 ),
375 "Failed to copy into destination buffer",
376 )
377 }
378 }
379
380 #[doc(alias = "gst_buffer_fill")]
381 pub fn copy_from_slice(&mut self, offset: usize, slice: &[u8]) -> Result<(), usize> {
382 let maxsize = self.maxsize();
383 let size = slice.len();
384
385 assert!(maxsize >= offset && maxsize - offset >= size);
386
387 let copied = unsafe {
388 let src = slice.as_ptr();
389 ffi::gst_buffer_fill(
390 self.as_mut_ptr(),
391 offset,
392 src as glib::ffi::gconstpointer,
393 size,
394 )
395 };
396
397 if copied == size {
398 Ok(())
399 } else {
400 Err(copied)
401 }
402 }
403
404 #[doc(alias = "gst_buffer_extract")]
405 pub fn copy_to_slice(&self, offset: usize, slice: &mut [u8]) -> Result<(), usize> {
406 let maxsize = self.size();
407 let size = slice.len();
408
409 assert!(maxsize >= offset && maxsize - offset >= size);
410
411 let copied = unsafe {
412 let dest = slice.as_mut_ptr();
413 ffi::gst_buffer_extract(self.as_mut_ptr(), offset, dest as glib::ffi::gpointer, size)
414 };
415
416 if copied == size {
417 Ok(())
418 } else {
419 Err(copied)
420 }
421 }
422
423 #[doc(alias = "gst_buffer_copy_deep")]
424 pub fn copy_deep(&self) -> Result<Buffer, glib::BoolError> {
425 unsafe {
426 Option::<_>::from_glib_full(ffi::gst_buffer_copy_deep(self.as_ptr()))
427 .ok_or_else(|| glib::bool_error!("Failed to deep copy buffer"))
428 }
429 }
430
431 #[doc(alias = "get_size")]
432 #[doc(alias = "gst_buffer_get_size")]
433 pub fn size(&self) -> usize {
434 unsafe { ffi::gst_buffer_get_size(self.as_mut_ptr()) }
435 }
436
437 #[doc(alias = "get_maxsize")]
438 pub fn maxsize(&self) -> usize {
439 unsafe {
440 let mut maxsize = mem::MaybeUninit::uninit();
441 ffi::gst_buffer_get_sizes_range(
442 self.as_mut_ptr(),
443 0,
444 -1,
445 ptr::null_mut(),
446 maxsize.as_mut_ptr(),
447 );
448
449 maxsize.assume_init()
450 }
451 }
452
453 #[doc(alias = "gst_buffer_set_size")]
454 pub fn set_size(&mut self, size: usize) {
455 assert!(self.maxsize() >= size);
456
457 unsafe {
458 ffi::gst_buffer_set_size(self.as_mut_ptr(), size as isize);
459 }
460 }
461
462 #[doc(alias = "get_offset")]
463 #[doc(alias = "GST_BUFFER_OFFSET")]
464 #[inline]
465 pub fn offset(&self) -> u64 {
466 self.0.offset
467 }
468
469 #[inline]
470 pub fn set_offset(&mut self, offset: u64) {
471 self.0.offset = offset;
472 }
473
474 #[doc(alias = "get_offset_end")]
475 #[doc(alias = "GST_BUFFER_OFFSET_END")]
476 #[inline]
477 pub fn offset_end(&self) -> u64 {
478 self.0.offset_end
479 }
480
481 #[inline]
482 pub fn set_offset_end(&mut self, offset_end: u64) {
483 self.0.offset_end = offset_end;
484 }
485
486 #[doc(alias = "get_pts")]
487 #[doc(alias = "GST_BUFFER_PTS")]
488 #[inline]
489 pub fn pts(&self) -> Option<ClockTime> {
490 unsafe { from_glib(self.0.pts) }
491 }
492
493 #[inline]
494 pub fn set_pts(&mut self, pts: impl Into<Option<ClockTime>>) {
495 self.0.pts = pts.into().into_glib();
496 }
497
498 #[doc(alias = "get_dts")]
499 #[doc(alias = "GST_BUFFER_DTS")]
500 #[inline]
501 pub fn dts(&self) -> Option<ClockTime> {
502 unsafe { from_glib(self.0.dts) }
503 }
504
505 #[inline]
506 pub fn set_dts(&mut self, dts: impl Into<Option<ClockTime>>) {
507 self.0.dts = dts.into().into_glib();
508 }
509
510 #[doc(alias = "get_dts_or_pts")]
511 #[doc(alias = "GST_BUFFER_DTS_OR_PTS")]
512 #[inline]
513 pub fn dts_or_pts(&self) -> Option<ClockTime> {
514 let val = self.dts();
515 if val.is_none() {
516 self.pts()
517 } else {
518 val
519 }
520 }
521
522 #[doc(alias = "get_duration")]
523 #[doc(alias = "GST_BUFFER_DURATION")]
524 #[inline]
525 pub fn duration(&self) -> Option<ClockTime> {
526 unsafe { from_glib(self.0.duration) }
527 }
528
529 #[inline]
530 pub fn set_duration(&mut self, duration: impl Into<Option<ClockTime>>) {
531 self.0.duration = duration.into().into_glib();
532 }
533
534 #[doc(alias = "get_flags")]
535 #[doc(alias = "GST_BUFFER_FLAGS")]
536 #[inline]
537 pub fn flags(&self) -> BufferFlags {
538 BufferFlags::from_bits_truncate(self.0.mini_object.flags)
539 }
540
541 #[doc(alias = "GST_BUFFER_FLAG_SET")]
542 #[inline]
543 pub fn set_flags(&mut self, flags: BufferFlags) {
544 self.0.mini_object.flags |= flags.bits();
545 }
546
547 #[doc(alias = "GST_BUFFER_FLAG_UNSET")]
548 #[inline]
549 pub fn unset_flags(&mut self, flags: BufferFlags) {
550 self.0.mini_object.flags &= !flags.bits();
551 }
552
553 #[doc(alias = "get_meta")]
554 #[doc(alias = "gst_buffer_get_meta")]
555 #[inline]
556 pub fn meta<T: MetaAPI>(&self) -> Option<MetaRef<T>> {
557 unsafe {
558 let meta = ffi::gst_buffer_get_meta(self.as_mut_ptr(), T::meta_api().into_glib());
559 if meta.is_null() {
560 None
561 } else {
562 Some(T::from_ptr(self, meta as *const <T as MetaAPI>::GstType))
563 }
564 }
565 }
566
567 #[doc(alias = "get_meta_mut")]
568 #[inline]
569 pub fn meta_mut<T: MetaAPI>(&mut self) -> Option<MetaRefMut<T, crate::meta::Standalone>> {
570 unsafe {
571 let meta = ffi::gst_buffer_get_meta(self.as_mut_ptr(), T::meta_api().into_glib());
572 if meta.is_null() {
573 None
574 } else {
575 Some(T::from_mut_ptr(self, meta as *mut <T as MetaAPI>::GstType))
576 }
577 }
578 }
579
580 pub fn iter_meta<T: MetaAPI>(&self) -> MetaIter<T> {
581 MetaIter::new(self)
582 }
583
584 pub fn iter_meta_mut<T: MetaAPI>(&mut self) -> MetaIterMut<T> {
585 MetaIterMut::new(self)
586 }
587
588 #[doc(alias = "gst_buffer_foreach_meta")]
589 pub fn foreach_meta<F: FnMut(MetaRef<Meta>) -> ControlFlow<(), ()>>(&self, func: F) -> bool {
590 unsafe extern "C" fn trampoline<F: FnMut(MetaRef<Meta>) -> ControlFlow<(), ()>>(
591 buffer: *mut ffi::GstBuffer,
592 meta: *mut *mut ffi::GstMeta,
593 user_data: glib::ffi::gpointer,
594 ) -> glib::ffi::gboolean {
595 let func = user_data as *mut F;
596 let res = (*func)(Meta::from_ptr(BufferRef::from_ptr(buffer), *meta));
597
598 matches!(res, ControlFlow::Continue(_)).into_glib()
599 }
600
601 unsafe {
602 let mut func = func;
603 let func_ptr: &mut F = &mut func;
604
605 from_glib(ffi::gst_buffer_foreach_meta(
606 mut_override(self.as_ptr()),
607 Some(trampoline::<F>),
608 func_ptr as *mut _ as *mut _,
609 ))
610 }
611 }
612
613 #[doc(alias = "gst_buffer_foreach_meta")]
614 pub fn foreach_meta_mut<
615 F: FnMut(
616 MetaRefMut<Meta, crate::meta::Iterated>,
617 ) -> ControlFlow<BufferMetaForeachAction, BufferMetaForeachAction>,
618 >(
619 &mut self,
620 func: F,
621 ) -> bool {
622 unsafe extern "C" fn trampoline<
623 F: FnMut(
624 MetaRefMut<Meta, crate::meta::Iterated>,
625 ) -> ControlFlow<BufferMetaForeachAction, BufferMetaForeachAction>,
626 >(
627 buffer: *mut ffi::GstBuffer,
628 meta: *mut *mut ffi::GstMeta,
629 user_data: glib::ffi::gpointer,
630 ) -> glib::ffi::gboolean {
631 let func = user_data as *mut F;
632 let res = (*func)(Meta::from_mut_ptr(BufferRef::from_mut_ptr(buffer), *meta));
633
634 let (cont, action) = match res {
635 ControlFlow::Continue(action) => (true, action),
636 ControlFlow::Break(action) => (false, action),
637 };
638
639 if action == BufferMetaForeachAction::Remove {
640 *meta = ptr::null_mut();
641 }
642
643 cont.into_glib()
644 }
645
646 unsafe {
647 let mut func = func;
648 let func_ptr: &mut F = &mut func;
649
650 from_glib(ffi::gst_buffer_foreach_meta(
651 mut_override(self.as_ptr()),
652 Some(trampoline::<F>),
653 func_ptr as *mut _ as *mut _,
654 ))
655 }
656 }
657
658 #[doc(alias = "gst_buffer_append_memory")]
659 pub fn append_memory(&mut self, mem: Memory) {
660 unsafe { ffi::gst_buffer_append_memory(self.as_mut_ptr(), mem.into_glib_ptr()) }
661 }
662
663 #[doc(alias = "gst_buffer_find_memory")]
664 pub fn find_memory(&self, range: impl RangeBounds<usize>) -> Option<(Range<usize>, usize)> {
665 let (offset, size) = self.byte_range_into_offset_len(range).ok()?;
666
667 unsafe {
668 let mut idx = mem::MaybeUninit::uninit();
669 let mut length = mem::MaybeUninit::uninit();
670 let mut skip = mem::MaybeUninit::uninit();
671
672 let res = from_glib(ffi::gst_buffer_find_memory(
673 self.as_mut_ptr(),
674 offset,
675 size,
676 idx.as_mut_ptr(),
677 length.as_mut_ptr(),
678 skip.as_mut_ptr(),
679 ));
680
681 if res {
682 let idx = idx.assume_init() as usize;
683 let length = length.assume_init() as usize;
684 let skip = skip.assume_init();
685 Some((idx..(idx + length), skip))
686 } else {
687 None
688 }
689 }
690 }
691
692 #[doc(alias = "get_all_memory")]
693 #[doc(alias = "gst_buffer_get_all_memory")]
694 pub fn all_memory(&self) -> Option<Memory> {
695 unsafe { from_glib_full(ffi::gst_buffer_get_all_memory(self.as_mut_ptr())) }
696 }
697
698 #[doc(alias = "get_max_memory")]
699 #[doc(alias = "gst_buffer_get_max_memory")]
700 pub fn max_memory() -> usize {
701 unsafe { ffi::gst_buffer_get_max_memory() as usize }
702 }
703
704 #[doc(alias = "get_memory")]
705 #[doc(alias = "gst_buffer_get_memory")]
706 pub fn memory(&self, idx: usize) -> Option<Memory> {
707 if idx >= self.n_memory() {
708 return None;
709 }
710 unsafe {
711 let res = ffi::gst_buffer_get_memory(self.as_mut_ptr(), idx as u32);
712 Some(from_glib_full(res))
713 }
714 }
715
716 #[doc(alias = "get_memory_range")]
717 #[doc(alias = "gst_buffer_get_memory_range")]
718 pub fn memory_range(&self, range: impl RangeBounds<usize>) -> Option<Memory> {
719 let (idx, len) = self.memory_range_into_idx_len(range).ok()?;
720
721 unsafe {
722 let res = ffi::gst_buffer_get_memory_range(self.as_mut_ptr(), idx, len);
723 from_glib_full(res)
724 }
725 }
726
727 #[doc(alias = "gst_buffer_insert_memory")]
728 pub fn insert_memory(&mut self, idx: impl Into<Option<usize>>, mem: Memory) {
729 let n_memory = self.n_memory();
730 let idx = idx.into();
731 let idx = idx.unwrap_or(n_memory);
732 assert!(idx <= self.n_memory());
733 unsafe { ffi::gst_buffer_insert_memory(self.as_mut_ptr(), idx as i32, mem.into_glib_ptr()) }
734 }
735
736 #[doc(alias = "gst_buffer_is_all_memory_writable")]
737 pub fn is_all_memory_writable(&self) -> bool {
738 unsafe { from_glib(ffi::gst_buffer_is_all_memory_writable(self.as_mut_ptr())) }
739 }
740
741 #[doc(alias = "gst_buffer_is_memory_range_writable")]
742 pub fn is_memory_range_writable(&self, range: impl RangeBounds<usize>) -> bool {
743 let Some((idx, len)) = self.memory_range_into_idx_len(range).ok() else {
744 return false;
745 };
746
747 unsafe {
748 from_glib(ffi::gst_buffer_is_memory_range_writable(
749 self.as_mut_ptr(),
750 idx,
751 len,
752 ))
753 }
754 }
755
756 #[doc(alias = "gst_buffer_n_memory")]
757 pub fn n_memory(&self) -> usize {
758 unsafe { ffi::gst_buffer_n_memory(self.as_ptr() as *mut _) as usize }
759 }
760
761 #[doc(alias = "gst_buffer_peek_memory")]
762 pub fn peek_memory(&self, idx: usize) -> &MemoryRef {
763 assert!(idx < self.n_memory());
764 unsafe { MemoryRef::from_ptr(ffi::gst_buffer_peek_memory(self.as_mut_ptr(), idx as u32)) }
765 }
766
767 #[doc(alias = "gst_buffer_peek_memory")]
768 pub fn peek_memory_mut(&mut self, idx: usize) -> Result<&mut MemoryRef, glib::BoolError> {
769 assert!(idx < self.n_memory());
770 unsafe {
771 let mem = ffi::gst_buffer_peek_memory(self.as_mut_ptr(), idx as u32);
772 if ffi::gst_mini_object_is_writable(mem as *mut _) == glib::ffi::GFALSE {
773 Err(glib::bool_error!("Memory not writable"))
774 } else {
775 Ok(MemoryRef::from_mut_ptr(mem))
776 }
777 }
778 }
779
780 #[doc(alias = "gst_buffer_prepend_memory")]
781 pub fn prepend_memory(&mut self, mem: Memory) {
782 unsafe { ffi::gst_buffer_prepend_memory(self.as_mut_ptr(), mem.into_glib_ptr()) }
783 }
784
785 #[doc(alias = "gst_buffer_remove_all_memory")]
786 pub fn remove_all_memory(&mut self) {
787 unsafe { ffi::gst_buffer_remove_all_memory(self.as_mut_ptr()) }
788 }
789
790 #[doc(alias = "gst_buffer_remove_memory")]
791 pub fn remove_memory(&mut self, idx: usize) {
792 assert!(idx < self.n_memory());
793 unsafe { ffi::gst_buffer_remove_memory(self.as_mut_ptr(), idx as u32) }
794 }
795
796 #[doc(alias = "gst_buffer_remove_memory_range")]
797 pub fn remove_memory_range(&mut self, range: impl RangeBounds<usize>) {
798 let (idx, len) = self
799 .memory_range_into_idx_len(range)
800 .expect("Invalid memory range");
801
802 unsafe { ffi::gst_buffer_remove_memory_range(self.as_mut_ptr(), idx, len) }
803 }
804
805 #[doc(alias = "gst_buffer_replace_all_memory")]
806 pub fn replace_all_memory(&mut self, mem: Memory) {
807 unsafe { ffi::gst_buffer_replace_all_memory(self.as_mut_ptr(), mem.into_glib_ptr()) }
808 }
809
810 #[doc(alias = "gst_buffer_replace_memory")]
811 pub fn replace_memory(&mut self, idx: usize, mem: Memory) {
812 assert!(idx < self.n_memory());
813 unsafe {
814 ffi::gst_buffer_replace_memory(self.as_mut_ptr(), idx as u32, mem.into_glib_ptr())
815 }
816 }
817
818 #[doc(alias = "gst_buffer_replace_memory_range")]
819 pub fn replace_memory_range(&mut self, range: impl RangeBounds<usize>, mem: Memory) {
820 let (idx, len) = self
821 .memory_range_into_idx_len(range)
822 .expect("Invalid memory range");
823
824 unsafe {
825 ffi::gst_buffer_replace_memory_range(self.as_mut_ptr(), idx, len, mem.into_glib_ptr())
826 }
827 }
828
829 pub fn iter_memories(&self) -> Iter {
830 Iter::new(self)
831 }
832
833 pub fn iter_memories_mut(&mut self) -> Result<IterMut, glib::BoolError> {
834 if !self.is_all_memory_writable() {
835 Err(glib::bool_error!("Not all memory are writable"))
836 } else {
837 Ok(IterMut::new(self))
838 }
839 }
840
841 pub fn iter_memories_owned(&self) -> IterOwned {
842 IterOwned::new(self)
843 }
844
845 pub fn as_cursor_readable(&self) -> BufferRefCursor<&BufferRef> {
846 BufferRefCursor::new_readable(self)
847 }
848
849 pub fn as_cursor_writable(
850 &mut self,
851 ) -> Result<BufferRefCursor<&mut BufferRef>, glib::BoolError> {
852 BufferRefCursor::new_writable(self)
853 }
854
855 #[doc(alias = "gst_util_dump_buffer")]
856 pub fn dump(&self) -> Dump {
857 Dump {
858 buffer: self,
859 start: Bound::Unbounded,
860 end: Bound::Unbounded,
861 }
862 }
863
864 #[doc(alias = "gst_util_dump_buffer")]
865 pub fn dump_range(&self, range: impl RangeBounds<usize>) -> Dump {
866 Dump {
867 buffer: self,
868 start: range.start_bound().cloned(),
869 end: range.end_bound().cloned(),
870 }
871 }
872}
873
874macro_rules! define_meta_iter(
875 ($name:ident, $typ:ty, $mtyp:ty, $prepare_buffer:expr, $from_ptr:expr) => {
876 pub struct $name<'a, T: MetaAPI + 'a> {
877 buffer: $typ,
878 state: glib::ffi::gpointer,
879 meta_api: glib::Type,
880 items: PhantomData<$mtyp>,
881 }
882
883 unsafe impl<'a, T: MetaAPI> Send for $name<'a, T> { }
884 unsafe impl<'a, T: MetaAPI> Sync for $name<'a, T> { }
885
886 impl<'a, T: MetaAPI> fmt::Debug for $name<'a, T> {
887 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
888 f.debug_struct(stringify!($name))
889 .field("buffer", &self.buffer)
890 .field("state", &self.state)
891 .field("meta_api", &self.meta_api)
892 .field("items", &self.items)
893 .finish()
894 }
895 }
896
897 impl<'a, T: MetaAPI> $name<'a, T> {
898 fn new(buffer: $typ) -> $name<'a, T> {
899 skip_assert_initialized!();
900
901 $name {
902 buffer,
903 state: ptr::null_mut(),
904 meta_api: T::meta_api(),
905 items: PhantomData,
906 }
907 }
908 }
909
910 #[allow(clippy::redundant_closure_call)]
911 impl<'a, T: MetaAPI> Iterator for $name<'a, T> {
912 type Item = $mtyp;
913
914 fn next(&mut self) -> Option<Self::Item> {
915 loop {
916 unsafe {
917 let meta = ffi::gst_buffer_iterate_meta(self.buffer.as_mut_ptr(), &mut self.state);
918
919 if meta.is_null() {
920 return None;
921 } else if self.meta_api == glib::Type::INVALID || glib::Type::from_glib((*(*meta).info).api) == self.meta_api {
922 let buffer = $prepare_buffer(self.buffer.as_mut_ptr());
924 let item = $from_ptr(buffer, meta);
925 return Some(item);
926 }
927 }
928 }
929 }
930 }
931
932 impl<'a, T: MetaAPI> std::iter::FusedIterator for $name<'a, T> { }
933 }
934);
935
936define_meta_iter!(
937 MetaIter,
938 &'a BufferRef,
939 MetaRef<'a, T>,
940 |buffer: *const ffi::GstBuffer| BufferRef::from_ptr(buffer),
941 |buffer, meta| T::from_ptr(buffer, meta as *const <T as MetaAPI>::GstType)
942);
943define_meta_iter!(
944 MetaIterMut,
945 &'a mut BufferRef,
946 MetaRefMut<'a, T, crate::meta::Iterated>,
947 |buffer: *mut ffi::GstBuffer| BufferRef::from_mut_ptr(buffer),
948 |buffer: &'a mut BufferRef, meta| T::from_mut_ptr(buffer, meta as *mut <T as MetaAPI>::GstType)
949);
950
951macro_rules! define_iter(
952 ($name:ident, $typ:ty, $mtyp:ty, $get_item:expr) => {
953 pub struct $name<'a> {
954 buffer: $typ,
955 idx: usize,
956 n_memory: usize,
957 }
958
959 impl<'a> fmt::Debug for $name<'a> {
960 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
961 f.debug_struct(stringify!($name))
962 .field("buffer", &self.buffer)
963 .field("idx", &self.idx)
964 .field("n_memory", &self.n_memory)
965 .finish()
966 }
967 }
968
969 impl<'a> $name<'a> {
970 fn new(buffer: $typ) -> $name<'a> {
971 skip_assert_initialized!();
972
973 let n_memory = buffer.n_memory();
974
975 $name {
976 buffer,
977 idx: 0,
978 n_memory,
979 }
980 }
981 }
982
983 #[allow(clippy::redundant_closure_call)]
984 impl<'a> Iterator for $name<'a> {
985 type Item = $mtyp;
986
987 fn next(&mut self) -> Option<Self::Item> {
988 if self.idx >= self.n_memory {
989 return None;
990 }
991
992 #[allow(unused_unsafe)]
993 unsafe {
994 let item = $get_item(self.buffer, self.idx).unwrap();
995 self.idx += 1;
996 Some(item)
997 }
998 }
999
1000 fn size_hint(&self) -> (usize, Option<usize>) {
1001 let remaining = self.n_memory - self.idx;
1002
1003 (remaining, Some(remaining))
1004 }
1005
1006 fn count(self) -> usize {
1007 self.n_memory - self.idx
1008 }
1009
1010 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1011 let (end, overflow) = self.idx.overflowing_add(n);
1012 if end >= self.n_memory || overflow {
1013 self.idx = self.n_memory;
1014 None
1015 } else {
1016 #[allow(unused_unsafe)]
1017 unsafe {
1018 self.idx = end + 1;
1019 Some($get_item(self.buffer, end).unwrap())
1020 }
1021 }
1022 }
1023
1024 fn last(self) -> Option<Self::Item> {
1025 if self.idx == self.n_memory {
1026 None
1027 } else {
1028 #[allow(unused_unsafe)]
1029 unsafe {
1030 Some($get_item(self.buffer, self.n_memory - 1).unwrap())
1031 }
1032 }
1033 }
1034 }
1035
1036 #[allow(clippy::redundant_closure_call)]
1037 impl<'a> DoubleEndedIterator for $name<'a> {
1038 fn next_back(&mut self) -> Option<Self::Item> {
1039 if self.idx == self.n_memory {
1040 return None;
1041 }
1042
1043 #[allow(unused_unsafe)]
1044 unsafe {
1045 self.n_memory -= 1;
1046 Some($get_item(self.buffer, self.n_memory).unwrap())
1047 }
1048 }
1049
1050 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1051 let (end, overflow) = self.n_memory.overflowing_sub(n);
1052 if end <= self.idx || overflow {
1053 self.idx = self.n_memory;
1054 None
1055 } else {
1056 #[allow(unused_unsafe)]
1057 unsafe {
1058 self.n_memory = end - 1;
1059 Some($get_item(self.buffer, self.n_memory).unwrap())
1060 }
1061 }
1062 }
1063 }
1064
1065 impl<'a> ExactSizeIterator for $name<'a> {}
1066
1067 impl<'a> std::iter::FusedIterator for $name<'a> {}
1068 }
1069);
1070
1071define_iter!(
1072 Iter,
1073 &'a BufferRef,
1074 &'a MemoryRef,
1075 |buffer: &BufferRef, idx| {
1076 let ptr = ffi::gst_buffer_peek_memory(buffer.as_mut_ptr(), idx as u32);
1077 if ptr.is_null() {
1078 None
1079 } else {
1080 Some(MemoryRef::from_ptr(ptr as *const ffi::GstMemory))
1081 }
1082 }
1083);
1084
1085define_iter!(
1086 IterMut,
1087 &'a mut BufferRef,
1088 &'a mut MemoryRef,
1089 |buffer: &mut BufferRef, idx| {
1090 let ptr = ffi::gst_buffer_peek_memory(buffer.as_mut_ptr(), idx as u32);
1091 if ptr.is_null() {
1092 None
1093 } else {
1094 Some(MemoryRef::from_mut_ptr(ptr))
1095 }
1096 }
1097);
1098
1099impl<'a> IntoIterator for &'a BufferRef {
1100 type IntoIter = Iter<'a>;
1101 type Item = &'a MemoryRef;
1102
1103 fn into_iter(self) -> Self::IntoIter {
1104 self.iter_memories()
1105 }
1106}
1107
1108impl From<Memory> for Buffer {
1109 fn from(value: Memory) -> Self {
1110 skip_assert_initialized!();
1111
1112 let mut buffer = Buffer::new();
1113 {
1114 let buffer = buffer.get_mut().unwrap();
1115 buffer.append_memory(value);
1116 }
1117 buffer
1118 }
1119}
1120
1121impl<const N: usize> From<[Memory; N]> for Buffer {
1122 fn from(value: [Memory; N]) -> Self {
1123 skip_assert_initialized!();
1124
1125 let mut buffer = Buffer::new();
1126 {
1127 let buffer = buffer.get_mut().unwrap();
1128 value.into_iter().for_each(|b| buffer.append_memory(b));
1129 }
1130 buffer
1131 }
1132}
1133
1134impl std::iter::FromIterator<Memory> for Buffer {
1135 fn from_iter<T: IntoIterator<Item = Memory>>(iter: T) -> Self {
1136 skip_assert_initialized!();
1137 let iter = iter.into_iter();
1138
1139 let mut buffer = Buffer::new();
1140
1141 {
1142 let buffer = buffer.get_mut().unwrap();
1143 iter.for_each(|m| buffer.append_memory(m));
1144 }
1145
1146 buffer
1147 }
1148}
1149
1150impl std::iter::Extend<Memory> for BufferRef {
1151 fn extend<T: IntoIterator<Item = Memory>>(&mut self, iter: T) {
1152 iter.into_iter().for_each(|m| self.append_memory(m));
1153 }
1154}
1155
1156define_iter!(
1157 IterOwned,
1158 &'a BufferRef,
1159 Memory,
1160 |buffer: &BufferRef, idx| { buffer.memory(idx) }
1161);
1162
1163impl fmt::Debug for Buffer {
1164 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1165 BufferRef::fmt(self, f)
1166 }
1167}
1168
1169impl PartialEq for Buffer {
1170 fn eq(&self, other: &Buffer) -> bool {
1171 BufferRef::eq(self, other)
1172 }
1173}
1174
1175impl Eq for Buffer {}
1176
1177impl PartialEq<BufferRef> for Buffer {
1178 fn eq(&self, other: &BufferRef) -> bool {
1179 BufferRef::eq(self, other)
1180 }
1181}
1182impl PartialEq<Buffer> for BufferRef {
1183 fn eq(&self, other: &Buffer) -> bool {
1184 BufferRef::eq(other, self)
1185 }
1186}
1187
1188impl fmt::Debug for BufferRef {
1189 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1190 use std::cell::RefCell;
1191
1192 use crate::utils::Displayable;
1193
1194 struct DebugIter<I>(RefCell<I>);
1195 impl<I: Iterator> fmt::Debug for DebugIter<I>
1196 where
1197 I::Item: fmt::Debug,
1198 {
1199 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1200 f.debug_list().entries(&mut *self.0.borrow_mut()).finish()
1201 }
1202 }
1203
1204 f.debug_struct("Buffer")
1205 .field("ptr", &self.as_ptr())
1206 .field("pts", &self.pts().display())
1207 .field("dts", &self.dts().display())
1208 .field("duration", &self.duration().display())
1209 .field("size", &self.size())
1210 .field("offset", &self.offset())
1211 .field("offset_end", &self.offset_end())
1212 .field("flags", &self.flags())
1213 .field(
1214 "metas",
1215 &DebugIter(RefCell::new(
1216 self.iter_meta::<crate::Meta>().map(|m| m.api()),
1217 )),
1218 )
1219 .finish()
1220 }
1221}
1222
1223impl PartialEq for BufferRef {
1224 fn eq(&self, other: &BufferRef) -> bool {
1225 if self.size() != other.size() {
1226 return false;
1227 }
1228
1229 let self_map = self.map_readable();
1230 let other_map = other.map_readable();
1231
1232 match (self_map, other_map) {
1233 (Ok(self_map), Ok(other_map)) => self_map.as_slice().eq(other_map.as_slice()),
1234 _ => false,
1235 }
1236 }
1237}
1238
1239impl Eq for BufferRef {}
1240
1241impl<T> BufferMap<'_, T> {
1242 #[doc(alias = "get_size")]
1243 #[inline]
1244 pub fn size(&self) -> usize {
1245 self.map_info.size
1246 }
1247
1248 #[doc(alias = "get_buffer")]
1249 #[inline]
1250 pub fn buffer(&self) -> &BufferRef {
1251 self.buffer
1252 }
1253
1254 #[inline]
1255 pub fn as_slice(&self) -> &[u8] {
1256 if self.map_info.size == 0 {
1257 return &[];
1258 }
1259 unsafe { slice::from_raw_parts(self.map_info.data, self.map_info.size) }
1260 }
1261}
1262
1263impl BufferMap<'_, Writable> {
1264 #[inline]
1265 pub fn as_mut_slice(&mut self) -> &mut [u8] {
1266 if self.map_info.size == 0 {
1267 return &mut [];
1268 }
1269 unsafe { slice::from_raw_parts_mut(self.map_info.data, self.map_info.size) }
1270 }
1271}
1272
1273impl<T> AsRef<[u8]> for BufferMap<'_, T> {
1274 #[inline]
1275 fn as_ref(&self) -> &[u8] {
1276 self.as_slice()
1277 }
1278}
1279
1280impl AsMut<[u8]> for BufferMap<'_, Writable> {
1281 #[inline]
1282 fn as_mut(&mut self) -> &mut [u8] {
1283 self.as_mut_slice()
1284 }
1285}
1286
1287impl<T> ops::Deref for BufferMap<'_, T> {
1288 type Target = [u8];
1289
1290 #[inline]
1291 fn deref(&self) -> &[u8] {
1292 self.as_slice()
1293 }
1294}
1295
1296impl ops::DerefMut for BufferMap<'_, Writable> {
1297 #[inline]
1298 fn deref_mut(&mut self) -> &mut [u8] {
1299 self.as_mut_slice()
1300 }
1301}
1302
1303impl<T> fmt::Debug for BufferMap<'_, T> {
1304 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1305 f.debug_tuple("BufferMap").field(&self.buffer()).finish()
1306 }
1307}
1308
1309impl<'a, T> PartialEq for BufferMap<'a, T> {
1310 fn eq(&self, other: &BufferMap<'a, T>) -> bool {
1311 self.as_slice().eq(other.as_slice())
1312 }
1313}
1314
1315impl<T> Eq for BufferMap<'_, T> {}
1316
1317impl<T> Drop for BufferMap<'_, T> {
1318 #[inline]
1319 fn drop(&mut self) {
1320 unsafe {
1321 ffi::gst_buffer_unmap(self.buffer.as_mut_ptr(), &mut self.map_info);
1322 }
1323 }
1324}
1325
1326unsafe impl<T> Send for BufferMap<'_, T> {}
1327unsafe impl<T> Sync for BufferMap<'_, T> {}
1328
1329impl<T> MappedBuffer<T> {
1330 #[inline]
1331 pub fn as_slice(&self) -> &[u8] {
1332 if self.map_info.size == 0 {
1333 return &[];
1334 }
1335 unsafe { slice::from_raw_parts(self.map_info.data, self.map_info.size) }
1336 }
1337
1338 #[doc(alias = "get_size")]
1339 #[inline]
1340 pub fn size(&self) -> usize {
1341 self.map_info.size
1342 }
1343
1344 #[doc(alias = "get_buffer")]
1345 #[inline]
1346 pub fn buffer(&self) -> &BufferRef {
1347 self.buffer.as_ref()
1348 }
1349
1350 #[inline]
1351 pub fn into_buffer(self) -> Buffer {
1352 let mut s = mem::ManuallyDrop::new(self);
1353 let buffer = unsafe { ptr::read(&s.buffer) };
1354 unsafe {
1355 ffi::gst_buffer_unmap(buffer.as_mut_ptr(), &mut s.map_info);
1356 }
1357
1358 buffer
1359 }
1360}
1361
1362impl MappedBuffer<Readable> {
1363 #[doc(alias = "get_buffer")]
1364 #[inline]
1365 pub fn buffer_owned(&self) -> Buffer {
1366 self.buffer.clone()
1367 }
1368}
1369
1370impl MappedBuffer<Writable> {
1371 #[inline]
1372 pub fn as_mut_slice(&mut self) -> &mut [u8] {
1373 if self.map_info.size == 0 {
1374 return &mut [];
1375 }
1376 unsafe { slice::from_raw_parts_mut(self.map_info.data, self.map_info.size) }
1377 }
1378}
1379
1380impl<T> AsRef<[u8]> for MappedBuffer<T> {
1381 #[inline]
1382 fn as_ref(&self) -> &[u8] {
1383 self.as_slice()
1384 }
1385}
1386
1387impl AsMut<[u8]> for MappedBuffer<Writable> {
1388 #[inline]
1389 fn as_mut(&mut self) -> &mut [u8] {
1390 self.as_mut_slice()
1391 }
1392}
1393
1394impl<T> ops::Deref for MappedBuffer<T> {
1395 type Target = [u8];
1396
1397 #[inline]
1398 fn deref(&self) -> &[u8] {
1399 self.as_slice()
1400 }
1401}
1402
1403impl ops::DerefMut for MappedBuffer<Writable> {
1404 #[inline]
1405 fn deref_mut(&mut self) -> &mut [u8] {
1406 self.as_mut_slice()
1407 }
1408}
1409
1410impl<T> Drop for MappedBuffer<T> {
1411 #[inline]
1412 fn drop(&mut self) {
1413 unsafe {
1414 ffi::gst_buffer_unmap(self.buffer.as_mut_ptr(), &mut self.map_info);
1415 }
1416 }
1417}
1418
1419impl<T> fmt::Debug for MappedBuffer<T> {
1420 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1421 f.debug_tuple("MappedBuffer").field(&self.buffer()).finish()
1422 }
1423}
1424
1425impl<T> PartialEq for MappedBuffer<T> {
1426 fn eq(&self, other: &MappedBuffer<T>) -> bool {
1427 self.as_slice().eq(other.as_slice())
1428 }
1429}
1430
1431impl<T> Eq for MappedBuffer<T> {}
1432
1433unsafe impl<T> Send for MappedBuffer<T> {}
1434unsafe impl<T> Sync for MappedBuffer<T> {}
1435
1436#[doc(alias = "GST_BUFFER_COPY_METADATA")]
1437pub const BUFFER_COPY_METADATA: crate::BufferCopyFlags =
1438 crate::BufferCopyFlags::from_bits_truncate(ffi::GST_BUFFER_COPY_METADATA);
1439#[doc(alias = "GST_BUFFER_COPY_ALL")]
1440pub const BUFFER_COPY_ALL: crate::BufferCopyFlags =
1441 crate::BufferCopyFlags::from_bits_truncate(ffi::GST_BUFFER_COPY_ALL);
1442
1443pub struct Dump<'a> {
1444 buffer: &'a BufferRef,
1445 start: Bound<usize>,
1446 end: Bound<usize>,
1447}
1448
1449struct BufferChunked16Iter<'a> {
1450 buffer: &'a BufferRef,
1451 mem_idx: usize,
1452 mem_len: usize,
1453 map: Option<crate::memory::MemoryMap<'a, crate::memory::Readable>>,
1454 map_offset: usize,
1455 len: usize,
1456}
1457
1458impl Iterator for BufferChunked16Iter<'_> {
1459 type Item = ([u8; 16], usize);
1461
1462 fn next(&mut self) -> Option<Self::Item> {
1463 if self.mem_idx == self.mem_len || self.len == 0 {
1464 return None;
1465 }
1466
1467 let mut item = [0u8; 16];
1468 let mut data = item.as_mut_slice();
1469
1470 while !data.is_empty() && self.mem_idx < self.mem_len && self.len > 0 {
1471 if self.map.is_none() {
1472 let mem = self.buffer.peek_memory(self.mem_idx);
1473 self.map = Some(mem.map_readable().expect("failed to map memory"));
1474 }
1475
1476 let map = self.map.as_ref().unwrap();
1477 debug_assert!(self.map_offset < map.len());
1478 let copy = cmp::min(cmp::min(map.len() - self.map_offset, data.len()), self.len);
1479 data[..copy].copy_from_slice(&map[self.map_offset..][..copy]);
1480 self.map_offset += copy;
1481 self.len -= copy;
1482 data = &mut data[copy..];
1483
1484 if self.map_offset == map.len() {
1485 self.map = None;
1486 self.map_offset = 0;
1487 self.mem_idx += 1;
1488 }
1489 }
1490
1491 let copied = 16 - data.len();
1492 Some((item, copied))
1493 }
1494}
1495
1496impl Dump<'_> {
1497 fn fmt(&self, f: &mut fmt::Formatter, debug: bool) -> fmt::Result {
1498 let n_memory = self.buffer.n_memory();
1499 if n_memory == 0 {
1500 write!(f, "<empty>")?;
1501 return Ok(());
1502 }
1503
1504 use std::fmt::Write;
1505
1506 let len = self.buffer.size();
1507
1508 let mut start_idx = match self.start {
1511 Bound::Included(idx) if idx >= len => {
1512 write!(f, "<start out of range>")?;
1513 return Ok(());
1514 }
1515 Bound::Excluded(idx) if idx.checked_add(1).map_or(true, |idx| idx >= len) => {
1516 write!(f, "<start out of range>")?;
1517 return Ok(());
1518 }
1519 Bound::Included(idx) => idx,
1520 Bound::Excluded(idx) => idx + 1,
1521 Bound::Unbounded => 0,
1522 };
1523
1524 let end_idx = match self.end {
1525 Bound::Included(idx) if idx.checked_add(1).map_or(true, |idx| idx > len) => {
1526 write!(f, "<end out of range>")?;
1527 return Ok(());
1528 }
1529 Bound::Excluded(idx) if idx > len => {
1530 write!(f, "<end out of range>")?;
1531 return Ok(());
1532 }
1533 Bound::Included(idx) => idx + 1,
1534 Bound::Excluded(idx) => idx,
1535 Bound::Unbounded => len,
1536 };
1537
1538 if start_idx >= end_idx {
1539 write!(f, "<empty range>")?;
1540 return Ok(());
1541 }
1542
1543 let (memory_range, skip) = self
1545 .buffer
1546 .find_memory(start_idx..)
1547 .expect("can't find memory");
1548
1549 let chunks = BufferChunked16Iter {
1550 buffer: self.buffer,
1551 mem_idx: memory_range.start,
1552 mem_len: n_memory,
1553 map: None,
1554 map_offset: skip,
1555 len: end_idx - start_idx,
1556 };
1557
1558 if debug {
1559 for (line, line_len) in chunks {
1560 let line = &line[..line_len];
1561
1562 match end_idx {
1563 0x00_00..=0xff_ff => write!(f, "{:04x}: ", start_idx)?,
1564 0x01_00_00..=0xff_ff_ff => write!(f, "{:06x}: ", start_idx)?,
1565 0x01_00_00_00..=0xff_ff_ff_ff => write!(f, "{:08x}: ", start_idx)?,
1566 _ => write!(f, "{:016x}: ", start_idx)?,
1567 }
1568
1569 for (i, v) in line.iter().enumerate() {
1570 if i > 0 {
1571 write!(f, " {:02x}", v)?;
1572 } else {
1573 write!(f, "{:02x}", v)?;
1574 }
1575 }
1576
1577 for _ in line.len()..16 {
1578 write!(f, " ")?;
1579 }
1580 write!(f, " ")?;
1581
1582 for v in line {
1583 if v.is_ascii() && !v.is_ascii_control() {
1584 f.write_char((*v).into())?;
1585 } else {
1586 f.write_char('.')?;
1587 }
1588 }
1589
1590 start_idx = start_idx.saturating_add(16);
1591 if start_idx < end_idx {
1592 writeln!(f)?;
1593 }
1594 }
1595
1596 Ok(())
1597 } else {
1598 for (line, line_len) in chunks {
1599 let line = &line[..line_len];
1600
1601 for (i, v) in line.iter().enumerate() {
1602 if i > 0 {
1603 write!(f, " {:02x}", v)?;
1604 } else {
1605 write!(f, "{:02x}", v)?;
1606 }
1607 }
1608
1609 start_idx = start_idx.saturating_add(16);
1610 if start_idx < end_idx {
1611 writeln!(f)?;
1612 }
1613 }
1614
1615 Ok(())
1616 }
1617 }
1618}
1619
1620impl fmt::Display for Dump<'_> {
1621 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1622 self.fmt(f, false)
1623 }
1624}
1625
1626impl fmt::Debug for Dump<'_> {
1627 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1628 self.fmt(f, true)
1629 }
1630}
1631
1632#[cfg(test)]
1633mod tests {
1634 use super::*;
1635
1636 #[test]
1637 fn test_fields() {
1638 crate::init().unwrap();
1639
1640 let mut buffer = Buffer::new();
1641
1642 {
1643 let buffer = buffer.get_mut().unwrap();
1644 buffer.set_pts(ClockTime::NSECOND);
1645 buffer.set_dts(2 * ClockTime::NSECOND);
1646 buffer.set_offset(3);
1647 buffer.set_offset_end(4);
1648 buffer.set_duration(Some(5 * ClockTime::NSECOND));
1649 }
1650 assert_eq!(buffer.pts(), Some(ClockTime::NSECOND));
1651 assert_eq!(buffer.dts(), Some(2 * ClockTime::NSECOND));
1652 assert_eq!(buffer.offset(), 3);
1653 assert_eq!(buffer.offset_end(), 4);
1654 assert_eq!(buffer.duration(), Some(5 * ClockTime::NSECOND));
1655 }
1656
1657 #[test]
1658 fn test_writability() {
1659 crate::init().unwrap();
1660
1661 let mut buffer = Buffer::from_slice(vec![1, 2, 3, 4]);
1662 {
1663 let data = buffer.map_readable().unwrap();
1664 assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice());
1665 }
1666 assert_ne!(buffer.get_mut(), None);
1667 {
1668 let buffer = buffer.get_mut().unwrap();
1669 buffer.set_pts(Some(ClockTime::NSECOND));
1670 }
1671
1672 let mut buffer2 = buffer.clone();
1673 assert_eq!(buffer.get_mut(), None);
1674
1675 assert_eq!(buffer2.as_ptr(), buffer.as_ptr());
1676
1677 {
1678 let buffer2 = buffer2.make_mut();
1679 assert_ne!(buffer2.as_ptr(), buffer.as_ptr());
1680
1681 buffer2.set_pts(Some(2 * ClockTime::NSECOND));
1682
1683 let mut data = buffer2.map_writable().unwrap();
1684 assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice());
1685 data.as_mut_slice()[0] = 0;
1686 }
1687
1688 assert_eq!(buffer.pts(), Some(ClockTime::NSECOND));
1689 assert_eq!(buffer2.pts(), Some(2 * ClockTime::NSECOND));
1690
1691 {
1692 let data = buffer.map_readable().unwrap();
1693 assert_eq!(data.as_slice(), vec![1, 2, 3, 4].as_slice());
1694
1695 let data = buffer2.map_readable().unwrap();
1696 assert_eq!(data.as_slice(), vec![0, 2, 3, 4].as_slice());
1697 }
1698 }
1699
1700 #[test]
1701 #[allow(clippy::cognitive_complexity)]
1702 fn test_memories() {
1703 crate::init().unwrap();
1704
1705 let mut buffer = Buffer::new();
1706 {
1707 let buffer = buffer.get_mut().unwrap();
1708 buffer.append_memory(crate::Memory::from_mut_slice(vec![0; 5]));
1709 buffer.append_memory(crate::Memory::from_mut_slice(vec![0; 5]));
1710 buffer.append_memory(crate::Memory::from_mut_slice(vec![0; 5]));
1711 buffer.append_memory(crate::Memory::from_mut_slice(vec![0; 5]));
1712 buffer.append_memory(crate::Memory::from_mut_slice(vec![0; 10]));
1713 }
1714
1715 assert!(buffer.is_all_memory_writable());
1716 assert_eq!(buffer.n_memory(), 5);
1717 assert_eq!(buffer.size(), 30);
1718
1719 for i in 0..5 {
1720 {
1721 let mem = buffer.memory(i).unwrap();
1722 assert_eq!(mem.size(), if i < 4 { 5 } else { 10 });
1723 let map = mem.map_readable().unwrap();
1724 assert_eq!(map.size(), if i < 4 { 5 } else { 10 });
1725 }
1726
1727 {
1728 let mem = buffer.peek_memory(i);
1729 assert_eq!(mem.size(), if i < 4 { 5 } else { 10 });
1730 let map = mem.map_readable().unwrap();
1731 assert_eq!(map.size(), if i < 4 { 5 } else { 10 });
1732 }
1733
1734 {
1735 let buffer = buffer.get_mut().unwrap();
1736 let mem = buffer.peek_memory_mut(i).unwrap();
1737 assert_eq!(mem.size(), if i < 4 { 5 } else { 10 });
1738 let map = mem.map_writable().unwrap();
1739 assert_eq!(map.size(), if i < 4 { 5 } else { 10 });
1740 }
1741 }
1742
1743 {
1744 let buffer = buffer.get_mut().unwrap();
1745 let mut last = 0;
1746 for (i, mem) in buffer.iter_memories_mut().unwrap().enumerate() {
1747 {
1748 assert_eq!(mem.size(), if i < 4 { 5 } else { 10 });
1749 let map = mem.map_readable().unwrap();
1750 assert_eq!(map.size(), if i < 4 { 5 } else { 10 });
1751 }
1752
1753 {
1754 assert_eq!(mem.size(), if i < 4 { 5 } else { 10 });
1755 let map = mem.map_readable().unwrap();
1756 assert_eq!(map.size(), if i < 4 { 5 } else { 10 });
1757 }
1758
1759 {
1760 assert_eq!(mem.size(), if i < 4 { 5 } else { 10 });
1761 let map = mem.map_writable().unwrap();
1762 assert_eq!(map.size(), if i < 4 { 5 } else { 10 });
1763 }
1764
1765 last = i;
1766 }
1767
1768 assert_eq!(last, 4);
1769 }
1770
1771 let mut last = 0;
1772 for (i, mem) in buffer.iter_memories().enumerate() {
1773 {
1774 assert_eq!(mem.size(), if i < 4 { 5 } else { 10 });
1775 let map = mem.map_readable().unwrap();
1776 assert_eq!(map.size(), if i < 4 { 5 } else { 10 });
1777 }
1778
1779 {
1780 assert_eq!(mem.size(), if i < 4 { 5 } else { 10 });
1781 let map = mem.map_readable().unwrap();
1782 assert_eq!(map.size(), if i < 4 { 5 } else { 10 });
1783 }
1784
1785 last = i;
1786 }
1787
1788 assert_eq!(last, 4);
1789
1790 let mut last = 0;
1791 for (i, mem) in buffer.iter_memories_owned().enumerate() {
1792 {
1793 assert_eq!(mem.size(), if i < 4 { 5 } else { 10 });
1794 let map = mem.map_readable().unwrap();
1795 assert_eq!(map.size(), if i < 4 { 5 } else { 10 });
1796 }
1797
1798 {
1799 assert_eq!(mem.size(), if i < 4 { 5 } else { 10 });
1800 let map = mem.map_readable().unwrap();
1801 assert_eq!(map.size(), if i < 4 { 5 } else { 10 });
1802 }
1803
1804 last = i;
1805 }
1806
1807 assert_eq!(last, 4);
1808 }
1809
1810 #[test]
1811 fn test_meta_foreach() {
1812 crate::init().unwrap();
1813
1814 let mut buffer = Buffer::new();
1815 {
1816 let buffer = buffer.get_mut().unwrap();
1817 crate::ReferenceTimestampMeta::add(
1818 buffer,
1819 &crate::Caps::builder("foo/bar").build(),
1820 ClockTime::ZERO,
1821 ClockTime::NONE,
1822 );
1823 crate::ReferenceTimestampMeta::add(
1824 buffer,
1825 &crate::Caps::builder("foo/bar").build(),
1826 ClockTime::SECOND,
1827 ClockTime::NONE,
1828 );
1829 }
1830
1831 let mut res = vec![];
1832 buffer.foreach_meta(|meta| {
1833 let meta = meta
1834 .downcast_ref::<crate::ReferenceTimestampMeta>()
1835 .unwrap();
1836 res.push(meta.timestamp());
1837 ControlFlow::Continue(())
1838 });
1839
1840 assert_eq!(&[ClockTime::ZERO, ClockTime::SECOND][..], &res[..]);
1841 }
1842
1843 #[test]
1844 fn test_meta_foreach_mut() {
1845 crate::init().unwrap();
1846
1847 let mut buffer = Buffer::new();
1848 {
1849 let buffer = buffer.get_mut().unwrap();
1850 crate::ReferenceTimestampMeta::add(
1851 buffer,
1852 &crate::Caps::builder("foo/bar").build(),
1853 ClockTime::ZERO,
1854 ClockTime::NONE,
1855 );
1856 crate::ReferenceTimestampMeta::add(
1857 buffer,
1858 &crate::Caps::builder("foo/bar").build(),
1859 ClockTime::SECOND,
1860 ClockTime::NONE,
1861 );
1862 }
1863
1864 let mut res = vec![];
1865 buffer.get_mut().unwrap().foreach_meta_mut(|mut meta| {
1866 let meta = meta
1867 .downcast_ref::<crate::ReferenceTimestampMeta>()
1868 .unwrap();
1869 res.push(meta.timestamp());
1870 if meta.timestamp() == ClockTime::SECOND {
1871 ControlFlow::Continue(BufferMetaForeachAction::Remove)
1872 } else {
1873 ControlFlow::Continue(BufferMetaForeachAction::Keep)
1874 }
1875 });
1876
1877 assert_eq!(&[ClockTime::ZERO, ClockTime::SECOND][..], &res[..]);
1878
1879 let mut res = vec![];
1880 buffer.foreach_meta(|meta| {
1881 let meta = meta
1882 .downcast_ref::<crate::ReferenceTimestampMeta>()
1883 .unwrap();
1884 res.push(meta.timestamp());
1885 ControlFlow::Continue(())
1886 });
1887
1888 assert_eq!(&[ClockTime::ZERO][..], &res[..]);
1889 }
1890
1891 #[test]
1892 fn test_ptr_eq() {
1893 crate::init().unwrap();
1894
1895 let buffer1 = Buffer::new();
1896 assert!(BufferRef::ptr_eq(&buffer1, &buffer1));
1897 let buffer2 = Buffer::new();
1898 assert!(!BufferRef::ptr_eq(&buffer1, &buffer2));
1899 }
1900
1901 #[test]
1902 fn test_copy_region() {
1903 crate::init().unwrap();
1904
1905 let buffer1 = Buffer::from_mut_slice(vec![0, 1, 2, 3, 4, 5, 6, 7]);
1906 let buffer2 = buffer1.copy_region(BUFFER_COPY_ALL, ..).unwrap();
1907 assert_eq!(
1908 buffer2.map_readable().unwrap().as_slice(),
1909 &[0, 1, 2, 3, 4, 5, 6, 7]
1910 );
1911 let buffer2 = buffer1.copy_region(BUFFER_COPY_ALL, 0..8).unwrap();
1912 assert_eq!(
1913 buffer2.map_readable().unwrap().as_slice(),
1914 &[0, 1, 2, 3, 4, 5, 6, 7]
1915 );
1916 let buffer2 = buffer1.copy_region(BUFFER_COPY_ALL, 0..=7).unwrap();
1917 assert_eq!(
1918 buffer2.map_readable().unwrap().as_slice(),
1919 &[0, 1, 2, 3, 4, 5, 6, 7]
1920 );
1921 let buffer2 = buffer1.copy_region(BUFFER_COPY_ALL, ..=7).unwrap();
1922 assert_eq!(
1923 buffer2.map_readable().unwrap().as_slice(),
1924 &[0, 1, 2, 3, 4, 5, 6, 7]
1925 );
1926 let buffer2 = buffer1.copy_region(BUFFER_COPY_ALL, ..8).unwrap();
1927 assert_eq!(
1928 buffer2.map_readable().unwrap().as_slice(),
1929 &[0, 1, 2, 3, 4, 5, 6, 7]
1930 );
1931 let buffer2 = buffer1.copy_region(BUFFER_COPY_ALL, 0..).unwrap();
1932 assert_eq!(
1933 buffer2.map_readable().unwrap().as_slice(),
1934 &[0, 1, 2, 3, 4, 5, 6, 7]
1935 );
1936
1937 assert!(buffer1.copy_region(BUFFER_COPY_ALL, 0..=8).is_err());
1938 assert!(buffer1.copy_region(BUFFER_COPY_ALL, 0..=10).is_err());
1939 assert!(buffer1.copy_region(BUFFER_COPY_ALL, 8..=10).is_err());
1940 assert!(buffer1.copy_region(BUFFER_COPY_ALL, 8..=8).is_err());
1941 assert!(buffer1.copy_region(BUFFER_COPY_ALL, 10..).is_err());
1942 assert!(buffer1.copy_region(BUFFER_COPY_ALL, 10..100).is_err());
1943
1944 let buffer2 = buffer1.copy_region(BUFFER_COPY_ALL, 2..4).unwrap();
1945 assert_eq!(buffer2.map_readable().unwrap().as_slice(), &[2, 3]);
1946
1947 let buffer2 = buffer1.copy_region(BUFFER_COPY_ALL, 2..=4).unwrap();
1948 assert_eq!(buffer2.map_readable().unwrap().as_slice(), &[2, 3, 4]);
1949
1950 let buffer2 = buffer1.copy_region(BUFFER_COPY_ALL, 2..).unwrap();
1951 assert_eq!(
1952 buffer2.map_readable().unwrap().as_slice(),
1953 &[2, 3, 4, 5, 6, 7]
1954 );
1955 let buffer2 = buffer1.copy_region(BUFFER_COPY_ALL, ..2).unwrap();
1956 assert_eq!(buffer2.map_readable().unwrap().as_slice(), &[0, 1]);
1957 let buffer2 = buffer1.copy_region(BUFFER_COPY_ALL, ..=2).unwrap();
1958 assert_eq!(buffer2.map_readable().unwrap().as_slice(), &[0, 1, 2]);
1959 }
1960
1961 #[test]
1962 fn test_dump() {
1963 use std::fmt::Write;
1964
1965 crate::init().unwrap();
1966
1967 let mut s = String::new();
1968 let buffer = crate::Buffer::from_slice(vec![1, 2, 3, 4]);
1969 write!(&mut s, "{:?}", buffer.dump()).unwrap();
1970 assert_eq!(
1971 s,
1972 "0000: 01 02 03 04 ...."
1973 );
1974 s.clear();
1975 write!(&mut s, "{}", buffer.dump()).unwrap();
1976 assert_eq!(s, "01 02 03 04");
1977 s.clear();
1978
1979 let buffer = crate::Buffer::from_slice(vec![1, 2, 3, 4]);
1980 write!(&mut s, "{:?}", buffer.dump_range(..)).unwrap();
1981 assert_eq!(
1982 s,
1983 "0000: 01 02 03 04 ...."
1984 );
1985 s.clear();
1986 write!(&mut s, "{:?}", buffer.dump_range(..2)).unwrap();
1987 assert_eq!(
1988 s,
1989 "0000: 01 02 .."
1990 );
1991 s.clear();
1992 write!(&mut s, "{:?}", buffer.dump_range(2..=3)).unwrap();
1993 assert_eq!(
1994 s,
1995 "0002: 03 04 .."
1996 );
1997 s.clear();
1998 write!(&mut s, "{:?}", buffer.dump_range(..100)).unwrap();
1999 assert_eq!(s, "<end out of range>",);
2000 s.clear();
2001 write!(&mut s, "{:?}", buffer.dump_range(90..100)).unwrap();
2002 assert_eq!(s, "<start out of range>",);
2003 s.clear();
2004
2005 let buffer = crate::Buffer::from_slice(vec![0; 19]);
2006 write!(&mut s, "{:?}", buffer.dump()).unwrap();
2007 assert_eq!(
2008 s,
2009 "0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................\n\
2010 0010: 00 00 00 ..."
2011 );
2012 s.clear();
2013 }
2014
2015 #[test]
2016 fn test_dump_multi_memories() {
2017 use std::fmt::Write;
2018
2019 crate::init().unwrap();
2020
2021 let mut buffer = crate::Buffer::new();
2022 {
2023 let buffer = buffer.get_mut().unwrap();
2024
2025 let mem = crate::Memory::from_slice(vec![1, 2, 3, 4]);
2026 buffer.append_memory(mem);
2027
2028 let mem = crate::Memory::from_slice(vec![5, 6, 7, 8]);
2029 buffer.append_memory(mem);
2030
2031 let mem = crate::Memory::from_slice(vec![9, 10, 11, 12]);
2032 buffer.append_memory(mem);
2033
2034 let mem = crate::Memory::from_slice(vec![13, 14, 15, 16]);
2035 buffer.append_memory(mem);
2036
2037 let mem = crate::Memory::from_slice(vec![17, 18, 19]);
2038 buffer.append_memory(mem);
2039 }
2040
2041 let mut s = String::new();
2042 write!(&mut s, "{:?}", buffer.dump()).unwrap();
2043 assert_eq!(
2044 s,
2045 "0000: 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 ................\n\
2046 0010: 11 12 13 ..."
2047 );
2048 s.clear();
2049 write!(&mut s, "{}", buffer.dump()).unwrap();
2050 assert_eq!(
2051 s,
2052 "01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10\n11 12 13"
2053 );
2054 s.clear();
2055
2056 write!(&mut s, "{:?}", buffer.dump_range(2..)).unwrap();
2057 assert_eq!(
2058 s,
2059 "0002: 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 ................\n\
2060 0012: 13 ."
2061 );
2062 s.clear();
2063
2064 write!(&mut s, "{:?}", buffer.dump_range(14..17)).unwrap();
2065 assert_eq!(
2066 s,
2067 "000e: 0f 10 11 ..."
2068 );
2069 s.clear();
2070
2071 write!(&mut s, "{:?}", buffer.dump_range(14..20)).unwrap();
2072 assert_eq!(s, "<end out of range>");
2073 s.clear();
2074
2075 #[allow(clippy::reversed_empty_ranges)]
2076 {
2077 write!(&mut s, "{:?}", buffer.dump_range(23..20)).unwrap();
2078 assert_eq!(s, "<start out of range>");
2079 s.clear();
2080 }
2081 }
2082}