Skip to main content

gstreamer_audio/
audio_buffer.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{fmt, marker::PhantomData, mem, ops, ptr, slice};
4
5use crate::ffi;
6use glib::translate::*;
7
8use smallvec::SmallVec;
9
10pub enum Readable {}
11pub enum Writable {}
12
13/// A structure containing the result of an audio buffer map operation,
14/// which is executed with [`from_buffer_readable()`][Self::from_buffer_readable()]. For non-interleaved (planar)
15/// buffers, the beginning of each channel in the buffer has its own pointer in
16/// the `planes` array. For interleaved buffers, the `planes` array only contains
17/// one item, which is the pointer to the beginning of the buffer, and `n_planes`
18/// equals 1.
19///
20/// The different channels in `planes` are always in the GStreamer channel order.
21pub struct AudioBuffer<T> {
22    // Has to be boxed because it contains self-references
23    audio_buffer: Box<ffi::GstAudioBuffer>,
24    phantom: PhantomData<T>,
25}
26
27unsafe impl<T> Send for AudioBuffer<T> {}
28unsafe impl<T> Sync for AudioBuffer<T> {}
29
30impl<T> fmt::Debug for AudioBuffer<T> {
31    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32        f.debug_struct("AudioBuffer")
33            .field("n_samples", &self.n_samples())
34            .field("n_planes", &self.n_planes())
35            .field("buffer", &self.buffer())
36            .field("info", &self.info())
37            .finish()
38    }
39}
40
41impl<T> AudioBuffer<T> {
42    #[inline]
43    pub fn info(&self) -> &crate::AudioInfo {
44        unsafe {
45            &*(&self.audio_buffer.info as *const ffi::GstAudioInfo as *const crate::AudioInfo)
46        }
47    }
48
49    #[inline]
50    pub fn into_buffer(self) -> gst::Buffer {
51        unsafe {
52            let mut s = mem::ManuallyDrop::new(self);
53            // Take ownership of the buffer stored here when mapping before unmapping
54            let buffer = from_glib_none(s.audio_buffer.buffer);
55            ffi::gst_audio_buffer_unmap(&mut *s.audio_buffer);
56            ptr::drop_in_place(&mut s.audio_buffer);
57
58            buffer
59        }
60    }
61
62    #[inline]
63    pub fn format(&self) -> crate::AudioFormat {
64        self.info().format()
65    }
66
67    #[inline]
68    pub fn format_info(&self) -> crate::AudioFormatInfo {
69        self.info().format_info()
70    }
71
72    #[inline]
73    pub fn channels(&self) -> u32 {
74        self.info().channels()
75    }
76
77    #[inline]
78    pub fn rate(&self) -> u32 {
79        self.info().rate()
80    }
81
82    #[inline]
83    pub fn layout(&self) -> crate::AudioLayout {
84        self.info().layout()
85    }
86
87    #[inline]
88    pub fn width(&self) -> u32 {
89        self.info().width()
90    }
91
92    #[inline]
93    pub fn depth(&self) -> u32 {
94        self.info().depth()
95    }
96
97    #[inline]
98    pub fn sample_stride(&self) -> u32 {
99        self.info().width() / 8
100    }
101
102    #[inline]
103    pub fn bps(&self) -> u32 {
104        self.info().bps()
105    }
106
107    #[inline]
108    pub fn bpf(&self) -> u32 {
109        self.info().bpf()
110    }
111
112    #[inline]
113    pub fn n_samples(&self) -> usize {
114        self.audio_buffer.n_samples
115    }
116
117    #[inline]
118    pub fn n_planes(&self) -> u32 {
119        self.audio_buffer.n_planes as u32
120    }
121
122    #[inline]
123    pub fn plane_size(&self) -> usize {
124        (self.n_samples() * self.sample_stride() as usize * self.channels() as usize)
125            / self.n_planes() as usize
126    }
127
128    #[inline]
129    pub fn buffer(&self) -> &gst::BufferRef {
130        unsafe { gst::BufferRef::from_ptr(self.audio_buffer.buffer) }
131    }
132
133    pub fn plane_data(&self, plane: u32) -> Result<&[u8], glib::BoolError> {
134        if plane >= self.n_planes() {
135            return Err(glib::bool_error!(
136                "Plane index higher than number of planes"
137            ));
138        }
139
140        unsafe {
141            Ok(slice::from_raw_parts(
142                (*self.audio_buffer.planes.add(plane as usize)) as *const u8,
143                self.plane_size(),
144            ))
145        }
146    }
147
148    pub fn planes_data(&self) -> SmallVec<[&[u8]; 8]> {
149        let mut planes = SmallVec::default();
150
151        for plane in 0..self.n_planes() {
152            planes[plane as usize] = self.plane_data(plane).unwrap();
153        }
154
155        planes
156    }
157
158    #[inline]
159    pub fn as_audio_buffer_ref(&self) -> AudioBufferRef<&gst::BufferRef> {
160        AudioBufferRef {
161            audio_buffer: AudioBufferPtr::Borrowed(ptr::NonNull::from(&*self.audio_buffer)),
162            phantom: PhantomData,
163        }
164    }
165
166    #[inline]
167    pub fn as_ptr(&self) -> *const ffi::GstAudioBuffer {
168        &*self.audio_buffer
169    }
170}
171
172impl<T> Drop for AudioBuffer<T> {
173    #[inline]
174    fn drop(&mut self) {
175        unsafe {
176            // Take ownership again of the buffer that was stored here when mapping
177            // and then drop it after unmapping.
178            let buffer = gst::Buffer::from_glib_full(self.audio_buffer.buffer);
179            ffi::gst_audio_buffer_unmap(&mut *self.audio_buffer);
180            drop(buffer);
181        }
182    }
183}
184
185impl AudioBuffer<Readable> {
186    #[inline]
187    pub fn from_buffer_readable(
188        buffer: gst::Buffer,
189        info: &crate::AudioInfo,
190    ) -> Result<Self, gst::Buffer> {
191        skip_assert_initialized!();
192
193        assert!(info.is_valid());
194
195        unsafe {
196            // Store the buffer as part of the audio buffer, we will retrieve / unref it
197            // again at a later time.
198            let buffer = mem::ManuallyDrop::new(buffer);
199            let mut audio_buffer = Box::new(mem::MaybeUninit::zeroed().assume_init());
200            let res: bool = from_glib(ffi::gst_audio_buffer_map(
201                &mut *audio_buffer,
202                info.to_glib_none().0 as *mut _,
203                buffer.to_glib_none().0,
204                gst::ffi::GST_MAP_READ,
205            ));
206
207            if !res {
208                Err(mem::ManuallyDrop::into_inner(buffer))
209            } else {
210                Ok(Self {
211                    audio_buffer,
212                    phantom: PhantomData,
213                })
214            }
215        }
216    }
217
218    #[inline]
219    pub fn buffer_owned(&self) -> gst::Buffer {
220        unsafe { from_glib_none(self.audio_buffer.buffer) }
221    }
222}
223
224impl AudioBuffer<Writable> {
225    #[inline]
226    pub fn from_buffer_writable(
227        buffer: gst::Buffer,
228        info: &crate::AudioInfo,
229    ) -> Result<Self, gst::Buffer> {
230        skip_assert_initialized!();
231
232        assert!(info.is_valid());
233
234        unsafe {
235            // Store the buffer as part of the audio buffer, we will retrieve / unref it
236            // again at a later time.
237            let buffer = mem::ManuallyDrop::new(buffer);
238            let mut audio_buffer = Box::new(mem::MaybeUninit::zeroed().assume_init());
239            let res: bool = from_glib(ffi::gst_audio_buffer_map(
240                &mut *audio_buffer,
241                info.to_glib_none().0 as *mut _,
242                buffer.to_glib_none().0,
243                gst::ffi::GST_MAP_READ | gst::ffi::GST_MAP_WRITE,
244            ));
245
246            if !res {
247                Err(mem::ManuallyDrop::into_inner(buffer))
248            } else {
249                Ok(Self {
250                    audio_buffer,
251                    phantom: PhantomData,
252                })
253            }
254        }
255    }
256
257    pub fn plane_data_mut(&mut self, plane: u32) -> Result<&mut [u8], glib::BoolError> {
258        if plane >= self.n_planes() {
259            return Err(glib::bool_error!(
260                "Plane index higher than number of planes"
261            ));
262        }
263
264        unsafe {
265            Ok(slice::from_raw_parts_mut(
266                (*self.audio_buffer.planes.add(plane as usize)) as *mut u8,
267                self.plane_size(),
268            ))
269        }
270    }
271
272    pub fn planes_data_mut(&mut self) -> SmallVec<[&mut [u8]; 8]> {
273        let mut planes = SmallVec::default();
274
275        unsafe {
276            for plane in 0..self.n_planes() {
277                let slice = self.plane_data_mut(plane).unwrap();
278                planes.push(slice::from_raw_parts_mut(slice.as_mut_ptr(), slice.len()));
279            }
280        }
281
282        planes
283    }
284
285    #[inline]
286    pub fn as_mut_audio_buffer_ref(&mut self) -> AudioBufferRef<&mut gst::BufferRef> {
287        AudioBufferRef {
288            audio_buffer: AudioBufferPtr::Borrowed(ptr::NonNull::from(&mut *self.audio_buffer)),
289            phantom: PhantomData,
290        }
291    }
292
293    #[inline]
294    pub fn as_mut_ptr(&mut self) -> *mut ffi::GstAudioBuffer {
295        &mut *self.audio_buffer
296    }
297}
298
299#[derive(Debug)]
300enum AudioBufferPtr {
301    // Has to be boxed because it contains self-references
302    Owned(Box<ffi::GstAudioBuffer>),
303    Borrowed(ptr::NonNull<ffi::GstAudioBuffer>),
304}
305
306impl ops::Deref for AudioBufferPtr {
307    type Target = ffi::GstAudioBuffer;
308
309    #[inline]
310    fn deref(&self) -> &Self::Target {
311        match self {
312            Self::Owned(b) => b,
313            Self::Borrowed(b) => unsafe { b.as_ref() },
314        }
315    }
316}
317
318impl ops::DerefMut for AudioBufferPtr {
319    #[inline]
320    fn deref_mut(&mut self) -> &mut Self::Target {
321        match self {
322            Self::Owned(b) => &mut *b,
323            Self::Borrowed(b) => unsafe { b.as_mut() },
324        }
325    }
326}
327
328pub struct AudioBufferRef<T> {
329    audio_buffer: AudioBufferPtr,
330    phantom: PhantomData<T>,
331}
332
333impl<T> fmt::Debug for AudioBufferRef<T> {
334    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
335        f.debug_struct("AudioBufferRef")
336            .field("n_samples", &self.n_samples())
337            .field("n_planes", &self.n_planes())
338            .field("buffer", &unsafe {
339                gst::BufferRef::from_ptr(self.audio_buffer.buffer)
340            })
341            .field("info", &self.info())
342            .finish()
343    }
344}
345
346impl<T> AudioBufferRef<T> {
347    #[inline]
348    pub fn info(&self) -> &crate::AudioInfo {
349        unsafe {
350            &*(&self.audio_buffer.info as *const ffi::GstAudioInfo as *const crate::AudioInfo)
351        }
352    }
353
354    #[inline]
355    pub fn format(&self) -> crate::AudioFormat {
356        self.info().format()
357    }
358
359    #[inline]
360    pub fn format_info(&self) -> crate::AudioFormatInfo {
361        self.info().format_info()
362    }
363
364    #[inline]
365    pub fn channels(&self) -> u32 {
366        self.info().channels()
367    }
368
369    #[inline]
370    pub fn rate(&self) -> u32 {
371        self.info().rate()
372    }
373
374    #[inline]
375    pub fn layout(&self) -> crate::AudioLayout {
376        self.info().layout()
377    }
378
379    #[inline]
380    pub fn width(&self) -> u32 {
381        self.info().width()
382    }
383
384    #[inline]
385    pub fn depth(&self) -> u32 {
386        self.info().depth()
387    }
388
389    #[inline]
390    pub fn sample_stride(&self) -> u32 {
391        self.info().width() / 8
392    }
393
394    #[inline]
395    pub fn bps(&self) -> u32 {
396        self.info().bps()
397    }
398
399    #[inline]
400    pub fn bpf(&self) -> u32 {
401        self.info().bpf()
402    }
403
404    #[inline]
405    pub fn n_samples(&self) -> usize {
406        self.audio_buffer.n_samples
407    }
408
409    #[inline]
410    pub fn n_planes(&self) -> u32 {
411        self.audio_buffer.n_planes as u32
412    }
413
414    #[inline]
415    pub fn plane_size(&self) -> usize {
416        (self.n_samples() * self.sample_stride() as usize * self.channels() as usize)
417            / self.n_planes() as usize
418    }
419
420    pub fn plane_data(&self, plane: u32) -> Result<&[u8], glib::BoolError> {
421        if plane >= self.n_planes() {
422            return Err(glib::bool_error!(
423                "Plane index higher than number of planes"
424            ));
425        }
426
427        if self.plane_size() == 0 {
428            return Ok(&[]);
429        }
430
431        unsafe {
432            Ok(slice::from_raw_parts(
433                (*self.audio_buffer.planes.add(plane as usize)) as *const u8,
434                self.plane_size(),
435            ))
436        }
437    }
438
439    pub fn planes_data(&self) -> SmallVec<[&[u8]; 8]> {
440        let mut planes = SmallVec::default();
441
442        for plane in 0..self.n_planes() {
443            planes[plane as usize] = self.plane_data(plane).unwrap();
444        }
445
446        planes
447    }
448
449    #[inline]
450    pub fn as_ptr(&self) -> *const ffi::GstAudioBuffer {
451        &*self.audio_buffer
452    }
453}
454
455impl<'a> AudioBufferRef<&'a gst::BufferRef> {
456    #[inline]
457    pub unsafe fn from_glib_borrow(audio_buffer: *const ffi::GstAudioBuffer) -> Borrowed<Self> {
458        unsafe {
459            debug_assert!(!audio_buffer.is_null());
460
461            Borrowed::new(Self {
462                audio_buffer: AudioBufferPtr::Borrowed(ptr::NonNull::new_unchecked(
463                    audio_buffer as *mut _,
464                )),
465                phantom: PhantomData,
466            })
467        }
468    }
469
470    #[inline]
471    pub fn from_buffer_ref_readable<'b>(
472        buffer: &'a gst::BufferRef,
473        info: &'b crate::AudioInfo,
474    ) -> Result<Self, glib::BoolError> {
475        skip_assert_initialized!();
476
477        assert!(info.is_valid());
478
479        unsafe {
480            let mut audio_buffer = Box::new(mem::MaybeUninit::zeroed().assume_init());
481            let res: bool = from_glib(ffi::gst_audio_buffer_map(
482                &mut *audio_buffer,
483                info.to_glib_none().0 as *mut _,
484                buffer.as_mut_ptr(),
485                gst::ffi::GST_MAP_READ,
486            ));
487
488            if !res {
489                Err(glib::bool_error!("Failed to map AudioBuffer"))
490            } else {
491                Ok(Self {
492                    audio_buffer: AudioBufferPtr::Owned(audio_buffer),
493                    phantom: PhantomData,
494                })
495            }
496        }
497    }
498
499    #[inline]
500    pub fn buffer(&self) -> &gst::BufferRef {
501        unsafe { gst::BufferRef::from_ptr(self.audio_buffer.buffer) }
502    }
503}
504
505impl<'a> AudioBufferRef<&'a mut gst::BufferRef> {
506    #[inline]
507    pub unsafe fn from_glib_borrow_mut(audio_buffer: *mut ffi::GstAudioBuffer) -> Borrowed<Self> {
508        unsafe {
509            debug_assert!(!audio_buffer.is_null());
510
511            Borrowed::new(Self {
512                audio_buffer: AudioBufferPtr::Borrowed(ptr::NonNull::new_unchecked(audio_buffer)),
513                phantom: PhantomData,
514            })
515        }
516    }
517
518    #[inline]
519    pub fn from_buffer_ref_writable<'b>(
520        buffer: &'a mut gst::BufferRef,
521        info: &'b crate::AudioInfo,
522    ) -> Result<Self, glib::BoolError> {
523        skip_assert_initialized!();
524
525        assert!(info.is_valid());
526
527        unsafe {
528            let mut audio_buffer = Box::new(mem::MaybeUninit::zeroed().assume_init());
529            let res: bool = from_glib(ffi::gst_audio_buffer_map(
530                &mut *audio_buffer,
531                info.to_glib_none().0 as *mut _,
532                buffer.as_mut_ptr(),
533                gst::ffi::GST_MAP_READ | gst::ffi::GST_MAP_WRITE,
534            ));
535
536            if !res {
537                Err(glib::bool_error!("Failed to map AudioBuffer"))
538            } else {
539                Ok(Self {
540                    audio_buffer: AudioBufferPtr::Owned(audio_buffer),
541                    phantom: PhantomData,
542                })
543            }
544        }
545    }
546
547    #[inline]
548    pub fn plane_data_mut(&mut self, plane: u32) -> Result<&mut [u8], glib::BoolError> {
549        if plane >= self.n_planes() {
550            return Err(glib::bool_error!(
551                "Plane index higher than number of planes"
552            ));
553        }
554
555        if self.plane_size() == 0 {
556            return Ok(&mut []);
557        }
558
559        unsafe {
560            Ok(slice::from_raw_parts_mut(
561                (*self.audio_buffer.planes.add(plane as usize)) as *mut u8,
562                self.plane_size(),
563            ))
564        }
565    }
566
567    pub fn planes_data_mut(&mut self) -> SmallVec<[&mut [u8]; 8]> {
568        let mut planes = SmallVec::default();
569
570        unsafe {
571            for plane in 0..self.n_planes() {
572                let slice = self.plane_data_mut(plane).unwrap();
573                planes.push(slice::from_raw_parts_mut(slice.as_mut_ptr(), slice.len()));
574            }
575        }
576
577        planes
578    }
579
580    #[inline]
581    pub fn as_mut_ptr(&mut self) -> *mut ffi::GstAudioBuffer {
582        &mut *self.audio_buffer
583    }
584}
585
586impl<'a> ops::Deref for AudioBufferRef<&'a mut gst::BufferRef> {
587    type Target = AudioBufferRef<&'a gst::BufferRef>;
588
589    #[inline]
590    fn deref(&self) -> &Self::Target {
591        unsafe { &*(self as *const Self as *const Self::Target) }
592    }
593}
594
595unsafe impl<T> Send for AudioBufferRef<T> {}
596unsafe impl<T> Sync for AudioBufferRef<T> {}
597
598impl<T> Drop for AudioBufferRef<T> {
599    #[inline]
600    fn drop(&mut self) {
601        unsafe {
602            if matches!(self.audio_buffer, AudioBufferPtr::Owned(..)) {
603                ffi::gst_audio_buffer_unmap(&mut *self.audio_buffer);
604            }
605        }
606    }
607}
608
609#[cfg(test)]
610mod tests {
611    use super::*;
612
613    #[test]
614    fn test_map_read() {
615        gst::init().unwrap();
616
617        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
618            .build()
619            .unwrap();
620        let buffer = gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
621        let buffer = AudioBuffer::from_buffer_readable(buffer, &info).unwrap();
622
623        assert!(buffer.plane_data(0).is_ok());
624        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
625        assert!(buffer.plane_data(1).is_err());
626        assert!(buffer.info() == &info);
627
628        {
629            let buffer = buffer.as_audio_buffer_ref();
630
631            assert!(buffer.plane_data(0).is_ok());
632            assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
633            assert!(buffer.plane_data(1).is_err());
634            assert!(buffer.info() == &info);
635        }
636
637        assert!(buffer.plane_data(0).is_ok());
638        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
639        assert!(buffer.plane_data(1).is_err());
640        assert!(buffer.info() == &info);
641    }
642
643    #[test]
644    fn test_map_read_planar() {
645        gst::init().unwrap();
646
647        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
648            .layout(crate::AudioLayout::NonInterleaved)
649            .build()
650            .unwrap();
651        let mut buffer =
652            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
653        {
654            let buffer = buffer.get_mut().unwrap();
655            crate::AudioMeta::add(buffer, &info, 48000, &[]).unwrap();
656        }
657        let buffer = AudioBuffer::from_buffer_readable(buffer, &info).unwrap();
658
659        assert!(buffer.plane_data(0).is_ok());
660        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
661        assert!(buffer.plane_data(1).is_ok());
662        assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
663        assert!(buffer.info() == &info);
664
665        {
666            let buffer = buffer.as_audio_buffer_ref();
667
668            assert!(buffer.plane_data(0).is_ok());
669            assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
670            assert!(buffer.plane_data(1).is_ok());
671            assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
672            assert!(buffer.info() == &info);
673        }
674
675        assert!(buffer.plane_data(0).is_ok());
676        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
677        assert!(buffer.plane_data(1).is_ok());
678        assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
679        assert!(buffer.info() == &info);
680    }
681
682    #[test]
683    fn test_map_write() {
684        gst::init().unwrap();
685
686        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
687            .build()
688            .unwrap();
689        let buffer = gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
690        let mut buffer = AudioBuffer::from_buffer_writable(buffer, &info).unwrap();
691
692        assert!(buffer.plane_data_mut(0).is_ok());
693        assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
694        assert!(buffer.plane_data_mut(1).is_err());
695        assert!(buffer.info() == &info);
696
697        {
698            let mut buffer = buffer.as_mut_audio_buffer_ref();
699
700            assert!(buffer.plane_data_mut(0).is_ok());
701            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
702            assert!(buffer.plane_data_mut(1).is_err());
703            assert!(buffer.info() == &info);
704        }
705
706        assert!(buffer.plane_data_mut(0).is_ok());
707        assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
708        assert!(buffer.plane_data_mut(1).is_err());
709        assert!(buffer.info() == &info);
710    }
711
712    #[test]
713    fn test_map_write_planar() {
714        gst::init().unwrap();
715
716        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
717            .layout(crate::AudioLayout::NonInterleaved)
718            .build()
719            .unwrap();
720        let mut buffer =
721            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
722        {
723            let buffer = buffer.get_mut().unwrap();
724            crate::AudioMeta::add(buffer, &info, 48000, &[]).unwrap();
725        }
726        let mut buffer = AudioBuffer::from_buffer_writable(buffer, &info).unwrap();
727
728        assert!(buffer.plane_data_mut(0).is_ok());
729        assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
730        assert!(buffer.plane_data_mut(1).is_ok());
731        assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
732        assert!(buffer.info() == &info);
733
734        {
735            let mut buffer = buffer.as_mut_audio_buffer_ref();
736
737            assert!(buffer.plane_data_mut(0).is_ok());
738            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
739            assert!(buffer.plane_data_mut(1).is_ok());
740            assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
741            assert!(buffer.info() == &info);
742        }
743
744        assert!(buffer.plane_data_mut(0).is_ok());
745        assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
746        assert!(buffer.plane_data_mut(1).is_ok());
747        assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
748        assert!(buffer.info() == &info);
749    }
750
751    #[test]
752    fn test_map_ref_read() {
753        gst::init().unwrap();
754
755        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
756            .build()
757            .unwrap();
758        let buffer = gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
759        let buffer = AudioBufferRef::from_buffer_ref_readable(&buffer, &info).unwrap();
760
761        assert!(buffer.plane_data(0).is_ok());
762        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
763        assert!(buffer.plane_data(1).is_err());
764        assert!(buffer.info() == &info);
765
766        assert!(buffer.plane_data(0).is_ok());
767        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
768        assert!(buffer.plane_data(1).is_err());
769        assert!(buffer.info() == &info);
770    }
771
772    #[test]
773    fn test_map_ref_read_planar() {
774        gst::init().unwrap();
775
776        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
777            .layout(crate::AudioLayout::NonInterleaved)
778            .build()
779            .unwrap();
780        let mut buffer =
781            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
782        {
783            let buffer = buffer.get_mut().unwrap();
784            crate::AudioMeta::add(buffer, &info, 48000, &[]).unwrap();
785        }
786        let buffer = AudioBufferRef::from_buffer_ref_readable(&buffer, &info).unwrap();
787
788        assert!(buffer.plane_data(0).is_ok());
789        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
790        assert!(buffer.plane_data(1).is_ok());
791        assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
792        assert!(buffer.info() == &info);
793
794        assert!(buffer.plane_data(0).is_ok());
795        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
796        assert!(buffer.plane_data(1).is_ok());
797        assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
798        assert!(buffer.info() == &info);
799    }
800
801    #[test]
802    fn test_map_ref_write() {
803        gst::init().unwrap();
804
805        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
806            .build()
807            .unwrap();
808        let mut buffer =
809            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
810
811        {
812            let buffer = buffer.get_mut().unwrap();
813            let mut buffer = AudioBufferRef::from_buffer_ref_writable(buffer, &info).unwrap();
814
815            assert!(buffer.plane_data_mut(0).is_ok());
816            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
817            assert!(buffer.plane_data_mut(1).is_err());
818            assert!(buffer.info() == &info);
819
820            assert!(buffer.plane_data_mut(0).is_ok());
821            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
822            assert!(buffer.plane_data_mut(1).is_err());
823            assert!(buffer.info() == &info);
824        }
825    }
826
827    #[test]
828    fn test_map_ref_write_planar() {
829        gst::init().unwrap();
830
831        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
832            .layout(crate::AudioLayout::NonInterleaved)
833            .build()
834            .unwrap();
835        let mut buffer =
836            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
837        {
838            let buffer = buffer.get_mut().unwrap();
839            crate::AudioMeta::add(buffer, &info, 48000, &[]).unwrap();
840        }
841
842        {
843            let buffer = buffer.get_mut().unwrap();
844            let mut buffer = AudioBufferRef::from_buffer_ref_writable(buffer, &info).unwrap();
845
846            assert!(buffer.plane_data_mut(0).is_ok());
847            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
848            assert!(buffer.plane_data_mut(1).is_ok());
849            assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
850            assert!(buffer.info() == &info);
851
852            assert!(buffer.plane_data_mut(0).is_ok());
853            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
854            assert!(buffer.plane_data_mut(1).is_ok());
855            assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
856            assert!(buffer.info() == &info);
857        }
858    }
859}