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