diff --git a/gstreamer-player/Cargo.toml b/gstreamer-player/Cargo.toml index b920b902b..302df4b02 100644 --- a/gstreamer-player/Cargo.toml +++ b/gstreamer-player/Cargo.toml @@ -20,6 +20,7 @@ ffi = { package = "gstreamer-player-sys", path = "sys" } glib = { git = "https://github.com/gtk-rs/gtk-rs" } gst = { package = "gstreamer", path = "../gstreamer", features = ["v1_12"] } gst-video = { package = "gstreamer-video", path = "../gstreamer-video", features = ["v1_12"] } +once_cell = "1.0" [build-dependencies] gstreamer-rs-lgpl-docs = { path = "../docs", optional = true } diff --git a/gstreamer-player/src/subclass/player_video_renderer.rs b/gstreamer-player/src/subclass/player_video_renderer.rs index af4217cd8..45c12074c 100644 --- a/gstreamer-player/src/subclass/player_video_renderer.rs +++ b/gstreamer-player/src/subclass/player_video_renderer.rs @@ -25,12 +25,37 @@ unsafe extern "C" fn video_renderer_create_video_sink *mut gst::ffi::GstElement { + use once_cell::sync::Lazy; + static VIDEO_SINK_QUARK: Lazy = + Lazy::new(|| glib::Quark::from_string("gstreamer-rs-player-video-sink")); + let instance = &*(video_renderer as *mut T::Instance); let imp = instance.get_impl(); - imp.create_video_sink( + let sink = imp.create_video_sink( from_glib_borrow::<_, PlayerVideoRenderer>(video_renderer).unsafe_cast_ref(), &Player::from_glib_borrow(player), - ) - .to_glib_full() + ); + + let sink_ptr: *mut gst::ffi::GstElement = sink.to_glib_none().0; + + let old_sink_ptr = + glib::gobject_ffi::g_object_get_qdata(video_renderer as *mut _, VIDEO_SINK_QUARK.to_glib()) + as *mut gst::ffi::GstElement; + if !old_sink_ptr.is_null() && old_sink_ptr != sink_ptr { + panic!("Video sink must not change"); + } + + unsafe extern "C" fn unref(ptr: glib::ffi::gpointer) { + glib::gobject_ffi::g_object_unref(ptr as *mut _); + } + + glib::gobject_ffi::g_object_set_qdata_full( + video_renderer as *mut _, + VIDEO_SINK_QUARK.to_glib(), + glib::gobject_ffi::g_object_ref(sink_ptr as *mut _) as *mut _, + Some(unref), + ); + + sink_ptr }