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