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