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