Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/video
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2023-10-30 12:21:25 +0300
committerSebastian Dröge <sebastian@centricular.com>2023-10-30 12:21:25 +0300
commit74c04d79c91fb58d4725c77876d6c6cde0559e66 (patch)
treeb90214a63b69ae1611a59a8d4d76b5dc5f918d10 /video
parentb771afe8be48198eadac1635ad0e897fdd12f1d3 (diff)
gtk4: Use async-channel instead of the glib MainContext channel
The latter will be removed in favour of using async code in the future, and async code generally allows for more flexible message handling than the callback based MainContext channel. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1375>
Diffstat (limited to 'video')
-rw-r--r--video/gtk4/Cargo.toml1
-rw-r--r--video/gtk4/src/sink/imp.rs46
2 files changed, 29 insertions, 18 deletions
diff --git a/video/gtk4/Cargo.toml b/video/gtk4/Cargo.toml
index b9f6b3948..b380303d0 100644
--- a/video/gtk4/Cargo.toml
+++ b/video/gtk4/Cargo.toml
@@ -21,6 +21,7 @@ gst_gl = { package = "gstreamer-gl", git = "https://gitlab.freedesktop.org/gstre
gst_gl_wayland = { package = "gstreamer-gl-wayland", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_16"], optional = true }
gst_gl_x11 = { package = "gstreamer-gl-x11", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_16"], optional = true }
gst_gl_egl = { package = "gstreamer-gl-egl", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_16"], optional = true }
+async-channel = "2.0.0"
[target.'cfg(target_os = "macos")'.dependencies]
diff --git a/video/gtk4/src/sink/imp.rs b/video/gtk4/src/sink/imp.rs
index 3a1059d6e..fd5b7fd42 100644
--- a/video/gtk4/src/sink/imp.rs
+++ b/video/gtk4/src/sink/imp.rs
@@ -13,7 +13,7 @@ use super::SinkEvent;
use crate::sink::frame::Frame;
use crate::sink::paintable::Paintable;
-use glib::{thread_guard::ThreadGuard, Sender};
+use glib::thread_guard::ThreadGuard;
use gtk::prelude::*;
use gtk::{gdk, glib};
@@ -60,7 +60,7 @@ static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
pub struct PaintableSink {
paintable: Mutex<Option<ThreadGuard<Paintable>>>,
info: Mutex<Option<gst_video::VideoInfo>>,
- sender: Mutex<Option<Sender<SinkEvent>>>,
+ sender: Mutex<Option<async_channel::Sender<SinkEvent>>>,
pending_frame: Mutex<Option<Frame>>,
cached_caps: Mutex<Option<gst::Caps>>,
}
@@ -449,10 +449,16 @@ impl VideoSinkImpl for PaintableSink {
gst::FlowError::Flushing
})?;
- sender.send(SinkEvent::FrameChanged).map_err(|_| {
- gst::error!(CAT, imp: self, "Have main thread receiver shut down");
- gst::FlowError::Flushing
- })?;
+ match sender.try_send(SinkEvent::FrameChanged) {
+ Ok(_) => (),
+ Err(async_channel::TrySendError::Full(_)) => {
+ gst::warning!(CAT, imp: self, "Have too many pending frames");
+ }
+ Err(async_channel::TrySendError::Closed(_)) => {
+ gst::error!(CAT, imp: self, "Have main thread receiver shut down");
+ return Err(gst::FlowError::Flushing);
+ }
+ }
Ok(gst::FlowSuccess::Ok)
}
@@ -521,20 +527,24 @@ impl PaintableSink {
gst::debug!(CAT, imp: self, "Initializing paintable");
// The channel for the SinkEvents
- let (sender, receiver) = glib::MainContext::channel(glib::Priority::DEFAULT);
- let self_ = self.to_owned();
+ let (sender, receiver) = async_channel::bounded(3);
- let paintable = utils::invoke_on_main_thread(move || {
- // Attach the receiver from the main thread to make sure it is called
- // from a place where it can acquire the default main context.
- receiver.attach(
- Some(&glib::MainContext::default()),
- glib::clone!(
- @weak self_ => @default-return glib::ControlFlow::Break,
- move |action| self_.do_action(action)
- ),
- );
+ // Spawn an async task on the main context to handle the channel messages
+ let main_context = glib::MainContext::default();
+
+ let self_ = self.downgrade();
+ main_context.spawn(async move {
+ while let Ok(action) = receiver.recv().await {
+ let Some(self_) = self_.upgrade() else {
+ break;
+ };
+ self_.do_action(action);
+ }
+ });
+
+ // Create the paintable from the main thread
+ let paintable = utils::invoke_on_main_thread(move || {
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
{
let gdk_context = if let GLContext::Initialized { gdk_context, .. } =