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