Skip to main content

gstreamer_app/
app_sink.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{mem, panic, ptr};
4
5#[cfg(not(panic = "abort"))]
6use std::sync::atomic::{AtomicBool, Ordering};
7
8use glib::{ffi::gpointer, prelude::*, translate::*};
9
10use crate::{AppSink, ffi};
11
12#[cfg(feature = "futures")]
13pub use crate::app_sink_futures::AppSinkStream;
14
15#[allow(clippy::type_complexity)]
16pub struct AppSinkCallbacks {
17    eos: Option<Box<dyn FnMut(&AppSink) + Send + 'static>>,
18    new_preroll: Option<
19        Box<dyn FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static>,
20    >,
21    new_sample: Option<
22        Box<dyn FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static>,
23    >,
24    new_event: Option<Box<dyn FnMut(&AppSink) -> bool + Send + 'static>>,
25    propose_allocation:
26        Option<Box<dyn FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static>>,
27    #[cfg(not(panic = "abort"))]
28    panicked: AtomicBool,
29    callbacks: ffi::GstAppSinkCallbacks,
30}
31
32unsafe impl Send for AppSinkCallbacks {}
33unsafe impl Sync for AppSinkCallbacks {}
34
35impl AppSinkCallbacks {
36    pub fn builder() -> AppSinkCallbacksBuilder {
37        skip_assert_initialized!();
38        AppSinkCallbacksBuilder {
39            eos: None,
40            new_preroll: None,
41            new_sample: None,
42            new_event: None,
43            propose_allocation: None,
44        }
45    }
46}
47
48#[allow(clippy::type_complexity)]
49#[must_use = "The builder must be built to be used"]
50pub struct AppSinkCallbacksBuilder {
51    eos: Option<Box<dyn FnMut(&AppSink) + Send + 'static>>,
52    new_preroll: Option<
53        Box<dyn FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static>,
54    >,
55    new_sample: Option<
56        Box<dyn FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static>,
57    >,
58    new_event: Option<Box<dyn FnMut(&AppSink) -> bool + Send + 'static>>,
59    propose_allocation:
60        Option<Box<dyn FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static>>,
61}
62
63impl AppSinkCallbacksBuilder {
64    pub fn eos<F: FnMut(&AppSink) + Send + 'static>(self, eos: F) -> Self {
65        Self {
66            eos: Some(Box::new(eos)),
67            ..self
68        }
69    }
70
71    pub fn eos_if<F: FnMut(&AppSink) + Send + 'static>(self, eos: F, predicate: bool) -> Self {
72        if predicate { self.eos(eos) } else { self }
73    }
74
75    pub fn eos_if_some<F: FnMut(&AppSink) + Send + 'static>(self, eos: Option<F>) -> Self {
76        if let Some(eos) = eos {
77            self.eos(eos)
78        } else {
79            self
80        }
81    }
82
83    pub fn new_preroll<
84        F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
85    >(
86        self,
87        new_preroll: F,
88    ) -> Self {
89        Self {
90            new_preroll: Some(Box::new(new_preroll)),
91            ..self
92        }
93    }
94
95    pub fn new_preroll_if<
96        F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
97    >(
98        self,
99        new_preroll: F,
100        predicate: bool,
101    ) -> Self {
102        if predicate {
103            self.new_preroll(new_preroll)
104        } else {
105            self
106        }
107    }
108
109    pub fn new_preroll_if_some<
110        F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
111    >(
112        self,
113        new_preroll: Option<F>,
114    ) -> Self {
115        if let Some(new_preroll) = new_preroll {
116            self.new_preroll(new_preroll)
117        } else {
118            self
119        }
120    }
121
122    pub fn new_sample<
123        F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
124    >(
125        self,
126        new_sample: F,
127    ) -> Self {
128        Self {
129            new_sample: Some(Box::new(new_sample)),
130            ..self
131        }
132    }
133
134    pub fn new_sample_if<
135        F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
136    >(
137        self,
138        new_sample: F,
139        predicate: bool,
140    ) -> Self {
141        if predicate {
142            self.new_sample(new_sample)
143        } else {
144            self
145        }
146    }
147
148    pub fn new_sample_if_some<
149        F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
150    >(
151        self,
152        new_sample: Option<F>,
153    ) -> Self {
154        if let Some(new_sample) = new_sample {
155            self.new_sample(new_sample)
156        } else {
157            self
158        }
159    }
160
161    #[cfg(feature = "v1_20")]
162    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
163    pub fn new_event<F: FnMut(&AppSink) -> bool + Send + 'static>(self, new_event: F) -> Self {
164        Self {
165            new_event: Some(Box::new(new_event)),
166            ..self
167        }
168    }
169
170    #[cfg(feature = "v1_20")]
171    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
172    pub fn new_event_if<F: FnMut(&AppSink) -> bool + Send + 'static>(
173        self,
174        new_event: F,
175        predicate: bool,
176    ) -> Self {
177        if predicate {
178            self.new_event(new_event)
179        } else {
180            self
181        }
182    }
183
184    #[cfg(feature = "v1_20")]
185    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
186    pub fn new_event_if_some<F: FnMut(&AppSink) -> bool + Send + 'static>(
187        self,
188        new_event: Option<F>,
189    ) -> Self {
190        if let Some(new_event) = new_event {
191            self.new_event(new_event)
192        } else {
193            self
194        }
195    }
196
197    #[cfg(feature = "v1_24")]
198    #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
199    pub fn propose_allocation<
200        F: FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static,
201    >(
202        self,
203        propose_allocation: F,
204    ) -> Self {
205        Self {
206            propose_allocation: Some(Box::new(propose_allocation)),
207            ..self
208        }
209    }
210
211    #[cfg(feature = "v1_24")]
212    #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
213    pub fn propose_allocation_if<
214        F: FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static,
215    >(
216        self,
217        propose_allocation: F,
218        predicate: bool,
219    ) -> Self {
220        if predicate {
221            self.propose_allocation(propose_allocation)
222        } else {
223            self
224        }
225    }
226
227    #[cfg(feature = "v1_24")]
228    #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
229    pub fn propose_allocation_if_some<
230        F: FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static,
231    >(
232        self,
233        propose_allocation: Option<F>,
234    ) -> Self {
235        if let Some(propose_allocation) = propose_allocation {
236            self.propose_allocation(propose_allocation)
237        } else {
238            self
239        }
240    }
241
242    #[must_use = "Building the callbacks without using them has no effect"]
243    pub fn build(self) -> AppSinkCallbacks {
244        let have_eos = self.eos.is_some();
245        let have_new_preroll = self.new_preroll.is_some();
246        let have_new_sample = self.new_sample.is_some();
247        let have_new_event = self.new_event.is_some();
248        let have_propose_allocation = self.propose_allocation.is_some();
249
250        AppSinkCallbacks {
251            eos: self.eos,
252            new_preroll: self.new_preroll,
253            new_sample: self.new_sample,
254            new_event: self.new_event,
255            propose_allocation: self.propose_allocation,
256            #[cfg(not(panic = "abort"))]
257            panicked: AtomicBool::new(false),
258            callbacks: ffi::GstAppSinkCallbacks {
259                eos: if have_eos { Some(trampoline_eos) } else { None },
260                new_preroll: if have_new_preroll {
261                    Some(trampoline_new_preroll)
262                } else {
263                    None
264                },
265                new_sample: if have_new_sample {
266                    Some(trampoline_new_sample)
267                } else {
268                    None
269                },
270                new_event: if have_new_event {
271                    Some(trampoline_new_event)
272                } else {
273                    None
274                },
275                propose_allocation: if have_propose_allocation {
276                    Some(trampoline_propose_allocation)
277                } else {
278                    None
279                },
280                _gst_reserved: [ptr::null_mut(), ptr::null_mut()],
281            },
282        }
283    }
284}
285
286unsafe extern "C" fn trampoline_eos(appsink: *mut ffi::GstAppSink, callbacks: gpointer) {
287    unsafe {
288        let callbacks = callbacks as *mut AppSinkCallbacks;
289        let element: Borrowed<AppSink> = from_glib_borrow(appsink);
290
291        #[cfg(not(panic = "abort"))]
292        if (*callbacks).panicked.load(Ordering::Relaxed) {
293            let element: Borrowed<AppSink> = from_glib_borrow(appsink);
294            gst::subclass::post_panic_error_message(
295                element.upcast_ref(),
296                element.upcast_ref(),
297                None,
298            );
299            return;
300        }
301
302        if let Some(ref mut eos) = (*callbacks).eos {
303            let result = panic::catch_unwind(panic::AssertUnwindSafe(|| eos(&element)));
304            match result {
305                Ok(result) => result,
306                Err(err) => {
307                    #[cfg(panic = "abort")]
308                    {
309                        unreachable!("{err:?}");
310                    }
311                    #[cfg(not(panic = "abort"))]
312                    {
313                        (*callbacks).panicked.store(true, Ordering::Relaxed);
314                        gst::subclass::post_panic_error_message(
315                            element.upcast_ref(),
316                            element.upcast_ref(),
317                            Some(err),
318                        );
319                    }
320                }
321            }
322        }
323    }
324}
325
326unsafe extern "C" fn trampoline_new_preroll(
327    appsink: *mut ffi::GstAppSink,
328    callbacks: gpointer,
329) -> gst::ffi::GstFlowReturn {
330    unsafe {
331        let callbacks = callbacks as *mut AppSinkCallbacks;
332        let element: Borrowed<AppSink> = from_glib_borrow(appsink);
333
334        #[cfg(not(panic = "abort"))]
335        if (*callbacks).panicked.load(Ordering::Relaxed) {
336            let element: Borrowed<AppSink> = from_glib_borrow(appsink);
337            gst::subclass::post_panic_error_message(
338                element.upcast_ref(),
339                element.upcast_ref(),
340                None,
341            );
342            return gst::FlowReturn::Error.into_glib();
343        }
344
345        let ret = if let Some(ref mut new_preroll) = (*callbacks).new_preroll {
346            let result =
347                panic::catch_unwind(panic::AssertUnwindSafe(|| new_preroll(&element).into()));
348            match result {
349                Ok(result) => result,
350                Err(err) => {
351                    #[cfg(panic = "abort")]
352                    {
353                        unreachable!("{err:?}");
354                    }
355                    #[cfg(not(panic = "abort"))]
356                    {
357                        (*callbacks).panicked.store(true, Ordering::Relaxed);
358                        gst::subclass::post_panic_error_message(
359                            element.upcast_ref(),
360                            element.upcast_ref(),
361                            Some(err),
362                        );
363
364                        gst::FlowReturn::Error
365                    }
366                }
367            }
368        } else {
369            gst::FlowReturn::Error
370        };
371
372        ret.into_glib()
373    }
374}
375
376unsafe extern "C" fn trampoline_new_sample(
377    appsink: *mut ffi::GstAppSink,
378    callbacks: gpointer,
379) -> gst::ffi::GstFlowReturn {
380    unsafe {
381        let callbacks = callbacks as *mut AppSinkCallbacks;
382        let element: Borrowed<AppSink> = from_glib_borrow(appsink);
383
384        #[cfg(not(panic = "abort"))]
385        if (*callbacks).panicked.load(Ordering::Relaxed) {
386            let element: Borrowed<AppSink> = from_glib_borrow(appsink);
387            gst::subclass::post_panic_error_message(
388                element.upcast_ref(),
389                element.upcast_ref(),
390                None,
391            );
392            return gst::FlowReturn::Error.into_glib();
393        }
394
395        let ret = if let Some(ref mut new_sample) = (*callbacks).new_sample {
396            let result =
397                panic::catch_unwind(panic::AssertUnwindSafe(|| new_sample(&element).into()));
398            match result {
399                Ok(result) => result,
400                Err(err) => {
401                    #[cfg(panic = "abort")]
402                    {
403                        unreachable!("{err:?}");
404                    }
405                    #[cfg(not(panic = "abort"))]
406                    {
407                        (*callbacks).panicked.store(true, Ordering::Relaxed);
408                        gst::subclass::post_panic_error_message(
409                            element.upcast_ref(),
410                            element.upcast_ref(),
411                            Some(err),
412                        );
413
414                        gst::FlowReturn::Error
415                    }
416                }
417            }
418        } else {
419            gst::FlowReturn::Error
420        };
421
422        ret.into_glib()
423    }
424}
425
426unsafe extern "C" fn trampoline_new_event(
427    appsink: *mut ffi::GstAppSink,
428    callbacks: gpointer,
429) -> glib::ffi::gboolean {
430    unsafe {
431        let callbacks = callbacks as *mut AppSinkCallbacks;
432        let element: Borrowed<AppSink> = from_glib_borrow(appsink);
433
434        #[cfg(not(panic = "abort"))]
435        if (*callbacks).panicked.load(Ordering::Relaxed) {
436            let element: Borrowed<AppSink> = from_glib_borrow(appsink);
437            gst::subclass::post_panic_error_message(
438                element.upcast_ref(),
439                element.upcast_ref(),
440                None,
441            );
442            return false.into_glib();
443        }
444
445        let ret = if let Some(ref mut new_event) = (*callbacks).new_event {
446            let result = panic::catch_unwind(panic::AssertUnwindSafe(|| new_event(&element)));
447            match result {
448                Ok(result) => result,
449                Err(err) => {
450                    #[cfg(panic = "abort")]
451                    {
452                        unreachable!("{err:?}");
453                    }
454                    #[cfg(not(panic = "abort"))]
455                    {
456                        (*callbacks).panicked.store(true, Ordering::Relaxed);
457                        gst::subclass::post_panic_error_message(
458                            element.upcast_ref(),
459                            element.upcast_ref(),
460                            Some(err),
461                        );
462
463                        false
464                    }
465                }
466            }
467        } else {
468            false
469        };
470
471        ret.into_glib()
472    }
473}
474
475unsafe extern "C" fn trampoline_propose_allocation(
476    appsink: *mut ffi::GstAppSink,
477    query: *mut gst::ffi::GstQuery,
478    callbacks: gpointer,
479) -> glib::ffi::gboolean {
480    unsafe {
481        let callbacks = callbacks as *mut AppSinkCallbacks;
482        let element: Borrowed<AppSink> = from_glib_borrow(appsink);
483
484        #[cfg(not(panic = "abort"))]
485        if (*callbacks).panicked.load(Ordering::Relaxed) {
486            let element: Borrowed<AppSink> = from_glib_borrow(appsink);
487            gst::subclass::post_panic_error_message(
488                element.upcast_ref(),
489                element.upcast_ref(),
490                None,
491            );
492            return false.into_glib();
493        }
494
495        let ret = if let Some(ref mut propose_allocation) = (*callbacks).propose_allocation {
496            let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
497                gst::QueryViewMut::Allocation(allocation) => allocation,
498                _ => unreachable!(),
499            };
500            let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
501                propose_allocation(&element, query)
502            }));
503            match result {
504                Ok(result) => result,
505                Err(err) => {
506                    #[cfg(panic = "abort")]
507                    {
508                        unreachable!("{err:?}");
509                    }
510                    #[cfg(not(panic = "abort"))]
511                    {
512                        (*callbacks).panicked.store(true, Ordering::Relaxed);
513                        gst::subclass::post_panic_error_message(
514                            element.upcast_ref(),
515                            element.upcast_ref(),
516                            Some(err),
517                        );
518                        false
519                    }
520                }
521            }
522        } else {
523            false
524        };
525
526        ret.into_glib()
527    }
528}
529
530unsafe extern "C" fn destroy_callbacks(ptr: gpointer) {
531    unsafe {
532        let _ = Box::<AppSinkCallbacks>::from_raw(ptr as *mut _);
533    }
534}
535
536impl AppSink {
537    // rustdoc-stripper-ignore-next
538    /// Creates a new builder-pattern struct instance to construct [`AppSink`] objects.
539    ///
540    /// This method returns an instance of [`AppSinkBuilder`](crate::builders::AppSinkBuilder) which can be used to create [`AppSink`] objects.
541    pub fn builder<'a>() -> AppSinkBuilder<'a> {
542        assert_initialized_main_thread!();
543        AppSinkBuilder {
544            builder: gst::Object::builder(),
545            callbacks: None,
546            drop_out_of_segment: None,
547        }
548    }
549
550    /// Set callbacks which will be executed for each new preroll, new sample and eos.
551    /// This is an alternative to using the signals, it has lower overhead and is thus
552    /// less expensive, but also less flexible.
553    ///
554    /// If callbacks are installed, no signals will be emitted for performance
555    /// reasons.
556    ///
557    /// Before 1.16.3 it was not possible to change the callbacks in a thread-safe
558    /// way.
559    ///
560    /// Since 1.28.3 it is allowed to set the `callbacks` to [`None`] to unset them.
561    ///
562    /// Note that `gst_app_sink_set_callbacks()` and
563    /// `gst_app_sink_set_simple_callbacks()` are mutually exclusive and setting one
564    /// will unset the other.
565    /// ## `callbacks`
566    /// the callbacks
567    /// ## `notify`
568    /// a destroy notify function
569    #[doc(alias = "gst_app_sink_set_callbacks")]
570    pub fn set_callbacks(&self, callbacks: AppSinkCallbacks) {
571        unsafe {
572            let sink = self.to_glib_none().0;
573
574            #[allow(clippy::manual_dangling_ptr)]
575            #[cfg(not(feature = "v1_18"))]
576            {
577                static SET_ONCE_QUARK: std::sync::OnceLock<glib::Quark> =
578                    std::sync::OnceLock::new();
579
580                let set_once_quark = SET_ONCE_QUARK
581                    .get_or_init(|| glib::Quark::from_str("gstreamer-rs-app-sink-callbacks"));
582
583                // This is not thread-safe before 1.16.3, see
584                // https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/merge_requests/570
585                if gst::version() < (1, 16, 3, 0) {
586                    if !glib::gobject_ffi::g_object_get_qdata(
587                        sink as *mut _,
588                        set_once_quark.into_glib(),
589                    )
590                    .is_null()
591                    {
592                        panic!("AppSink callbacks can only be set once");
593                    }
594
595                    glib::gobject_ffi::g_object_set_qdata(
596                        sink as *mut _,
597                        set_once_quark.into_glib(),
598                        1 as *mut _,
599                    );
600                }
601            }
602
603            ffi::gst_app_sink_set_callbacks(
604                sink,
605                mut_override(&callbacks.callbacks),
606                Box::into_raw(Box::new(callbacks)) as *mut _,
607                Some(destroy_callbacks),
608            );
609        }
610    }
611
612    #[doc(alias = "drop-out-of-segment")]
613    pub fn drops_out_of_segment(&self) -> bool {
614        unsafe {
615            from_glib(gst_base::ffi::gst_base_sink_get_drop_out_of_segment(
616                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
617            ))
618        }
619    }
620
621    #[doc(alias = "max-bitrate")]
622    #[doc(alias = "gst_base_sink_get_max_bitrate")]
623    pub fn max_bitrate(&self) -> u64 {
624        unsafe {
625            gst_base::ffi::gst_base_sink_get_max_bitrate(
626                self.as_ptr() as *mut gst_base::ffi::GstBaseSink
627            )
628        }
629    }
630
631    #[doc(alias = "max-lateness")]
632    #[doc(alias = "gst_base_sink_get_max_lateness")]
633    pub fn max_lateness(&self) -> i64 {
634        unsafe {
635            gst_base::ffi::gst_base_sink_get_max_lateness(
636                self.as_ptr() as *mut gst_base::ffi::GstBaseSink
637            )
638        }
639    }
640
641    #[doc(alias = "processing-deadline")]
642    #[cfg(feature = "v1_16")]
643    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
644    #[doc(alias = "gst_base_sink_get_processing_deadline")]
645    pub fn processing_deadline(&self) -> gst::ClockTime {
646        unsafe {
647            try_from_glib(gst_base::ffi::gst_base_sink_get_processing_deadline(
648                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
649            ))
650            .expect("undefined processing_deadline")
651        }
652    }
653
654    #[doc(alias = "render-delay")]
655    #[doc(alias = "gst_base_sink_get_render_delay")]
656    pub fn render_delay(&self) -> gst::ClockTime {
657        unsafe {
658            try_from_glib(gst_base::ffi::gst_base_sink_get_render_delay(
659                self.as_ptr() as *mut gst_base::ffi::GstBaseSink
660            ))
661            .expect("undefined render_delay")
662        }
663    }
664
665    #[cfg(feature = "v1_18")]
666    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
667    #[doc(alias = "gst_base_sink_get_stats")]
668    pub fn stats(&self) -> gst::Structure {
669        unsafe {
670            from_glib_full(gst_base::ffi::gst_base_sink_get_stats(
671                self.as_ptr() as *mut gst_base::ffi::GstBaseSink
672            ))
673        }
674    }
675
676    #[doc(alias = "sync")]
677    pub fn is_sync(&self) -> bool {
678        unsafe {
679            from_glib(gst_base::ffi::gst_base_sink_get_sync(
680                self.as_ptr() as *mut gst_base::ffi::GstBaseSink
681            ))
682        }
683    }
684
685    #[doc(alias = "throttle-time")]
686    #[doc(alias = "gst_base_sink_get_throttle_time")]
687    pub fn throttle_time(&self) -> u64 {
688        unsafe {
689            gst_base::ffi::gst_base_sink_get_throttle_time(
690                self.as_ptr() as *mut gst_base::ffi::GstBaseSink
691            )
692        }
693    }
694
695    #[doc(alias = "ts-offset")]
696    #[doc(alias = "gst_base_sink_get_ts_offset")]
697    pub fn ts_offset(&self) -> gst::ClockTimeDiff {
698        unsafe {
699            gst_base::ffi::gst_base_sink_get_ts_offset(
700                self.as_ptr() as *mut gst_base::ffi::GstBaseSink
701            )
702        }
703    }
704
705    #[doc(alias = "async")]
706    #[doc(alias = "gst_base_sink_is_async_enabled")]
707    pub fn is_async(&self) -> bool {
708        unsafe {
709            from_glib(gst_base::ffi::gst_base_sink_is_async_enabled(
710                self.as_ptr() as *mut gst_base::ffi::GstBaseSink
711            ))
712        }
713    }
714
715    #[doc(alias = "last-sample")]
716    pub fn enables_last_sample(&self) -> bool {
717        unsafe {
718            from_glib(gst_base::ffi::gst_base_sink_is_last_sample_enabled(
719                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
720            ))
721        }
722    }
723
724    #[doc(alias = "qos")]
725    #[doc(alias = "gst_base_sink_is_qos_enabled")]
726    pub fn is_qos(&self) -> bool {
727        unsafe {
728            from_glib(gst_base::ffi::gst_base_sink_is_qos_enabled(
729                self.as_ptr() as *mut gst_base::ffi::GstBaseSink
730            ))
731        }
732    }
733
734    #[doc(alias = "async")]
735    #[doc(alias = "gst_base_sink_set_async_enabled")]
736    pub fn set_async(&self, enabled: bool) {
737        unsafe {
738            gst_base::ffi::gst_base_sink_set_async_enabled(
739                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
740                enabled.into_glib(),
741            );
742        }
743    }
744
745    #[doc(alias = "drop-out-of-segment")]
746    #[doc(alias = "gst_base_sink_set_drop_out_of_segment")]
747    pub fn set_drop_out_of_segment(&self, drop_out_of_segment: bool) {
748        unsafe {
749            gst_base::ffi::gst_base_sink_set_drop_out_of_segment(
750                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
751                drop_out_of_segment.into_glib(),
752            );
753        }
754    }
755
756    #[doc(alias = "last-sample")]
757    pub fn set_enable_last_sample(&self, enabled: bool) {
758        unsafe {
759            gst_base::ffi::gst_base_sink_set_last_sample_enabled(
760                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
761                enabled.into_glib(),
762            );
763        }
764    }
765
766    #[doc(alias = "max-bitrate")]
767    #[doc(alias = "gst_base_sink_set_max_bitrate")]
768    pub fn set_max_bitrate(&self, max_bitrate: u64) {
769        unsafe {
770            gst_base::ffi::gst_base_sink_set_max_bitrate(
771                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
772                max_bitrate,
773            );
774        }
775    }
776
777    #[doc(alias = "max-lateness")]
778    #[doc(alias = "gst_base_sink_set_max_lateness")]
779    pub fn set_max_lateness(&self, max_lateness: i64) {
780        unsafe {
781            gst_base::ffi::gst_base_sink_set_max_lateness(
782                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
783                max_lateness,
784            );
785        }
786    }
787
788    #[doc(alias = "processing-deadline")]
789    #[cfg(feature = "v1_16")]
790    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
791    #[doc(alias = "gst_base_sink_set_processing_deadline")]
792    pub fn set_processing_deadline(&self, processing_deadline: gst::ClockTime) {
793        unsafe {
794            gst_base::ffi::gst_base_sink_set_processing_deadline(
795                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
796                processing_deadline.into_glib(),
797            );
798        }
799    }
800
801    #[doc(alias = "qos")]
802    #[doc(alias = "gst_base_sink_set_qos_enabled")]
803    pub fn set_qos(&self, enabled: bool) {
804        unsafe {
805            gst_base::ffi::gst_base_sink_set_qos_enabled(
806                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
807                enabled.into_glib(),
808            );
809        }
810    }
811
812    #[doc(alias = "render-delay")]
813    #[doc(alias = "gst_base_sink_set_render_delay")]
814    pub fn set_render_delay(&self, delay: gst::ClockTime) {
815        unsafe {
816            gst_base::ffi::gst_base_sink_set_render_delay(
817                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
818                delay.into_glib(),
819            );
820        }
821    }
822
823    #[doc(alias = "sync")]
824    #[doc(alias = "gst_base_sink_set_sync")]
825    pub fn set_sync(&self, sync: bool) {
826        unsafe {
827            gst_base::ffi::gst_base_sink_set_sync(
828                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
829                sync.into_glib(),
830            );
831        }
832    }
833
834    #[doc(alias = "throttle-time")]
835    #[doc(alias = "gst_base_sink_set_throttle_time")]
836    pub fn set_throttle_time(&self, throttle: u64) {
837        unsafe {
838            gst_base::ffi::gst_base_sink_set_throttle_time(
839                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
840                throttle,
841            );
842        }
843    }
844
845    #[doc(alias = "ts-offset")]
846    #[doc(alias = "gst_base_sink_set_ts_offset")]
847    pub fn set_ts_offset(&self, offset: gst::ClockTimeDiff) {
848        unsafe {
849            gst_base::ffi::gst_base_sink_set_ts_offset(
850                self.as_ptr() as *mut gst_base::ffi::GstBaseSink,
851                offset,
852            );
853        }
854    }
855
856    #[doc(alias = "async")]
857    pub fn connect_async_notify<F: Fn(&Self) + Send + Sync + 'static>(
858        &self,
859        f: F,
860    ) -> glib::SignalHandlerId {
861        unsafe extern "C" fn notify_async_trampoline<F: Fn(&AppSink) + Send + Sync + 'static>(
862            this: *mut ffi::GstAppSink,
863            _param_spec: glib::ffi::gpointer,
864            f: glib::ffi::gpointer,
865        ) {
866            unsafe {
867                let f: &F = &*(f as *const F);
868                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
869            }
870        }
871        unsafe {
872            let f: Box<F> = Box::new(f);
873            glib::signal::connect_raw(
874                self.as_ptr() as *mut _,
875                b"notify::async\0".as_ptr() as *const _,
876                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
877                    notify_async_trampoline::<F> as *const (),
878                )),
879                Box::into_raw(f),
880            )
881        }
882    }
883
884    #[doc(alias = "blocksize")]
885    pub fn connect_blocksize_notify<F: Fn(&Self) + Send + Sync + 'static>(
886        &self,
887        f: F,
888    ) -> glib::SignalHandlerId {
889        unsafe extern "C" fn notify_blocksize_trampoline<
890            F: Fn(&AppSink) + Send + Sync + 'static,
891        >(
892            this: *mut ffi::GstAppSink,
893            _param_spec: glib::ffi::gpointer,
894            f: glib::ffi::gpointer,
895        ) {
896            unsafe {
897                let f: &F = &*(f as *const F);
898                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
899            }
900        }
901        unsafe {
902            let f: Box<F> = Box::new(f);
903            glib::signal::connect_raw(
904                self.as_ptr() as *mut _,
905                b"notify::blocksize\0".as_ptr() as *const _,
906                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
907                    notify_blocksize_trampoline::<F> as *const (),
908                )),
909                Box::into_raw(f),
910            )
911        }
912    }
913
914    #[doc(alias = "enable-last-sample")]
915    pub fn connect_enable_last_sample_notify<F: Fn(&Self) + Send + Sync + 'static>(
916        &self,
917        f: F,
918    ) -> glib::SignalHandlerId {
919        unsafe extern "C" fn notify_enable_last_sample_trampoline<
920            F: Fn(&AppSink) + Send + Sync + 'static,
921        >(
922            this: *mut ffi::GstAppSink,
923            _param_spec: glib::ffi::gpointer,
924            f: glib::ffi::gpointer,
925        ) {
926            unsafe {
927                let f: &F = &*(f as *const F);
928                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
929            }
930        }
931        unsafe {
932            let f: Box<F> = Box::new(f);
933            glib::signal::connect_raw(
934                self.as_ptr() as *mut _,
935                b"notify::enable-last-sample\0".as_ptr() as *const _,
936                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
937                    notify_enable_last_sample_trampoline::<F> as *const (),
938                )),
939                Box::into_raw(f),
940            )
941        }
942    }
943
944    #[doc(alias = "last-sample")]
945    pub fn connect_last_sample_notify<F: Fn(&Self) + Send + Sync + 'static>(
946        &self,
947        f: F,
948    ) -> glib::SignalHandlerId {
949        unsafe extern "C" fn notify_last_sample_trampoline<
950            F: Fn(&AppSink) + Send + Sync + 'static,
951        >(
952            this: *mut ffi::GstAppSink,
953            _param_spec: glib::ffi::gpointer,
954            f: glib::ffi::gpointer,
955        ) {
956            unsafe {
957                let f: &F = &*(f as *const F);
958                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
959            }
960        }
961        unsafe {
962            let f: Box<F> = Box::new(f);
963            glib::signal::connect_raw(
964                self.as_ptr() as *mut _,
965                b"notify::last-sample\0".as_ptr() as *const _,
966                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
967                    notify_last_sample_trampoline::<F> as *const (),
968                )),
969                Box::into_raw(f),
970            )
971        }
972    }
973
974    #[doc(alias = "max-bitrate")]
975    pub fn connect_max_bitrate_notify<F: Fn(&Self) + Send + Sync + 'static>(
976        &self,
977        f: F,
978    ) -> glib::SignalHandlerId {
979        unsafe extern "C" fn notify_max_bitrate_trampoline<
980            F: Fn(&AppSink) + Send + Sync + 'static,
981        >(
982            this: *mut ffi::GstAppSink,
983            _param_spec: glib::ffi::gpointer,
984            f: glib::ffi::gpointer,
985        ) {
986            unsafe {
987                let f: &F = &*(f as *const F);
988                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
989            }
990        }
991        unsafe {
992            let f: Box<F> = Box::new(f);
993            glib::signal::connect_raw(
994                self.as_ptr() as *mut _,
995                b"notify::max-bitrate\0".as_ptr() as *const _,
996                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
997                    notify_max_bitrate_trampoline::<F> as *const (),
998                )),
999                Box::into_raw(f),
1000            )
1001        }
1002    }
1003
1004    #[doc(alias = "max-lateness")]
1005    pub fn connect_max_lateness_notify<F: Fn(&Self) + Send + Sync + 'static>(
1006        &self,
1007        f: F,
1008    ) -> glib::SignalHandlerId {
1009        unsafe extern "C" fn notify_max_lateness_trampoline<
1010            F: Fn(&AppSink) + Send + Sync + 'static,
1011        >(
1012            this: *mut ffi::GstAppSink,
1013            _param_spec: glib::ffi::gpointer,
1014            f: glib::ffi::gpointer,
1015        ) {
1016            unsafe {
1017                let f: &F = &*(f as *const F);
1018                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
1019            }
1020        }
1021        unsafe {
1022            let f: Box<F> = Box::new(f);
1023            glib::signal::connect_raw(
1024                self.as_ptr() as *mut _,
1025                b"notify::max-lateness\0".as_ptr() as *const _,
1026                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
1027                    notify_max_lateness_trampoline::<F> as *const (),
1028                )),
1029                Box::into_raw(f),
1030            )
1031        }
1032    }
1033
1034    #[cfg(feature = "v1_16")]
1035    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
1036    #[doc(alias = "processing-deadline")]
1037    pub fn connect_processing_deadline_notify<F: Fn(&Self) + Send + Sync + 'static>(
1038        &self,
1039        f: F,
1040    ) -> glib::SignalHandlerId {
1041        unsafe extern "C" fn notify_processing_deadline_trampoline<
1042            F: Fn(&AppSink) + Send + Sync + 'static,
1043        >(
1044            this: *mut ffi::GstAppSink,
1045            _param_spec: glib::ffi::gpointer,
1046            f: glib::ffi::gpointer,
1047        ) {
1048            unsafe {
1049                let f: &F = &*(f as *const F);
1050                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
1051            }
1052        }
1053        unsafe {
1054            let f: Box<F> = Box::new(f);
1055            glib::signal::connect_raw(
1056                self.as_ptr() as *mut _,
1057                b"notify::processing-deadline\0".as_ptr() as *const _,
1058                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
1059                    notify_processing_deadline_trampoline::<F> as *const (),
1060                )),
1061                Box::into_raw(f),
1062            )
1063        }
1064    }
1065
1066    #[doc(alias = "qos")]
1067    pub fn connect_qos_notify<F: Fn(&Self) + Send + Sync + 'static>(
1068        &self,
1069        f: F,
1070    ) -> glib::SignalHandlerId {
1071        unsafe extern "C" fn notify_qos_trampoline<F: Fn(&AppSink) + Send + Sync + 'static>(
1072            this: *mut ffi::GstAppSink,
1073            _param_spec: glib::ffi::gpointer,
1074            f: glib::ffi::gpointer,
1075        ) {
1076            unsafe {
1077                let f: &F = &*(f as *const F);
1078                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
1079            }
1080        }
1081        unsafe {
1082            let f: Box<F> = Box::new(f);
1083            glib::signal::connect_raw(
1084                self.as_ptr() as *mut _,
1085                b"notify::qos\0".as_ptr() as *const _,
1086                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
1087                    notify_qos_trampoline::<F> as *const (),
1088                )),
1089                Box::into_raw(f),
1090            )
1091        }
1092    }
1093
1094    #[doc(alias = "render-delay")]
1095    pub fn connect_render_delay_notify<F: Fn(&Self) + Send + Sync + 'static>(
1096        &self,
1097        f: F,
1098    ) -> glib::SignalHandlerId {
1099        unsafe extern "C" fn notify_render_delay_trampoline<
1100            F: Fn(&AppSink) + Send + Sync + 'static,
1101        >(
1102            this: *mut ffi::GstAppSink,
1103            _param_spec: glib::ffi::gpointer,
1104            f: glib::ffi::gpointer,
1105        ) {
1106            unsafe {
1107                let f: &F = &*(f as *const F);
1108                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
1109            }
1110        }
1111        unsafe {
1112            let f: Box<F> = Box::new(f);
1113            glib::signal::connect_raw(
1114                self.as_ptr() as *mut _,
1115                b"notify::render-delay\0".as_ptr() as *const _,
1116                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
1117                    notify_render_delay_trampoline::<F> as *const (),
1118                )),
1119                Box::into_raw(f),
1120            )
1121        }
1122    }
1123
1124    #[cfg(feature = "v1_18")]
1125    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1126    #[doc(alias = "stats")]
1127    pub fn connect_stats_notify<F: Fn(&Self) + Send + Sync + 'static>(
1128        &self,
1129        f: F,
1130    ) -> glib::SignalHandlerId {
1131        unsafe extern "C" fn notify_stats_trampoline<F: Fn(&AppSink) + Send + Sync + 'static>(
1132            this: *mut ffi::GstAppSink,
1133            _param_spec: glib::ffi::gpointer,
1134            f: glib::ffi::gpointer,
1135        ) {
1136            unsafe {
1137                let f: &F = &*(f as *const F);
1138                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
1139            }
1140        }
1141        unsafe {
1142            let f: Box<F> = Box::new(f);
1143            glib::signal::connect_raw(
1144                self.as_ptr() as *mut _,
1145                b"notify::stats\0".as_ptr() as *const _,
1146                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
1147                    notify_stats_trampoline::<F> as *const (),
1148                )),
1149                Box::into_raw(f),
1150            )
1151        }
1152    }
1153
1154    #[doc(alias = "sync")]
1155    pub fn connect_sync_notify<F: Fn(&Self) + Send + Sync + 'static>(
1156        &self,
1157        f: F,
1158    ) -> glib::SignalHandlerId {
1159        unsafe extern "C" fn notify_sync_trampoline<F: Fn(&AppSink) + Send + Sync + 'static>(
1160            this: *mut ffi::GstAppSink,
1161            _param_spec: glib::ffi::gpointer,
1162            f: glib::ffi::gpointer,
1163        ) {
1164            unsafe {
1165                let f: &F = &*(f as *const F);
1166                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
1167            }
1168        }
1169        unsafe {
1170            let f: Box<F> = Box::new(f);
1171            glib::signal::connect_raw(
1172                self.as_ptr() as *mut _,
1173                b"notify::sync\0".as_ptr() as *const _,
1174                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
1175                    notify_sync_trampoline::<F> as *const (),
1176                )),
1177                Box::into_raw(f),
1178            )
1179        }
1180    }
1181
1182    #[doc(alias = "throttle-time")]
1183    pub fn connect_throttle_time_notify<F: Fn(&Self) + Send + Sync + 'static>(
1184        &self,
1185        f: F,
1186    ) -> glib::SignalHandlerId {
1187        unsafe extern "C" fn notify_throttle_time_trampoline<
1188            F: Fn(&AppSink) + Send + Sync + 'static,
1189        >(
1190            this: *mut ffi::GstAppSink,
1191            _param_spec: glib::ffi::gpointer,
1192            f: glib::ffi::gpointer,
1193        ) {
1194            unsafe {
1195                let f: &F = &*(f as *const F);
1196                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
1197            }
1198        }
1199        unsafe {
1200            let f: Box<F> = Box::new(f);
1201            glib::signal::connect_raw(
1202                self.as_ptr() as *mut _,
1203                b"notify::throttle-time\0".as_ptr() as *const _,
1204                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
1205                    notify_throttle_time_trampoline::<F> as *const (),
1206                )),
1207                Box::into_raw(f),
1208            )
1209        }
1210    }
1211
1212    #[doc(alias = "ts-offset")]
1213    pub fn connect_ts_offset_notify<F: Fn(&Self) + Send + Sync + 'static>(
1214        &self,
1215        f: F,
1216    ) -> glib::SignalHandlerId {
1217        unsafe extern "C" fn notify_ts_offset_trampoline<
1218            F: Fn(&AppSink) + Send + Sync + 'static,
1219        >(
1220            this: *mut ffi::GstAppSink,
1221            _param_spec: glib::ffi::gpointer,
1222            f: glib::ffi::gpointer,
1223        ) {
1224            unsafe {
1225                let f: &F = &*(f as *const F);
1226                f(AppSink::from_glib_borrow(this).unsafe_cast_ref())
1227            }
1228        }
1229        unsafe {
1230            let f: Box<F> = Box::new(f);
1231            glib::signal::connect_raw(
1232                self.as_ptr() as *mut _,
1233                b"notify::ts-offset\0".as_ptr() as *const _,
1234                Some(mem::transmute::<*const (), unsafe extern "C" fn()>(
1235                    notify_ts_offset_trampoline::<F> as *const (),
1236                )),
1237                Box::into_raw(f),
1238            )
1239        }
1240    }
1241
1242    #[cfg(feature = "futures")]
1243    pub fn stream(&self) -> AppSinkStream {
1244        AppSinkStream::new(self)
1245    }
1246}
1247
1248// rustdoc-stripper-ignore-next
1249/// A [builder-pattern] type to construct [`AppSink`] objects.
1250///
1251/// [builder-pattern]: https://doc.rust-lang.org/1.0.0/style/ownership/builders.html
1252#[must_use = "The builder must be built to be used"]
1253pub struct AppSinkBuilder<'a> {
1254    builder: gst::gobject::GObjectBuilder<'a, AppSink>,
1255    callbacks: Option<AppSinkCallbacks>,
1256    drop_out_of_segment: Option<bool>,
1257}
1258
1259impl<'a> AppSinkBuilder<'a> {
1260    // rustdoc-stripper-ignore-next
1261    /// Build the [`AppSink`].
1262    ///
1263    /// # Panics
1264    ///
1265    /// This panics if the [`AppSink`] doesn't have all the given properties or
1266    /// property values of the wrong type are provided.
1267    #[must_use = "Building the object from the builder is usually expensive and is not expected to have side effects"]
1268    pub fn build(self) -> AppSink {
1269        let appsink = self.builder.build().unwrap();
1270
1271        if let Some(callbacks) = self.callbacks {
1272            appsink.set_callbacks(callbacks);
1273        }
1274
1275        if let Some(drop_out_of_segment) = self.drop_out_of_segment {
1276            appsink.set_drop_out_of_segment(drop_out_of_segment);
1277        }
1278
1279        appsink
1280    }
1281
1282    pub fn async_(self, async_: bool) -> Self {
1283        Self {
1284            builder: self.builder.property("async", async_),
1285            ..self
1286        }
1287    }
1288
1289    pub fn buffer_list(self, buffer_list: bool) -> Self {
1290        Self {
1291            builder: self.builder.property("buffer-list", buffer_list),
1292            ..self
1293        }
1294    }
1295
1296    pub fn callbacks(self, callbacks: AppSinkCallbacks) -> Self {
1297        Self {
1298            callbacks: Some(callbacks),
1299            ..self
1300        }
1301    }
1302
1303    pub fn caps(self, caps: &'a gst::Caps) -> Self {
1304        Self {
1305            builder: self.builder.property("caps", caps),
1306            ..self
1307        }
1308    }
1309
1310    #[cfg_attr(feature = "v1_28", deprecated = "Since 1.28")]
1311    #[allow(deprecated)]
1312    pub fn drop(self, drop: bool) -> Self {
1313        Self {
1314            builder: self.builder.property("drop", drop),
1315            ..self
1316        }
1317    }
1318
1319    pub fn drop_out_of_segment(self, drop_out_of_segment: bool) -> Self {
1320        Self {
1321            drop_out_of_segment: Some(drop_out_of_segment),
1322            ..self
1323        }
1324    }
1325
1326    pub fn enable_last_sample(self, enable_last_sample: bool) -> Self {
1327        Self {
1328            builder: self
1329                .builder
1330                .property("enable-last-sample", enable_last_sample),
1331            ..self
1332        }
1333    }
1334
1335    pub fn max_bitrate(self, max_bitrate: u64) -> Self {
1336        Self {
1337            builder: self.builder.property("max-bitrate", max_bitrate),
1338            ..self
1339        }
1340    }
1341
1342    pub fn max_buffers(self, max_buffers: u32) -> Self {
1343        Self {
1344            builder: self.builder.property("max-buffers", max_buffers),
1345            ..self
1346        }
1347    }
1348
1349    pub fn max_lateness(self, max_lateness: i64) -> Self {
1350        Self {
1351            builder: self.builder.property("max-lateness", max_lateness),
1352            ..self
1353        }
1354    }
1355
1356    #[cfg(feature = "v1_16")]
1357    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
1358    pub fn processing_deadline(self, processing_deadline: gst::ClockTime) -> Self {
1359        Self {
1360            builder: self
1361                .builder
1362                .property("processing-deadline", processing_deadline),
1363            ..self
1364        }
1365    }
1366
1367    pub fn qos(self, qos: bool) -> Self {
1368        Self {
1369            builder: self.builder.property("qos", qos),
1370            ..self
1371        }
1372    }
1373
1374    pub fn render_delay(self, render_delay: Option<gst::ClockTime>) -> Self {
1375        Self {
1376            builder: self.builder.property("render-delay", render_delay),
1377            ..self
1378        }
1379    }
1380
1381    pub fn sync(self, sync: bool) -> Self {
1382        Self {
1383            builder: self.builder.property("sync", sync),
1384            ..self
1385        }
1386    }
1387
1388    pub fn throttle_time(self, throttle_time: u64) -> Self {
1389        Self {
1390            builder: self.builder.property("throttle-time", throttle_time),
1391            ..self
1392        }
1393    }
1394
1395    pub fn ts_offset(self, ts_offset: gst::ClockTimeDiff) -> Self {
1396        Self {
1397            builder: self.builder.property("ts-offset", ts_offset),
1398            ..self
1399        }
1400    }
1401
1402    pub fn wait_on_eos(self, wait_on_eos: bool) -> Self {
1403        Self {
1404            builder: self.builder.property("wait-on-eos", wait_on_eos),
1405            ..self
1406        }
1407    }
1408
1409    #[cfg(feature = "v1_24")]
1410    #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1411    pub fn max_time(self, max_time: Option<gst::ClockTime>) -> Self {
1412        Self {
1413            builder: self.builder.property("max-time", max_time),
1414            ..self
1415        }
1416    }
1417
1418    #[cfg(feature = "v1_24")]
1419    #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1420    pub fn max_bytes(self, max_bytes: u64) -> Self {
1421        Self {
1422            builder: self.builder.property("max-bytes", max_bytes),
1423            ..self
1424        }
1425    }
1426
1427    #[cfg(feature = "v1_28")]
1428    #[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
1429    pub fn leaky_type(self, leaky_type: crate::AppLeakyType) -> Self {
1430        Self {
1431            builder: self.builder.property("leaky-type", leaky_type),
1432            ..self
1433        }
1434    }
1435
1436    #[cfg(feature = "v1_28")]
1437    #[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
1438    pub fn silent(self, silent: bool) -> Self {
1439        Self {
1440            builder: self.builder.property("silent", silent),
1441            ..self
1442        }
1443    }
1444
1445    // rustdoc-stripper-ignore-next
1446    /// Sets property `name` to the given value `value`.
1447    ///
1448    /// Overrides any default or previously defined value for `name`.
1449    #[inline]
1450    pub fn property(self, name: &'a str, value: impl Into<glib::Value> + 'a) -> Self {
1451        Self {
1452            builder: self.builder.property(name, value),
1453            ..self
1454        }
1455    }
1456
1457    // rustdoc-stripper-ignore-next
1458    /// Sets property `name` to the given string value `value`.
1459    #[inline]
1460    pub fn property_from_str(self, name: &'a str, value: &'a str) -> Self {
1461        Self {
1462            builder: self.builder.property_from_str(name, value),
1463            ..self
1464        }
1465    }
1466
1467    gst::impl_builder_gvalue_extra_setters!(property_and_name);
1468}