1use std::{mem, ptr};
4
5use atomic_refcell::AtomicRefCell;
6use glib::{prelude::*, translate::*};
7use gst::{prelude::*, subclass::prelude::*};
8
9use crate::{BaseSrc, ffi, prelude::*};
10
11#[derive(Default)]
12pub(super) struct InstanceData {
13 pub(super) pending_buffer_list: AtomicRefCell<Option<gst::BufferList>>,
14}
15
16#[derive(Debug)]
17pub enum CreateSuccess {
18 FilledBuffer,
19 NewBuffer(gst::Buffer),
20 NewBufferList(gst::BufferList),
21}
22
23pub trait BaseSrcImpl: ElementImpl + ObjectSubclass<Type: IsA<BaseSrc>> {
24 fn start(&self) -> Result<(), gst::ErrorMessage> {
29 self.parent_start()
30 }
31
32 fn stop(&self) -> Result<(), gst::ErrorMessage> {
34 self.parent_stop()
35 }
36
37 fn is_seekable(&self) -> bool {
39 self.parent_is_seekable()
40 }
41
42 fn size(&self) -> Option<u64> {
49 self.parent_size()
50 }
51
52 #[doc(alias = "get_times")]
58 fn times(&self, buffer: &gst::BufferRef) -> (Option<gst::ClockTime>, Option<gst::ClockTime>) {
59 self.parent_times(buffer)
60 }
61
62 fn fill(
65 &self,
66 offset: u64,
67 length: u32,
68 buffer: &mut gst::BufferRef,
69 ) -> Result<gst::FlowSuccess, gst::FlowError> {
70 self.parent_fill(offset, length, buffer)
71 }
72
73 fn alloc(&self, offset: u64, length: u32) -> Result<gst::Buffer, gst::FlowError> {
79 self.parent_alloc(offset, length)
80 }
81
82 fn create(
88 &self,
89 offset: u64,
90 buffer: Option<&mut gst::BufferRef>,
91 length: u32,
92 ) -> Result<CreateSuccess, gst::FlowError> {
93 self.parent_create(offset, buffer, length)
94 }
95
96 fn do_seek(&self, segment: &mut gst::Segment) -> bool {
98 self.parent_do_seek(segment)
99 }
100
101 fn query(&self, query: &mut gst::QueryRef) -> bool {
103 BaseSrcImplExt::parent_query(self, query)
104 }
105
106 fn event(&self, event: &gst::Event) -> bool {
108 self.parent_event(event)
109 }
110
111 fn caps(&self, filter: Option<&gst::Caps>) -> Option<gst::Caps> {
113 self.parent_caps(filter)
114 }
115
116 fn negotiate(&self) -> Result<(), gst::LoggableError> {
128 self.parent_negotiate()
129 }
130
131 fn set_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
139 self.parent_set_caps(caps)
140 }
141
142 fn fixate(&self, caps: gst::Caps) -> gst::Caps {
148 self.parent_fixate(caps)
149 }
150
151 fn unlock(&self) -> Result<(), gst::ErrorMessage> {
158 self.parent_unlock()
159 }
160
161 fn unlock_stop(&self) -> Result<(), gst::ErrorMessage> {
165 self.parent_unlock_stop()
166 }
167
168 fn decide_allocation(
170 &self,
171 query: &mut gst::query::Allocation,
172 ) -> Result<(), gst::LoggableError> {
173 self.parent_decide_allocation(query)
174 }
175
176 #[cfg(feature = "v1_30")]
184 #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
185 fn prepare_allocator(&self, caps: Option<&gst::Caps>) -> Result<(), gst::LoggableError> {
186 self.parent_prepare_allocator(caps)
187 }
188}
189
190pub trait BaseSrcImplExt: BaseSrcImpl {
191 fn parent_start(&self) -> Result<(), gst::ErrorMessage> {
192 unsafe {
193 let data = Self::type_data();
194 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
195 (*parent_class)
196 .start
197 .map(|f| {
198 if from_glib(f(self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0)) {
199 Ok(())
200 } else {
201 Err(gst::error_msg!(
202 gst::CoreError::StateChange,
203 ["Parent function `start` failed"]
204 ))
205 }
206 })
207 .unwrap_or(Ok(()))
208 }
209 }
210
211 fn parent_stop(&self) -> Result<(), gst::ErrorMessage> {
212 unsafe {
213 let data = Self::type_data();
214 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
215 (*parent_class)
216 .stop
217 .map(|f| {
218 if from_glib(f(self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0)) {
219 Ok(())
220 } else {
221 Err(gst::error_msg!(
222 gst::CoreError::StateChange,
223 ["Parent function `stop` failed"]
224 ))
225 }
226 })
227 .unwrap_or(Ok(()))
228 }
229 }
230
231 fn parent_is_seekable(&self) -> bool {
232 unsafe {
233 let data = Self::type_data();
234 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
235 (*parent_class)
236 .is_seekable
237 .map(|f| from_glib(f(self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0)))
238 .unwrap_or(false)
239 }
240 }
241
242 fn parent_size(&self) -> Option<u64> {
243 unsafe {
244 let data = Self::type_data();
245 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
246 (*parent_class)
247 .get_size
248 .map(|f| {
249 let mut size = mem::MaybeUninit::uninit();
250 if from_glib(f(
251 self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0,
252 size.as_mut_ptr(),
253 )) {
254 Some(size.assume_init())
255 } else {
256 None
257 }
258 })
259 .unwrap_or(None)
260 }
261 }
262
263 fn parent_times(
264 &self,
265 buffer: &gst::BufferRef,
266 ) -> (Option<gst::ClockTime>, Option<gst::ClockTime>) {
267 unsafe {
268 let data = Self::type_data();
269 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
270 (*parent_class)
271 .get_times
272 .map(|f| {
273 let mut start = mem::MaybeUninit::uninit();
274 let mut stop = mem::MaybeUninit::uninit();
275 f(
276 self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0,
277 buffer.as_mut_ptr(),
278 start.as_mut_ptr(),
279 stop.as_mut_ptr(),
280 );
281 (
282 from_glib(start.assume_init()),
283 from_glib(stop.assume_init()),
284 )
285 })
286 .unwrap_or((gst::ClockTime::NONE, gst::ClockTime::NONE))
287 }
288 }
289
290 fn parent_fill(
291 &self,
292 offset: u64,
293 length: u32,
294 buffer: &mut gst::BufferRef,
295 ) -> Result<gst::FlowSuccess, gst::FlowError> {
296 unsafe {
297 let data = Self::type_data();
298 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
299 (*parent_class)
300 .fill
301 .map(|f| {
302 try_from_glib(f(
303 self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0,
304 offset,
305 length,
306 buffer.as_mut_ptr(),
307 ))
308 })
309 .unwrap_or(Err(gst::FlowError::NotSupported))
310 }
311 }
312
313 fn parent_alloc(&self, offset: u64, length: u32) -> Result<gst::Buffer, gst::FlowError> {
314 unsafe {
315 let data = Self::type_data();
316 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
317 (*parent_class)
318 .alloc
319 .map(|f| {
320 let mut buffer_ptr: *mut gst::ffi::GstBuffer = ptr::null_mut();
321
322 let buffer_ref = &mut buffer_ptr as *mut _ as *mut gst::ffi::GstBuffer;
325
326 gst::FlowSuccess::try_from_glib(f(
327 self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0,
328 offset,
329 length,
330 buffer_ref,
331 ))
332 .map(|_| from_glib_full(buffer_ptr))
333 })
334 .unwrap_or(Err(gst::FlowError::NotSupported))
335 }
336 }
337
338 fn parent_create(
339 &self,
340 offset: u64,
341 mut buffer: Option<&mut gst::BufferRef>,
342 length: u32,
343 ) -> Result<CreateSuccess, gst::FlowError> {
344 unsafe {
345 let data = Self::type_data();
346 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
347 (*parent_class)
348 .create
349 .map(|f| {
350 let instance = self.obj();
351 let instance = instance.unsafe_cast_ref::<BaseSrc>();
352 let orig_buffer_ptr = buffer
353 .as_mut()
354 .map(|b| b.as_mut_ptr())
355 .unwrap_or(ptr::null_mut());
356 let mut buffer_ptr = orig_buffer_ptr;
357
358 let buffer_ref = &mut buffer_ptr as *mut _ as *mut gst::ffi::GstBuffer;
361
362 let instance_data = self.instance_data::<InstanceData>(BaseSrc::static_type()).unwrap();
363
364 if let Err(err) = gst::FlowSuccess::try_from_glib(
365 f(
366 instance.to_glib_none().0,
367 offset,
368 length,
369 buffer_ref,
370 )
371 ) {
372 *instance_data.pending_buffer_list.borrow_mut() = None;
373 return Err(err);
374 }
375
376 let pending_buffer_list = instance_data.pending_buffer_list.borrow_mut().take();
377 if pending_buffer_list.is_some() &&
378 (buffer.is_some() || instance.src_pad().mode() == gst::PadMode::Pull) {
379 panic!("Buffer lists can only be returned in push mode");
380 }
381
382 if buffer_ptr.is_null() && pending_buffer_list.is_none() {
383 gst::error!(
384 gst::CAT_RUST,
385 obj = instance,
386 "No buffer and no buffer list returned"
387 );
388 return Err(gst::FlowError::Error);
389 }
390
391 if !buffer_ptr.is_null() && pending_buffer_list.is_some() {
392 gst::error!(
393 gst::CAT_RUST,
394 obj = instance,
395 "Both buffer and buffer list returned"
396 );
397 return Err(gst::FlowError::Error);
398 }
399
400 if let Some(passed_buffer) = buffer {
401 if buffer_ptr != orig_buffer_ptr {
402 let new_buffer = gst::Buffer::from_glib_full(buffer_ptr);
403
404 gst::debug!(
405 gst::CAT_PERFORMANCE,
406 obj = instance,
407 "Returned new buffer from parent create function, copying into passed buffer"
408 );
409
410 let mut map = match passed_buffer.map_writable() {
411 Ok(map) => map,
412 Err(_) => {
413 gst::error!(
414 gst::CAT_RUST,
415 obj = instance,
416 "Failed to map passed buffer writable"
417 );
418 return Err(gst::FlowError::Error);
419 }
420 };
421
422 let copied_size = new_buffer.copy_to_slice(0, &mut map);
423 drop(map);
424
425 if let Err(copied_size) = copied_size {
426 passed_buffer.set_size(copied_size);
427 }
428
429 match new_buffer.copy_into(passed_buffer, gst::BUFFER_COPY_METADATA, ..) {
430 Ok(_) => Ok(CreateSuccess::FilledBuffer),
431 Err(_) => {
432 gst::error!(
433 gst::CAT_RUST,
434 obj = instance,
435 "Failed to copy buffer metadata"
436 );
437
438 Err(gst::FlowError::Error)
439 }
440 }
441 } else {
442 Ok(CreateSuccess::FilledBuffer)
443 }
444 } else if let Some(buffer_list) = pending_buffer_list {
445 Ok(CreateSuccess::NewBufferList(buffer_list))
446 } else {
447 Ok(CreateSuccess::NewBuffer(from_glib_full(buffer_ptr)))
448 }
449 })
450 .unwrap_or(Err(gst::FlowError::NotSupported))
451 }
452 }
453
454 fn parent_do_seek(&self, segment: &mut gst::Segment) -> bool {
455 unsafe {
456 let data = Self::type_data();
457 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
458 (*parent_class)
459 .do_seek
460 .map(|f| {
461 from_glib(f(
462 self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0,
463 segment.to_glib_none_mut().0,
464 ))
465 })
466 .unwrap_or(false)
467 }
468 }
469
470 fn parent_query(&self, query: &mut gst::QueryRef) -> bool {
471 unsafe {
472 let data = Self::type_data();
473 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
474 (*parent_class)
475 .query
476 .map(|f| {
477 from_glib(f(
478 self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0,
479 query.as_mut_ptr(),
480 ))
481 })
482 .unwrap_or(false)
483 }
484 }
485
486 fn parent_event(&self, event: &gst::Event) -> bool {
487 unsafe {
488 let data = Self::type_data();
489 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
490 (*parent_class)
491 .event
492 .map(|f| {
493 from_glib(f(
494 self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0,
495 event.to_glib_none().0,
496 ))
497 })
498 .unwrap_or(false)
499 }
500 }
501
502 fn parent_caps(&self, filter: Option<&gst::Caps>) -> Option<gst::Caps> {
503 unsafe {
504 let data = Self::type_data();
505 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
506
507 (*parent_class)
508 .get_caps
509 .map(|f| {
510 from_glib_full(f(
511 self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0,
512 filter.to_glib_none().0,
513 ))
514 })
515 .unwrap_or(None)
516 }
517 }
518
519 fn parent_negotiate(&self) -> Result<(), gst::LoggableError> {
520 unsafe {
521 let data = Self::type_data();
522 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
523 (*parent_class)
524 .negotiate
525 .map(|f| {
526 gst::result_from_gboolean!(
527 f(self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0),
528 gst::CAT_RUST,
529 "Parent function `negotiate` failed"
530 )
531 })
532 .unwrap_or(Ok(()))
533 }
534 }
535
536 fn parent_set_caps(&self, caps: &gst::Caps) -> Result<(), gst::LoggableError> {
537 unsafe {
538 let data = Self::type_data();
539 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
540 (*parent_class)
541 .set_caps
542 .map(|f| {
543 gst::result_from_gboolean!(
544 f(
545 self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0,
546 caps.to_glib_none().0
547 ),
548 gst::CAT_RUST,
549 "Parent function `set_caps` failed"
550 )
551 })
552 .unwrap_or(Ok(()))
553 }
554 }
555
556 fn parent_fixate(&self, caps: gst::Caps) -> gst::Caps {
557 unsafe {
558 let data = Self::type_data();
559 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
560
561 match (*parent_class).fixate {
562 Some(fixate) => from_glib_full(fixate(
563 self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0,
564 caps.into_glib_ptr(),
565 )),
566 None => caps,
567 }
568 }
569 }
570
571 fn parent_unlock(&self) -> Result<(), gst::ErrorMessage> {
572 unsafe {
573 let data = Self::type_data();
574 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
575 (*parent_class)
576 .unlock
577 .map(|f| {
578 if from_glib(f(self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0)) {
579 Ok(())
580 } else {
581 Err(gst::error_msg!(
582 gst::CoreError::Failed,
583 ["Parent function `unlock` failed"]
584 ))
585 }
586 })
587 .unwrap_or(Ok(()))
588 }
589 }
590
591 fn parent_unlock_stop(&self) -> Result<(), gst::ErrorMessage> {
592 unsafe {
593 let data = Self::type_data();
594 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
595 (*parent_class)
596 .unlock_stop
597 .map(|f| {
598 if from_glib(f(self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0)) {
599 Ok(())
600 } else {
601 Err(gst::error_msg!(
602 gst::CoreError::Failed,
603 ["Parent function `unlock_stop` failed"]
604 ))
605 }
606 })
607 .unwrap_or(Ok(()))
608 }
609 }
610
611 fn parent_decide_allocation(
612 &self,
613 query: &mut gst::query::Allocation,
614 ) -> Result<(), gst::LoggableError> {
615 unsafe {
616 let data = Self::type_data();
617 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
618 (*parent_class)
619 .decide_allocation
620 .map(|f| {
621 gst::result_from_gboolean!(
622 f(
623 self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0,
624 query.as_mut_ptr(),
625 ),
626 gst::CAT_RUST,
627 "Parent function `decide_allocation` failed",
628 )
629 })
630 .unwrap_or(Ok(()))
631 }
632 }
633
634 #[cfg(feature = "v1_30")]
635 #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
636 fn parent_prepare_allocator(&self, caps: Option<&gst::Caps>) -> Result<(), gst::LoggableError> {
637 unsafe {
638 let data = Self::type_data();
639 let parent_class = data.as_ref().parent_class() as *mut ffi::GstBaseSrcClass;
640 (*parent_class)
641 .prepare_allocator
642 .map(|f| {
643 gst::result_from_gboolean!(
644 f(
645 self.obj().unsafe_cast_ref::<BaseSrc>().to_glib_none().0,
646 caps.to_glib_none().0
647 ),
648 gst::CAT_RUST,
649 "Parent function `prepare_allocator` failed",
650 )
651 })
652 .unwrap_or(Ok(()))
653 }
654 }
655}
656
657impl<T: BaseSrcImpl> BaseSrcImplExt for T {}
658
659unsafe impl<T: BaseSrcImpl> IsSubclassable<T> for BaseSrc {
660 fn class_init(klass: &mut glib::Class<Self>) {
661 Self::parent_class_init::<T>(klass);
662 let klass = klass.as_mut();
663 klass.start = Some(base_src_start::<T>);
664 klass.stop = Some(base_src_stop::<T>);
665 klass.is_seekable = Some(base_src_is_seekable::<T>);
666 klass.get_size = Some(base_src_get_size::<T>);
667 klass.get_times = Some(base_src_get_times::<T>);
668 klass.fill = Some(base_src_fill::<T>);
669 klass.alloc = Some(base_src_alloc::<T>);
670 klass.create = Some(base_src_create::<T>);
671 klass.do_seek = Some(base_src_do_seek::<T>);
672 klass.query = Some(base_src_query::<T>);
673 klass.event = Some(base_src_event::<T>);
674 klass.get_caps = Some(base_src_get_caps::<T>);
675 klass.negotiate = Some(base_src_negotiate::<T>);
676 klass.set_caps = Some(base_src_set_caps::<T>);
677 klass.fixate = Some(base_src_fixate::<T>);
678 klass.unlock = Some(base_src_unlock::<T>);
679 klass.unlock_stop = Some(base_src_unlock_stop::<T>);
680 klass.decide_allocation = Some(base_src_decide_allocation::<T>);
681 #[cfg(feature = "v1_30")]
682 {
683 klass.prepare_allocator = Some(base_src_prepare_allocator::<T>);
684 }
685 }
686
687 fn instance_init(instance: &mut glib::subclass::InitializingObject<T>) {
688 Self::parent_instance_init(instance);
689
690 instance.set_instance_data(BaseSrc::static_type(), InstanceData::default());
691 }
692}
693
694unsafe extern "C" fn base_src_start<T: BaseSrcImpl>(
695 ptr: *mut ffi::GstBaseSrc,
696) -> glib::ffi::gboolean {
697 unsafe {
698 let instance = &*(ptr as *mut T::Instance);
699 let imp = instance.imp();
700
701 gst::element_panic_to_error!(imp, false, {
702 match imp.start() {
703 Ok(()) => true,
704 Err(err) => {
705 imp.post_error_message(err);
706 false
707 }
708 }
709 })
710 .into_glib()
711 }
712}
713
714unsafe extern "C" fn base_src_stop<T: BaseSrcImpl>(
715 ptr: *mut ffi::GstBaseSrc,
716) -> glib::ffi::gboolean {
717 unsafe {
718 let instance = &*(ptr as *mut T::Instance);
719 let imp = instance.imp();
720
721 gst::element_panic_to_error!(imp, false, {
722 match imp.stop() {
723 Ok(()) => true,
724 Err(err) => {
725 imp.post_error_message(err);
726 false
727 }
728 }
729 })
730 .into_glib()
731 }
732}
733
734unsafe extern "C" fn base_src_is_seekable<T: BaseSrcImpl>(
735 ptr: *mut ffi::GstBaseSrc,
736) -> glib::ffi::gboolean {
737 unsafe {
738 let instance = &*(ptr as *mut T::Instance);
739 let imp = instance.imp();
740
741 gst::element_panic_to_error!(imp, false, { imp.is_seekable() }).into_glib()
742 }
743}
744
745unsafe extern "C" fn base_src_get_size<T: BaseSrcImpl>(
746 ptr: *mut ffi::GstBaseSrc,
747 size: *mut u64,
748) -> glib::ffi::gboolean {
749 unsafe {
750 let instance = &*(ptr as *mut T::Instance);
751 let imp = instance.imp();
752
753 gst::element_panic_to_error!(imp, false, {
754 match imp.size() {
755 Some(s) => {
756 *size = s;
757 true
758 }
759 None => false,
760 }
761 })
762 .into_glib()
763 }
764}
765
766unsafe extern "C" fn base_src_get_times<T: BaseSrcImpl>(
767 ptr: *mut ffi::GstBaseSrc,
768 buffer: *mut gst::ffi::GstBuffer,
769 start: *mut gst::ffi::GstClockTime,
770 stop: *mut gst::ffi::GstClockTime,
771) {
772 unsafe {
773 let instance = &*(ptr as *mut T::Instance);
774 let imp = instance.imp();
775 let buffer = gst::BufferRef::from_ptr(buffer);
776
777 *start = gst::ffi::GST_CLOCK_TIME_NONE;
778 *stop = gst::ffi::GST_CLOCK_TIME_NONE;
779
780 gst::element_panic_to_error!(imp, (), {
781 let (start_, stop_) = imp.times(buffer);
782 *start = start_.into_glib();
783 *stop = stop_.into_glib();
784 });
785 }
786}
787
788unsafe extern "C" fn base_src_fill<T: BaseSrcImpl>(
789 ptr: *mut ffi::GstBaseSrc,
790 offset: u64,
791 length: u32,
792 buffer: *mut gst::ffi::GstBuffer,
793) -> gst::ffi::GstFlowReturn {
794 unsafe {
795 let instance = &*(ptr as *mut T::Instance);
796 let imp = instance.imp();
797 let buffer = gst::BufferRef::from_mut_ptr(buffer);
798
799 gst::element_panic_to_error!(imp, gst::FlowReturn::Error, {
800 imp.fill(offset, length, buffer).into()
801 })
802 .into_glib()
803 }
804}
805
806unsafe extern "C" fn base_src_alloc<T: BaseSrcImpl>(
807 ptr: *mut ffi::GstBaseSrc,
808 offset: u64,
809 length: u32,
810 buffer_ptr: *mut gst::ffi::GstBuffer,
811) -> gst::ffi::GstFlowReturn {
812 unsafe {
813 let instance = &*(ptr as *mut T::Instance);
814 let imp = instance.imp();
815 let buffer_ptr = buffer_ptr as *mut *mut gst::ffi::GstBuffer;
818
819 gst::element_panic_to_error!(imp, gst::FlowReturn::Error, {
820 match imp.alloc(offset, length) {
821 Ok(buffer) => {
822 *buffer_ptr = buffer.into_glib_ptr();
823 gst::FlowReturn::Ok
824 }
825 Err(err) => gst::FlowReturn::from(err),
826 }
827 })
828 .into_glib()
829 }
830}
831
832#[allow(clippy::needless_option_as_deref)]
833unsafe extern "C" fn base_src_create<T: BaseSrcImpl>(
834 ptr: *mut ffi::GstBaseSrc,
835 offset: u64,
836 length: u32,
837 buffer_ptr: *mut gst::ffi::GstBuffer,
838) -> gst::ffi::GstFlowReturn {
839 unsafe {
840 let instance = &*(ptr as *mut T::Instance);
841 let imp = instance.imp();
842 let instance = imp.obj();
843 let instance = instance.unsafe_cast_ref::<BaseSrc>();
844 let buffer_ptr = buffer_ptr as *mut *mut gst::ffi::GstBuffer;
847
848 let mut buffer = if (*buffer_ptr).is_null() {
849 None
850 } else {
851 Some(gst::BufferRef::from_mut_ptr(*buffer_ptr))
852 };
853
854 let instance_data = imp
855 .instance_data::<InstanceData>(BaseSrc::static_type())
856 .unwrap();
857
858 if instance.type_() == T::Type::static_type() {
860 *instance_data.pending_buffer_list.borrow_mut() = None;
861 }
862
863 let res = gst::element_panic_to_error!(imp, gst::FlowReturn::Error, {
864 match imp.create(offset, buffer.as_deref_mut(), length) {
865 Ok(CreateSuccess::NewBuffer(new_buffer)) => {
866 if let Some(passed_buffer) = buffer {
867 if passed_buffer.as_ptr() != new_buffer.as_ptr() {
868 gst::debug!(
869 gst::CAT_PERFORMANCE,
870 obj = instance,
871 "Returned new buffer from create function, copying into passed buffer"
872 );
873
874 let mut map = match passed_buffer.map_writable() {
875 Ok(map) => map,
876 Err(_) => {
877 gst::error!(
878 gst::CAT_RUST,
879 obj = instance,
880 "Failed to map passed buffer writable"
881 );
882 return gst::FlowReturn::Error;
883 }
884 };
885
886 let copied_size = new_buffer.copy_to_slice(0, &mut map);
887 drop(map);
888
889 if let Err(copied_size) = copied_size {
890 passed_buffer.set_size(copied_size);
891 }
892
893 match new_buffer.copy_into(passed_buffer, gst::BUFFER_COPY_METADATA, ..)
894 {
895 Ok(_) => gst::FlowReturn::Ok,
896 Err(_) => {
897 gst::error!(
898 gst::CAT_RUST,
899 obj = instance,
900 "Failed to copy buffer metadata"
901 );
902
903 gst::FlowReturn::Error
904 }
905 }
906 } else {
907 gst::FlowReturn::Ok
908 }
909 } else {
910 *buffer_ptr = new_buffer.into_glib_ptr();
911 gst::FlowReturn::Ok
912 }
913 }
914 Ok(CreateSuccess::NewBufferList(new_buffer_list)) => {
915 if buffer.is_some() || instance.src_pad().mode() == gst::PadMode::Pull {
916 panic!("Buffer lists can only be returned in push mode");
917 }
918
919 *buffer_ptr = ptr::null_mut();
920
921 if instance.type_() == T::Type::static_type() {
925 ffi::gst_base_src_submit_buffer_list(
926 instance.to_glib_none().0,
927 new_buffer_list.into_glib_ptr(),
928 );
929 } else {
930 *instance_data.pending_buffer_list.borrow_mut() = Some(new_buffer_list);
931 }
932
933 gst::FlowReturn::Ok
934 }
935 Ok(CreateSuccess::FilledBuffer) => gst::FlowReturn::Ok,
936 Err(err) => gst::FlowReturn::from(err),
937 }
938 })
939 .into_glib();
940
941 if instance.type_() == T::Type::static_type() {
943 *instance_data.pending_buffer_list.borrow_mut() = None;
944 }
945
946 res
947 }
948}
949
950unsafe extern "C" fn base_src_do_seek<T: BaseSrcImpl>(
951 ptr: *mut ffi::GstBaseSrc,
952 segment: *mut gst::ffi::GstSegment,
953) -> glib::ffi::gboolean {
954 unsafe {
955 let instance = &*(ptr as *mut T::Instance);
956 let imp = instance.imp();
957
958 gst::element_panic_to_error!(imp, false, {
959 let mut s = from_glib_none(segment);
960 let res = imp.do_seek(&mut s);
961 ptr::write(segment, *(s.to_glib_none().0));
962
963 res
964 })
965 .into_glib()
966 }
967}
968
969unsafe extern "C" fn base_src_query<T: BaseSrcImpl>(
970 ptr: *mut ffi::GstBaseSrc,
971 query_ptr: *mut gst::ffi::GstQuery,
972) -> glib::ffi::gboolean {
973 unsafe {
974 let instance = &*(ptr as *mut T::Instance);
975 let imp = instance.imp();
976 let query = gst::QueryRef::from_mut_ptr(query_ptr);
977
978 gst::element_panic_to_error!(imp, false, { BaseSrcImpl::query(imp, query) }).into_glib()
979 }
980}
981
982unsafe extern "C" fn base_src_event<T: BaseSrcImpl>(
983 ptr: *mut ffi::GstBaseSrc,
984 event_ptr: *mut gst::ffi::GstEvent,
985) -> glib::ffi::gboolean {
986 unsafe {
987 let instance = &*(ptr as *mut T::Instance);
988 let imp = instance.imp();
989
990 gst::element_panic_to_error!(imp, false, { imp.event(&from_glib_borrow(event_ptr)) })
991 .into_glib()
992 }
993}
994
995unsafe extern "C" fn base_src_get_caps<T: BaseSrcImpl>(
996 ptr: *mut ffi::GstBaseSrc,
997 filter: *mut gst::ffi::GstCaps,
998) -> *mut gst::ffi::GstCaps {
999 unsafe {
1000 let instance = &*(ptr as *mut T::Instance);
1001 let imp = instance.imp();
1002 let filter = Option::<gst::Caps>::from_glib_borrow(filter);
1003
1004 gst::element_panic_to_error!(imp, None, { imp.caps(filter.as_ref().as_ref()) })
1005 .map(|caps| caps.into_glib_ptr())
1006 .unwrap_or(ptr::null_mut())
1007 }
1008}
1009
1010unsafe extern "C" fn base_src_negotiate<T: BaseSrcImpl>(
1011 ptr: *mut ffi::GstBaseSrc,
1012) -> glib::ffi::gboolean {
1013 unsafe {
1014 let instance = &*(ptr as *mut T::Instance);
1015 let imp = instance.imp();
1016
1017 gst::element_panic_to_error!(imp, false, {
1018 match imp.negotiate() {
1019 Ok(()) => true,
1020 Err(err) => {
1021 err.log_with_imp(imp);
1022 false
1023 }
1024 }
1025 })
1026 .into_glib()
1027 }
1028}
1029
1030unsafe extern "C" fn base_src_set_caps<T: BaseSrcImpl>(
1031 ptr: *mut ffi::GstBaseSrc,
1032 caps: *mut gst::ffi::GstCaps,
1033) -> glib::ffi::gboolean {
1034 unsafe {
1035 let instance = &*(ptr as *mut T::Instance);
1036 let imp = instance.imp();
1037 let caps = from_glib_borrow(caps);
1038
1039 gst::element_panic_to_error!(imp, false, {
1040 match imp.set_caps(&caps) {
1041 Ok(()) => true,
1042 Err(err) => {
1043 err.log_with_imp(imp);
1044 false
1045 }
1046 }
1047 })
1048 .into_glib()
1049 }
1050}
1051
1052unsafe extern "C" fn base_src_fixate<T: BaseSrcImpl>(
1053 ptr: *mut ffi::GstBaseSrc,
1054 caps: *mut gst::ffi::GstCaps,
1055) -> *mut gst::ffi::GstCaps {
1056 unsafe {
1057 let instance = &*(ptr as *mut T::Instance);
1058 let imp = instance.imp();
1059 let caps = from_glib_full(caps);
1060
1061 gst::element_panic_to_error!(imp, gst::Caps::new_empty(), { imp.fixate(caps) })
1062 .into_glib_ptr()
1063 }
1064}
1065
1066unsafe extern "C" fn base_src_unlock<T: BaseSrcImpl>(
1067 ptr: *mut ffi::GstBaseSrc,
1068) -> glib::ffi::gboolean {
1069 unsafe {
1070 let instance = &*(ptr as *mut T::Instance);
1071 let imp = instance.imp();
1072
1073 gst::element_panic_to_error!(imp, false, {
1074 match imp.unlock() {
1075 Ok(()) => true,
1076 Err(err) => {
1077 imp.post_error_message(err);
1078 false
1079 }
1080 }
1081 })
1082 .into_glib()
1083 }
1084}
1085
1086unsafe extern "C" fn base_src_unlock_stop<T: BaseSrcImpl>(
1087 ptr: *mut ffi::GstBaseSrc,
1088) -> glib::ffi::gboolean {
1089 unsafe {
1090 let instance = &*(ptr as *mut T::Instance);
1091 let imp = instance.imp();
1092
1093 gst::element_panic_to_error!(imp, false, {
1094 match imp.unlock_stop() {
1095 Ok(()) => true,
1096 Err(err) => {
1097 imp.post_error_message(err);
1098 false
1099 }
1100 }
1101 })
1102 .into_glib()
1103 }
1104}
1105
1106unsafe extern "C" fn base_src_decide_allocation<T: BaseSrcImpl>(
1107 ptr: *mut ffi::GstBaseSrc,
1108 query: *mut gst::ffi::GstQuery,
1109) -> glib::ffi::gboolean {
1110 unsafe {
1111 let instance = &*(ptr as *mut T::Instance);
1112 let imp = instance.imp();
1113 let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
1114 gst::QueryViewMut::Allocation(allocation) => allocation,
1115 _ => unreachable!(),
1116 };
1117
1118 gst::element_panic_to_error!(imp, false, {
1119 match imp.decide_allocation(query) {
1120 Ok(()) => true,
1121 Err(err) => {
1122 err.log_with_imp(imp);
1123 false
1124 }
1125 }
1126 })
1127 .into_glib()
1128 }
1129}
1130
1131#[cfg(feature = "v1_30")]
1132#[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
1133unsafe extern "C" fn base_src_prepare_allocator<T: BaseSrcImpl>(
1134 ptr: *mut ffi::GstBaseSrc,
1135 caps: *mut gst::ffi::GstCaps,
1136) -> glib::ffi::gboolean {
1137 unsafe {
1138 let instance = &*(ptr as *mut T::Instance);
1139 let imp = instance.imp();
1140 let caps = Option::<gst::Caps>::from_glib_none(caps);
1141
1142 gst::element_panic_to_error!(imp, false, {
1143 match imp.prepare_allocator(caps.as_ref()) {
1144 Ok(()) => true,
1145 Err(err) => {
1146 err.log_with_imp(imp);
1147 false
1148 }
1149 }
1150 })
1151 .into_glib()
1152 }
1153}