Hello, I have been trying to make use the sample of the gtk4paintablesink to play a local video file, this is what I have to far:
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 file_path = format!("{}{}", cwd, "/duck.mp4");
println!("playing {}", file_path);
let pipeline = gst::Pipeline::new();
let src = gst::ElementFactory::make("filesrc").build().unwrap();
src.set_property("location", &file_path);
let decode = gst::ElementFactory::make("decodebin").build().unwrap();
let convert = gst::ElementFactory::make("videoconvert").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()
{
// let src = gst::ElementFactory::make("gltestsrc").build().unwrap();
println!("using glsink");
let sink = gst::ElementFactory::make("glsinkbin")
.property("sink", >ksink)
.build()
.unwrap();
sink
} else {
// let src: gst::Element = gst::ElementFactory::make("videotestsrc").build().unwrap();
println!("using videoconvert");
let sink = gst::Bin::default();
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()
};
pipeline.add_many([&src, &decode, &sink]).unwrap();
src.link(&decode).unwrap();
// decode.link(>ksink).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 = pipeline.bus().unwrap();
pipeline
.set_state(gst::State::Playing)
.expect("Unable to set the pipeline 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 pipeline = RefCell::new(Some(pipeline));
let bus_watch = RefCell::new(Some(bus_watch));
app.connect_shutdown(move |_| {
window.close();
drop(bus_watch.borrow_mut().take());
if let Some(pipeline) = pipeline.borrow_mut().take() {
pipeline
.set_state(gst::State::Null)
.expect("Unable to set the pipeline 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
}
it runs but fails with these errors using GST_DEBUG=3
0:00:00.975147544 51628 0x7d57e80010a0 FIXME qtdemux qtdemux_types.c:268:qtdemux_type_get: unknown QuickTime node type iods
0:00:00.979885445 51628 0x7d57e80010a0 WARN h264parse gsth264parse.c:2201:gst_h264_parse_update_src_caps:<h264parse0> VUI framerate 30000.0 exceeds allowed maximum 64.0
0:00:01.038495649 51628 0x7d57e8001380 WARN h264parse gsth264parse.c:2201:gst_h264_parse_update_src_caps:<h264parse0> VUI framerate 30000.0 exceeds allowed maximum 64.0
0:00:01.040271549 51628 0x7d57e8001380 WARN h264parse gsth264parse.c:2201:gst_h264_parse_update_src_caps:<h264parse0> VUI framerate 30000.0 exceeds allowed maximum 64.0
0:00:01.178174540 51628 0x7d57e80010a0 WARN qtdemux qtdemux.c:7439:gst_qtdemux_loop:<qtdemux0> error: Internal data stream error.
0:00:01.178203154 51628 0x7d57e80010a0 WARN qtdemux qtdemux.c:7439:gst_qtdemux_loop:<qtdemux0> error: streaming stopped, reason not-linked (-1)
Error from Some("/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstQTDemux:qtdemux0"): Internal data stream error. (Some("../gst/isomp4/qtdemux.c(7439): gst_qtdemux_loop (): /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstQTDemux:qtdemux0:\nstreaming stopped, reason not-linked (-1)"))