gstreamer_base/
adapter.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{io, mem, ops};
4
5use glib::translate::*;
6
7use crate::{ffi, Adapter};
8
9impl Adapter {
10    #[doc(alias = "gst_adapter_copy")]
11    pub fn copy(&self, offset: usize, dest: &mut [u8]) -> Result<(), glib::BoolError> {
12        assert!(
13            offset
14                .checked_add(dest.len())
15                .map(|end| end <= self.available())
16                == Some(true)
17        );
18
19        if dest.is_empty() {
20            return Ok(());
21        }
22
23        unsafe {
24            let size = dest.len();
25            ffi::gst_adapter_copy(
26                self.to_glib_none().0,
27                dest.as_mut_ptr() as *mut _,
28                offset,
29                size,
30            );
31        }
32
33        Ok(())
34    }
35
36    /// Similar to gst_adapter_copy, but more suitable for language bindings. `size`
37    /// bytes of data starting at `offset` will be copied out of the buffers contained
38    /// in `self` and into a new [`glib::Bytes`][crate::glib::Bytes] structure which is returned. Depending on
39    /// the value of the `size` argument an empty [`glib::Bytes`][crate::glib::Bytes] structure may be returned.
40    /// ## `offset`
41    /// the bytes offset in the adapter to start from
42    /// ## `size`
43    /// the number of bytes to copy
44    ///
45    /// # Returns
46    ///
47    /// A new [`glib::Bytes`][crate::glib::Bytes] structure containing the copied data.
48    #[doc(alias = "gst_adapter_copy_bytes")]
49    pub fn copy_bytes(&self, offset: usize, size: usize) -> Result<glib::Bytes, glib::BoolError> {
50        assert!(offset.checked_add(size).map(|end| end <= self.available()) == Some(true));
51
52        if size == 0 {
53            return Ok(glib::Bytes::from_static(&[]));
54        }
55
56        unsafe {
57            Ok(from_glib_full(ffi::gst_adapter_copy_bytes(
58                self.to_glib_none().0,
59                offset,
60                size,
61            )))
62        }
63    }
64
65    /// Flushes the first `flush` bytes in the `self`. The caller must ensure that
66    /// at least this many bytes are available.
67    ///
68    /// See also: `gst_adapter_map()`, `gst_adapter_unmap()`
69    /// ## `flush`
70    /// the number of bytes to flush
71    #[doc(alias = "gst_adapter_flush")]
72    pub fn flush(&self, flush: usize) {
73        assert!(flush <= self.available());
74
75        if flush == 0 {
76            return;
77        }
78
79        unsafe {
80            ffi::gst_adapter_flush(self.to_glib_none().0, flush);
81        }
82    }
83
84    #[doc(alias = "get_buffer")]
85    #[doc(alias = "gst_adapter_get_buffer")]
86    pub fn buffer(&self, nbytes: usize) -> Result<gst::Buffer, glib::BoolError> {
87        assert!(nbytes <= self.available());
88        assert!(nbytes != 0);
89
90        unsafe {
91            Option::<_>::from_glib_full(ffi::gst_adapter_get_buffer(self.to_glib_none().0, nbytes))
92                .ok_or_else(|| glib::bool_error!("Failed to get buffer"))
93        }
94    }
95
96    #[doc(alias = "get_buffer_fast")]
97    #[doc(alias = "gst_adapter_get_buffer_fast")]
98    pub fn buffer_fast(&self, nbytes: usize) -> Result<gst::Buffer, glib::BoolError> {
99        assert!(nbytes <= self.available());
100        assert!(nbytes != 0);
101
102        unsafe {
103            Option::<_>::from_glib_full(ffi::gst_adapter_get_buffer_fast(
104                self.to_glib_none().0,
105                nbytes,
106            ))
107            .ok_or_else(|| glib::bool_error!("Failed to get buffer"))
108        }
109    }
110
111    #[doc(alias = "get_buffer_list")]
112    #[doc(alias = "gst_adapter_get_buffer_list")]
113    pub fn buffer_list(&self, nbytes: usize) -> Result<gst::BufferList, glib::BoolError> {
114        assert!(nbytes <= self.available());
115        assert!(nbytes != 0);
116
117        unsafe {
118            Option::<_>::from_glib_full(ffi::gst_adapter_get_buffer_list(
119                self.to_glib_none().0,
120                nbytes,
121            ))
122            .ok_or_else(|| glib::bool_error!("Failed to get buffer list"))
123        }
124    }
125
126    #[doc(alias = "get_list")]
127    #[doc(alias = "gst_adapter_get_list")]
128    pub fn list(&self, nbytes: usize) -> Result<Vec<gst::Buffer>, glib::BoolError> {
129        assert!(nbytes <= self.available());
130        assert!(nbytes != 0);
131
132        unsafe {
133            Ok(FromGlibPtrContainer::from_glib_full(
134                ffi::gst_adapter_get_list(self.to_glib_none().0, nbytes),
135            ))
136        }
137    }
138
139    #[doc(alias = "gst_adapter_masked_scan_uint32")]
140    pub fn masked_scan_uint32(
141        &self,
142        mask: u32,
143        pattern: u32,
144        offset: usize,
145        size: usize,
146    ) -> Result<Option<usize>, glib::BoolError> {
147        assert!(offset.checked_add(size).map(|end| end <= self.available()) == Some(true));
148        assert!(size != 0);
149        assert!(((!mask) & pattern) == 0);
150
151        unsafe {
152            let ret = ffi::gst_adapter_masked_scan_uint32(
153                self.to_glib_none().0,
154                mask,
155                pattern,
156                offset,
157                size,
158            );
159            if ret == -1 {
160                Ok(None)
161            } else {
162                assert!(ret >= 0);
163                Ok(Some(ret as usize))
164            }
165        }
166    }
167
168    #[doc(alias = "gst_adapter_masked_scan_uint32_peek")]
169    pub fn masked_scan_uint32_peek(
170        &self,
171        mask: u32,
172        pattern: u32,
173        offset: usize,
174        size: usize,
175    ) -> Result<Option<(usize, u32)>, glib::BoolError> {
176        assert!(offset.checked_add(size).map(|end| end <= self.available()) == Some(true));
177        assert!(size != 0);
178        assert!(((!mask) & pattern) == 0);
179
180        unsafe {
181            let mut value = mem::MaybeUninit::uninit();
182            let ret = ffi::gst_adapter_masked_scan_uint32_peek(
183                self.to_glib_none().0,
184                mask,
185                pattern,
186                offset,
187                size,
188                value.as_mut_ptr(),
189            );
190
191            if ret == -1 {
192                Ok(None)
193            } else {
194                assert!(ret >= 0);
195                let value = value.assume_init();
196                Ok(Some((ret as usize, value)))
197            }
198        }
199    }
200
201    #[doc(alias = "gst_adapter_take_buffer")]
202    pub fn take_buffer(&self, nbytes: usize) -> Result<gst::Buffer, glib::BoolError> {
203        assert!(nbytes <= self.available());
204        assert!(nbytes != 0);
205
206        unsafe {
207            Option::<_>::from_glib_full(ffi::gst_adapter_take_buffer(self.to_glib_none().0, nbytes))
208                .ok_or_else(|| glib::bool_error!("Failed to take buffer"))
209        }
210    }
211
212    #[doc(alias = "gst_adapter_take_buffer_fast")]
213    pub fn take_buffer_fast(&self, nbytes: usize) -> Result<gst::Buffer, glib::BoolError> {
214        assert!(nbytes <= self.available());
215        assert!(nbytes != 0);
216
217        unsafe {
218            Option::<_>::from_glib_full(ffi::gst_adapter_take_buffer_fast(
219                self.to_glib_none().0,
220                nbytes,
221            ))
222            .ok_or_else(|| glib::bool_error!("Failed to take buffer"))
223        }
224    }
225
226    #[doc(alias = "gst_adapter_take_buffer_list")]
227    pub fn take_buffer_list(&self, nbytes: usize) -> Result<gst::BufferList, glib::BoolError> {
228        assert!(nbytes <= self.available());
229        assert!(nbytes != 0);
230
231        unsafe {
232            Option::<_>::from_glib_full(ffi::gst_adapter_take_buffer_list(
233                self.to_glib_none().0,
234                nbytes,
235            ))
236            .ok_or_else(|| glib::bool_error!("Failed to take buffer list"))
237        }
238    }
239
240    #[doc(alias = "gst_adapter_take_list")]
241    pub fn take_list(&self, nbytes: usize) -> Result<Vec<gst::Buffer>, glib::BoolError> {
242        assert!(nbytes <= self.available());
243        assert!(nbytes != 0);
244
245        unsafe {
246            Ok(FromGlibPtrContainer::from_glib_full(
247                ffi::gst_adapter_take_list(self.to_glib_none().0, nbytes),
248            ))
249        }
250    }
251
252    /// Adds the data from `buf` to the data stored inside `self` and takes
253    /// ownership of the buffer.
254    /// ## `buf`
255    /// a [`gst::Buffer`][crate::gst::Buffer] to add to queue in the adapter
256    #[doc(alias = "gst_adapter_push")]
257    pub fn push(&self, buf: gst::Buffer) {
258        unsafe {
259            ffi::gst_adapter_push(self.to_glib_none().0, buf.into_glib_ptr());
260        }
261    }
262}
263
264impl io::Read for Adapter {
265    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
266        let mut len = self.available();
267
268        if len == 0 {
269            return Err(io::Error::new(
270                io::ErrorKind::WouldBlock,
271                format!(
272                    "Missing data: requesting {} but only got {}.",
273                    buf.len(),
274                    len
275                ),
276            ));
277        }
278
279        if buf.len() < len {
280            len = buf.len();
281        }
282
283        self.copy(0, &mut buf[0..len])
284            .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
285
286        self.flush(len);
287
288        Ok(len)
289    }
290}
291
292#[derive(Debug)]
293pub struct UniqueAdapter(Adapter);
294
295unsafe impl Send for UniqueAdapter {}
296unsafe impl Sync for UniqueAdapter {}
297
298impl UniqueAdapter {
299    pub fn new() -> Self {
300        Self(Adapter::new())
301    }
302
303    pub fn available(&self) -> usize {
304        self.0.available()
305    }
306
307    pub fn available_fast(&self) -> usize {
308        self.0.available_fast()
309    }
310
311    pub fn clear(&mut self) {
312        self.0.clear();
313    }
314
315    pub fn copy_bytes(&self, offset: usize, size: usize) -> Result<glib::Bytes, glib::BoolError> {
316        self.0.copy_bytes(offset, size)
317    }
318
319    pub fn distance_from_discont(&self) -> u64 {
320        self.0.distance_from_discont()
321    }
322
323    pub fn dts_at_discont(&self) -> Option<gst::ClockTime> {
324        self.0.dts_at_discont()
325    }
326
327    pub fn flush(&mut self, flush: usize) {
328        self.0.flush(flush);
329    }
330
331    #[doc(alias = "get_buffer")]
332    pub fn buffer(&self, nbytes: usize) -> Result<gst::Buffer, glib::BoolError> {
333        self.0.buffer(nbytes)
334    }
335
336    #[doc(alias = "get_buffer_fast")]
337    pub fn buffer_fast(&self, nbytes: usize) -> Result<gst::Buffer, glib::BoolError> {
338        self.0.buffer_fast(nbytes)
339    }
340
341    #[doc(alias = "get_buffer_list")]
342    pub fn buffer_list(&self, nbytes: usize) -> Result<gst::BufferList, glib::BoolError> {
343        self.0.buffer_list(nbytes)
344    }
345
346    #[doc(alias = "get_list")]
347    pub fn list(&self, nbytes: usize) -> Result<Vec<gst::Buffer>, glib::BoolError> {
348        self.0.list(nbytes)
349    }
350
351    pub fn masked_scan_uint32(
352        &self,
353        mask: u32,
354        pattern: u32,
355        offset: usize,
356        size: usize,
357    ) -> Result<Option<usize>, glib::BoolError> {
358        self.0.masked_scan_uint32(mask, pattern, offset, size)
359    }
360
361    pub fn masked_scan_uint32_peek(
362        &self,
363        mask: u32,
364        pattern: u32,
365        offset: usize,
366        size: usize,
367    ) -> Result<Option<(usize, u32)>, glib::BoolError> {
368        self.0.masked_scan_uint32_peek(mask, pattern, offset, size)
369    }
370
371    pub fn offset_at_discont(&self) -> u64 {
372        self.0.offset_at_discont()
373    }
374
375    pub fn prev_dts(&self) -> (Option<gst::ClockTime>, u64) {
376        self.0.prev_dts()
377    }
378
379    pub fn prev_dts_at_offset(&self, offset: usize) -> (Option<gst::ClockTime>, u64) {
380        self.0.prev_dts_at_offset(offset)
381    }
382
383    pub fn prev_offset(&self) -> (u64, u64) {
384        self.0.prev_offset()
385    }
386
387    pub fn prev_pts(&self) -> (Option<gst::ClockTime>, u64) {
388        self.0.prev_pts()
389    }
390
391    pub fn prev_pts_at_offset(&self, offset: usize) -> (Option<gst::ClockTime>, u64) {
392        self.0.prev_pts_at_offset(offset)
393    }
394
395    pub fn pts_at_discont(&self) -> Option<gst::ClockTime> {
396        self.0.pts_at_discont()
397    }
398
399    pub fn take_buffer(&mut self, nbytes: usize) -> Result<gst::Buffer, glib::BoolError> {
400        self.0.take_buffer(nbytes)
401    }
402
403    pub fn take_buffer_fast(&mut self, nbytes: usize) -> Result<gst::Buffer, glib::BoolError> {
404        self.0.take_buffer_fast(nbytes)
405    }
406
407    pub fn take_buffer_list(&mut self, nbytes: usize) -> Result<gst::BufferList, glib::BoolError> {
408        self.0.take_buffer_list(nbytes)
409    }
410
411    pub fn take_list(&mut self, nbytes: usize) -> Result<Vec<gst::Buffer>, glib::BoolError> {
412        self.0.take_list(nbytes)
413    }
414
415    pub fn copy(&self, offset: usize, dest: &mut [u8]) -> Result<(), glib::BoolError> {
416        self.0.copy(offset, dest)
417    }
418
419    pub fn push(&mut self, buf: gst::Buffer) {
420        self.0.push(buf);
421    }
422
423    #[doc(alias = "gst_adapter_map")]
424    pub fn map(&mut self, nbytes: usize) -> Result<UniqueAdapterMap, glib::error::BoolError> {
425        assert!(nbytes <= self.available());
426        assert!(nbytes != 0);
427
428        use std::slice;
429
430        unsafe {
431            let ptr = ffi::gst_adapter_map(self.0.to_glib_none().0, nbytes);
432            if ptr.is_null() {
433                Err(glib::bool_error!("size bytes are not available"))
434            } else {
435                Ok(UniqueAdapterMap(
436                    self,
437                    slice::from_raw_parts(ptr as *const u8, nbytes),
438                ))
439            }
440        }
441    }
442}
443
444#[derive(Debug)]
445pub struct UniqueAdapterMap<'a>(&'a UniqueAdapter, &'a [u8]);
446
447impl Drop for UniqueAdapterMap<'_> {
448    #[inline]
449    fn drop(&mut self) {
450        unsafe {
451            ffi::gst_adapter_unmap((self.0).0.to_glib_none().0);
452        }
453    }
454}
455
456impl ops::Deref for UniqueAdapterMap<'_> {
457    type Target = [u8];
458
459    #[inline]
460    fn deref(&self) -> &[u8] {
461        self.1
462    }
463}
464
465impl AsRef<[u8]> for UniqueAdapterMap<'_> {
466    #[inline]
467    fn as_ref(&self) -> &[u8] {
468        self.1
469    }
470}
471
472impl Default for UniqueAdapter {
473    #[inline]
474    fn default() -> Self {
475        Self::new()
476    }
477}
478
479impl io::Read for UniqueAdapter {
480    #[inline]
481    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
482        self.0.read(buf)
483    }
484}