Skip to main content

gstreamer_audio/
audio_buffer.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{fmt, marker::PhantomData, mem, ops, ptr, slice};
4
5use crate::ffi;
6use glib::translate::*;
7
8use smallvec::SmallVec;
9
10pub enum Readable {}
11pub enum Writable {}
12
13pub struct AudioBuffer<T> {
14    // Has to be boxed because it contains self-references
15    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            // Take ownership of the buffer stored here when mapping before unmapping
46            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            // Take ownership again of the buffer that was stored here when mapping
169            // and then drop it after unmapping.
170            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            // Store the buffer as part of the audio buffer, we will retrieve / unref it
189            // again at a later time.
190            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            // Store the buffer as part of the audio buffer, we will retrieve / unref it
228            // again at a later time.
229            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    // Has to be boxed because it contains self-references
294    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(b) => b,
305            Self::Borrowed(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(b) => &mut *b,
315            Self::Borrowed(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        unsafe {
451            debug_assert!(!audio_buffer.is_null());
452
453            Borrowed::new(Self {
454                audio_buffer: AudioBufferPtr::Borrowed(ptr::NonNull::new_unchecked(
455                    audio_buffer as *mut _,
456                )),
457                phantom: PhantomData,
458            })
459        }
460    }
461
462    #[inline]
463    pub fn from_buffer_ref_readable<'b>(
464        buffer: &'a gst::BufferRef,
465        info: &'b crate::AudioInfo,
466    ) -> Result<Self, glib::BoolError> {
467        skip_assert_initialized!();
468
469        assert!(info.is_valid());
470
471        unsafe {
472            let mut audio_buffer = Box::new(mem::MaybeUninit::zeroed().assume_init());
473            let res: bool = from_glib(ffi::gst_audio_buffer_map(
474                &mut *audio_buffer,
475                info.to_glib_none().0 as *mut _,
476                buffer.as_mut_ptr(),
477                gst::ffi::GST_MAP_READ,
478            ));
479
480            if !res {
481                Err(glib::bool_error!("Failed to map AudioBuffer"))
482            } else {
483                Ok(Self {
484                    audio_buffer: AudioBufferPtr::Owned(audio_buffer),
485                    phantom: PhantomData,
486                })
487            }
488        }
489    }
490
491    #[inline]
492    pub fn buffer(&self) -> &gst::BufferRef {
493        unsafe { gst::BufferRef::from_ptr(self.audio_buffer.buffer) }
494    }
495}
496
497impl<'a> AudioBufferRef<&'a mut gst::BufferRef> {
498    #[inline]
499    pub unsafe fn from_glib_borrow_mut(audio_buffer: *mut ffi::GstAudioBuffer) -> Borrowed<Self> {
500        unsafe {
501            debug_assert!(!audio_buffer.is_null());
502
503            Borrowed::new(Self {
504                audio_buffer: AudioBufferPtr::Borrowed(ptr::NonNull::new_unchecked(audio_buffer)),
505                phantom: PhantomData,
506            })
507        }
508    }
509
510    #[inline]
511    pub fn from_buffer_ref_writable<'b>(
512        buffer: &'a mut gst::BufferRef,
513        info: &'b crate::AudioInfo,
514    ) -> Result<Self, glib::BoolError> {
515        skip_assert_initialized!();
516
517        assert!(info.is_valid());
518
519        unsafe {
520            let mut audio_buffer = Box::new(mem::MaybeUninit::zeroed().assume_init());
521            let res: bool = from_glib(ffi::gst_audio_buffer_map(
522                &mut *audio_buffer,
523                info.to_glib_none().0 as *mut _,
524                buffer.as_mut_ptr(),
525                gst::ffi::GST_MAP_READ | gst::ffi::GST_MAP_WRITE,
526            ));
527
528            if !res {
529                Err(glib::bool_error!("Failed to map AudioBuffer"))
530            } else {
531                Ok(Self {
532                    audio_buffer: AudioBufferPtr::Owned(audio_buffer),
533                    phantom: PhantomData,
534                })
535            }
536        }
537    }
538
539    #[inline]
540    pub fn plane_data_mut(&mut self, plane: u32) -> Result<&mut [u8], glib::BoolError> {
541        if plane >= self.n_planes() {
542            return Err(glib::bool_error!(
543                "Plane index higher than number of planes"
544            ));
545        }
546
547        if self.plane_size() == 0 {
548            return Ok(&mut []);
549        }
550
551        unsafe {
552            Ok(slice::from_raw_parts_mut(
553                (*self.audio_buffer.planes.add(plane as usize)) as *mut u8,
554                self.plane_size(),
555            ))
556        }
557    }
558
559    pub fn planes_data_mut(&mut self) -> SmallVec<[&mut [u8]; 8]> {
560        let mut planes = SmallVec::default();
561
562        unsafe {
563            for plane in 0..self.n_planes() {
564                let slice = self.plane_data_mut(plane).unwrap();
565                planes.push(slice::from_raw_parts_mut(slice.as_mut_ptr(), slice.len()));
566            }
567        }
568
569        planes
570    }
571
572    #[inline]
573    pub fn as_mut_ptr(&mut self) -> *mut ffi::GstAudioBuffer {
574        &mut *self.audio_buffer
575    }
576}
577
578impl<'a> ops::Deref for AudioBufferRef<&'a mut gst::BufferRef> {
579    type Target = AudioBufferRef<&'a gst::BufferRef>;
580
581    #[inline]
582    fn deref(&self) -> &Self::Target {
583        unsafe { &*(self as *const Self as *const Self::Target) }
584    }
585}
586
587unsafe impl<T> Send for AudioBufferRef<T> {}
588unsafe impl<T> Sync for AudioBufferRef<T> {}
589
590impl<T> Drop for AudioBufferRef<T> {
591    #[inline]
592    fn drop(&mut self) {
593        unsafe {
594            if matches!(self.audio_buffer, AudioBufferPtr::Owned(..)) {
595                ffi::gst_audio_buffer_unmap(&mut *self.audio_buffer);
596            }
597        }
598    }
599}
600
601#[cfg(test)]
602mod tests {
603    use super::*;
604
605    #[test]
606    fn test_map_read() {
607        gst::init().unwrap();
608
609        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
610            .build()
611            .unwrap();
612        let buffer = gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
613        let buffer = AudioBuffer::from_buffer_readable(buffer, &info).unwrap();
614
615        assert!(buffer.plane_data(0).is_ok());
616        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
617        assert!(buffer.plane_data(1).is_err());
618        assert!(buffer.info() == &info);
619
620        {
621            let buffer = buffer.as_audio_buffer_ref();
622
623            assert!(buffer.plane_data(0).is_ok());
624            assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
625            assert!(buffer.plane_data(1).is_err());
626            assert!(buffer.info() == &info);
627        }
628
629        assert!(buffer.plane_data(0).is_ok());
630        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
631        assert!(buffer.plane_data(1).is_err());
632        assert!(buffer.info() == &info);
633    }
634
635    #[test]
636    fn test_map_read_planar() {
637        gst::init().unwrap();
638
639        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
640            .layout(crate::AudioLayout::NonInterleaved)
641            .build()
642            .unwrap();
643        let mut buffer =
644            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
645        {
646            let buffer = buffer.get_mut().unwrap();
647            crate::AudioMeta::add(buffer, &info, 48000, &[]).unwrap();
648        }
649        let buffer = AudioBuffer::from_buffer_readable(buffer, &info).unwrap();
650
651        assert!(buffer.plane_data(0).is_ok());
652        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
653        assert!(buffer.plane_data(1).is_ok());
654        assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
655        assert!(buffer.info() == &info);
656
657        {
658            let buffer = buffer.as_audio_buffer_ref();
659
660            assert!(buffer.plane_data(0).is_ok());
661            assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
662            assert!(buffer.plane_data(1).is_ok());
663            assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
664            assert!(buffer.info() == &info);
665        }
666
667        assert!(buffer.plane_data(0).is_ok());
668        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
669        assert!(buffer.plane_data(1).is_ok());
670        assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
671        assert!(buffer.info() == &info);
672    }
673
674    #[test]
675    fn test_map_write() {
676        gst::init().unwrap();
677
678        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
679            .build()
680            .unwrap();
681        let buffer = gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
682        let mut buffer = AudioBuffer::from_buffer_writable(buffer, &info).unwrap();
683
684        assert!(buffer.plane_data_mut(0).is_ok());
685        assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
686        assert!(buffer.plane_data_mut(1).is_err());
687        assert!(buffer.info() == &info);
688
689        {
690            let mut buffer = buffer.as_mut_audio_buffer_ref();
691
692            assert!(buffer.plane_data_mut(0).is_ok());
693            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
694            assert!(buffer.plane_data_mut(1).is_err());
695            assert!(buffer.info() == &info);
696        }
697
698        assert!(buffer.plane_data_mut(0).is_ok());
699        assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
700        assert!(buffer.plane_data_mut(1).is_err());
701        assert!(buffer.info() == &info);
702    }
703
704    #[test]
705    fn test_map_write_planar() {
706        gst::init().unwrap();
707
708        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
709            .layout(crate::AudioLayout::NonInterleaved)
710            .build()
711            .unwrap();
712        let mut buffer =
713            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
714        {
715            let buffer = buffer.get_mut().unwrap();
716            crate::AudioMeta::add(buffer, &info, 48000, &[]).unwrap();
717        }
718        let mut buffer = AudioBuffer::from_buffer_writable(buffer, &info).unwrap();
719
720        assert!(buffer.plane_data_mut(0).is_ok());
721        assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
722        assert!(buffer.plane_data_mut(1).is_ok());
723        assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
724        assert!(buffer.info() == &info);
725
726        {
727            let mut buffer = buffer.as_mut_audio_buffer_ref();
728
729            assert!(buffer.plane_data_mut(0).is_ok());
730            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
731            assert!(buffer.plane_data_mut(1).is_ok());
732            assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
733            assert!(buffer.info() == &info);
734        }
735
736        assert!(buffer.plane_data_mut(0).is_ok());
737        assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
738        assert!(buffer.plane_data_mut(1).is_ok());
739        assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
740        assert!(buffer.info() == &info);
741    }
742
743    #[test]
744    fn test_map_ref_read() {
745        gst::init().unwrap();
746
747        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
748            .build()
749            .unwrap();
750        let buffer = gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
751        let buffer = AudioBufferRef::from_buffer_ref_readable(&buffer, &info).unwrap();
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        assert!(buffer.plane_data(0).is_ok());
759        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 2 * 48000);
760        assert!(buffer.plane_data(1).is_err());
761        assert!(buffer.info() == &info);
762    }
763
764    #[test]
765    fn test_map_ref_read_planar() {
766        gst::init().unwrap();
767
768        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
769            .layout(crate::AudioLayout::NonInterleaved)
770            .build()
771            .unwrap();
772        let mut buffer =
773            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
774        {
775            let buffer = buffer.get_mut().unwrap();
776            crate::AudioMeta::add(buffer, &info, 48000, &[]).unwrap();
777        }
778        let buffer = AudioBufferRef::from_buffer_ref_readable(&buffer, &info).unwrap();
779
780        assert!(buffer.plane_data(0).is_ok());
781        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
782        assert!(buffer.plane_data(1).is_ok());
783        assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
784        assert!(buffer.info() == &info);
785
786        assert!(buffer.plane_data(0).is_ok());
787        assert_eq!(buffer.plane_data(0).unwrap().len(), 2 * 48000);
788        assert!(buffer.plane_data(1).is_ok());
789        assert_eq!(buffer.plane_data(1).unwrap().len(), 2 * 48000);
790        assert!(buffer.info() == &info);
791    }
792
793    #[test]
794    fn test_map_ref_write() {
795        gst::init().unwrap();
796
797        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
798            .build()
799            .unwrap();
800        let mut buffer =
801            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
802
803        {
804            let buffer = buffer.get_mut().unwrap();
805            let mut buffer = AudioBufferRef::from_buffer_ref_writable(buffer, &info).unwrap();
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            assert!(buffer.plane_data_mut(0).is_ok());
813            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 2 * 48000);
814            assert!(buffer.plane_data_mut(1).is_err());
815            assert!(buffer.info() == &info);
816        }
817    }
818
819    #[test]
820    fn test_map_ref_write_planar() {
821        gst::init().unwrap();
822
823        let info = crate::AudioInfo::builder(crate::AUDIO_FORMAT_S16, 48000, 2)
824            .layout(crate::AudioLayout::NonInterleaved)
825            .build()
826            .unwrap();
827        let mut buffer =
828            gst::Buffer::with_size(info.rate() as usize * info.bpf() as usize).unwrap();
829        {
830            let buffer = buffer.get_mut().unwrap();
831            crate::AudioMeta::add(buffer, &info, 48000, &[]).unwrap();
832        }
833
834        {
835            let buffer = buffer.get_mut().unwrap();
836            let mut buffer = AudioBufferRef::from_buffer_ref_writable(buffer, &info).unwrap();
837
838            assert!(buffer.plane_data_mut(0).is_ok());
839            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
840            assert!(buffer.plane_data_mut(1).is_ok());
841            assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
842            assert!(buffer.info() == &info);
843
844            assert!(buffer.plane_data_mut(0).is_ok());
845            assert_eq!(buffer.plane_data_mut(0).unwrap().len(), 2 * 48000);
846            assert!(buffer.plane_data_mut(1).is_ok());
847            assert_eq!(buffer.plane_data_mut(1).unwrap().len(), 2 * 48000);
848            assert!(buffer.info() == &info);
849        }
850    }
851}