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