在Rust中,有没有一种方法可以对"gstreamer::Bin"进行子类化,这样我仍然有它原来的方



我正在尝试将gstreamer::Bin子类化以覆盖其Bin::handle_message方法,目的是拦截流结束消息、丢弃它们并发出它们已被丢弃的信号(如果它们不是流结束消息,则使用默认的Bin::handle_message行为(。

问题是,我仍然需要它的原始方法(如Bin::addBin::add_pad等(,因为我唯一需要堆叠在原始gstreamer::Bin之上的行为就是前面提到的消息拦截。

我提到我仍然需要它的原始方法,因为当我试图遵循这个例子时,我编写的CustomBin不满足IsA<Bin>,因此不符合gstreamer::GstBinExt的一揽子实现,这反过来又使它没有原始的gstreamer::Bin方法。

我也遇到过这个例子,但最终我不想为我想从管道中动态添加和删除的每一组元素重新实现消息拦截行为。我也不需要将其注册为适当的元素,我只需要在我自己的机箱中使用它,以及在其中定义的管道。

作为参考,我将在下面附上我实现这一目标的尝试。

我错过了什么?


pub struct CustomBin {
eos_guard: Mutex<Option<Sender<()>>>,
}
impl Default for CustomBin {
fn default() -> Self {
Self {
eos_guard: Mutex::new(None),
}
}
}
impl ObjectImpl for CustomBin {
glib_object_impl!();
}
impl ElementImpl for CustomBin {}
impl BinImpl for CustomBin {
fn handle_message(&self, bin: &Bin, message: Message) {
if let MessageView::Eos(_) = message.view() {
if let Some(sender) = self.eos_guard.lock().unwrap().take() {
sender.send(()).unwrap_or(());
} else {
self.parent_handle_message(bin, message);
}
} else {
self.parent_handle_message(bin, message);
}
}
}
impl ObjectSubclass for CustomBin {
const NAME: &'static str = "GstCustomBin";
type ParentType = Bin;
type Instance = ElementInstanceStruct<Self>;
type Class = ClassStruct<Self>;
glib_object_subclass!();
fn new() -> Self {
Self::default()
}
}
impl CustomBin {
pub fn install_eos_guard(&self) -> Receiver<()> {
let mut eos_guard = self.eos_guard.lock().unwrap();
let (sender, receiver) = channel();
if eos_guard.is_some() {
panic!("End-of-stream guard was already installed");
} else {
eos_guard.replace(sender);
}
receiver
}
}

您的CustomBin结构是该类型的内部实现,而不是glib::Object(或gst::Bin(本身。如果将其与Java进行比较,那么这就是所有的私有字段和受保护的虚拟方法。

这足以创建一个新实例,并将其用作其任何父类

let obj: glib::Object = glib::Object::new(CustomBin::get_type(), &[("name", "bla")]).unwrap();
let bin: gst::Bin = obj.downcast::<gst::Bin>().unwrap();

请注意,上面的objbin不是您的CustomBin结构。

要围绕CustomBin创建公共Rust API,您需要使用glib_wrapper!宏。你可以在这里找到一个例子。不要只看那些突出显示的行,还要看上面的所有代码

最新更新