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(ref b) => b,
313            Self::Borrowed(ref 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(ref mut b) => &mut *b,
323            Self::Borrowed(ref mut 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        debug_assert!(!audio_buffer.is_null());
459
460        Borrowed::new(Self {
461            audio_buffer: AudioBufferPtr::Borrowed(ptr::NonNull::new_unchecked(
462                audio_buffer as *mut _,
463            )),
464            phantom: PhantomData,
465        })
466    }
467
468    #[inline]
469    pub fn from_buffer_ref_readable<'b>(
470        buffer: &'a gst::BufferRef,
471        info: &'b crate::AudioInfo,
472    ) -> Result<Self, glib::BoolError> {
473        skip_assert_initialized!();
474
475        assert!(info.is_valid());
476
477        unsafe {
478            let mut audio_buffer = Box::new(mem::MaybeUninit::zeroed().assume_init());
479            let res: bool = from_glib(ffi::gst_audio_buffer_map(
480                &mut *audio_buffer,
481                info.to_glib_none().0 as *mut _,
482                buffer.as_mut_ptr(),
483                gst::ffi::GST_MAP_READ,
484            ));
485
486            if !res {
487                Err(glib::bool_error!("Failed to map AudioBuffer"))
488            } else {
489                Ok(Self {
490                    audio_buffer: AudioBufferPtr::Owned(audio_buffer),
491                    phantom: PhantomData,
492                })
493            }
494        }
495    }
496
497    #[inline]
498    pub fn buffer(&self) -> &gst::BufferRef {
499        unsafe { gst::BufferRef::from_ptr(self.audio_buffer.buffer) }
500    }
501}
502
503impl<'a> AudioBufferRef<&'a mut gst::BufferRef> {
504    #[inline]
505    pub unsafe fn from_glib_borrow_mut(audio_buffer: *mut ffi::GstAudioBuffer) -> Borrowed<Self> {
506        debug_assert!(!audio_buffer.is_null());
507
508        Borrowed::new(Self {
509            audio_buffer: AudioBufferPtr::Borrowed(ptr::NonNull::new_unchecked(audio_buffer)),
510            phantom: PhantomData,
511        })
512    }
513
514    #[inline]
515    pub fn from_buffer_ref_writable<'b>(
516        buffer: &'a mut gst::BufferRef,
517        info: &'b crate::AudioInfo,
518    ) -> Result<Self, glib::BoolError> {
519        skip_assert_initialized!();
520
521        assert!(info.is_valid());
522
523        unsafe {
524            let mut audio_buffer = Box::new(mem::MaybeUninit::zeroed().assume_init());
525            let res: bool = from_glib(ffi::gst_audio_buffer_map(
526                &mut *audio_buffer,
527                info.to_glib_none().0 as *mut _,
528                buffer.as_mut_ptr(),
529                gst::ffi::GST_MAP_READ | gst::ffi::GST_MAP_WRITE,
530            ));
531
532            if !res {
533                Err(glib::bool_error!("Failed to map AudioBuffer"))
534            } else {
535                Ok(Self {
536                    audio_buffer: AudioBufferPtr::Owned(audio_buffer),
537                    phantom: PhantomData,
538                })
539            }
540        }
541    }
542
543    #[inline]
544    pub fn plane_data_mut(&mut self, plane: u32) -> Result<&mut [u8], glib::BoolError> {
545        if plane >= self.n_planes() {
546            return Err(glib::bool_error!(
547                "Plane index higher than number of planes"
548            ));
549        }
550
551        if self.plane_size() == 0 {
552            return Ok(&mut []);
553        }
554
555        unsafe {
556            Ok(slice::from_raw_parts_mut(
557                (*self.audio_buffer.planes.add(plane as usize)) as *mut u8,
558                self.plane_size(),
559            ))
560        }
561    }
562
563    pub fn planes_data_mut(&mut self) -> SmallVec<[&mut [u8]; 8]> {
564        let mut planes = SmallVec::default();
565
566        unsafe {
567            for plane in 0..self.n_planes() {
568                let slice = self.plane_data_mut(plane).unwrap();
569                planes.push(slice::from_raw_parts_mut(slice.as_mut_ptr(), slice.len()));
570            }
571        }
572
573        planes
574    }
575
576    #[inline]
577    pub fn as_mut_ptr(&mut self) -> *mut ffi::GstAudioBuffer {
578        &mut *self.audio_buffer
579    }
580}
581
582impl<'a> ops::Deref for AudioBufferRef<&'a mut gst::BufferRef> {
583    type Target = AudioBufferRef<&'a gst::BufferRef>;
584
585    #[inline]
586    fn deref(&self) -> &Self::Target {
587        unsafe { &*(self as *const Self as *const Self::Target) }
588    }
589}
590
591unsafe impl<T> Send for AudioBufferRef<T> {}
592unsafe impl<T> Sync for AudioBufferRef<T> {}
593
594impl<T> Drop for AudioBufferRef<T> {
595    #[inline]
596    fn drop(&mut self) {
597        unsafe {
598            if matches!(self.audio_buffer, AudioBufferPtr::Owned(..)) {
599                ffi::gst_audio_buffer_unmap(&mut *self.audio_buffer);
600            }
601        }
602    }
603}
604
605#[cfg(test)]
606mod tests {
607    use super::*;
608
609    #[test]
610    fn test_map_read() {
611        gst::init().unwrap();
612
613        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
614            .build()
615            .unwrap();
616        let buffer = gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
617        let buffer = AudioBuffer::from_buffer_readable(buffer, &info).unwrap();
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            let buffer = buffer.as_audio_buffer_ref();
626
627            assert!(buffer.plane_data(0).is_ok());
628            assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
629            assert!(buffer.plane_data(1).is_err());
630            assert!(buffer.info() == &info);
631        }
632
633        assert!(buffer.plane_data(0).is_ok());
634        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
635        assert!(buffer.plane_data(1).is_err());
636        assert!(buffer.info() == &info);
637    }
638
639    #[test]
640    fn test_map_read_planar() {
641        gst::init().unwrap();
642
643        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
644            .layout(crate::AudioLayout::NonInterleaved)
645            .build()
646            .unwrap();
647        let mut buffer =
648            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
649        {
650            let buffer = buffer.get_mut().unwrap();
651            crate::AudioMeta::add(buffer, &info, 48000, &[]).unwrap();
652        }
653        let buffer = AudioBuffer::from_buffer_readable(buffer, &info).unwrap();
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            let buffer = buffer.as_audio_buffer_ref();
663
664            assert!(buffer.plane_data(0).is_ok());
665            assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
666            assert!(buffer.plane_data(1).is_ok());
667            assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
668            assert!(buffer.info() == &info);
669        }
670
671        assert!(buffer.plane_data(0).is_ok());
672        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
673        assert!(buffer.plane_data(1).is_ok());
674        assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
675        assert!(buffer.info() == &info);
676    }
677
678    #[test]
679    fn test_map_write() {
680        gst::init().unwrap();
681
682        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
683            .build()
684            .unwrap();
685        let buffer = gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
686        let mut buffer = AudioBuffer::from_buffer_writable(buffer, &info).unwrap();
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            let mut buffer = buffer.as_mut_audio_buffer_ref();
695
696            assert!(buffer.plane_data_mut(0).is_ok());
697            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
698            assert!(buffer.plane_data_mut(1).is_err());
699            assert!(buffer.info() == &info);
700        }
701
702        assert!(buffer.plane_data_mut(0).is_ok());
703        assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
704        assert!(buffer.plane_data_mut(1).is_err());
705        assert!(buffer.info() == &info);
706    }
707
708    #[test]
709    fn test_map_write_planar() {
710        gst::init().unwrap();
711
712        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
713            .layout(crate::AudioLayout::NonInterleaved)
714            .build()
715            .unwrap();
716        let mut buffer =
717            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
718        {
719            let buffer = buffer.get_mut().unwrap();
720            crate::AudioMeta::add(buffer, &info, 48000, &[]).unwrap();
721        }
722        let mut buffer = AudioBuffer::from_buffer_writable(buffer, &info).unwrap();
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            let mut buffer = buffer.as_mut_audio_buffer_ref();
732
733            assert!(buffer.plane_data_mut(0).is_ok());
734            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
735            assert!(buffer.plane_data_mut(1).is_ok());
736            assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
737            assert!(buffer.info() == &info);
738        }
739
740        assert!(buffer.plane_data_mut(0).is_ok());
741        assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
742        assert!(buffer.plane_data_mut(1).is_ok());
743        assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
744        assert!(buffer.info() == &info);
745    }
746
747    #[test]
748    fn test_map_ref_read() {
749        gst::init().unwrap();
750
751        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
752            .build()
753            .unwrap();
754        let buffer = gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
755        let buffer = AudioBufferRef::from_buffer_ref_readable(&buffer, &info).unwrap();
756
757        assert!(buffer.plane_data(0).is_ok());
758        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
759        assert!(buffer.plane_data(1).is_err());
760        assert!(buffer.info() == &info);
761
762        assert!(buffer.plane_data(0).is_ok());
763        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
764        assert!(buffer.plane_data(1).is_err());
765        assert!(buffer.info() == &info);
766    }
767
768    #[test]
769    fn test_map_ref_read_planar() {
770        gst::init().unwrap();
771
772        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
773            .layout(crate::AudioLayout::NonInterleaved)
774            .build()
775            .unwrap();
776        let mut buffer =
777            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
778        {
779            let buffer = buffer.get_mut().unwrap();
780            crate::AudioMeta::add(buffer, &info, 48000, &[]).unwrap();
781        }
782        let buffer = AudioBufferRef::from_buffer_ref_readable(&buffer, &info).unwrap();
783
784        assert!(buffer.plane_data(0).is_ok());
785        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
786        assert!(buffer.plane_data(1).is_ok());
787        assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
788        assert!(buffer.info() == &info);
789
790        assert!(buffer.plane_data(0).is_ok());
791        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
792        assert!(buffer.plane_data(1).is_ok());
793        assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
794        assert!(buffer.info() == &info);
795    }
796
797    #[test]
798    fn test_map_ref_write() {
799        gst::init().unwrap();
800
801        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
802            .build()
803            .unwrap();
804        let mut buffer =
805            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
806
807        {
808            let buffer = buffer.get_mut().unwrap();
809            let mut buffer = AudioBufferRef::from_buffer_ref_writable(buffer, &info).unwrap();
810
811            assert!(buffer.plane_data_mut(0).is_ok());
812            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
813            assert!(buffer.plane_data_mut(1).is_err());
814            assert!(buffer.info() == &info);
815
816            assert!(buffer.plane_data_mut(0).is_ok());
817            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
818            assert!(buffer.plane_data_mut(1).is_err());
819            assert!(buffer.info() == &info);
820        }
821    }
822
823    #[test]
824    fn test_map_ref_write_planar() {
825        gst::init().unwrap();
826
827        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
828            .layout(crate::AudioLayout::NonInterleaved)
829            .build()
830            .unwrap();
831        let mut buffer =
832            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
833        {
834            let buffer = buffer.get_mut().unwrap();
835            crate::AudioMeta::add(buffer, &info, 48000, &[]).unwrap();
836        }
837
838        {
839            let buffer = buffer.get_mut().unwrap();
840            let mut buffer = AudioBufferRef::from_buffer_ref_writable(buffer, &info).unwrap();
841
842            assert!(buffer.plane_data_mut(0).is_ok());
843            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
844            assert!(buffer.plane_data_mut(1).is_ok());
845            assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
846            assert!(buffer.info() == &info);
847
848            assert!(buffer.plane_data_mut(0).is_ok());
849            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
850            assert!(buffer.plane_data_mut(1).is_ok());
851            assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
852            assert!(buffer.info() == &info);
853        }
854    }
855}