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