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]).map_err(io::Error::other)?;
284
285        self.flush(len);
286
287        Ok(len)
288    }
289}
290
291#[derive(Debug)]
292pub struct UniqueAdapter(Adapter);
293
294unsafe impl Send for UniqueAdapter {}
295unsafe impl Sync for UniqueAdapter {}
296
297impl UniqueAdapter {
298    pub fn new() -> Self {
299        Self(Adapter::new())
300    }
301
302    pub fn available(&self) -> usize {
303        self.0.available()
304    }
305
306    pub fn available_fast(&self) -> usize {
307        self.0.available_fast()
308    }
309
310    pub fn clear(&mut self) {
311        self.0.clear();
312    }
313
314    pub fn copy_bytes(&self, offset: usize, size: usize) -> Result<glib::Bytes, glib::BoolError> {
315        self.0.copy_bytes(offset, size)
316    }
317
318    pub fn distance_from_discont(&self) -> u64 {
319        self.0.distance_from_discont()
320    }
321
322    pub fn dts_at_discont(&self) -> Option<gst::ClockTime> {
323        self.0.dts_at_discont()
324    }
325
326    pub fn flush(&mut self, flush: usize) {
327        self.0.flush(flush);
328    }
329
330    #[doc(alias = "get_buffer")]
331    pub fn buffer(&self, nbytes: usize) -> Result<gst::Buffer, glib::BoolError> {
332        self.0.buffer(nbytes)
333    }
334
335    #[doc(alias = "get_buffer_fast")]
336    pub fn buffer_fast(&self, nbytes: usize) -> Result<gst::Buffer, glib::BoolError> {
337        self.0.buffer_fast(nbytes)
338    }
339
340    #[doc(alias = "get_buffer_list")]
341    pub fn buffer_list(&self, nbytes: usize) -> Result<gst::BufferList, glib::BoolError> {
342        self.0.buffer_list(nbytes)
343    }
344
345    #[doc(alias = "get_list")]
346    pub fn list(&self, nbytes: usize) -> Result<Vec<gst::Buffer>, glib::BoolError> {
347        self.0.list(nbytes)
348    }
349
350    pub fn masked_scan_uint32(
351        &self,
352        mask: u32,
353        pattern: u32,
354        offset: usize,
355        size: usize,
356    ) -> Result<Option<usize>, glib::BoolError> {
357        self.0.masked_scan_uint32(mask, pattern, offset, size)
358    }
359
360    pub fn masked_scan_uint32_peek(
361        &self,
362        mask: u32,
363        pattern: u32,
364        offset: usize,
365        size: usize,
366    ) -> Result<Option<(usize, u32)>, glib::BoolError> {
367        self.0.masked_scan_uint32_peek(mask, pattern, offset, size)
368    }
369
370    pub fn offset_at_discont(&self) -> u64 {
371        self.0.offset_at_discont()
372    }
373
374    pub fn prev_dts(&self) -> (Option<gst::ClockTime>, u64) {
375        self.0.prev_dts()
376    }
377
378    pub fn prev_dts_at_offset(&self, offset: usize) -> (Option<gst::ClockTime>, u64) {
379        self.0.prev_dts_at_offset(offset)
380    }
381
382    pub fn prev_offset(&self) -> (u64, u64) {
383        self.0.prev_offset()
384    }
385
386    pub fn prev_pts(&self) -> (Option<gst::ClockTime>, u64) {
387        self.0.prev_pts()
388    }
389
390    pub fn prev_pts_at_offset(&self, offset: usize) -> (Option<gst::ClockTime>, u64) {
391        self.0.prev_pts_at_offset(offset)
392    }
393
394    pub fn pts_at_discont(&self) -> Option<gst::ClockTime> {
395        self.0.pts_at_discont()
396    }
397
398    pub fn take_buffer(&mut self, nbytes: usize) -> Result<gst::Buffer, glib::BoolError> {
399        self.0.take_buffer(nbytes)
400    }
401
402    pub fn take_buffer_fast(&mut self, nbytes: usize) -> Result<gst::Buffer, glib::BoolError> {
403        self.0.take_buffer_fast(nbytes)
404    }
405
406    pub fn take_buffer_list(&mut self, nbytes: usize) -> Result<gst::BufferList, glib::BoolError> {
407        self.0.take_buffer_list(nbytes)
408    }
409
410    pub fn take_list(&mut self, nbytes: usize) -> Result<Vec<gst::Buffer>, glib::BoolError> {
411        self.0.take_list(nbytes)
412    }
413
414    pub fn copy(&self, offset: usize, dest: &mut [u8]) -> Result<(), glib::BoolError> {
415        self.0.copy(offset, dest)
416    }
417
418    pub fn push(&mut self, buf: gst::Buffer) {
419        self.0.push(buf);
420    }
421
422    #[doc(alias = "gst_adapter_map")]
423    pub fn map(&mut self, nbytes: usize) -> Result<UniqueAdapterMap, glib::error::BoolError> {
424        assert!(nbytes <= self.available());
425        assert!(nbytes != 0);
426
427        use std::slice;
428
429        unsafe {
430            let ptr = ffi::gst_adapter_map(self.0.to_glib_none().0, nbytes);
431            if ptr.is_null() {
432                Err(glib::bool_error!("size bytes are not available"))
433            } else {
434                Ok(UniqueAdapterMap(
435                    self,
436                    slice::from_raw_parts(ptr as *const u8, nbytes),
437                ))
438            }
439        }
440    }
441}
442
443#[derive(Debug)]
444pub struct UniqueAdapterMap<'a>(&'a UniqueAdapter, &'a [u8]);
445
446impl Drop for UniqueAdapterMap<'_> {
447    #[inline]
448    fn drop(&mut self) {
449        unsafe {
450            ffi::gst_adapter_unmap((self.0).0.to_glib_none().0);
451        }
452    }
453}
454
455impl ops::Deref for UniqueAdapterMap<'_> {
456    type Target = [u8];
457
458    #[inline]
459    fn deref(&self) -> &[u8] {
460        self.1
461    }
462}
463
464impl AsRef<[u8]> for UniqueAdapterMap<'_> {
465    #[inline]
466    fn as_ref(&self) -> &[u8] {
467        self.1
468    }
469}
470
471impl Default for UniqueAdapter {
472    #[inline]
473    fn default() -> Self {
474        Self::new()
475    }
476}
477
478impl io::Read for UniqueAdapter {
479    #[inline]
480    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
481        self.0.read(buf)
482    }
483}