forked from mirrors/gstreamer-rs
gstreamer/pad: Add support for filling the passed in buffer in the getrange function
Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/issues/242
This commit is contained in:
parent
7c2f3bafa0
commit
d7e6c2e37f
2 changed files with 90 additions and 7 deletions
|
@ -238,7 +238,7 @@ pub use enums::{
|
||||||
StateChangeError, StateChangeSuccess, TagError,
|
StateChangeError, StateChangeSuccess, TagError,
|
||||||
};
|
};
|
||||||
pub use gobject::GObjectExtManualGst;
|
pub use gobject::GObjectExtManualGst;
|
||||||
pub use pad::{PadExtManual, PadProbeData, PadProbeId, PadProbeInfo};
|
pub use pad::{PadExtManual, PadGetRangeSuccess, PadProbeData, PadProbeId, PadProbeInfo};
|
||||||
pub use parse_context::ParseContext;
|
pub use parse_context::ParseContext;
|
||||||
mod plugin_feature;
|
mod plugin_feature;
|
||||||
pub use plugin_feature::PluginFeatureExtManual;
|
pub use plugin_feature::PluginFeatureExtManual;
|
||||||
|
|
|
@ -115,6 +115,12 @@ impl Drop for StreamLock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PadGetRangeSuccess {
|
||||||
|
FilledBuffer,
|
||||||
|
NewBuffer(::Buffer),
|
||||||
|
}
|
||||||
|
|
||||||
pub trait PadExtManual: 'static {
|
pub trait PadExtManual: 'static {
|
||||||
fn add_probe<F>(&self, mask: PadProbeType, func: F) -> Option<PadProbeId>
|
fn add_probe<F>(&self, mask: PadProbeType, func: F) -> Option<PadProbeId>
|
||||||
where
|
where
|
||||||
|
@ -207,7 +213,13 @@ pub trait PadExtManual: 'static {
|
||||||
|
|
||||||
fn set_getrange_function<F>(&self, func: F)
|
fn set_getrange_function<F>(&self, func: F)
|
||||||
where
|
where
|
||||||
F: Fn(&Self, Option<&::Object>, u64, u32) -> Result<::Buffer, ::FlowError>
|
F: Fn(
|
||||||
|
&Self,
|
||||||
|
Option<&::Object>,
|
||||||
|
u64,
|
||||||
|
Option<&mut ::BufferRef>,
|
||||||
|
u32,
|
||||||
|
) -> Result<PadGetRangeSuccess, ::FlowError>
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
+ 'static;
|
+ 'static;
|
||||||
|
@ -680,7 +692,13 @@ impl<O: IsA<Pad>> PadExtManual for O {
|
||||||
|
|
||||||
fn set_getrange_function<F>(&self, func: F)
|
fn set_getrange_function<F>(&self, func: F)
|
||||||
where
|
where
|
||||||
F: Fn(&Self, Option<&::Object>, u64, u32) -> Result<::Buffer, FlowError>
|
F: Fn(
|
||||||
|
&Self,
|
||||||
|
Option<&::Object>,
|
||||||
|
u64,
|
||||||
|
Option<&mut ::BufferRef>,
|
||||||
|
u32,
|
||||||
|
) -> Result<PadGetRangeSuccess, ::FlowError>
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
+ 'static,
|
+ 'static,
|
||||||
|
@ -1344,7 +1362,16 @@ where
|
||||||
|
|
||||||
unsafe extern "C" fn trampoline_getrange_function<
|
unsafe extern "C" fn trampoline_getrange_function<
|
||||||
T,
|
T,
|
||||||
F: Fn(&T, Option<&::Object>, u64, u32) -> Result<::Buffer, FlowError> + Send + Sync + 'static,
|
F: Fn(
|
||||||
|
&T,
|
||||||
|
Option<&::Object>,
|
||||||
|
u64,
|
||||||
|
Option<&mut ::BufferRef>,
|
||||||
|
u32,
|
||||||
|
) -> Result<PadGetRangeSuccess, ::FlowError>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
>(
|
>(
|
||||||
pad: *mut gst_sys::GstPad,
|
pad: *mut gst_sys::GstPad,
|
||||||
parent: *mut gst_sys::GstObject,
|
parent: *mut gst_sys::GstObject,
|
||||||
|
@ -1355,16 +1382,72 @@ unsafe extern "C" fn trampoline_getrange_function<
|
||||||
where
|
where
|
||||||
T: IsA<Pad>,
|
T: IsA<Pad>,
|
||||||
{
|
{
|
||||||
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
let func: &F = &*((*pad).getrangedata as *const F);
|
let func: &F = &*((*pad).getrangedata as *const F);
|
||||||
|
|
||||||
|
assert!(!buffer.is_null());
|
||||||
|
|
||||||
|
let pad = Pad::from_glib_borrow(pad).unsafe_cast();
|
||||||
|
let mut passed_buffer = if (*buffer).is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(::BufferRef::from_mut_ptr(*buffer))
|
||||||
|
};
|
||||||
|
|
||||||
match func(
|
match func(
|
||||||
&Pad::from_glib_borrow(pad).unsafe_cast(),
|
&pad,
|
||||||
Option::<::Object>::from_glib_borrow(parent).as_ref(),
|
Option::<::Object>::from_glib_borrow(parent).as_ref(),
|
||||||
offset,
|
offset,
|
||||||
|
passed_buffer.as_mut().map(|b| b.deref_mut()),
|
||||||
length,
|
length,
|
||||||
) {
|
) {
|
||||||
Ok(new_buffer) => {
|
Ok(PadGetRangeSuccess::NewBuffer(new_buffer)) => {
|
||||||
*buffer = new_buffer.into_ptr();
|
if let Some(passed_buffer) = passed_buffer {
|
||||||
|
gst_debug!(
|
||||||
|
::CAT_PERFORMANCE,
|
||||||
|
obj: pad.unsafe_cast_ref::<glib::Object>(),
|
||||||
|
"Returned new buffer from getrange function, copying into passed buffer"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut map = match passed_buffer.map_writable() {
|
||||||
|
Ok(map) => map,
|
||||||
|
Err(_) => {
|
||||||
|
gst_error!(
|
||||||
|
::CAT_RUST,
|
||||||
|
obj: pad.unsafe_cast_ref::<glib::Object>(),
|
||||||
|
"Failed to map passed buffer writable"
|
||||||
|
);
|
||||||
|
return gst_sys::GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let copied_size = new_buffer.copy_to_slice(0, &mut *map);
|
||||||
|
drop(map);
|
||||||
|
|
||||||
|
if let Err(copied_size) = copied_size {
|
||||||
|
passed_buffer.set_size(copied_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
match new_buffer.copy_into(passed_buffer, ::BUFFER_COPY_METADATA, 0, None) {
|
||||||
|
Ok(_) => FlowReturn::Ok.to_glib(),
|
||||||
|
Err(_) => {
|
||||||
|
gst_error!(
|
||||||
|
::CAT_RUST,
|
||||||
|
obj: pad.unsafe_cast_ref::<glib::Object>(),
|
||||||
|
"Failed to copy buffer metadata"
|
||||||
|
);
|
||||||
|
|
||||||
|
FlowReturn::Error.to_glib()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*buffer = new_buffer.into_ptr();
|
||||||
|
FlowReturn::Ok.to_glib()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(PadGetRangeSuccess::FilledBuffer) => {
|
||||||
|
assert!(passed_buffer.is_some());
|
||||||
FlowReturn::Ok.to_glib()
|
FlowReturn::Ok.to_glib()
|
||||||
}
|
}
|
||||||
Err(ret) => FlowReturn::from_error(ret).to_glib(),
|
Err(ret) => FlowReturn::from_error(ret).to_glib(),
|
||||||
|
|
Loading…
Reference in a new issue