Commit 9bb3e75f authored by Sebastian Dröge's avatar Sebastian Dröge 🍵
Browse files

Update to use the new pad builders for safely setting pad functions

Only two uses of unsafely setting the pad functions is left:
- fallbacksrc for overriding the chain function of the proxy pad of a
  ghost pad
- threadshare for overriding the pad functions after creationg, which
  probably needs some fixing at some point
parent c917e776
Pipeline #165075 passed with stages
in 19 minutes and 22 seconds
......@@ -1746,34 +1746,35 @@ impl ObjectSubclass for AudioLoudNorm {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::from_template(&templ, Some("sink"));
sinkpad.set_pad_flags(gst::PadFlags::PROXY_CAPS);
let templ = klass.get_pad_template("src").unwrap();
let srcpad = gst::Pad::from_template(&templ, Some("src"));
srcpad.set_pad_flags(gst::PadFlags::PROXY_CAPS);
sinkpad.set_chain_function(|pad, parent, buffer| {
Self::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.sink_chain(pad, element, buffer),
)
});
sinkpad.set_event_function(|pad, parent, event| {
Self::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
)
});
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.chain_function(|pad, parent, buffer| {
Self::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
Self::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
)
})
.flags(gst::PadFlags::PROXY_CAPS)
.build();
srcpad.set_query_function(|pad, parent, query| {
Self::catch_panic_pad_function(
parent,
|| false,
|this, element| this.src_query(pad, element, query),
)
});
let templ = klass.get_pad_template("src").unwrap();
let srcpad = gst::Pad::builder_with_template(&templ, Some("src"))
.query_function(|pad, parent, query| {
Self::catch_panic_pad_function(
parent,
|| false,
|this, element| this.src_query(pad, element, query),
)
})
.flags(gst::PadFlags::PROXY_CAPS)
.build();
Self {
sinkpad,
......
......@@ -269,39 +269,6 @@ struct Decrypter {
}
impl Decrypter {
fn set_pad_functions(_sinkpad: &gst::Pad, srcpad: &gst::Pad) {
srcpad.set_getrange_function(|pad, parent, offset, buffer, size| {
Decrypter::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|decrypter, element| decrypter.get_range(pad, element, offset, buffer, size),
)
});
srcpad.set_activatemode_function(|pad, parent, mode, active| {
Decrypter::catch_panic_pad_function(
parent,
|| {
Err(gst_loggable_error!(
CAT,
"Panic activating srcpad with mode"
))
},
|decrypter, element| {
decrypter.src_activatemode_function(pad, element, mode, active)
},
)
});
srcpad.set_query_function(|pad, parent, query| {
Decrypter::catch_panic_pad_function(
parent,
|| false,
|decrypter, element| decrypter.src_query(pad, element, query),
)
});
}
fn src_activatemode_function(
&self,
_pad: &gst::Pad,
......@@ -597,10 +564,39 @@ impl ObjectSubclass for Decrypter {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::from_template(&templ, Some("sink"));
let templ = klass.get_pad_template("src").unwrap();
let srcpad = gst::Pad::from_template(&templ, Some("src"));
let srcpad = gst::Pad::builder_with_template(&templ, Some("src"))
.getrange_function(|pad, parent, offset, buffer, size| {
Decrypter::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|decrypter, element| decrypter.get_range(pad, element, offset, buffer, size),
)
})
.activatemode_function(|pad, parent, mode, active| {
Decrypter::catch_panic_pad_function(
parent,
|| {
Err(gst_loggable_error!(
CAT,
"Panic activating srcpad with mode"
))
},
|decrypter, element| {
decrypter.src_activatemode_function(pad, element, mode, active)
},
)
})
.query_function(|pad, parent, query| {
Decrypter::catch_panic_pad_function(
parent,
|| false,
|decrypter, element| decrypter.src_query(pad, element, query),
)
})
.build();
Decrypter::set_pad_functions(&sinkpad, &srcpad);
let props = Mutex::new(Props::default());
let state = Mutex::new(None);
......
......@@ -198,38 +198,6 @@ struct Encrypter {
}
impl Encrypter {
fn set_pad_functions(sinkpad: &gst::Pad, srcpad: &gst::Pad) {
sinkpad.set_chain_function(|pad, parent, buffer| {
Encrypter::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|encrypter, element| encrypter.sink_chain(pad, element, buffer),
)
});
sinkpad.set_event_function(|pad, parent, event| {
Encrypter::catch_panic_pad_function(
parent,
|| false,
|encrypter, element| encrypter.sink_event(pad, element, event),
)
});
srcpad.set_query_function(|pad, parent, query| {
Encrypter::catch_panic_pad_function(
parent,
|| false,
|encrypter, element| encrypter.src_query(pad, element, query),
)
});
srcpad.set_event_function(|pad, parent, event| {
Encrypter::catch_panic_pad_function(
parent,
|| false,
|encrypter, element| encrypter.src_event(pad, element, event),
)
});
}
fn sink_chain(
&self,
pad: &gst::Pad,
......@@ -425,11 +393,41 @@ impl ObjectSubclass for Encrypter {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::from_template(&templ, Some("sink"));
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.chain_function(|pad, parent, buffer| {
Encrypter::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|encrypter, element| encrypter.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
Encrypter::catch_panic_pad_function(
parent,
|| false,
|encrypter, element| encrypter.sink_event(pad, element, event),
)
})
.build();
let templ = klass.get_pad_template("src").unwrap();
let srcpad = gst::Pad::from_template(&templ, Some("src"));
let srcpad = gst::Pad::builder_with_template(&templ, Some("src"))
.query_function(|pad, parent, query| {
Encrypter::catch_panic_pad_function(
parent,
|| false,
|encrypter, element| encrypter.src_query(pad, element, query),
)
})
.event_function(|pad, parent, event| {
Encrypter::catch_panic_pad_function(
parent,
|| false,
|encrypter, element| encrypter.src_event(pad, element, event),
)
})
.build();
Encrypter::set_pad_functions(&sinkpad, &srcpad);
let props = Mutex::new(Props::default());
let state = Mutex::new(None);
......
This diff is collapsed.
......@@ -65,21 +65,26 @@ impl Harness {
let (sender, receiver) = mpsc::sync_channel(0);
// Sink pad that receives everything the source is generating
let pad = gst::Pad::new(Some("sink"), gst::PadDirection::Sink);
let pad = gst::Pad::builder(Some("sink"), gst::PadDirection::Sink)
.chain_function({
let sender_clone = sender.clone();
move |_pad, _parent, buffer| {
let _ = sender_clone.send(Message::Buffer(buffer));
Ok(gst::FlowSuccess::Ok)
}
})
.event_function({
let sender_clone = sender.clone();
move |_pad, _parent, event| {
let _ = sender_clone.send(Message::Event(event));
true
}
})
.build();
let srcpad = src.get_static_pad("src").unwrap();
srcpad.link(&pad).unwrap();
// Collect all buffers, events and messages sent from the source
let sender_clone = sender.clone();
pad.set_chain_function(move |_pad, _parent, buffer| {
let _ = sender_clone.send(Message::Buffer(buffer));
Ok(gst::FlowSuccess::Ok)
});
let sender_clone = sender.clone();
pad.set_event_function(move |_pad, _parent, event| {
let _ = sender_clone.send(Message::Event(event));
true
});
let bus = gst::Bus::new();
bus.set_flushing(false);
src.set_bus(Some(&bus));
......
......@@ -230,43 +230,6 @@ fn build_packet(payload: &[u8]) -> Vec<u8> {
}
impl Transcriber {
fn set_pad_functions(sinkpad: &gst::Pad, srcpad: &gst::Pad) {
sinkpad.set_chain_function(|pad, parent, buffer| {
Transcriber::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|transcriber, element| transcriber.sink_chain(pad, element, buffer),
)
});
sinkpad.set_event_function(|pad, parent, event| {
Transcriber::catch_panic_pad_function(
parent,
|| false,
|transcriber, element| transcriber.sink_event(pad, element, event),
)
});
srcpad.set_activatemode_function(|pad, parent, mode, active| {
Transcriber::catch_panic_pad_function(
parent,
|| {
Err(gst_loggable_error!(
CAT,
"Panic activating src pad with mode"
))
},
|transcriber, element| transcriber.src_activatemode(pad, element, mode, active),
)
});
srcpad.set_query_function(|pad, parent, query| {
Transcriber::catch_panic_pad_function(
parent,
|| false,
|transcriber, element| transcriber.src_query(pad, element, query),
)
});
}
fn dequeue(&self, element: &gst::Element) -> bool {
/* First, check our pending buffers */
let mut items = vec![];
......@@ -1031,13 +994,47 @@ impl ObjectSubclass for Transcriber {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::from_template(&templ, Some("sink"));
let templ = klass.get_pad_template("src").unwrap();
let srcpad = gst::Pad::from_template(&templ, Some("src"));
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.chain_function(|pad, parent, buffer| {
Transcriber::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|transcriber, element| transcriber.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
Transcriber::catch_panic_pad_function(
parent,
|| false,
|transcriber, element| transcriber.sink_event(pad, element, event),
)
})
.build();
srcpad.use_fixed_caps();
let templ = klass.get_pad_template("src").unwrap();
let srcpad = gst::Pad::builder_with_template(&templ, Some("src"))
.activatemode_function(|pad, parent, mode, active| {
Transcriber::catch_panic_pad_function(
parent,
|| {
Err(gst_loggable_error!(
CAT,
"Panic activating src pad with mode"
))
},
|transcriber, element| transcriber.src_activatemode(pad, element, mode, active),
)
})
.query_function(|pad, parent, query| {
Transcriber::catch_panic_pad_function(
parent,
|| false,
|transcriber, element| transcriber.src_query(pad, element, query),
)
})
.flags(gst::PadFlags::FIXED_CAPS)
.build();
Transcriber::set_pad_functions(&sinkpad, &srcpad);
let settings = Mutex::new(Settings::default());
Self {
......
......@@ -127,16 +127,6 @@ struct TextWrap {
}
impl TextWrap {
fn set_pad_functions(sinkpad: &gst::Pad) {
sinkpad.set_chain_function(|pad, parent, buffer| {
TextWrap::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|textwrap, element| textwrap.sink_chain(pad, element, buffer),
)
});
}
fn update_wrapper(&self, element: &gst::Element) {
let settings = self.settings.lock().unwrap();
let mut state = self.state.lock().unwrap();
......@@ -279,16 +269,21 @@ impl ObjectSubclass for TextWrap {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::from_template(&templ, Some("sink"));
sinkpad.set_pad_flags(gst::PadFlags::PROXY_CAPS);
let templ = klass.get_pad_template("src").unwrap();
let srcpad = gst::Pad::from_template(&templ, Some("src"));
srcpad.set_pad_flags(gst::PadFlags::PROXY_CAPS);
srcpad.use_fixed_caps();
sinkpad.use_fixed_caps();
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.chain_function(|pad, parent, buffer| {
TextWrap::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|textwrap, element| textwrap.sink_chain(pad, element, buffer),
)
})
.flags(gst::PadFlags::PROXY_CAPS | gst::PadFlags::FIXED_CAPS)
.build();
TextWrap::set_pad_functions(&sinkpad);
let templ = klass.get_pad_template("src").unwrap();
let srcpad = gst::Pad::builder_with_template(&templ, Some("src"))
.flags(gst::PadFlags::PROXY_CAPS | gst::PadFlags::FIXED_CAPS)
.build();
let settings = Mutex::new(Settings::default());
let state = Mutex::new(State::default());
......
......@@ -29,54 +29,6 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
});
impl Identity {
// After creating of our two pads set all the functions on them
//
// Each function is wrapped in catch_panic_pad_function(), which will
// - Catch panics from the pad functions and instead of aborting the process
// it will simply convert them into an error message and poison the element
// instance
// - Extract our Identity struct from the object instance and pass it to us
//
// Details about what each function is good for is next to each function definition
fn set_pad_functions(sinkpad: &gst::Pad, srcpad: &gst::Pad) {
sinkpad.set_chain_function(|pad, parent, buffer| {
Identity::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|identity, element| identity.sink_chain(pad, element, buffer),
)
});
sinkpad.set_event_function(|pad, parent, event| {
Identity::catch_panic_pad_function(
parent,
|| false,
|identity, element| identity.sink_event(pad, element, event),
)
});
sinkpad.set_query_function(|pad, parent, query| {
Identity::catch_panic_pad_function(
parent,
|| false,
|identity, element| identity.sink_query(pad, element, query),
)
});
srcpad.set_event_function(|pad, parent, event| {
Identity::catch_panic_pad_function(
parent,
|| false,
|identity, element| identity.src_event(pad, element, event),
)
});
srcpad.set_query_function(|pad, parent, query| {
Identity::catch_panic_pad_function(
parent,
|| false,
|identity, element| identity.src_query(pad, element, query),
)
});
}
// Called whenever a new buffer is passed to our sink pad. Here buffers should be processed and
// whenever some output buffer is available have to push it out of the source pad.
// Here we just pass through all buffers directly
......@@ -173,15 +125,57 @@ impl ObjectSubclass for Identity {
// of our struct here and also get the class struct passed in case it's needed
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
// Create our two pads from the templates that were registered with
// the class
// the class and set all the functions on them.
//
// Each function is wrapped in catch_panic_pad_function(), which will
// - Catch panics from the pad functions and instead of aborting the process
// it will simply convert them into an error message and poison the element
// instance
// - Extract our Identity struct from the object instance and pass it to us
//
// Details about what each function is good for is next to each function definition
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::from_template(&templ, Some("sink"));
let templ = klass.get_pad_template("src").unwrap();
let srcpad = gst::Pad::from_template(&templ, Some("src"));
let sinkpad = gst::Pad::builder_with_template(&templ, Some("sink"))
.chain_function(|pad, parent, buffer| {
Identity::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|identity, element| identity.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
Identity::catch_panic_pad_function(
parent,
|| false,
|identity, element| identity.sink_event(pad, element, event),
)
})
.query_function(|pad, parent, query| {
Identity::catch_panic_pad_function(
parent,
|| false,
|identity, element| identity.sink_query(pad, element, query),
)
})
.build();
// And then set all our pad functions for handling anything that happens
// on these pads
Identity::set_pad_functions(&sinkpad, &srcpad);
let templ = klass.get_pad_template("src").unwrap();
let srcpad = gst::Pad::builder_with_template(&templ, Some("src"))
.event_function(|pad, parent, event| {
Identity::catch_panic_pad_function(
parent,
|| false,
|identity, element| identity.src_event(pad, element, event),
)
})
.query_function(|pad, parent, query| {
Identity::catch_panic_pad_function(
parent,
|| false,
|identity, element| identity.src_query(pad, element, query),
)
})
.build();
// Return an instance of our struct and also include our debug category here.
// The debug category will be used later whenever we need to put something
......
......@@ -88,9 +88,9 @@ impl ObjectSubclass for ProgressBin {
//
// We do that and adding the pads inside glib::Object::constructed() later.
let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::GhostPad::new_no_target_from_template(Some("sink"), &templ).unwrap();
let sinkpad = gst::GhostPad::from_template(&templ, Some("sink"));
let templ = klass.get_pad_template("src").unwrap();
let srcpad = gst::GhostPad::new_no_target_from_template(Some("src"), &templ).unwrap();
let srcpad = gst::GhostPad::from_template(&templ, Some("src"));
// Create the progressreport element.
let progress = gst::ElementFactory::make("progressreport", Some("progress")).unwrap();
......
......@@ -704,7 +704,11 @@ impl FallbackSrc {
};
input
.add_pad(&gst::GhostPad::new(Some("src"), &srcpad).unwrap())
.add_pad(
&gst::GhostPad::builder(Some("src"), gst::PadDirection::Src)
.build_with_target(&srcpad)
.unwrap(),
)
.unwrap();
Ok(input.upcast())
......@@ -724,7 +728,11 @@ impl FallbackSrc {
let srcpad = audiotestsrc.get_static_pad("src").unwrap();
input
.add_pad(&gst::GhostPad::new(Some("src"), &srcpad).unwrap())
.add_pad(
&gst::GhostPad::builder(Some("src"), gst::PadDirection::Src)
.build_with_target(&srcpad)
.unwrap(),
)
.unwrap();
Ok(input.upcast())
......@@ -772,22 +780,27 @@ impl FallbackSrc {
let templ = element
.get_pad_template(if is_audio { "audio" } else { "video" })
.unwrap();
let ghostpad =
gst::GhostPad::from_template(Some(&templ.get_name()), &srcpad, &templ).unwrap();
element.add_pad(&ghostpad).unwrap();
let ghostpad = gst::GhostPad::builder_with_template(&templ, Some(&templ.get_name()))
.build_with_target(&srcpad)
.unwrap();
let proxypad = ghostpad.get_internal().expect("no internal pad");