threadshare/inputselector: fix tearing down

GstElementClass.release_pad() may be called after the element
has transitioned back to NULL, we need to keep our sink_pads
map around until then.

They should also not be affected by state transitions at all but only be
removed once the user does so or the element is destroyed, so they need
to live independent of the state.
This commit is contained in:
Mathieu Duponchelle 2020-01-29 20:18:15 +01:00 committed by Sebastian Dröge
parent 575efcab7e
commit 0b240b829e
2 changed files with 24 additions and 10 deletions

View file

@ -318,8 +318,6 @@ struct State {
active_sinkpad: Option<gst::Pad>,
send_sticky: bool,
send_stream_start: bool,
pad_serial: u32,
sink_pads: HashMap<gst::Pad, PadSink>,
}
impl Default for State {
@ -328,6 +326,19 @@ impl Default for State {
active_sinkpad: None,
send_sticky: false,
send_stream_start: true,
}
}
}
#[derive(Debug)]
struct Pads {
pad_serial: u32,
sink_pads: HashMap<gst::Pad, PadSink>,
}
impl Default for Pads {
fn default() -> Pads {
Pads {
pad_serial: 0,
sink_pads: HashMap::new(),
}
@ -339,6 +350,7 @@ struct InputSelector {
src_pad: PadSrc,
state: Mutex<State>,
settings: Mutex<Settings>,
pads: Mutex<Pads>,
}
lazy_static! {
@ -453,6 +465,7 @@ impl ObjectSubclass for InputSelector {
src_pad,
state: Mutex::new(State::default()),
settings: Mutex::new(Settings::default()),
pads: Mutex::new(Pads::default()),
}
}
}
@ -554,18 +567,17 @@ impl ElementImpl for InputSelector {
_caps: Option<&gst::Caps>,
) -> Option<gst::Pad> {
let mut state = block_on(self.state.lock());
let sink_pad = gst::Pad::new_from_template(
&templ,
Some(format!("sink_{}", state.pad_serial).as_str()),
);
state.pad_serial += 1;
let mut pads = block_on(self.pads.lock());
let sink_pad =
gst::Pad::new_from_template(&templ, Some(format!("sink_{}", pads.pad_serial).as_str()));
pads.pad_serial += 1;
sink_pad.set_active(true).unwrap();
element.add_pad(&sink_pad).unwrap();
let sink_pad = PadSink::new(sink_pad);
let ret = sink_pad.gst_pad().clone();
block_on(sink_pad.prepare(&InputSelectorPadSinkHandler::new()));
state.sink_pads.insert(ret.clone(), sink_pad);
pads.sink_pads.insert(ret.clone(), sink_pad);
if state.active_sinkpad.is_none() {
state.active_sinkpad = Some(ret.clone());
@ -576,8 +588,8 @@ impl ElementImpl for InputSelector {
}
fn release_pad(&self, element: &gst::Element, pad: &gst::Pad) {
let mut state = block_on(self.state.lock());
let sink_pad = state.sink_pads.remove(pad).unwrap();
let mut pads = block_on(self.pads.lock());
let sink_pad = pads.sink_pads.remove(pad).unwrap();
block_on(sink_pad.unprepare());
element.remove_pad(pad).unwrap();
}

View file

@ -102,4 +102,6 @@ fn test_active_pad() {
assert!(event.get_type() == gst::EventType::Caps);
let event = h1.pull_event().unwrap();
assert!(event.get_type() == gst::EventType::Segment);
let _ = is.set_state(gst::State::Null);
}