gst-plugins-rs/generic/threadshare/src/udpsink/imp.rs

1334 lines
48 KiB
Rust
Raw Normal View History

// Copyright (C) 2019 Mathieu Duponchelle <mathieu@centricular.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
// Boston, MA 02110-1335, USA.
//
// SPDX-License-Identifier: LGPL-2.1-or-later
use futures::future::BoxFuture;
use futures::prelude::*;
use futures::stream::Peekable;
2021-06-03 18:20:54 +00:00
use gst::glib;
use gst::prelude::*;
use gst::subclass::prelude::*;
use gst::EventView;
use gst::{element_error, error_msg};
2020-11-22 14:24:55 +00:00
use once_cell::sync::Lazy;
use crate::runtime::prelude::*;
use crate::runtime::{self, Async, Context, PadSink, PadSinkRef, PadSinkWeak, Task};
use crate::socket::{wrap_socket, GioSocketWrapper};
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
use std::collections::BTreeSet;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
use std::pin::Pin;
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
use std::sync::Mutex;
use std::task::Poll;
use std::time::Duration;
use std::u16;
use std::u8;
const DEFAULT_HOST: Option<&str> = Some("127.0.0.1");
const DEFAULT_PORT: i32 = 5004;
const DEFAULT_SYNC: bool = true;
const DEFAULT_BIND_ADDRESS: &str = "0.0.0.0";
const DEFAULT_BIND_PORT: i32 = 0;
const DEFAULT_BIND_ADDRESS_V6: &str = "::";
const DEFAULT_BIND_PORT_V6: i32 = 0;
const DEFAULT_SOCKET: Option<GioSocketWrapper> = None;
const DEFAULT_USED_SOCKET: Option<GioSocketWrapper> = None;
const DEFAULT_SOCKET_V6: Option<GioSocketWrapper> = None;
const DEFAULT_USED_SOCKET_V6: Option<GioSocketWrapper> = None;
const DEFAULT_AUTO_MULTICAST: bool = true;
const DEFAULT_LOOP: bool = true;
const DEFAULT_TTL: u32 = 64;
const DEFAULT_TTL_MC: u32 = 1;
const DEFAULT_QOS_DSCP: i32 = -1;
const DEFAULT_CLIENTS: &str = "";
const DEFAULT_CONTEXT: &str = "";
const DEFAULT_CONTEXT_WAIT: Duration = Duration::ZERO;
#[derive(Debug, Clone)]
struct Settings {
sync: bool,
bind_address: String,
bind_port: i32,
bind_address_v6: String,
bind_port_v6: i32,
socket: Option<GioSocketWrapper>,
used_socket: Option<GioSocketWrapper>,
socket_v6: Option<GioSocketWrapper>,
used_socket_v6: Option<GioSocketWrapper>,
auto_multicast: bool,
multicast_loop: bool,
ttl: u32,
ttl_mc: u32,
qos_dscp: i32,
context: String,
context_wait: Duration,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
clients: BTreeSet<SocketAddr>,
latency: Option<gst::ClockTime>,
}
impl Default for Settings {
fn default() -> Self {
Settings {
sync: DEFAULT_SYNC,
bind_address: DEFAULT_BIND_ADDRESS.into(),
bind_port: DEFAULT_BIND_PORT,
bind_address_v6: DEFAULT_BIND_ADDRESS_V6.into(),
bind_port_v6: DEFAULT_BIND_PORT_V6,
socket: DEFAULT_SOCKET,
used_socket: DEFAULT_USED_SOCKET,
socket_v6: DEFAULT_SOCKET_V6,
used_socket_v6: DEFAULT_USED_SOCKET_V6,
auto_multicast: DEFAULT_AUTO_MULTICAST,
multicast_loop: DEFAULT_LOOP,
ttl: DEFAULT_TTL,
ttl_mc: DEFAULT_TTL_MC,
qos_dscp: DEFAULT_QOS_DSCP,
context: DEFAULT_CONTEXT.into(),
context_wait: DEFAULT_CONTEXT_WAIT,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
clients: BTreeSet::from([SocketAddr::new(
DEFAULT_HOST.unwrap().parse().unwrap(),
DEFAULT_PORT as u16,
)]),
latency: None,
}
}
}
2020-11-22 14:24:55 +00:00
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
gst::DebugCategory::new(
"ts-udpsink",
gst::DebugColorFlags::empty(),
Some("Thread-sharing UDP sink"),
2020-11-22 14:24:55 +00:00
)
});
#[derive(Debug)]
2020-03-26 18:07:25 +00:00
enum TaskItem {
Buffer(gst::Buffer),
Event(gst::Event),
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
#[derive(Clone, Debug)]
struct UdpSinkPadHandler;
2020-03-26 18:07:25 +00:00
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
impl PadSinkHandler for UdpSinkPadHandler {
type ElementImpl = UdpSink;
2020-03-26 18:07:25 +00:00
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn sink_chain(
self,
_pad: PadSinkWeak,
elem: super::UdpSink,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
buffer: gst::Buffer,
) -> BoxFuture<'static, Result<gst::FlowSuccess, gst::FlowError>> {
let sender = elem.imp().clone_item_sender();
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
async move {
if sender.send_async(TaskItem::Buffer(buffer)).await.is_err() {
gst::debug!(CAT, obj: &elem, "Flushing");
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
return Err(gst::FlowError::Flushing);
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
Ok(gst::FlowSuccess::Ok)
2020-03-26 18:07:25 +00:00
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
.boxed()
2020-03-26 18:07:25 +00:00
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn sink_chain_list(
self,
_pad: PadSinkWeak,
elem: super::UdpSink,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
list: gst::BufferList,
) -> BoxFuture<'static, Result<gst::FlowSuccess, gst::FlowError>> {
let sender = elem.imp().clone_item_sender();
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
async move {
for buffer in list.iter_owned() {
if sender.send_async(TaskItem::Buffer(buffer)).await.is_err() {
gst::debug!(CAT, obj: &elem, "Flushing");
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
return Err(gst::FlowError::Flushing);
}
}
Ok(gst::FlowSuccess::Ok)
2020-03-26 18:07:25 +00:00
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
.boxed()
}
2020-03-26 18:07:25 +00:00
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn sink_event_serialized(
self,
_pad: PadSinkWeak,
elem: super::UdpSink,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
event: gst::Event,
) -> BoxFuture<'static, bool> {
let sender = elem.imp().clone_item_sender();
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
async move {
if let EventView::FlushStop(_) = event.view() {
let imp = elem.imp();
return imp.task.flush_stop().await_maybe_on_context().is_ok();
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
} else if sender.send_async(TaskItem::Event(event)).await.is_err() {
gst::debug!(CAT, obj: &elem, "Flushing");
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
}
2020-03-26 18:07:25 +00:00
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
true
}
.boxed()
2020-03-26 18:07:25 +00:00
}
fn sink_event(&self, _pad: &PadSinkRef, imp: &UdpSink, event: gst::Event) -> bool {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
if let EventView::FlushStart(..) = event.view() {
return imp.task.flush_start().await_maybe_on_context().is_ok();
2020-03-26 18:07:25 +00:00
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
true
2020-03-26 18:07:25 +00:00
}
}
#[derive(Debug)]
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
enum Command {
AddClient(SocketAddr),
RemoveClient(SocketAddr),
ReplaceWithClients(BTreeSet<SocketAddr>),
SetLatency(Option<gst::ClockTime>),
SetSync(bool),
2020-03-26 18:07:25 +00:00
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
struct UdpSinkTask {
element: super::UdpSink,
item_receiver: Peekable<flume::r#async::RecvStream<'static, TaskItem>>,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
cmd_receiver: flume::Receiver<Command>,
clients: BTreeSet<SocketAddr>,
socket: Option<Async<UdpSocket>>,
socket_v6: Option<Async<UdpSocket>>,
sync: bool,
latency: Option<gst::ClockTime>,
segment: Option<gst::Segment>,
}
2020-03-26 18:07:25 +00:00
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
impl UdpSinkTask {
fn new(
element: &super::UdpSink,
item_receiver: flume::Receiver<TaskItem>,
cmd_receiver: flume::Receiver<Command>,
) -> Self {
UdpSinkTask {
element: element.clone(),
item_receiver: item_receiver.into_stream().peekable(),
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
cmd_receiver,
clients: Default::default(),
socket: None,
socket_v6: None,
sync: false,
latency: None,
segment: None,
}
2020-03-26 18:07:25 +00:00
}
async fn flush(&mut self) {
// Purge the channel
while let Poll::Ready(Some(_item)) = futures::poll!(self.item_receiver.next()) {}
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn process_command(&mut self, cmd: Command) {
use Command::*;
match cmd {
AddClient(client) => self.add_client(client),
RemoveClient(client) => self.remove_client(&client),
ReplaceWithClients(clients) => self.replace_with_clients(clients),
SetSync(sync) => self.sync = sync,
SetLatency(latency) => self.latency = latency,
}
2020-03-26 18:07:25 +00:00
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
}
2020-03-26 18:07:25 +00:00
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
/// Socket configuration.
impl UdpSinkTask {
fn prepare_socket(
&self,
settings: &mut Settings,
family: SocketFamily,
) -> Result<Option<Async<UdpSocket>>, gst::ErrorMessage> {
let wrapped_socket = match family {
SocketFamily::Ipv4 => &settings.socket,
SocketFamily::Ipv6 => &settings.socket_v6,
};
2020-03-26 18:07:25 +00:00
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
if let Some(ref wrapped_socket) = wrapped_socket {
let socket: UdpSocket = wrapped_socket.get();
let socket = Async::<UdpSocket>::try_from(socket).map_err(|err| {
error_msg!(
gst::ResourceError::OpenWrite,
["Failed to setup Async socket: {}", err]
)
})?;
2020-03-26 18:07:25 +00:00
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
match family {
SocketFamily::Ipv4 => {
settings.used_socket = Some(wrapped_socket.clone());
}
SocketFamily::Ipv6 => {
settings.used_socket_v6 = Some(wrapped_socket.clone());
}
}
Ok(Some(socket))
} else {
let bind_addr = match family {
SocketFamily::Ipv4 => &settings.bind_address,
SocketFamily::Ipv6 => &settings.bind_address_v6,
};
let bind_addr: IpAddr = bind_addr.parse().map_err(|err| {
error_msg!(
gst::ResourceError::Settings,
["Invalid address '{}' set: {}", bind_addr, err]
)
})?;
let bind_port = match family {
SocketFamily::Ipv4 => settings.bind_port,
SocketFamily::Ipv6 => settings.bind_port_v6,
};
let saddr = SocketAddr::new(bind_addr, bind_port as u16);
gst::debug!(CAT, obj: &self.element, "Binding to {:?}", saddr);
let socket = match family {
SocketFamily::Ipv4 => socket2::Socket::new(
socket2::Domain::IPV4,
socket2::Type::DGRAM,
Some(socket2::Protocol::UDP),
),
SocketFamily::Ipv6 => socket2::Socket::new(
socket2::Domain::IPV6,
socket2::Type::DGRAM,
Some(socket2::Protocol::UDP),
),
};
let socket = match socket {
Ok(socket) => socket,
Err(err) => {
gst::warning!(
CAT,
obj: &self.element,
"Failed to create {} socket: {}",
match family {
SocketFamily::Ipv4 => "IPv4",
SocketFamily::Ipv6 => "IPv6",
},
err
);
return Ok(None);
}
};
socket.bind(&saddr.into()).map_err(|err| {
error_msg!(
gst::ResourceError::OpenWrite,
["Failed to bind socket: {}", err]
)
})?;
let socket = Async::<UdpSocket>::try_from(socket).map_err(|err| {
error_msg!(
gst::ResourceError::OpenWrite,
["Failed to setup Async socket: {}", err]
)
})?;
let wrapper = wrap_socket(&socket)?;
if settings.qos_dscp != -1 {
wrapper.set_tos(settings.qos_dscp).map_err(|err| {
error_msg!(
gst::ResourceError::OpenWrite,
["Failed to set QoS DSCP: {}", err]
)
})?;
}
match family {
SocketFamily::Ipv4 => {
settings.used_socket = Some(wrapper);
}
SocketFamily::Ipv6 => {
settings.used_socket_v6 = Some(wrapper);
}
}
Ok(Some(socket))
2020-03-26 18:07:25 +00:00
}
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn add_client(&mut self, addr: SocketAddr) {
if self.clients.contains(&addr) {
gst::warning!(CAT, obj: &self.element, "Not adding client {:?} again", &addr);
return;
}
2020-03-26 18:07:25 +00:00
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
let udpsink = self.element.imp();
let mut settings = udpsink.settings.lock().unwrap();
match self.configure_client(&settings, &addr) {
Ok(()) => {
gst::info!(CAT, obj: &self.element, "Added client {:?}", addr);
self.clients.insert(addr);
}
Err(err) => {
gst::error!(CAT, obj: &self.element, "Failed to add client {:?}: {}", addr, err);
settings.clients = self.clients.clone();
self.element.post_error_message(err);
}
}
2020-03-26 18:07:25 +00:00
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn remove_client(&mut self, addr: &SocketAddr) {
if self.clients.take(addr).is_none() {
gst::warning!(CAT, obj: &self.element, "Not removing unknown client {:?}", &addr);
return;
}
2020-03-26 18:07:25 +00:00
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
let udpsink = self.element.imp();
let mut settings = udpsink.settings.lock().unwrap();
match self.unconfigure_client(&settings, addr) {
Ok(()) => {
gst::info!(CAT, obj: &self.element, "Removed client {:?}", addr);
}
Err(err) => {
gst::error!(CAT, obj: &self.element, "Failed to remove client {:?}: {}", addr, err);
settings.clients = self.clients.clone();
self.element.post_error_message(err);
}
}
2020-03-26 18:07:25 +00:00
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn replace_with_clients(&mut self, mut clients_to_add: BTreeSet<SocketAddr>) {
if clients_to_add.is_empty() {
gst::info!(CAT, obj: &self.element, "Clearing clients");
} else {
gst::info!(CAT, obj: &self.element, "Replacing clients");
}
let old_clients = std::mem::take(&mut self.clients);
let mut res = Ok(());
let udpsink = self.element.imp();
let mut settings = udpsink.settings.lock().unwrap();
for addr in old_clients.iter() {
if clients_to_add.take(addr).is_some() {
// client is already configured
self.clients.insert(*addr);
} else if let Err(err) = self.unconfigure_client(&settings, addr) {
gst::error!(CAT, obj: &self.element, "Failed to remove client {:?}: {}", addr, err);
res = Err(err);
} else {
gst::info!(CAT, obj: &self.element, "Removed client {:?}", addr);
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
}
}
for addr in clients_to_add.into_iter() {
if let Err(err) = self.configure_client(&settings, &addr) {
gst::error!(CAT, obj: &self.element, "Failed to add client {:?}: {}", addr, err);
res = Err(err);
} else {
gst::info!(CAT, obj: &self.element, "Added client {:?}", addr);
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
self.clients.insert(addr);
}
}
// FIXME: which error handling:
// - If at least one client could be configured, should we keep going? (current)
// - or, should we consider the preparation failed when the first client
// configuration fails? (previously)
if let Err(err) = res {
settings.clients = self.clients.clone();
self.element.post_error_message(err);
}
}
fn configure_client(
&self,
settings: &Settings,
client: &SocketAddr,
) -> Result<(), gst::ErrorMessage> {
if client.ip().is_multicast() {
match client.ip() {
IpAddr::V4(addr) => {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
if let Some(socket) = self.socket.as_ref() {
if settings.auto_multicast {
socket
.as_ref()
.join_multicast_v4(&addr, &Ipv4Addr::new(0, 0, 0, 0))
.map_err(|err| {
2020-12-20 18:43:45 +00:00
error_msg!(
gst::ResourceError::OpenWrite,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
[
"Failed to join multicast group for {:?}: {}",
client,
err
]
)
})?;
}
if settings.multicast_loop {
socket.as_ref().set_multicast_loop_v4(true).map_err(|err| {
2020-12-20 18:43:45 +00:00
error_msg!(
gst::ResourceError::OpenWrite,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
["Failed to set multicast loop for {:?}: {}", client, err]
)
})?;
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
socket
.as_ref()
.set_multicast_ttl_v4(settings.ttl_mc)
.map_err(|err| {
2020-12-20 18:43:45 +00:00
error_msg!(
gst::ResourceError::OpenWrite,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
["Failed to set multicast ttl for {:?}: {}", client, err]
)
})?;
}
}
IpAddr::V6(addr) => {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
if let Some(socket) = self.socket_v6.as_ref() {
if settings.auto_multicast {
socket.as_ref().join_multicast_v6(&addr, 0).map_err(|err| {
2020-12-20 18:43:45 +00:00
error_msg!(
gst::ResourceError::OpenWrite,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
["Failed to join multicast group for {:?}: {}", client, err]
)
})?;
}
if settings.multicast_loop {
socket.as_ref().set_multicast_loop_v6(true).map_err(|err| {
2020-12-20 18:43:45 +00:00
error_msg!(
gst::ResourceError::OpenWrite,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
["Failed to set multicast loop for {:?}: {}", client, err]
)
})?;
}
/* FIXME no API for set_multicast_ttl_v6 ? */
}
}
}
} else {
match client.ip() {
IpAddr::V4(_) => {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
if let Some(socket) = self.socket.as_ref() {
socket.as_ref().set_ttl(settings.ttl).map_err(|err| {
2020-12-20 18:43:45 +00:00
error_msg!(
gst::ResourceError::OpenWrite,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
["Failed to set unicast ttl for {:?}: {}", client, err]
)
})?;
}
}
IpAddr::V6(_) => {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
if let Some(socket) = self.socket_v6.as_ref() {
socket.as_ref().set_ttl(settings.ttl).map_err(|err| {
2020-12-20 18:43:45 +00:00
error_msg!(
gst::ResourceError::OpenWrite,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
["Failed to set unicast ttl for {:?}: {}", client, err]
)
})?;
}
}
}
}
Ok(())
}
fn unconfigure_client(
&self,
settings: &Settings,
client: &SocketAddr,
) -> Result<(), gst::ErrorMessage> {
if client.ip().is_multicast() {
match client.ip() {
IpAddr::V4(addr) => {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
if let Some(socket) = self.socket.as_ref() {
if settings.auto_multicast {
socket
.as_ref()
.leave_multicast_v4(&addr, &Ipv4Addr::new(0, 0, 0, 0))
.map_err(|err| {
2020-12-20 18:43:45 +00:00
error_msg!(
gst::ResourceError::OpenWrite,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
[
"Failed to leave multicast group for {:?}: {}",
client,
err
]
)
})?;
}
}
}
IpAddr::V6(addr) => {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
if let Some(socket) = self.socket_v6.as_ref() {
if settings.auto_multicast {
socket
.as_ref()
.leave_multicast_v6(&addr, 0)
.map_err(|err| {
error_msg!(
gst::ResourceError::OpenWrite,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
[
"Failed to leave multicast group for {:?}: {}",
client,
err
]
)
})?;
}
}
}
}
}
Ok(())
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
/// Buffer handling.
impl UdpSinkTask {
async fn render(&mut self, buffer: gst::Buffer) -> Result<(), gst::FlowError> {
let data = buffer.map_readable().map_err(|_| {
2020-12-20 18:43:45 +00:00
element_error!(
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
self.element,
gst::StreamError::Format,
["Failed to map buffer readable"]
);
gst::FlowError::Error
})?;
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
for client in self.clients.iter() {
let socket = match client.ip() {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
IpAddr::V4(_) => &mut self.socket,
IpAddr::V6(_) => &mut self.socket_v6,
};
if let Some(socket) = socket.as_mut() {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
gst::log!(CAT, obj: &self.element, "Sending to {:?}", &client);
socket.send_to(&data, *client).await.map_err(|err| {
2020-12-20 18:43:45 +00:00
element_error!(
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
self.element,
gst::StreamError::Failed,
("I/O error"),
["streaming stopped, I/O error {}", err]
);
gst::FlowError::Error
})?;
} else {
2020-12-20 18:43:45 +00:00
element_error!(
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
self.element,
gst::StreamError::Failed,
("I/O error"),
["No socket available for sending to {}", client]
);
return Err(gst::FlowError::Error);
}
}
gst::log!(
CAT,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
obj: &self.element,
"Sent buffer {:?} to all clients",
&buffer
);
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
Ok(())
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
/// Waits until specified time.
async fn sync(&self, running_time: gst::ClockTime) {
let now = self.element.current_running_time();
if let Ok(Some(delay)) = running_time.opt_checked_sub(now) {
gst::trace!(CAT, obj: &self.element, "sync: waiting {}", delay);
runtime::timer::delay_for(delay.into()).await;
}
}
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
impl TaskImpl for UdpSinkTask {
type Item = TaskItem;
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn prepare(&mut self) -> BoxFuture<'_, Result<(), gst::ErrorMessage>> {
async move {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
gst::info!(CAT, obj: &self.element, "Preparing Task");
assert!(self.clients.is_empty());
let clients = {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
let udpsink = self.element.imp();
let mut settings = udpsink.settings.lock().unwrap();
self.sync = settings.sync;
self.socket = self.prepare_socket(&mut settings, SocketFamily::Ipv4)?;
self.socket_v6 = self.prepare_socket(&mut settings, SocketFamily::Ipv6)?;
self.latency = settings.latency;
settings.clients.clone()
};
self.replace_with_clients(clients);
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
Ok(())
}
.boxed()
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn unprepare(&mut self) -> BoxFuture<'_, ()> {
async move {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
gst::info!(CAT, obj: &self.element, "Unpreparing Task");
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
let udpsink = self.element.imp();
let settings = udpsink.settings.lock().unwrap();
for addr in self.clients.iter() {
let _ = self.unconfigure_client(&settings, addr);
}
}
.boxed()
}
fn try_next(&mut self) -> BoxFuture<'_, Result<TaskItem, gst::FlowError>> {
async move {
loop {
gst::info!(CAT, obj: &self.element, "Awaiting next item or command");
futures::select_biased! {
cmd = self.cmd_receiver.recv_async() => {
self.process_command(cmd.unwrap());
}
item_opt = Pin::new(&mut self.item_receiver).peek() => {
// Check the peeked item in case we need to sync.
// The item will still be available in the channel
// in case this is cancelled by a state transition.
match item_opt {
Some(TaskItem::Buffer(buffer)) => {
if self.sync {
let rtime = self.segment.as_ref().and_then(|segment| {
segment
.downcast_ref::<gst::format::Time>()
.and_then(|segment| {
segment.to_running_time(buffer.pts()).opt_add(self.latency)
})
});
if let Some(rtime) = rtime {
// This can be cancelled by a state transition.
self.sync(rtime).await;
}
}
}
Some(_) => (),
None => {
panic!("Internal channel sender dropped while Task is Started");
}
}
// An item was peeked above, we can now pop it without losing it.
return Ok(self.item_receiver.next().await.unwrap());
}
}
}
}
.boxed()
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn handle_item(&mut self, item: TaskItem) -> BoxFuture<'_, Result<(), gst::FlowError>> {
async move {
gst::info!(CAT, obj: &self.element, "Handling {:?}", item);
match item {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
TaskItem::Buffer(buffer) => self.render(buffer).await.map_err(|err| {
element_error!(
&self.element,
gst::StreamError::Failed,
["Failed to render item, stopping task: {}", err]
);
gst::FlowError::Error
})?,
TaskItem::Event(event) => match event.view() {
EventView::Eos(_) => {
let _ = self
.element
.post_message(gst::message::Eos::builder().src(&self.element).build());
}
EventView::Segment(e) => {
self.segment = Some(e.segment().clone());
}
EventView::SinkMessage(e) => {
let _ = self.element.post_message(e.message());
}
_ => (),
},
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
Ok(())
}
.boxed()
}
fn stop(&mut self) -> BoxFuture<'_, Result<(), gst::ErrorMessage>> {
async {
gst::info!(CAT, obj: &self.element, "Stopping Task");
self.flush().await;
Ok(())
}
.boxed()
}
fn flush_start(&mut self) -> BoxFuture<'_, Result<(), gst::ErrorMessage>> {
async {
gst::info!(CAT, obj: &self.element, "Starting Task Flush");
self.flush().await;
Ok(())
}
.boxed()
}
}
2020-03-26 18:07:25 +00:00
#[derive(Debug)]
enum SocketFamily {
Ipv4,
Ipv6,
}
#[derive(Debug)]
pub struct UdpSink {
2020-03-26 18:07:25 +00:00
sink_pad: PadSink,
task: Task,
item_sender: Mutex<Option<flume::Sender<TaskItem>>>,
cmd_sender: Mutex<Option<flume::Sender<Command>>>,
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
settings: Mutex<Settings>,
2020-03-26 18:07:25 +00:00
}
impl UdpSink {
#[track_caller]
fn clone_item_sender(&self) -> flume::Sender<TaskItem> {
self.item_sender.lock().unwrap().as_ref().unwrap().clone()
}
fn prepare(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Preparing");
let context = {
let settings = self.settings.lock().unwrap();
Context::acquire(&settings.context, settings.context_wait).map_err(|err| {
2020-12-20 18:43:45 +00:00
error_msg!(
gst::ResourceError::OpenWrite,
["Failed to acquire Context: {}", err]
)
})?
};
// Enable backpressure for items
let (item_sender, item_receiver) = flume::bounded(0);
let (cmd_sender, cmd_receiver) = flume::unbounded();
let task_impl = UdpSinkTask::new(&*self.instance(), item_receiver, cmd_receiver);
self.task.prepare(task_impl, context).block_on()?;
*self.item_sender.lock().unwrap() = Some(item_sender);
*self.cmd_sender.lock().unwrap() = Some(cmd_sender);
gst::debug!(CAT, imp: self, "Started preparation");
Ok(())
}
fn unprepare(&self) {
gst::debug!(CAT, imp: self, "Unpreparing");
self.task.unprepare().block_on().unwrap();
gst::debug!(CAT, imp: self, "Unprepared");
}
fn stop(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Stopping");
self.task.stop().block_on()?;
gst::debug!(CAT, imp: self, "Stopped");
Ok(())
}
fn start(&self) -> Result<(), gst::ErrorMessage> {
gst::debug!(CAT, imp: self, "Starting");
self.task.start().block_on()?;
gst::debug!(CAT, imp: self, "Started");
Ok(())
2020-03-26 18:07:25 +00:00
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn add_client(&self, settings: &mut Settings, client: SocketAddr) {
settings.clients.insert(client);
if let Some(cmd_sender) = self.cmd_sender.lock().unwrap().as_mut() {
cmd_sender.send(Command::AddClient(client)).unwrap();
}
2020-03-26 18:07:25 +00:00
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn remove_client(&self, settings: &mut Settings, client: SocketAddr) {
settings.clients.remove(&client);
if let Some(cmd_sender) = self.cmd_sender.lock().unwrap().as_mut() {
cmd_sender.send(Command::RemoveClient(client)).unwrap();
}
}
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
fn replace_with_clients(
&self,
settings: &mut Settings,
clients: impl IntoIterator<Item = SocketAddr>,
) {
let clients = BTreeSet::<SocketAddr>::from_iter(clients);
if let Some(cmd_sender) = self.cmd_sender.lock().unwrap().as_mut() {
settings.clients = clients.clone();
cmd_sender
.send(Command::ReplaceWithClients(clients))
.unwrap();
} else {
settings.clients = clients;
}
2020-03-26 18:07:25 +00:00
}
}
fn try_into_socket_addr(imp: &UdpSink, host: &str, port: i32) -> Result<SocketAddr, ()> {
2020-03-26 18:07:25 +00:00
let addr: IpAddr = match host.parse() {
Err(err) => {
gst::error!(CAT, imp: imp, "Failed to parse host {}: {}", host, err);
2020-03-26 18:07:25 +00:00
return Err(());
}
2020-03-26 18:07:25 +00:00
Ok(addr) => addr,
};
2020-03-26 18:07:25 +00:00
let port: u16 = match port.try_into() {
Err(err) => {
gst::error!(CAT, imp: imp, "Invalid port {}: {}", port, err);
2020-03-26 18:07:25 +00:00
return Err(());
}
Ok(port) => port,
};
2020-03-26 18:07:25 +00:00
Ok(SocketAddr::new(addr, port))
}
#[glib::object_subclass]
impl ObjectSubclass for UdpSink {
const NAME: &'static str = "GstTsUdpSink";
type Type = super::UdpSink;
type ParentType = gst::Element;
fn with_class(klass: &Self::Class) -> Self {
Self {
sink_pad: PadSink::new(
2021-04-20 12:58:11 +00:00
gst::Pad::from_template(&klass.pad_template("sink").unwrap(), Some("sink")),
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
UdpSinkPadHandler,
),
2020-03-26 18:07:25 +00:00
task: Task::default(),
item_sender: Default::default(),
cmd_sender: Default::default(),
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
settings: Default::default(),
}
}
}
impl ObjectImpl for UdpSink {
fn properties() -> &'static [glib::ParamSpec] {
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
vec![
glib::ParamSpecString::builder("context")
.nick("Context")
.blurb("Context name to share threads with")
.default_value(Some(DEFAULT_CONTEXT))
.build(),
glib::ParamSpecUInt::builder("context-wait")
.nick("Context Wait")
.blurb("Throttle poll loop to run at most once every this many ms")
.maximum(1000)
.default_value(DEFAULT_CONTEXT_WAIT.as_millis() as u32)
.build(),
glib::ParamSpecBoolean::builder("sync")
.nick("Sync")
.blurb("Sync on the clock")
.default_value(DEFAULT_SYNC)
.build(),
glib::ParamSpecString::builder("bind-address")
.nick("Bind Address")
.blurb("Address to bind the socket to")
.default_value(Some(DEFAULT_BIND_ADDRESS))
.build(),
glib::ParamSpecInt::builder("bind-port")
.nick("Bind Port")
.blurb("Port to bind the socket to")
.minimum(0)
.maximum(u16::MAX as i32)
.default_value(DEFAULT_BIND_PORT)
.build(),
glib::ParamSpecString::builder("bind-address-v6")
.nick("Bind Address V6")
.blurb("Address to bind the V6 socket to")
.default_value(Some(DEFAULT_BIND_ADDRESS_V6))
.build(),
glib::ParamSpecInt::builder("bind-port-v6")
.nick("Bind Port")
.blurb("Port to bind the V6 socket to")
.minimum(0)
.maximum(u16::MAX as i32)
.default_value(DEFAULT_BIND_PORT_V6)
.build(),
glib::ParamSpecObject::builder::<gio::Socket>("socket")
.nick("Socket")
.blurb("Socket to use for UDP transmission. (None == allocate)")
.build(),
glib::ParamSpecObject::builder::<gio::Socket>("used-socket")
.nick("Used Socket")
.blurb("Socket currently in use for UDP transmission. (None = no socket)")
.read_only()
.build(),
glib::ParamSpecObject::builder::<gio::Socket>("socket-v6")
.nick("Socket V6")
.blurb("IPV6 Socket to use for UDP transmission. (None == allocate)")
.build(),
glib::ParamSpecObject::builder::<gio::Socket>("used-socket-v6")
.nick("Used Socket V6")
.blurb("V6 Socket currently in use for UDP transmission. (None = no socket)")
.read_only()
.build(),
glib::ParamSpecBoolean::builder("auto-multicast")
.nick("Auto multicast")
.blurb("Automatically join/leave the multicast groups, FALSE means user has to do it himself")
.default_value(DEFAULT_AUTO_MULTICAST)
.build(),
glib::ParamSpecBoolean::builder("loop")
.nick("Loop")
.blurb("Set the multicast loop parameter.")
.default_value(DEFAULT_LOOP)
.build(),
glib::ParamSpecUInt::builder("ttl")
.nick("Time To Live")
.blurb("Used for setting the unicast TTL parameter")
.maximum(u8::MAX as u32)
.default_value(DEFAULT_TTL)
.build(),
glib::ParamSpecUInt::builder("ttl-mc")
.nick("Time To Live Multicast")
.blurb("Used for setting the multicast TTL parameter")
.maximum(u8::MAX as u32)
.default_value(DEFAULT_TTL_MC)
.build(),
glib::ParamSpecInt::builder("qos-dscp")
.nick("QoS DSCP")
.blurb("Quality of Service, differentiated services code point (-1 default)")
.minimum(-1)
.maximum(63)
.default_value(DEFAULT_QOS_DSCP)
.build(),
glib::ParamSpecString::builder("clients")
.nick("Clients")
.blurb("A comma separated list of host:port pairs with destinations")
.default_value(Some(DEFAULT_CLIENTS))
.build(),
]
});
PROPERTIES.as_ref()
}
fn signals() -> &'static [glib::subclass::Signal] {
static SIGNALS: Lazy<Vec<glib::subclass::Signal>> = Lazy::new(|| {
vec![
2022-07-21 15:09:17 +00:00
glib::subclass::Signal::builder("add")
.param_types([String::static_type(), i32::static_type()])
2022-07-21 15:09:17 +00:00
.action()
.class_handler(|_, args| {
let element = args[0].get::<super::UdpSink>().expect("signal arg");
let host = args[1].get::<String>().expect("signal arg");
let port = args[2].get::<i32>().expect("signal arg");
let udpsink = element.imp();
if let Ok(addr) = try_into_socket_addr(udpsink, &host, port) {
2022-07-21 15:09:17 +00:00
let mut settings = udpsink.settings.lock().unwrap();
udpsink.add_client(&mut settings, addr);
}
2022-07-21 15:09:17 +00:00
None
})
.build(),
glib::subclass::Signal::builder("remove")
.param_types([String::static_type(), i32::static_type()])
2022-07-21 15:09:17 +00:00
.action()
.class_handler(|_, args| {
let element = args[0].get::<super::UdpSink>().expect("signal arg");
let host = args[1].get::<String>().expect("signal arg");
let port = args[2].get::<i32>().expect("signal arg");
let udpsink = element.imp();
if let Ok(addr) = try_into_socket_addr(udpsink, &host, port) {
2022-07-21 15:09:17 +00:00
let mut settings = udpsink.settings.lock().unwrap();
udpsink.remove_client(&mut settings, addr);
}
2022-07-21 15:09:17 +00:00
None
})
.build(),
glib::subclass::Signal::builder("clear")
.action()
.class_handler(|_, args| {
2021-04-25 12:41:22 +00:00
let element = args[0].get::<super::UdpSink>().expect("signal arg");
let udpsink = element.imp();
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
let mut settings = udpsink.settings.lock().unwrap();
udpsink.replace_with_clients(&mut settings, BTreeSet::new());
None
})
.build(),
]
});
SIGNALS.as_ref()
}
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let mut settings = self.settings.lock().unwrap();
2021-04-12 12:49:54 +00:00
match pspec.name() {
"sync" => {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
let sync = value.get().expect("type checked upstream");
settings.sync = sync;
if let Some(cmd_sender) = self.cmd_sender.lock().unwrap().as_mut() {
cmd_sender.send(Command::SetSync(sync)).unwrap();
}
}
"bind-address" => {
settings.bind_address = value
2021-04-25 12:41:22 +00:00
.get::<Option<String>>()
.expect("type checked upstream")
.unwrap_or_else(|| "".into());
}
"bind-port" => {
2021-04-25 12:41:22 +00:00
settings.bind_port = value.get().expect("type checked upstream");
}
"bind-address-v6" => {
settings.bind_address_v6 = value
2021-04-25 12:41:22 +00:00
.get::<Option<String>>()
.expect("type checked upstream")
.unwrap_or_else(|| "".into());
}
"bind-port-v6" => {
2021-04-25 12:41:22 +00:00
settings.bind_port_v6 = value.get().expect("type checked upstream");
}
"socket" => {
settings.socket = value
2021-04-25 12:41:22 +00:00
.get::<Option<gio::Socket>>()
.expect("type checked upstream")
.map(|socket| GioSocketWrapper::new(&socket));
}
"used-socket" => {
unreachable!();
}
"socket-v6" => {
settings.socket_v6 = value
2021-04-25 12:41:22 +00:00
.get::<Option<gio::Socket>>()
.expect("type checked upstream")
.map(|socket| GioSocketWrapper::new(&socket));
}
"used-socket-v6" => {
unreachable!();
}
"auto-multicast" => {
2021-04-25 12:41:22 +00:00
settings.auto_multicast = value.get().expect("type checked upstream");
}
"loop" => {
2021-04-25 12:41:22 +00:00
settings.multicast_loop = value.get().expect("type checked upstream");
}
"ttl" => {
2021-04-25 12:41:22 +00:00
settings.ttl = value.get().expect("type checked upstream");
}
"ttl-mc" => {
2021-04-25 12:41:22 +00:00
settings.ttl_mc = value.get().expect("type checked upstream");
}
"qos-dscp" => {
2021-04-25 12:41:22 +00:00
settings.qos_dscp = value.get().expect("type checked upstream");
}
"clients" => {
2021-04-25 12:41:22 +00:00
let clients = value
.get::<Option<String>>()
.expect("type checked upstream")
.unwrap_or_else(|| "".into());
2020-03-26 18:07:25 +00:00
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
let clients = clients.split(',').filter_map(|client| {
2020-03-26 18:07:25 +00:00
let rsplit: Vec<&str> = client.rsplitn(2, ':').collect();
if rsplit.len() == 2 {
rsplit[0]
.parse::<i32>()
2020-03-26 18:07:25 +00:00
.map_err(|err| {
gst::error!(CAT, imp: self, "Invalid port {}: {}", rsplit[0], err);
2020-03-26 18:07:25 +00:00
})
.and_then(|port| try_into_socket_addr(self, rsplit[1], port))
2020-03-26 18:07:25 +00:00
.ok()
} else {
None
}
});
2020-03-26 18:07:25 +00:00
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
self.replace_with_clients(&mut settings, clients);
}
"context" => {
settings.context = value
2021-04-25 12:41:22 +00:00
.get::<Option<String>>()
.expect("type checked upstream")
.unwrap_or_else(|| DEFAULT_CONTEXT.into());
}
"context-wait" => {
settings.context_wait = Duration::from_millis(
value.get::<u32>().expect("type checked upstream").into(),
);
}
_ => unimplemented!(),
}
}
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let settings = self.settings.lock().unwrap();
2021-04-12 12:49:54 +00:00
match pspec.name() {
"sync" => settings.sync.to_value(),
"bind-address" => settings.bind_address.to_value(),
"bind-port" => settings.bind_port.to_value(),
"bind-address-v6" => settings.bind_address_v6.to_value(),
"bind-port-v6" => settings.bind_port_v6.to_value(),
"socket" => settings
.socket
.as_ref()
.map(GioSocketWrapper::as_socket)
.to_value(),
"used-socket" => settings
.used_socket
.as_ref()
.map(GioSocketWrapper::as_socket)
.to_value(),
"socket-v6" => settings
.socket_v6
.as_ref()
.map(GioSocketWrapper::as_socket)
.to_value(),
"used-socket-v6" => settings
.used_socket_v6
.as_ref()
.map(GioSocketWrapper::as_socket)
.to_value(),
"auto-multicast" => settings.sync.to_value(),
"loop" => settings.multicast_loop.to_value(),
"ttl" => settings.ttl.to_value(),
"ttl-mc" => settings.ttl_mc.to_value(),
"qos-dscp" => settings.qos_dscp.to_value(),
"clients" => {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
let clients = settings.clients.clone();
drop(settings);
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
let clients: Vec<String> = clients.iter().map(ToString::to_string).collect();
clients.join(",").to_value()
}
"context" => settings.context.to_value(),
"context-wait" => (settings.context_wait.as_millis() as u32).to_value(),
_ => unimplemented!(),
}
}
fn constructed(&self) {
self.parent_constructed();
let obj = self.instance();
obj.add_pad(self.sink_pad.gst_pad()).unwrap();
obj.set_element_flags(gst::ElementFlags::SINK);
}
}
2021-10-23 08:57:31 +00:00
impl GstObjectImpl for UdpSink {}
impl ElementImpl for UdpSink {
fn metadata() -> Option<&'static gst::subclass::ElementMetadata> {
static ELEMENT_METADATA: Lazy<gst::subclass::ElementMetadata> = Lazy::new(|| {
gst::subclass::ElementMetadata::new(
"Thread-sharing UDP sink",
"Sink/Network",
"Thread-sharing UDP sink",
"Mathieu <mathieu@centricular.com>",
)
});
Some(&*ELEMENT_METADATA)
}
fn pad_templates() -> &'static [gst::PadTemplate] {
static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| {
let caps = gst::Caps::new_any();
let sink_pad_template = gst::PadTemplate::new(
"sink",
gst::PadDirection::Sink,
gst::PadPresence::Always,
&caps,
)
.unwrap();
vec![sink_pad_template]
});
PAD_TEMPLATES.as_ref()
}
fn change_state(
&self,
transition: gst::StateChange,
) -> Result<gst::StateChangeSuccess, gst::StateChangeError> {
gst::trace!(CAT, imp: self, "Changing state {:?}", transition);
match transition {
gst::StateChange::NullToReady => {
self.prepare().map_err(|err| {
self.post_error_message(err);
gst::StateChangeError
})?;
}
gst::StateChange::ReadyToPaused => {
self.start().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::PausedToReady => {
self.stop().map_err(|_| gst::StateChangeError)?;
}
gst::StateChange::ReadyToNull => {
self.unprepare();
}
_ => (),
}
self.parent_change_state(transition)
}
fn send_event(&self, event: gst::Event) -> bool {
match event.view() {
EventView::Latency(ev) => {
ts/udpsink: reduce sync primitives in async hot path The way the runtime::Task is implemented, UdpSinkTask is available as a mutable ref in all the TaskImpl functions, which offers the opportunity to avoid using Mutexes. Main higlights: - Removed the back and forth calls between UdpSinkPadHandler and UdpSinkTask. - Udp sockets are now part of UdpSinkTask, which is also in charge of preparing them instead of leaving this to UdpSink. This removed the need for Context::enter since TaskImpl::prepare already operates under the target Context. - In order for the clients list to be visible from the UdpSink, this list was maintained by UdpSinkPadHandler which was also in charge of (un)configuring the Udp sockets. The sockets are now part of UdpSinkTask, which is also in charge of the (un)configuration. Add/remove/replace requests are passed as commands to the UdpSinkTask via a channel. - The clients list visible to the UdpSink is now part of the Settings (it is also a read/write property). Since the actual socket (un)configuration is asynchronously handled by the Task, the clients list is updated by the add/remove/replace signals and set_property("clients", ..). Should a problem occur during the async (un)configuration, and only in this case, the UdpSinkTask would update the clients lists in Settings accordingly so that it stays consistent with the internal state. - The function clear_clients was renamed as replace_with_clients. - clients is now based on a BTreeSet instead of a Vec. All the managing functions perform some sort of lookup prior to updating the collection. It also ease implementation. - Removed the UdpSinkPadHandler RwLock. Using flume channels, we are able to clone the Receiver so it can be stored in UdpSink and reused when preparing the UdpSinkTask.
2022-06-23 16:50:11 +00:00
let latency = Some(ev.latency());
if let Some(cmd_sender) = self.cmd_sender.lock().unwrap().as_mut() {
cmd_sender.send(Command::SetLatency(latency)).unwrap();
}
self.settings.lock().unwrap().latency = latency;
self.sink_pad.gst_pad().push_event(event)
}
EventView::Step(..) => false,
_ => self.sink_pad.gst_pad().push_event(event),
}
}
}