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
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 unsafe {
593 let instance = &*(ptr as *mut T::Instance);
594 let imp = instance.imp();
595
596 gst::panic_to_error!(imp, false, {
597 match imp.start() {
598 Ok(()) => true,
599 Err(err) => {
600 imp.post_error_message(err);
601 false
602 }
603 }
604 })
605 .into_glib()
606 }
607}
608
609unsafe extern "C" fn base_src_stop<T: BaseSrcImpl>(
610 ptr: *mut ffi::GstBaseSrc,
611) -> glib::ffi::gboolean {
612 unsafe {
613 let instance = &*(ptr as *mut T::Instance);
614 let imp = instance.imp();
615
616 gst::panic_to_error!(imp, false, {
617 match imp.stop() {
618 Ok(()) => true,
619 Err(err) => {
620 imp.post_error_message(err);
621 false
622 }
623 }
624 })
625 .into_glib()
626 }
627}
628
629unsafe extern "C" fn base_src_is_seekable<T: BaseSrcImpl>(
630 ptr: *mut ffi::GstBaseSrc,
631) -> glib::ffi::gboolean {
632 unsafe {
633 let instance = &*(ptr as *mut T::Instance);
634 let imp = instance.imp();
635
636 gst::panic_to_error!(imp, false, { imp.is_seekable() }).into_glib()
637 }
638}
639
640unsafe extern "C" fn base_src_get_size<T: BaseSrcImpl>(
641 ptr: *mut ffi::GstBaseSrc,
642 size: *mut u64,
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.size() {
650 Some(s) => {
651 *size = s;
652 true
653 }
654 None => false,
655 }
656 })
657 .into_glib()
658 }
659}
660
661unsafe extern "C" fn base_src_get_times<T: BaseSrcImpl>(
662 ptr: *mut ffi::GstBaseSrc,
663 buffer: *mut gst::ffi::GstBuffer,
664 start: *mut gst::ffi::GstClockTime,
665 stop: *mut gst::ffi::GstClockTime,
666) {
667 unsafe {
668 let instance = &*(ptr as *mut T::Instance);
669 let imp = instance.imp();
670 let buffer = gst::BufferRef::from_ptr(buffer);
671
672 *start = gst::ffi::GST_CLOCK_TIME_NONE;
673 *stop = gst::ffi::GST_CLOCK_TIME_NONE;
674
675 gst::panic_to_error!(imp, (), {
676 let (start_, stop_) = imp.times(buffer);
677 *start = start_.into_glib();
678 *stop = stop_.into_glib();
679 });
680 }
681}
682
683unsafe extern "C" fn base_src_fill<T: BaseSrcImpl>(
684 ptr: *mut ffi::GstBaseSrc,
685 offset: u64,
686 length: u32,
687 buffer: *mut gst::ffi::GstBuffer,
688) -> gst::ffi::GstFlowReturn {
689 unsafe {
690 let instance = &*(ptr as *mut T::Instance);
691 let imp = instance.imp();
692 let buffer = gst::BufferRef::from_mut_ptr(buffer);
693
694 gst::panic_to_error!(imp, gst::FlowReturn::Error, {
695 imp.fill(offset, length, buffer).into()
696 })
697 .into_glib()
698 }
699}
700
701unsafe extern "C" fn base_src_alloc<T: BaseSrcImpl>(
702 ptr: *mut ffi::GstBaseSrc,
703 offset: u64,
704 length: u32,
705 buffer_ptr: *mut gst::ffi::GstBuffer,
706) -> gst::ffi::GstFlowReturn {
707 unsafe {
708 let instance = &*(ptr as *mut T::Instance);
709 let imp = instance.imp();
710 let buffer_ptr = buffer_ptr as *mut *mut gst::ffi::GstBuffer;
713
714 gst::panic_to_error!(imp, gst::FlowReturn::Error, {
715 match imp.alloc(offset, length) {
716 Ok(buffer) => {
717 *buffer_ptr = buffer.into_glib_ptr();
718 gst::FlowReturn::Ok
719 }
720 Err(err) => gst::FlowReturn::from(err),
721 }
722 })
723 .into_glib()
724 }
725}
726
727#[allow(clippy::needless_option_as_deref)]
728unsafe extern "C" fn base_src_create<T: BaseSrcImpl>(
729 ptr: *mut ffi::GstBaseSrc,
730 offset: u64,
731 length: u32,
732 buffer_ptr: *mut gst::ffi::GstBuffer,
733) -> gst::ffi::GstFlowReturn {
734 unsafe {
735 let instance = &*(ptr as *mut T::Instance);
736 let imp = instance.imp();
737 let instance = imp.obj();
738 let instance = instance.unsafe_cast_ref::<BaseSrc>();
739 let buffer_ptr = buffer_ptr as *mut *mut gst::ffi::GstBuffer;
742
743 let mut buffer = if (*buffer_ptr).is_null() {
744 None
745 } else {
746 Some(gst::BufferRef::from_mut_ptr(*buffer_ptr))
747 };
748
749 let instance_data = imp
750 .instance_data::<InstanceData>(BaseSrc::static_type())
751 .unwrap();
752
753 if instance.type_() == T::Type::static_type() {
755 *instance_data.pending_buffer_list.borrow_mut() = None;
756 }
757
758 let res = gst::panic_to_error!(imp, gst::FlowReturn::Error, {
759 match imp.create(offset, buffer.as_deref_mut(), length) {
760 Ok(CreateSuccess::NewBuffer(new_buffer)) => {
761 if let Some(passed_buffer) = buffer {
762 if passed_buffer.as_ptr() != new_buffer.as_ptr() {
763 gst::debug!(
764 gst::CAT_PERFORMANCE,
765 obj = instance,
766 "Returned new buffer from create function, copying into passed buffer"
767 );
768
769 let mut map = match passed_buffer.map_writable() {
770 Ok(map) => map,
771 Err(_) => {
772 gst::error!(
773 gst::CAT_RUST,
774 obj = instance,
775 "Failed to map passed buffer writable"
776 );
777 return gst::FlowReturn::Error;
778 }
779 };
780
781 let copied_size = new_buffer.copy_to_slice(0, &mut map);
782 drop(map);
783
784 if let Err(copied_size) = copied_size {
785 passed_buffer.set_size(copied_size);
786 }
787
788 match new_buffer.copy_into(passed_buffer, gst::BUFFER_COPY_METADATA, ..)
789 {
790 Ok(_) => gst::FlowReturn::Ok,
791 Err(_) => {
792 gst::error!(
793 gst::CAT_RUST,
794 obj = instance,
795 "Failed to copy buffer metadata"
796 );
797
798 gst::FlowReturn::Error
799 }
800 }
801 } else {
802 gst::FlowReturn::Ok
803 }
804 } else {
805 *buffer_ptr = new_buffer.into_glib_ptr();
806 gst::FlowReturn::Ok
807 }
808 }
809 Ok(CreateSuccess::NewBufferList(new_buffer_list)) => {
810 if buffer.is_some() || instance.src_pad().mode() == gst::PadMode::Pull {
811 panic!("Buffer lists can only be returned in push mode");
812 }
813
814 *buffer_ptr = ptr::null_mut();
815
816 if instance.type_() == T::Type::static_type() {
820 ffi::gst_base_src_submit_buffer_list(
821 instance.to_glib_none().0,
822 new_buffer_list.into_glib_ptr(),
823 );
824 } else {
825 *instance_data.pending_buffer_list.borrow_mut() = Some(new_buffer_list);
826 }
827
828 gst::FlowReturn::Ok
829 }
830 Ok(CreateSuccess::FilledBuffer) => gst::FlowReturn::Ok,
831 Err(err) => gst::FlowReturn::from(err),
832 }
833 })
834 .into_glib();
835
836 if instance.type_() == T::Type::static_type() {
838 *instance_data.pending_buffer_list.borrow_mut() = None;
839 }
840
841 res
842 }
843}
844
845unsafe extern "C" fn base_src_do_seek<T: BaseSrcImpl>(
846 ptr: *mut ffi::GstBaseSrc,
847 segment: *mut gst::ffi::GstSegment,
848) -> glib::ffi::gboolean {
849 unsafe {
850 let instance = &*(ptr as *mut T::Instance);
851 let imp = instance.imp();
852
853 gst::panic_to_error!(imp, false, {
854 let mut s = from_glib_none(segment);
855 let res = imp.do_seek(&mut s);
856 ptr::write(segment, *(s.to_glib_none().0));
857
858 res
859 })
860 .into_glib()
861 }
862}
863
864unsafe extern "C" fn base_src_query<T: BaseSrcImpl>(
865 ptr: *mut ffi::GstBaseSrc,
866 query_ptr: *mut gst::ffi::GstQuery,
867) -> glib::ffi::gboolean {
868 unsafe {
869 let instance = &*(ptr as *mut T::Instance);
870 let imp = instance.imp();
871 let query = gst::QueryRef::from_mut_ptr(query_ptr);
872
873 gst::panic_to_error!(imp, false, { BaseSrcImpl::query(imp, query) }).into_glib()
874 }
875}
876
877unsafe extern "C" fn base_src_event<T: BaseSrcImpl>(
878 ptr: *mut ffi::GstBaseSrc,
879 event_ptr: *mut gst::ffi::GstEvent,
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, { imp.event(&from_glib_borrow(event_ptr)) }).into_glib()
886 }
887}
888
889unsafe extern "C" fn base_src_get_caps<T: BaseSrcImpl>(
890 ptr: *mut ffi::GstBaseSrc,
891 filter: *mut gst::ffi::GstCaps,
892) -> *mut gst::ffi::GstCaps {
893 unsafe {
894 let instance = &*(ptr as *mut T::Instance);
895 let imp = instance.imp();
896 let filter = Option::<gst::Caps>::from_glib_borrow(filter);
897
898 gst::panic_to_error!(imp, None, { imp.caps(filter.as_ref().as_ref()) })
899 .map(|caps| caps.into_glib_ptr())
900 .unwrap_or(ptr::null_mut())
901 }
902}
903
904unsafe extern "C" fn base_src_negotiate<T: BaseSrcImpl>(
905 ptr: *mut ffi::GstBaseSrc,
906) -> glib::ffi::gboolean {
907 unsafe {
908 let instance = &*(ptr as *mut T::Instance);
909 let imp = instance.imp();
910
911 gst::panic_to_error!(imp, false, {
912 match imp.negotiate() {
913 Ok(()) => true,
914 Err(err) => {
915 err.log_with_imp(imp);
916 false
917 }
918 }
919 })
920 .into_glib()
921 }
922}
923
924unsafe extern "C" fn base_src_set_caps<T: BaseSrcImpl>(
925 ptr: *mut ffi::GstBaseSrc,
926 caps: *mut gst::ffi::GstCaps,
927) -> glib::ffi::gboolean {
928 unsafe {
929 let instance = &*(ptr as *mut T::Instance);
930 let imp = instance.imp();
931 let caps = from_glib_borrow(caps);
932
933 gst::panic_to_error!(imp, false, {
934 match imp.set_caps(&caps) {
935 Ok(()) => true,
936 Err(err) => {
937 err.log_with_imp(imp);
938 false
939 }
940 }
941 })
942 .into_glib()
943 }
944}
945
946unsafe extern "C" fn base_src_fixate<T: BaseSrcImpl>(
947 ptr: *mut ffi::GstBaseSrc,
948 caps: *mut gst::ffi::GstCaps,
949) -> *mut gst::ffi::GstCaps {
950 unsafe {
951 let instance = &*(ptr as *mut T::Instance);
952 let imp = instance.imp();
953 let caps = from_glib_full(caps);
954
955 gst::panic_to_error!(imp, gst::Caps::new_empty(), { imp.fixate(caps) }).into_glib_ptr()
956 }
957}
958
959unsafe extern "C" fn base_src_unlock<T: BaseSrcImpl>(
960 ptr: *mut ffi::GstBaseSrc,
961) -> glib::ffi::gboolean {
962 unsafe {
963 let instance = &*(ptr as *mut T::Instance);
964 let imp = instance.imp();
965
966 gst::panic_to_error!(imp, false, {
967 match imp.unlock() {
968 Ok(()) => true,
969 Err(err) => {
970 imp.post_error_message(err);
971 false
972 }
973 }
974 })
975 .into_glib()
976 }
977}
978
979unsafe extern "C" fn base_src_unlock_stop<T: BaseSrcImpl>(
980 ptr: *mut ffi::GstBaseSrc,
981) -> glib::ffi::gboolean {
982 unsafe {
983 let instance = &*(ptr as *mut T::Instance);
984 let imp = instance.imp();
985
986 gst::panic_to_error!(imp, false, {
987 match imp.unlock_stop() {
988 Ok(()) => true,
989 Err(err) => {
990 imp.post_error_message(err);
991 false
992 }
993 }
994 })
995 .into_glib()
996 }
997}
998
999unsafe extern "C" fn base_src_decide_allocation<T: BaseSrcImpl>(
1000 ptr: *mut ffi::GstBaseSrc,
1001 query: *mut gst::ffi::GstQuery,
1002) -> glib::ffi::gboolean {
1003 unsafe {
1004 let instance = &*(ptr as *mut T::Instance);
1005 let imp = instance.imp();
1006 let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
1007 gst::QueryViewMut::Allocation(allocation) => allocation,
1008 _ => unreachable!(),
1009 };
1010
1011 gst::panic_to_error!(imp, false, {
1012 match imp.decide_allocation(query) {
1013 Ok(()) => true,
1014 Err(err) => {
1015 err.log_with_imp(imp);
1016 false
1017 }
1018 }
1019 })
1020 .into_glib()
1021 }
1022}