oh I got it working but using playbin
use gst::prelude::*;
use gtk::prelude::*;
use gtk::{gdk, gio, glib};
use std::cell::RefCell;
fn create_ui(app: >k::Application) {
let _cwd = std::env::current_dir().unwrap();
let cwd = _cwd.to_str().unwrap();
let uri = format!("file://{}/{}", cwd, "/duck.mp4");
println!("playing {}", uri);
let playbin = gst::ElementFactory::make("playbin")
.property("uri", uri)
.build()
.unwrap();
let gtksink = gst::ElementFactory::make("gtk4paintablesink")
.build()
.unwrap();
let paintable = gtksink.property::<gdk::Paintable>("paintable");
// TODO: future plans to provide a bin-like element that works with less setup
let sink = if paintable
.property::<Option<gdk::GLContext>>("gl-context")
.is_some()
{
println!("using glsink");
let sink = gst::ElementFactory::make("glsinkbin")
.property("sink", >ksink)
.build()
.unwrap();
sink
} else {
println!("using videoconvert");
let sink = gst::Bin::default();
let convert = gst::ElementFactory::make("videoconvert").build().unwrap();
sink.add(&convert).unwrap();
sink.add(>ksink).unwrap();
convert.link(>ksink).unwrap();
sink.add_pad(&gst::GhostPad::with_target(&convert.static_pad("sink").unwrap()).unwrap())
.unwrap();
sink.upcast()
};
playbin.set_property("video-sink", >ksink);
playbin
.add_pad(&gst::GhostPad::with_target(&sink.static_pad("sink").unwrap()).unwrap())
.unwrap();
// playbin.link(&sink).unwrap();
let window = gtk::ApplicationWindow::new(app);
window.set_default_size(640, 480);
let gst_widget = gstgtk4::RenderWidget::new(>ksink);
let overlay = gtk::Overlay::new();
overlay.add_overlay(&gst_widget);
window.set_child(Some(&overlay));
window.present();
// window.fullscreen();
app.add_window(&window);
let bus: gst::Bus = playbin.bus().unwrap();
playbin
.set_state(gst::State::Playing)
.expect("Unable to set the playbin to the `Playing` state");
let app_weak = app.downgrade();
let bus_watch = bus
.add_watch_local(move |_, msg| {
use gst::MessageView;
let Some(app) = app_weak.upgrade() else {
return glib::ControlFlow::Break;
};
match msg.view() {
MessageView::Eos(..) => app.quit(),
MessageView::Error(err) => {
println!(
"Error from {:?}: {} ({:?})",
err.src().map(|s| s.path_string()),
err.error(),
err.debug()
);
app.quit();
}
_ => (),
};
glib::ControlFlow::Continue
})
.expect("Failed to add bus watch");
let playbin = RefCell::new(Some(playbin));
let bus_watch = RefCell::new(Some(bus_watch));
app.connect_shutdown(move |_| {
window.close();
drop(bus_watch.borrow_mut().take());
if let Some(playbin) = playbin.borrow_mut().take() {
playbin
.set_state(gst::State::Null)
.expect("Unable to set the playbin to the `Null` state");
}
});
}
fn main() -> glib::ExitCode {
gst::init().unwrap();
gstgtk4::plugin_register_static().expect("Failed to register gstgtk4 plugin");
let app = gtk::Application::new(None::<&str>, gio::ApplicationFlags::FLAGS_NONE);
app.connect_activate(create_ui);
let res = app.run();
unsafe {
gst::deinit();
}
res
}
was missing the playbin.set_property("video-sink", >ksink);
to make the playbin use the sink, found here