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
This commit is contained in:
Sebastian Dröge 2020-06-22 11:03:52 +03:00
parent c917e77687
commit 9bb3e75fb9
19 changed files with 872 additions and 822 deletions

View file

@ -1746,34 +1746,35 @@ impl ObjectSubclass for AudioLoudNorm {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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"))
sinkpad.set_pad_flags(gst::PadFlags::PROXY_CAPS); .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();
let templ = klass.get_pad_template("src").unwrap(); 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"))
srcpad.set_pad_flags(gst::PadFlags::PROXY_CAPS); .query_function(|pad, parent, query| {
Self::catch_panic_pad_function(
sinkpad.set_chain_function(|pad, parent, buffer| { parent,
Self::catch_panic_pad_function( || false,
parent, |this, element| this.src_query(pad, element, query),
|| Err(gst::FlowError::Error), )
|this, element| this.sink_chain(pad, element, buffer), })
) .flags(gst::PadFlags::PROXY_CAPS)
}); .build();
sinkpad.set_event_function(|pad, parent, event| {
Self::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
)
});
srcpad.set_query_function(|pad, parent, query| {
Self::catch_panic_pad_function(
parent,
|| false,
|this, element| this.src_query(pad, element, query),
)
});
Self { Self {
sinkpad, sinkpad,

View file

@ -269,39 +269,6 @@ struct Decrypter {
} }
impl 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( fn src_activatemode_function(
&self, &self,
_pad: &gst::Pad, _pad: &gst::Pad,
@ -597,10 +564,39 @@ impl ObjectSubclass for Decrypter {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); let templ = klass.get_pad_template("sink").unwrap();
let sinkpad = gst::Pad::from_template(&templ, Some("sink")); 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"));
Decrypter::set_pad_functions(&sinkpad, &srcpad); let templ = klass.get_pad_template("src").unwrap();
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();
let props = Mutex::new(Props::default()); let props = Mutex::new(Props::default());
let state = Mutex::new(None); let state = Mutex::new(None);

View file

@ -198,38 +198,6 @@ struct Encrypter {
} }
impl 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( fn sink_chain(
&self, &self,
pad: &gst::Pad, pad: &gst::Pad,
@ -425,11 +393,41 @@ impl ObjectSubclass for Encrypter {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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"))
let templ = klass.get_pad_template("src").unwrap(); .chain_function(|pad, parent, buffer| {
let srcpad = gst::Pad::from_template(&templ, Some("src")); 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::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 props = Mutex::new(Props::default());
let state = Mutex::new(None); let state = Mutex::new(None);

View file

@ -385,69 +385,71 @@ impl PadSrc {
} }
fn init_pad_functions<H: PadSrcHandler>(&self, handler: H) { fn init_pad_functions<H: PadSrcHandler>(&self, handler: H) {
let handler_clone = handler.clone(); // FIXME: Do this better
let inner_arc = Arc::clone(&self.0); unsafe {
self.0 let handler_clone = handler.clone();
.gst_pad() let inner_arc = Arc::clone(&self.0);
.set_activate_function(move |gst_pad, parent| { self.0
let handler = handler_clone.clone(); .gst_pad()
let inner_arc = inner_arc.clone(); .set_activate_function(move |gst_pad, parent| {
H::ElementImpl::catch_panic_pad_function( let handler = handler_clone.clone();
parent, let inner_arc = inner_arc.clone();
|| { H::ElementImpl::catch_panic_pad_function(
gst_error!(RUNTIME_CAT, obj: gst_pad, "Panic in PadSrc activate"); parent,
Err(gst_loggable_error!(RUNTIME_CAT, "Panic in PadSrc activate")) || {
}, gst_error!(RUNTIME_CAT, obj: gst_pad, "Panic in PadSrc activate");
move |imp, element| { Err(gst_loggable_error!(RUNTIME_CAT, "Panic in PadSrc activate"))
let this_ref = PadSrcRef::new(inner_arc); },
handler.src_activate(&this_ref, imp, element) move |imp, element| {
}, let this_ref = PadSrcRef::new(inner_arc);
) handler.src_activate(&this_ref, imp, element)
}); },
)
});
let handler_clone = handler.clone(); let handler_clone = handler.clone();
let inner_arc = Arc::clone(&self.0); let inner_arc = Arc::clone(&self.0);
self.gst_pad() self.gst_pad()
.set_activatemode_function(move |gst_pad, parent, mode, active| { .set_activatemode_function(move |gst_pad, parent, mode, active| {
let handler = handler_clone.clone(); let handler = handler_clone.clone();
let inner_arc = inner_arc.clone(); let inner_arc = inner_arc.clone();
H::ElementImpl::catch_panic_pad_function( H::ElementImpl::catch_panic_pad_function(
parent, parent,
|| { || {
gst_error!(RUNTIME_CAT, obj: gst_pad, "Panic in PadSrc activatemode"); gst_error!(RUNTIME_CAT, obj: gst_pad, "Panic in PadSrc activatemode");
Err(gst_loggable_error!( Err(gst_loggable_error!(
RUNTIME_CAT, RUNTIME_CAT,
"Panic in PadSrc activatemode" "Panic in PadSrc activatemode"
)) ))
}, },
move |imp, element| { move |imp, element| {
let this_ref = PadSrcRef::new(inner_arc); let this_ref = PadSrcRef::new(inner_arc);
this_ref.activate_mode_hook(mode, active)?; this_ref.activate_mode_hook(mode, active)?;
handler.src_activatemode(&this_ref, imp, element, mode, active) handler.src_activatemode(&this_ref, imp, element, mode, active)
}, },
) )
}); });
// No need to `set_event_function` since `set_event_full_function` // No need to `set_event_function` since `set_event_full_function`
// overrides it and dispatches to `src_event` when necessary // overrides it and dispatches to `src_event` when necessary
let handler_clone = handler.clone(); let handler_clone = handler.clone();
let inner_arc = Arc::clone(&self.0); let inner_arc = Arc::clone(&self.0);
self.gst_pad() self.gst_pad()
.set_event_full_function(move |_gst_pad, parent, event| { .set_event_full_function(move |_gst_pad, parent, event| {
let handler = handler_clone.clone(); let handler = handler_clone.clone();
let inner_arc = inner_arc.clone(); let inner_arc = inner_arc.clone();
H::ElementImpl::catch_panic_pad_function( H::ElementImpl::catch_panic_pad_function(
parent, parent,
|| Err(FlowError::Error), || Err(FlowError::Error),
move |imp, element| { move |imp, element| {
let this_ref = PadSrcRef::new(inner_arc); let this_ref = PadSrcRef::new(inner_arc);
handler.src_event_full(&this_ref, imp, &element, event) handler.src_event_full(&this_ref, imp, &element, event)
}, },
) )
}); });
let inner_arc = Arc::clone(&self.0); let inner_arc = Arc::clone(&self.0);
self.gst_pad() self.gst_pad()
.set_query_function(move |_gst_pad, parent, query| { .set_query_function(move |_gst_pad, parent, query| {
let handler = handler.clone(); let handler = handler.clone();
let inner_arc = inner_arc.clone(); let inner_arc = inner_arc.clone();
@ -465,25 +467,29 @@ impl PadSrc {
}, },
) )
}); });
}
} }
} }
impl Drop for PadSrc { impl Drop for PadSrc {
fn drop(&mut self) { fn drop(&mut self) {
self.gst_pad() // FIXME: Do this better
.set_activate_function(move |_gst_pad, _parent| { unsafe {
Err(gst_loggable_error!(RUNTIME_CAT, "PadSrc no longer exists")) self.gst_pad()
}); .set_activate_function(move |_gst_pad, _parent| {
self.gst_pad() Err(gst_loggable_error!(RUNTIME_CAT, "PadSrc no longer exists"))
.set_activatemode_function(move |_gst_pad, _parent, _mode, _active| { });
Err(gst_loggable_error!(RUNTIME_CAT, "PadSrc no longer exists")) self.gst_pad()
}); .set_activatemode_function(move |_gst_pad, _parent, _mode, _active| {
self.gst_pad() Err(gst_loggable_error!(RUNTIME_CAT, "PadSrc no longer exists"))
.set_event_function(move |_gst_pad, _parent, _event| false); });
self.gst_pad() self.gst_pad()
.set_event_full_function(move |_gst_pad, _parent, _event| Err(FlowError::Flushing)); .set_event_function(move |_gst_pad, _parent, _event| false);
self.gst_pad() self.gst_pad()
.set_query_function(move |_gst_pad, _parent, _query| false); .set_event_full_function(move |_gst_pad, _parent, _event| Err(FlowError::Flushing));
self.gst_pad()
.set_query_function(move |_gst_pad, _parent, _query| false);
}
} }
} }
@ -781,134 +787,64 @@ impl PadSink {
} }
fn init_pad_functions<H: PadSinkHandler>(&self, handler: H) { fn init_pad_functions<H: PadSinkHandler>(&self, handler: H) {
let handler_clone = handler.clone(); // FIXME: Do this better
let inner_arc = Arc::clone(&self.0); unsafe {
self.gst_pad() let handler_clone = handler.clone();
.set_activate_function(move |gst_pad, parent| { let inner_arc = Arc::clone(&self.0);
let handler = handler_clone.clone(); self.gst_pad()
let inner_arc = inner_arc.clone(); .set_activate_function(move |gst_pad, parent| {
H::ElementImpl::catch_panic_pad_function( let handler = handler_clone.clone();
parent, let inner_arc = inner_arc.clone();
|| { H::ElementImpl::catch_panic_pad_function(
gst_error!(RUNTIME_CAT, obj: gst_pad, "Panic in PadSink activate"); parent,
Err(gst_loggable_error!( || {
RUNTIME_CAT, gst_error!(RUNTIME_CAT, obj: gst_pad, "Panic in PadSink activate");
"Panic in PadSink activate" Err(gst_loggable_error!(
)) RUNTIME_CAT,
}, "Panic in PadSink activate"
move |imp, element| { ))
let this_ref = PadSinkRef::new(inner_arc); },
handler.sink_activate(&this_ref, imp, element) move |imp, element| {
},
)
});
let handler_clone = handler.clone();
let inner_arc = Arc::clone(&self.0);
self.gst_pad()
.set_activatemode_function(move |gst_pad, parent, mode, active| {
let handler = handler_clone.clone();
let inner_arc = inner_arc.clone();
H::ElementImpl::catch_panic_pad_function(
parent,
|| {
gst_error!(RUNTIME_CAT, obj: gst_pad, "Panic in PadSink activatemode");
Err(gst_loggable_error!(
RUNTIME_CAT,
"Panic in PadSink activatemode"
))
},
move |imp, element| {
let this_ref = PadSinkRef::new(inner_arc);
this_ref.activate_mode_hook(mode, active)?;
handler.sink_activatemode(&this_ref, imp, element, mode, active)
},
)
});
let handler_clone = handler.clone();
let inner_arc = Arc::clone(&self.0);
self.gst_pad()
.set_chain_function(move |_gst_pad, parent, buffer| {
let handler = handler_clone.clone();
let inner_arc = inner_arc.clone();
H::ElementImpl::catch_panic_pad_function(
parent,
|| Err(FlowError::Error),
move |imp, element| {
if Context::current_has_sub_tasks() {
let this_weak = PadSinkWeak(Arc::downgrade(&inner_arc));
let handler = handler.clone();
let element = element.clone();
let delayed_fut = async move {
let imp =
<H::ElementImpl as ObjectSubclass>::from_instance(&element);
let this_ref =
this_weak.upgrade().ok_or(gst::FlowError::Flushing)?;
handler.sink_chain(&this_ref, imp, &element, buffer).await
};
let _ = Context::add_sub_task(delayed_fut.map(|res| res.map(drop)));
Ok(gst::FlowSuccess::Ok)
} else {
let this_ref = PadSinkRef::new(inner_arc); let this_ref = PadSinkRef::new(inner_arc);
let chain_fut = handler.sink_chain(&this_ref, imp, &element, buffer); handler.sink_activate(&this_ref, imp, element)
this_ref.handle_future(chain_fut) },
} )
}, });
)
});
let handler_clone = handler.clone(); let handler_clone = handler.clone();
let inner_arc = Arc::clone(&self.0); let inner_arc = Arc::clone(&self.0);
self.gst_pad() self.gst_pad()
.set_chain_list_function(move |_gst_pad, parent, list| { .set_activatemode_function(move |gst_pad, parent, mode, active| {
let handler = handler_clone.clone(); let handler = handler_clone.clone();
let inner_arc = inner_arc.clone(); let inner_arc = inner_arc.clone();
H::ElementImpl::catch_panic_pad_function( H::ElementImpl::catch_panic_pad_function(
parent, parent,
|| Err(FlowError::Error), || {
move |imp, element| { gst_error!(RUNTIME_CAT, obj: gst_pad, "Panic in PadSink activatemode");
if Context::current_has_sub_tasks() { Err(gst_loggable_error!(
let this_weak = PadSinkWeak(Arc::downgrade(&inner_arc)); RUNTIME_CAT,
let handler = handler.clone(); "Panic in PadSink activatemode"
let element = element.clone(); ))
let delayed_fut = async move { },
let imp = move |imp, element| {
<H::ElementImpl as ObjectSubclass>::from_instance(&element);
let this_ref =
this_weak.upgrade().ok_or(gst::FlowError::Flushing)?;
handler
.sink_chain_list(&this_ref, imp, &element, list)
.await
};
let _ = Context::add_sub_task(delayed_fut.map(|res| res.map(drop)));
Ok(gst::FlowSuccess::Ok)
} else {
let this_ref = PadSinkRef::new(inner_arc); let this_ref = PadSinkRef::new(inner_arc);
let chain_list_fut = this_ref.activate_mode_hook(mode, active)?;
handler.sink_chain_list(&this_ref, imp, &element, list);
this_ref.handle_future(chain_list_fut)
}
},
)
});
// No need to `set_event_function` since `set_event_full_function` handler.sink_activatemode(&this_ref, imp, element, mode, active)
// overrides it and dispatches to `sink_event` when necessary },
let handler_clone = handler.clone(); )
let inner_arc = Arc::clone(&self.0); });
self.gst_pad()
.set_event_full_function(move |_gst_pad, parent, event| { let handler_clone = handler.clone();
let handler = handler_clone.clone(); let inner_arc = Arc::clone(&self.0);
let inner_arc = inner_arc.clone(); self.gst_pad()
H::ElementImpl::catch_panic_pad_function( .set_chain_function(move |_gst_pad, parent, buffer| {
parent, let handler = handler_clone.clone();
|| Err(FlowError::Error), let inner_arc = inner_arc.clone();
move |imp, element| { H::ElementImpl::catch_panic_pad_function(
if event.is_serialized() { parent,
|| Err(FlowError::Error),
move |imp, element| {
if Context::current_has_sub_tasks() { if Context::current_has_sub_tasks() {
let this_weak = PadSinkWeak(Arc::downgrade(&inner_arc)); let this_weak = PadSinkWeak(Arc::downgrade(&inner_arc));
let handler = handler.clone(); let handler = handler.clone();
@ -918,9 +854,42 @@ impl PadSink {
<H::ElementImpl as ObjectSubclass>::from_instance(&element); <H::ElementImpl as ObjectSubclass>::from_instance(&element);
let this_ref = let this_ref =
this_weak.upgrade().ok_or(gst::FlowError::Flushing)?; this_weak.upgrade().ok_or(gst::FlowError::Flushing)?;
handler.sink_chain(&this_ref, imp, &element, buffer).await
};
let _ = Context::add_sub_task(delayed_fut.map(|res| res.map(drop)));
Ok(gst::FlowSuccess::Ok)
} else {
let this_ref = PadSinkRef::new(inner_arc);
let chain_fut =
handler.sink_chain(&this_ref, imp, &element, buffer);
this_ref.handle_future(chain_fut)
}
},
)
});
let handler_clone = handler.clone();
let inner_arc = Arc::clone(&self.0);
self.gst_pad()
.set_chain_list_function(move |_gst_pad, parent, list| {
let handler = handler_clone.clone();
let inner_arc = inner_arc.clone();
H::ElementImpl::catch_panic_pad_function(
parent,
|| Err(FlowError::Error),
move |imp, element| {
if Context::current_has_sub_tasks() {
let this_weak = PadSinkWeak(Arc::downgrade(&inner_arc));
let handler = handler.clone();
let element = element.clone();
let delayed_fut = async move {
let imp =
<H::ElementImpl as ObjectSubclass>::from_instance(&element);
let this_ref =
this_weak.upgrade().ok_or(gst::FlowError::Flushing)?;
handler handler
.sink_event_full_serialized(&this_ref, imp, &element, event) .sink_chain_list(&this_ref, imp, &element, list)
.await .await
}; };
let _ = Context::add_sub_task(delayed_fut.map(|res| res.map(drop))); let _ = Context::add_sub_task(delayed_fut.map(|res| res.map(drop)));
@ -928,20 +897,65 @@ impl PadSink {
Ok(gst::FlowSuccess::Ok) Ok(gst::FlowSuccess::Ok)
} else { } else {
let this_ref = PadSinkRef::new(inner_arc); let this_ref = PadSinkRef::new(inner_arc);
let event_fut = handler let chain_list_fut =
.sink_event_full_serialized(&this_ref, imp, &element, event); handler.sink_chain_list(&this_ref, imp, &element, list);
this_ref.handle_future(event_fut) this_ref.handle_future(chain_list_fut)
} }
} else { },
let this_ref = PadSinkRef::new(inner_arc); )
handler.sink_event_full(&this_ref, imp, &element, event) });
}
},
)
});
let inner_arc = Arc::clone(&self.0); // No need to `set_event_function` since `set_event_full_function`
self.gst_pad() // overrides it and dispatches to `sink_event` when necessary
let handler_clone = handler.clone();
let inner_arc = Arc::clone(&self.0);
self.gst_pad()
.set_event_full_function(move |_gst_pad, parent, event| {
let handler = handler_clone.clone();
let inner_arc = inner_arc.clone();
H::ElementImpl::catch_panic_pad_function(
parent,
|| Err(FlowError::Error),
move |imp, element| {
if event.is_serialized() {
if Context::current_has_sub_tasks() {
let this_weak = PadSinkWeak(Arc::downgrade(&inner_arc));
let handler = handler.clone();
let element = element.clone();
let delayed_fut = async move {
let imp = <H::ElementImpl as ObjectSubclass>::from_instance(
&element,
);
let this_ref =
this_weak.upgrade().ok_or(gst::FlowError::Flushing)?;
handler
.sink_event_full_serialized(
&this_ref, imp, &element, event,
)
.await
};
let _ =
Context::add_sub_task(delayed_fut.map(|res| res.map(drop)));
Ok(gst::FlowSuccess::Ok)
} else {
let this_ref = PadSinkRef::new(inner_arc);
let event_fut = handler.sink_event_full_serialized(
&this_ref, imp, &element, event,
);
this_ref.handle_future(event_fut)
}
} else {
let this_ref = PadSinkRef::new(inner_arc);
handler.sink_event_full(&this_ref, imp, &element, event)
}
},
)
});
let inner_arc = Arc::clone(&self.0);
self.gst_pad()
.set_query_function(move |_gst_pad, parent, query| { .set_query_function(move |_gst_pad, parent, query| {
let handler = handler.clone(); let handler = handler.clone();
let inner_arc = inner_arc.clone(); let inner_arc = inner_arc.clone();
@ -959,29 +973,33 @@ impl PadSink {
}, },
) )
}); });
}
} }
} }
impl Drop for PadSink { impl Drop for PadSink {
fn drop(&mut self) { fn drop(&mut self) {
self.gst_pad() // FIXME: Do this better
.set_activate_function(move |_gst_pad, _parent| { unsafe {
Err(gst_loggable_error!(RUNTIME_CAT, "PadSink no longer exists")) self.gst_pad()
}); .set_activate_function(move |_gst_pad, _parent| {
self.gst_pad() Err(gst_loggable_error!(RUNTIME_CAT, "PadSink no longer exists"))
.set_activatemode_function(move |_gst_pad, _parent, _mode, _active| { });
Err(gst_loggable_error!(RUNTIME_CAT, "PadSink no longer exists")) self.gst_pad()
}); .set_activatemode_function(move |_gst_pad, _parent, _mode, _active| {
self.gst_pad() Err(gst_loggable_error!(RUNTIME_CAT, "PadSink no longer exists"))
.set_chain_function(move |_gst_pad, _parent, _buffer| Err(FlowError::Flushing)); });
self.gst_pad() self.gst_pad()
.set_chain_list_function(move |_gst_pad, _parent, _list| Err(FlowError::Flushing)); .set_chain_function(move |_gst_pad, _parent, _buffer| Err(FlowError::Flushing));
self.gst_pad() self.gst_pad()
.set_event_function(move |_gst_pad, _parent, _event| false); .set_chain_list_function(move |_gst_pad, _parent, _list| Err(FlowError::Flushing));
self.gst_pad() self.gst_pad()
.set_event_full_function(move |_gst_pad, _parent, _event| Err(FlowError::Flushing)); .set_event_function(move |_gst_pad, _parent, _event| false);
self.gst_pad() self.gst_pad()
.set_query_function(move |_gst_pad, _parent, _query| false); .set_event_full_function(move |_gst_pad, _parent, _event| Err(FlowError::Flushing));
self.gst_pad()
.set_query_function(move |_gst_pad, _parent, _query| false);
}
} }
} }

View file

@ -65,21 +65,26 @@ impl Harness {
let (sender, receiver) = mpsc::sync_channel(0); let (sender, receiver) = mpsc::sync_channel(0);
// Sink pad that receives everything the source is generating // 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(); let srcpad = src.get_static_pad("src").unwrap();
srcpad.link(&pad).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(); let bus = gst::Bus::new();
bus.set_flushing(false); bus.set_flushing(false);
src.set_bus(Some(&bus)); src.set_bus(Some(&bus));

View file

@ -230,43 +230,6 @@ fn build_packet(payload: &[u8]) -> Vec<u8> {
} }
impl Transcriber { 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 { fn dequeue(&self, element: &gst::Element) -> bool {
/* First, check our pending buffers */ /* First, check our pending buffers */
let mut items = vec![]; let mut items = vec![];
@ -1031,13 +994,47 @@ impl ObjectSubclass for Transcriber {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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| {
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();
let templ = klass.get_pad_template("src").unwrap(); 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"))
.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();
srcpad.use_fixed_caps();
Transcriber::set_pad_functions(&sinkpad, &srcpad);
let settings = Mutex::new(Settings::default()); let settings = Mutex::new(Settings::default());
Self { Self {

View file

@ -127,16 +127,6 @@ struct TextWrap {
} }
impl 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) { fn update_wrapper(&self, element: &gst::Element) {
let settings = self.settings.lock().unwrap(); let settings = self.settings.lock().unwrap();
let mut state = self.state.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 { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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"))
sinkpad.set_pad_flags(gst::PadFlags::PROXY_CAPS); .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();
let templ = klass.get_pad_template("src").unwrap(); 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"))
srcpad.set_pad_flags(gst::PadFlags::PROXY_CAPS); .flags(gst::PadFlags::PROXY_CAPS | gst::PadFlags::FIXED_CAPS)
.build();
srcpad.use_fixed_caps();
sinkpad.use_fixed_caps();
TextWrap::set_pad_functions(&sinkpad);
let settings = Mutex::new(Settings::default()); let settings = Mutex::new(Settings::default());
let state = Mutex::new(State::default()); let state = Mutex::new(State::default());

View file

@ -29,54 +29,6 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
}); });
impl Identity { 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 // 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. // whenever some output buffer is available have to push it out of the source pad.
// Here we just pass through all buffers directly // 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 // 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 { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
// Create our two pads from the templates that were registered with // 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 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"))
let templ = klass.get_pad_template("src").unwrap(); .chain_function(|pad, parent, buffer| {
let srcpad = gst::Pad::from_template(&templ, Some("src")); 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 let templ = klass.get_pad_template("src").unwrap();
// on these pads let srcpad = gst::Pad::builder_with_template(&templ, Some("src"))
Identity::set_pad_functions(&sinkpad, &srcpad); .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. // 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 // The debug category will be used later whenever we need to put something

View file

@ -88,9 +88,9 @@ impl ObjectSubclass for ProgressBin {
// //
// We do that and adding the pads inside glib::Object::constructed() later. // We do that and adding the pads inside glib::Object::constructed() later.
let templ = klass.get_pad_template("sink").unwrap(); 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 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. // Create the progressreport element.
let progress = gst::ElementFactory::make("progressreport", Some("progress")).unwrap(); let progress = gst::ElementFactory::make("progressreport", Some("progress")).unwrap();

View file

@ -704,7 +704,11 @@ impl FallbackSrc {
}; };
input 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(); .unwrap();
Ok(input.upcast()) Ok(input.upcast())
@ -724,7 +728,11 @@ impl FallbackSrc {
let srcpad = audiotestsrc.get_static_pad("src").unwrap(); let srcpad = audiotestsrc.get_static_pad("src").unwrap();
input 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(); .unwrap();
Ok(input.upcast()) Ok(input.upcast())
@ -772,22 +780,27 @@ impl FallbackSrc {
let templ = element let templ = element
.get_pad_template(if is_audio { "audio" } else { "video" }) .get_pad_template(if is_audio { "audio" } else { "video" })
.unwrap(); .unwrap();
let ghostpad = let ghostpad = gst::GhostPad::builder_with_template(&templ, Some(&templ.get_name()))
gst::GhostPad::from_template(Some(&templ.get_name()), &srcpad, &templ).unwrap(); .build_with_target(&srcpad)
.unwrap();
element.add_pad(&ghostpad).unwrap();
let proxypad = ghostpad.get_internal().expect("no internal pad"); let proxypad = ghostpad.get_internal().expect("no internal pad");
let element_weak = element.downgrade(); let element_weak = element.downgrade();
proxypad.set_chain_function(move |pad, _parent, buffer| { // Safety: Nothing else can have a reference to the proxy pad yet apart from the ghost pad
let element = match element_weak.upgrade() { // itself, so changing the chain function is still safe.
None => return Err(gst::FlowError::Flushing), unsafe {
Some(element) => element, proxypad.set_chain_function(move |pad, _parent, buffer| {
}; let element = match element_weak.upgrade() {
None => return Err(gst::FlowError::Flushing),
Some(element) => element,
};
let src = FallbackSrc::from_instance(&element); let src = FallbackSrc::from_instance(&element);
src.proxy_pad_chain(&element, pad, buffer) src.proxy_pad_chain(&element, pad, buffer)
}); });
}
element.add_pad(&ghostpad).unwrap();
Ok(Stream { Ok(Stream {
fallback_input, fallback_input,
@ -2215,7 +2228,9 @@ mod custom_source {
(element.get_pad_template("video_%u").unwrap(), name) (element.get_pad_template("video_%u").unwrap(), name)
}; };
let ghost_pad = gst::GhostPad::from_template(Some(&name), pad, &templ).unwrap(); let ghost_pad = gst::GhostPad::builder_with_template(&templ, Some(&name))
.build_with_target(pad)
.unwrap();
let stream = Stream { let stream = Stream {
source_pad: pad.clone(), source_pad: pad.clone(),

View file

@ -362,59 +362,6 @@ lazy_static! {
} }
impl ToggleRecord { impl ToggleRecord {
fn set_pad_functions(sinkpad: &gst::Pad, srcpad: &gst::Pad) {
sinkpad.set_chain_function(|pad, parent, buffer| {
ToggleRecord::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|togglerecord, element| togglerecord.sink_chain(pad, element, buffer),
)
});
sinkpad.set_event_function(|pad, parent, event| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.sink_event(pad, element, event),
)
});
sinkpad.set_query_function(|pad, parent, query| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.sink_query(pad, element, query),
)
});
sinkpad.set_iterate_internal_links_function(|pad, parent| {
ToggleRecord::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|togglerecord, element| togglerecord.iterate_internal_links(pad, element),
)
});
srcpad.set_event_function(|pad, parent, event| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.src_event(pad, element, event),
)
});
srcpad.set_query_function(|pad, parent, query| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.src_query(pad, element, query),
)
});
srcpad.set_iterate_internal_links_function(|pad, parent| {
ToggleRecord::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|togglerecord, element| togglerecord.iterate_internal_links(pad, element),
)
});
}
fn handle_main_stream<T: HandleData>( fn handle_main_stream<T: HandleData>(
&self, &self,
element: &gst::Element, element: &gst::Element,
@ -1537,11 +1484,61 @@ impl ObjectSubclass for ToggleRecord {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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"))
let templ = klass.get_pad_template("src").unwrap(); .chain_function(|pad, parent, buffer| {
let srcpad = gst::Pad::from_template(&templ, Some("src")); ToggleRecord::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|togglerecord, element| togglerecord.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.sink_event(pad, element, event),
)
})
.query_function(|pad, parent, query| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.sink_query(pad, element, query),
)
})
.iterate_internal_links_function(|pad, parent| {
ToggleRecord::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|togglerecord, element| togglerecord.iterate_internal_links(pad, element),
)
})
.build();
ToggleRecord::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| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.src_event(pad, element, event),
)
})
.query_function(|pad, parent, query| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.src_query(pad, element, query),
)
})
.iterate_internal_links_function(|pad, parent| {
ToggleRecord::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|togglerecord, element| togglerecord.iterate_internal_links(pad, element),
)
})
.build();
let main_stream = Stream::new(sinkpad, srcpad); let main_stream = Stream::new(sinkpad, srcpad);
@ -1734,12 +1731,62 @@ impl ElementImpl for ToggleRecord {
*pad_count += 1; *pad_count += 1;
let templ = element.get_pad_template("sink_%u").unwrap(); let templ = element.get_pad_template("sink_%u").unwrap();
let sinkpad = gst::Pad::from_template(&templ, Some(format!("sink_{}", id).as_str())); let sinkpad =
gst::Pad::builder_with_template(&templ, Some(format!("sink_{}", id).as_str()))
.chain_function(|pad, parent, buffer| {
ToggleRecord::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|togglerecord, element| togglerecord.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.sink_event(pad, element, event),
)
})
.query_function(|pad, parent, query| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.sink_query(pad, element, query),
)
})
.iterate_internal_links_function(|pad, parent| {
ToggleRecord::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|togglerecord, element| togglerecord.iterate_internal_links(pad, element),
)
})
.build();
let templ = element.get_pad_template("src_%u").unwrap(); let templ = element.get_pad_template("src_%u").unwrap();
let srcpad = gst::Pad::from_template(&templ, Some(format!("src_{}", id).as_str())); let srcpad = gst::Pad::builder_with_template(&templ, Some(format!("src_{}", id).as_str()))
.event_function(|pad, parent, event| {
ToggleRecord::set_pad_functions(&sinkpad, &srcpad); ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.src_event(pad, element, event),
)
})
.query_function(|pad, parent, query| {
ToggleRecord::catch_panic_pad_function(
parent,
|| false,
|togglerecord, element| togglerecord.src_query(pad, element, query),
)
})
.iterate_internal_links_function(|pad, parent| {
ToggleRecord::catch_panic_pad_function(
parent,
|| gst::Iterator::from_vec(vec![]),
|togglerecord, element| togglerecord.iterate_internal_links(pad, element),
)
})
.build();
sinkpad.set_active(true).unwrap(); sinkpad.set_active(true).unwrap();
srcpad.set_active(true).unwrap(); srcpad.set_active(true).unwrap();

View file

@ -75,23 +75,6 @@ struct Cea608Overlay {
} }
impl Cea608Overlay { impl Cea608Overlay {
fn set_pad_functions(sinkpad: &gst::Pad, _srcpad: &gst::Pad) {
sinkpad.set_chain_function(|pad, parent, buffer| {
Cea608Overlay::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|overlay, element| overlay.sink_chain(pad, element, buffer),
)
});
sinkpad.set_event_function(|pad, parent, event| {
Cea608Overlay::catch_panic_pad_function(
parent,
|| false,
|overlay, element| overlay.sink_event(pad, element, event),
)
});
}
// FIXME: we want to render the text in the largest 32 x 15 characters // FIXME: we want to render the text in the largest 32 x 15 characters
// that will fit the viewport. This is a truly terrible way to determine // that will fit the viewport. This is a truly terrible way to determine
// the appropriate font size, but we only need to run that on resolution // the appropriate font size, but we only need to run that on resolution
@ -413,13 +396,28 @@ impl ObjectSubclass for Cea608Overlay {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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"))
sinkpad.set_pad_flags(gst::PadFlags::PROXY_CAPS); .chain_function(|pad, parent, buffer| {
let templ = klass.get_pad_template("src").unwrap(); Cea608Overlay::catch_panic_pad_function(
let srcpad = gst::Pad::from_template(&templ, Some("src")); parent,
srcpad.set_pad_flags(gst::PadFlags::PROXY_CAPS); || Err(gst::FlowError::Error),
|overlay, element| overlay.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
Cea608Overlay::catch_panic_pad_function(
parent,
|| false,
|overlay, element| overlay.sink_event(pad, element, event),
)
})
.flags(gst::PadFlags::PROXY_CAPS)
.build();
Cea608Overlay::set_pad_functions(&sinkpad, &srcpad); let templ = klass.get_pad_template("src").unwrap();
let srcpad = gst::Pad::builder_with_template(&templ, Some("src"))
.flags(gst::PadFlags::PROXY_CAPS)
.build();
Self { Self {
srcpad, srcpad,

View file

@ -379,27 +379,28 @@ impl ObjectSubclass for Cea608ToTt {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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| {
Cea608ToTt::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
Cea608ToTt::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
)
})
.flags(gst::PadFlags::FIXED_CAPS)
.build();
let templ = klass.get_pad_template("src").unwrap(); 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"))
.flags(gst::PadFlags::FIXED_CAPS)
sinkpad.set_chain_function(|pad, parent, buffer| { .build();
Cea608ToTt::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.sink_chain(pad, element, buffer),
)
});
sinkpad.set_event_function(|pad, parent, event| {
Cea608ToTt::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
)
});
sinkpad.use_fixed_caps();
srcpad.use_fixed_caps();
Self { Self {
srcpad, srcpad,

View file

@ -105,38 +105,6 @@ lazy_static! {
} }
impl MccEnc { impl MccEnc {
fn set_pad_functions(sinkpad: &gst::Pad, srcpad: &gst::Pad) {
sinkpad.set_chain_function(|pad, parent, buffer| {
MccEnc::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|enc, element| enc.sink_chain(pad, element, buffer),
)
});
sinkpad.set_event_function(|pad, parent, event| {
MccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.sink_event(pad, element, event),
)
});
srcpad.set_event_function(|pad, parent, event| {
MccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.src_event(pad, element, event),
)
});
srcpad.set_query_function(|pad, parent, query| {
MccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.src_query(pad, element, query),
)
});
}
#[allow(clippy::write_with_newline)] #[allow(clippy::write_with_newline)]
fn generate_headers(&self, _state: &State, buffer: &mut Vec<u8>) -> Result<(), gst::FlowError> { fn generate_headers(&self, _state: &State, buffer: &mut Vec<u8>) -> Result<(), gst::FlowError> {
let settings = self.settings.lock().unwrap(); let settings = self.settings.lock().unwrap();
@ -502,11 +470,40 @@ impl ObjectSubclass for MccEnc {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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"))
let templ = klass.get_pad_template("src").unwrap(); .chain_function(|pad, parent, buffer| {
let srcpad = gst::Pad::from_template(&templ, Some("src")); MccEnc::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|enc, element| enc.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
MccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.sink_event(pad, element, event),
)
})
.build();
MccEnc::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| {
MccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.src_event(pad, element, event),
)
})
.query_function(|pad, parent, query| {
MccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.src_query(pad, element, query),
)
})
.build();
Self { Self {
srcpad, srcpad,

View file

@ -367,58 +367,6 @@ impl AsMut<[u8]> for OffsetVec {
} }
impl MccParse { impl MccParse {
fn set_pad_functions(sinkpad: &gst::Pad, srcpad: &gst::Pad) {
sinkpad.set_activate_function(|pad, parent| {
MccParse::catch_panic_pad_function(
parent,
|| Err(gst_loggable_error!(CAT, "Panic activating sink pad")),
|parse, element| parse.sink_activate(pad, element),
)
});
sinkpad.set_activatemode_function(|pad, parent, mode, active| {
MccParse::catch_panic_pad_function(
parent,
|| {
Err(gst_loggable_error!(
CAT,
"Panic activating sink pad with mode"
))
},
|parse, element| parse.sink_activatemode(pad, element, mode, active),
)
});
sinkpad.set_chain_function(|pad, parent, buffer| {
MccParse::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|parse, element| parse.sink_chain(pad, element, buffer),
)
});
sinkpad.set_event_function(|pad, parent, event| {
MccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.sink_event(pad, element, event),
)
});
srcpad.set_event_function(|pad, parent, event| {
MccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_event(pad, element, event),
)
});
srcpad.set_query_function(|pad, parent, query| {
MccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_query(pad, element, query),
)
});
}
fn handle_buffer( fn handle_buffer(
&self, &self,
element: &gst::Element, element: &gst::Element,
@ -1174,11 +1122,59 @@ impl ObjectSubclass for MccParse {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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"))
let templ = klass.get_pad_template("src").unwrap(); .activate_function(|pad, parent| {
let srcpad = gst::Pad::from_template(&templ, Some("src")); MccParse::catch_panic_pad_function(
parent,
|| Err(gst_loggable_error!(CAT, "Panic activating sink pad")),
|parse, element| parse.sink_activate(pad, element),
)
})
.activatemode_function(|pad, parent, mode, active| {
MccParse::catch_panic_pad_function(
parent,
|| {
Err(gst_loggable_error!(
CAT,
"Panic activating sink pad with mode"
))
},
|parse, element| parse.sink_activatemode(pad, element, mode, active),
)
})
.chain_function(|pad, parent, buffer| {
MccParse::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|parse, element| parse.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
MccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.sink_event(pad, element, event),
)
})
.build();
MccParse::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| {
MccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_event(pad, element, event),
)
})
.query_function(|pad, parent, query| {
MccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_query(pad, element, query),
)
})
.build();
Self { Self {
srcpad, srcpad,

View file

@ -225,38 +225,6 @@ struct SccEnc {
} }
impl SccEnc { impl SccEnc {
fn set_pad_functions(sinkpad: &gst::Pad, srcpad: &gst::Pad) {
sinkpad.set_chain_function(|pad, parent, buffer| {
SccEnc::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|enc, element| enc.sink_chain(pad, element, buffer),
)
});
sinkpad.set_event_function(|pad, parent, event| {
SccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.sink_event(pad, element, event),
)
});
srcpad.set_event_function(|pad, parent, event| {
SccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.src_event(pad, element, event),
)
});
srcpad.set_query_function(|pad, parent, query| {
SccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.src_query(pad, element, query),
)
});
}
fn sink_chain( fn sink_chain(
&self, &self,
pad: &gst::Pad, pad: &gst::Pad,
@ -370,11 +338,40 @@ impl ObjectSubclass for SccEnc {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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"))
let templ = klass.get_pad_template("src").unwrap(); .chain_function(|pad, parent, buffer| {
let srcpad = gst::Pad::from_template(&templ, Some("src")); SccEnc::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|enc, element| enc.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
SccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.sink_event(pad, element, event),
)
})
.build();
SccEnc::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| {
SccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.src_event(pad, element, event),
)
})
.query_function(|pad, parent, query| {
SccEnc::catch_panic_pad_function(
parent,
|| false,
|enc, element| enc.src_query(pad, element, query),
)
})
.build();
Self { Self {
srcpad, srcpad,

View file

@ -182,38 +182,6 @@ struct SccParse {
} }
impl SccParse { impl SccParse {
fn set_pad_functions(sinkpad: &gst::Pad, srcpad: &gst::Pad) {
sinkpad.set_chain_function(|pad, parent, buffer| {
SccParse::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|parse, element| parse.sink_chain(pad, element, buffer),
)
});
sinkpad.set_event_function(|pad, parent, event| {
SccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.sink_event(pad, element, event),
)
});
srcpad.set_event_function(|pad, parent, event| {
SccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_event(pad, element, event),
)
});
srcpad.set_query_function(|pad, parent, query| {
SccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_query(pad, element, query),
)
});
}
fn handle_buffer( fn handle_buffer(
&self, &self,
element: &gst::Element, element: &gst::Element,
@ -453,11 +421,40 @@ impl ObjectSubclass for SccParse {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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"))
let templ = klass.get_pad_template("src").unwrap(); .chain_function(|pad, parent, buffer| {
let srcpad = gst::Pad::from_template(&templ, Some("src")); SccParse::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|parse, element| parse.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
SccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.sink_event(pad, element, event),
)
})
.build();
SccParse::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| {
SccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_event(pad, element, event),
)
})
.query_function(|pad, parent, query| {
SccParse::catch_panic_pad_function(
parent,
|| false,
|parse, element| parse.src_query(pad, element, query),
)
})
.build();
Self { Self {
srcpad, srcpad,

View file

@ -793,34 +793,35 @@ impl ObjectSubclass for TtToCea608 {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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| {
TtToCea608::catch_panic_pad_function(
parent,
|| Err(gst::FlowError::Error),
|this, element| this.sink_chain(pad, element, buffer),
)
})
.event_function(|pad, parent, event| {
TtToCea608::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
)
})
.flags(gst::PadFlags::FIXED_CAPS)
.build();
let templ = klass.get_pad_template("src").unwrap(); 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| {
sinkpad.set_chain_function(|pad, parent, buffer| { TtToCea608::catch_panic_pad_function(
TtToCea608::catch_panic_pad_function( parent,
parent, || false,
|| Err(gst::FlowError::Error), |this, element| this.src_query(pad, element, query),
|this, element| this.sink_chain(pad, element, buffer), )
) })
}); .flags(gst::PadFlags::FIXED_CAPS)
sinkpad.set_event_function(|pad, parent, event| { .build();
TtToCea608::catch_panic_pad_function(
parent,
|| false,
|this, element| this.sink_event(pad, element, event),
)
});
srcpad.set_query_function(|pad, parent, query| {
TtToCea608::catch_panic_pad_function(
parent,
|| false,
|this, element| this.src_query(pad, element, query),
)
});
sinkpad.use_fixed_caps();
srcpad.use_fixed_caps();
Self { Self {
srcpad, srcpad,

View file

@ -132,43 +132,41 @@ impl ObjectSubclass for FlvDemux {
fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self { fn with_class(klass: &subclass::simple::ClassStruct<Self>) -> Self {
let templ = klass.get_pad_template("sink").unwrap(); 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"))
.activate_function(|pad, parent| {
sinkpad.set_activate_function(|pad, parent| { FlvDemux::catch_panic_pad_function(
FlvDemux::catch_panic_pad_function( parent,
parent, || Err(gst_loggable_error!(CAT, "Panic activating sink pad")),
|| Err(gst_loggable_error!(CAT, "Panic activating sink pad")), |demux, element| demux.sink_activate(pad, element),
|demux, element| demux.sink_activate(pad, element), )
) })
}); .activatemode_function(|pad, parent, mode, active| {
FlvDemux::catch_panic_pad_function(
sinkpad.set_activatemode_function(|pad, parent, mode, active| { parent,
FlvDemux::catch_panic_pad_function( || {
parent, Err(gst_loggable_error!(
|| { CAT,
Err(gst_loggable_error!( "Panic activating sink pad with mode"
CAT, ))
"Panic activating sink pad with mode" },
)) |demux, element| demux.sink_activatemode(pad, element, mode, active),
}, )
|demux, element| demux.sink_activatemode(pad, element, mode, active), })
) .chain_function(|pad, parent, buffer| {
}); FlvDemux::catch_panic_pad_function(
parent,
sinkpad.set_chain_function(|pad, parent, buffer| { || Err(gst::FlowError::Error),
FlvDemux::catch_panic_pad_function( |demux, element| demux.sink_chain(pad, element, buffer),
parent, )
|| Err(gst::FlowError::Error), })
|demux, element| demux.sink_chain(pad, element, buffer), .event_function(|pad, parent, event| {
) FlvDemux::catch_panic_pad_function(
}); parent,
sinkpad.set_event_function(|pad, parent, event| { || false,
FlvDemux::catch_panic_pad_function( |demux, element| demux.sink_event(pad, element, event),
parent, )
|| false, })
|demux, element| demux.sink_event(pad, element, event), .build();
)
});
FlvDemux { FlvDemux {
sinkpad, sinkpad,
@ -639,23 +637,22 @@ impl FlvDemux {
fn create_srcpad(&self, element: &gst::Element, name: &str, caps: &gst::Caps) -> gst::Pad { fn create_srcpad(&self, element: &gst::Element, name: &str, caps: &gst::Caps) -> gst::Pad {
let templ = element.get_element_class().get_pad_template(name).unwrap(); let templ = element.get_element_class().get_pad_template(name).unwrap();
let srcpad = gst::Pad::from_template(&templ, Some(name)); let srcpad = gst::Pad::builder_with_template(&templ, Some(name))
.event_function(|pad, parent, event| {
srcpad.set_event_function(|pad, parent, event| { FlvDemux::catch_panic_pad_function(
FlvDemux::catch_panic_pad_function( parent,
parent, || false,
|| false, |demux, element| demux.src_event(pad, element, event),
|demux, element| demux.src_event(pad, element, event), )
) })
}); .query_function(|pad, parent, query| {
FlvDemux::catch_panic_pad_function(
srcpad.set_query_function(|pad, parent, query| { parent,
FlvDemux::catch_panic_pad_function( || false,
parent, |demux, element| demux.src_query(pad, element, query),
|| false, )
|demux, element| demux.src_query(pad, element, query), })
) .build();
});
srcpad.set_active(true).unwrap(); srcpad.set_active(true).unwrap();