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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Take a look at the license at the top of the repository in the LICENSE file.

use glib::prelude::*;
use glib::translate::*;
use std::mem;
use std::ptr;

use crate::BaseSrc;

pub trait BaseSrcExtManual: 'static {
    /// Lets [`BaseSrc`][crate::BaseSrc] sub-classes to know the memory `allocator`
    /// used by the base class and its `params`.
    ///
    /// Unref the `allocator` after usage.
    ///
    /// # Returns
    ///
    ///
    /// ## `allocator`
    /// the [`gst::Allocator`][crate::gst::Allocator]
    /// used
    ///
    /// ## `params`
    /// the [`gst::AllocationParams`][crate::gst::AllocationParams] of `allocator`
    #[doc(alias = "get_allocator")]
    #[doc(alias = "gst_base_src_get_allocator")]
    fn allocator(&self) -> (Option<gst::Allocator>, gst::AllocationParams);

    #[doc(alias = "get_segment")]
    fn segment(&self) -> gst::Segment;

    /// Query the source for the latency parameters. `live` will be [`true`] when `self` is
    /// configured as a live source. `min_latency` and `max_latency` will be set
    /// to the difference between the running time and the timestamp of the first
    /// buffer.
    ///
    /// This function is mostly used by subclasses.
    ///
    /// # Returns
    ///
    /// [`true`] if the query succeeded.
    ///
    /// ## `live`
    /// if the source is live
    ///
    /// ## `min_latency`
    /// the min latency of the source
    ///
    /// ## `max_latency`
    /// the max latency of the source
    #[doc(alias = "gst_base_src_query_latency")]
    fn query_latency(
        &self,
    ) -> Result<(bool, Option<gst::ClockTime>, Option<gst::ClockTime>), glib::BoolError>;

    /// Prepare a new segment for emission downstream. This function must
    /// only be called by derived sub-classes, and only from the `GstBaseSrcClass::create` function,
    /// as the stream-lock needs to be held.
    ///
    /// The format for the `segment` must be identical with the current format
    /// of the source, as configured with [`BaseSrcExt::set_format()`][crate::prelude::BaseSrcExt::set_format()].
    ///
    /// The format of `self` must not be [`gst::Format::Undefined`][crate::gst::Format::Undefined] and the format
    /// should be configured via [`BaseSrcExt::set_format()`][crate::prelude::BaseSrcExt::set_format()] before calling this method.
    /// ## `segment`
    /// a pointer to a [`gst::Segment`][crate::gst::Segment]
    ///
    /// # Returns
    ///
    /// [`true`] if preparation of new segment succeeded.
    #[cfg(any(feature = "v1_18", feature = "dox"))]
    #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
    #[doc(alias = "gst_base_src_new_segment")]
    fn new_segment(&self, segment: &gst::Segment) -> Result<(), glib::BoolError>;

    fn src_pad(&self) -> gst::Pad;
}

impl<O: IsA<BaseSrc>> BaseSrcExtManual for O {
    fn allocator(&self) -> (Option<gst::Allocator>, gst::AllocationParams) {
        unsafe {
            let mut allocator = ptr::null_mut();
            let mut params = mem::zeroed();
            ffi::gst_base_src_get_allocator(
                self.as_ref().to_glib_none().0,
                &mut allocator,
                &mut params,
            );
            (from_glib_full(allocator), params.into())
        }
    }

    fn segment(&self) -> gst::Segment {
        unsafe {
            let src: &ffi::GstBaseSrc = &*(self.as_ptr() as *const _);
            let _guard = crate::utils::MutexGuard::lock(&src.element.object.lock);
            from_glib_none(&src.segment as *const _)
        }
    }

    fn query_latency(
        &self,
    ) -> Result<(bool, Option<gst::ClockTime>, Option<gst::ClockTime>), glib::BoolError> {
        unsafe {
            let mut live = mem::MaybeUninit::uninit();
            let mut min_latency = mem::MaybeUninit::uninit();
            let mut max_latency = mem::MaybeUninit::uninit();
            let ret = from_glib(ffi::gst_base_src_query_latency(
                self.as_ref().to_glib_none().0,
                live.as_mut_ptr(),
                min_latency.as_mut_ptr(),
                max_latency.as_mut_ptr(),
            ));
            let live = live.assume_init();
            let min_latency = min_latency.assume_init();
            let max_latency = max_latency.assume_init();
            if ret {
                Ok((
                    from_glib(live),
                    from_glib(min_latency),
                    from_glib(max_latency),
                ))
            } else {
                Err(glib::bool_error!("Failed to query latency"))
            }
        }
    }

    #[cfg(any(feature = "v1_18", feature = "dox"))]
    #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
    fn new_segment(&self, segment: &gst::Segment) -> Result<(), glib::BoolError> {
        unsafe {
            let ret = from_glib(ffi::gst_base_src_new_segment(
                self.as_ref().to_glib_none().0,
                segment.to_glib_none().0,
            ));

            if ret {
                Ok(())
            } else {
                Err(glib::bool_error!("Failed to configure new segment"))
            }
        }
    }

    fn src_pad(&self) -> gst::Pad {
        unsafe {
            let ptr: &ffi::GstBaseSrc = &*(self.as_ptr() as *const _);

            from_glib_none(ptr.srcpad)
        }
    }
}