1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::{
    fmt,
    os::unix::prelude::{IntoRawFd, RawFd},
};

use glib::{prelude::*, translate::*};
use gst::{Memory, MemoryRef};

#[cfg(feature = "v1_16")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
use crate::FdMemoryFlags;
use crate::{ffi, DmaBufAllocator, FdMemory, FdMemoryRef};

gst::memory_object_wrapper!(
    DmaBufMemory,
    DmaBufMemoryRef,
    gst::ffi::GstMemory,
    |mem: &gst::MemoryRef| { unsafe { from_glib(ffi::gst_is_dmabuf_memory(mem.as_mut_ptr())) } },
    FdMemory,
    FdMemoryRef,
    Memory,
    MemoryRef
);

impl fmt::Debug for DmaBufMemory {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        DmaBufMemoryRef::fmt(self, f)
    }
}

impl fmt::Debug for DmaBufMemoryRef {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        MemoryRef::fmt(self, f)
    }
}

impl DmaBufMemoryRef {
    #[doc(alias = "gst_dmabuf_memory_get_fd")]
    pub fn fd(&self) -> RawFd {
        skip_assert_initialized!();
        unsafe { ffi::gst_dmabuf_memory_get_fd(self.as_mut_ptr()) }
    }
}

impl DmaBufAllocator {
    /// Return a `GstMemory` that wraps a dmabuf file descriptor.
    /// ## `allocator`
    /// allocator to be used for this memory
    /// ## `fd`
    /// dmabuf file descriptor
    /// ## `size`
    /// memory size
    ///
    /// # Returns
    ///
    /// a GstMemory based on `allocator`.
    /// When the buffer will be released dmabuf allocator will close the `fd`.
    /// The memory is only mmapped on [`gst::Buffer::map()`][crate::gst::Buffer::map()] request.
    #[doc(alias = "gst_dmabuf_allocator_alloc")]
    pub unsafe fn alloc<A: IntoRawFd>(
        &self,
        fd: A,
        size: usize,
    ) -> Result<gst::Memory, glib::BoolError> {
        skip_assert_initialized!();
        Option::<_>::from_glib_full(ffi::gst_dmabuf_allocator_alloc(
            self.unsafe_cast_ref::<gst::Allocator>().to_glib_none().0,
            fd.into_raw_fd(),
            size,
        ))
        .ok_or_else(|| glib::bool_error!("Failed to allocate memory"))
    }

    /// Return a `GstMemory` that wraps a dmabuf file descriptor.
    /// ## `allocator`
    /// allocator to be used for this memory
    /// ## `fd`
    /// dmabuf file descriptor
    /// ## `size`
    /// memory size
    /// ## `flags`
    /// extra [`FdMemoryFlags`][crate::FdMemoryFlags]
    ///
    /// # Returns
    ///
    /// a GstMemory based on `allocator`.
    ///
    /// When the buffer will be released the allocator will close the `fd` unless
    /// the [`FdMemoryFlags::DONT_CLOSE`][crate::FdMemoryFlags::DONT_CLOSE] flag is specified.
    /// The memory is only mmapped on `gst_buffer_mmap()` request.
    #[cfg(feature = "v1_16")]
    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
    #[doc(alias = "gst_dmabuf_allocator_alloc_with_flags")]
    pub unsafe fn alloc_with_flags(
        &self,
        fd: RawFd,
        size: usize,
        flags: FdMemoryFlags,
    ) -> Result<gst::Memory, glib::BoolError> {
        skip_assert_initialized!();
        Option::<_>::from_glib_full(ffi::gst_dmabuf_allocator_alloc_with_flags(
            self.unsafe_cast_ref::<gst::Allocator>().to_glib_none().0,
            fd,
            size,
            flags.into_glib(),
        ))
        .ok_or_else(|| glib::bool_error!("Failed to allocate memory"))
    }
}