2018-03-06 09:38:27 +00:00
// Copyright (C) 2018 Sebastian Dröge <sebastian@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.
2022-01-15 19:18:47 +00:00
//
// SPDX-License-Identifier: LGPL-2.1-or-later
2018-03-06 09:38:27 +00:00
2019-12-02 09:30:07 +00:00
use futures ::future ::BoxFuture ;
2019-11-24 20:12:40 +00:00
use futures ::prelude ::* ;
2021-06-03 18:20:54 +00:00
use gst ::glib ;
2018-03-06 09:38:27 +00:00
use gst ::prelude ::* ;
2018-12-06 11:03:04 +00:00
use gst ::subclass ::prelude ::* ;
2019-03-13 16:07:53 +00:00
use gst_net ::* ;
2018-03-06 09:38:27 +00:00
2020-11-22 14:24:55 +00:00
use once_cell ::sync ::Lazy ;
2018-11-13 12:13:23 +00:00
2020-04-27 09:22:26 +00:00
use std ::i32 ;
2018-07-06 07:19:59 +00:00
use std ::io ;
2021-12-14 18:40:27 +00:00
use std ::net ::{ IpAddr , Ipv4Addr , Ipv6Addr , SocketAddr , UdpSocket } ;
2022-06-24 09:48:04 +00:00
use std ::sync ::Mutex ;
2021-05-26 09:54:34 +00:00
use std ::time ::Duration ;
2018-03-09 15:32:21 +00:00
use std ::u16 ;
2018-03-06 09:38:27 +00:00
2019-12-02 09:30:07 +00:00
use crate ::runtime ::prelude ::* ;
2022-06-24 09:48:04 +00:00
use crate ::runtime ::{ Async , Context , PadSrc , PadSrcRef , Task } ;
2019-12-02 09:30:07 +00:00
2020-11-14 17:09:42 +00:00
use crate ::socket ::{ wrap_socket , GioSocketWrapper , Socket , SocketError , SocketRead } ;
2018-03-08 20:26:34 +00:00
2020-04-27 09:22:26 +00:00
const DEFAULT_ADDRESS : Option < & str > = Some ( " 0.0.0.0 " ) ;
2022-08-09 15:42:53 +00:00
const DEFAULT_PORT : i32 = 5004 ;
2018-05-23 07:32:06 +00:00
const DEFAULT_REUSE : bool = true ;
2018-03-08 20:26:34 +00:00
const DEFAULT_CAPS : Option < gst ::Caps > = None ;
2020-04-27 09:22:26 +00:00
const DEFAULT_MTU : u32 = 1492 ;
2018-11-13 12:13:23 +00:00
const DEFAULT_SOCKET : Option < GioSocketWrapper > = None ;
const DEFAULT_USED_SOCKET : Option < GioSocketWrapper > = None ;
2019-02-21 18:12:09 +00:00
const DEFAULT_CONTEXT : & str = " " ;
2021-10-09 10:17:05 +00:00
const DEFAULT_CONTEXT_WAIT : Duration = Duration ::ZERO ;
2019-03-13 16:07:53 +00:00
const DEFAULT_RETRIEVE_SENDER_ADDRESS : bool = true ;
2018-03-08 20:26:34 +00:00
#[ derive(Debug, Clone) ]
struct Settings {
address : Option < String > ,
2020-04-27 09:22:26 +00:00
port : i32 , // for conformity with C based udpsrc
2018-05-23 07:32:06 +00:00
reuse : bool ,
2018-03-08 20:26:34 +00:00
caps : Option < gst ::Caps > ,
mtu : u32 ,
2018-11-13 12:13:23 +00:00
socket : Option < GioSocketWrapper > ,
used_socket : Option < GioSocketWrapper > ,
2018-03-08 20:26:34 +00:00
context : String ,
2021-05-26 09:54:34 +00:00
context_wait : Duration ,
2019-03-13 16:07:53 +00:00
retrieve_sender_address : bool ,
2018-03-08 20:26:34 +00:00
}
impl Default for Settings {
fn default ( ) -> Self {
Settings {
address : DEFAULT_ADDRESS . map ( Into ::into ) ,
port : DEFAULT_PORT ,
2018-05-23 07:32:06 +00:00
reuse : DEFAULT_REUSE ,
2018-03-08 20:26:34 +00:00
caps : DEFAULT_CAPS ,
mtu : DEFAULT_MTU ,
2018-11-13 12:13:23 +00:00
socket : DEFAULT_SOCKET ,
used_socket : DEFAULT_USED_SOCKET ,
2018-03-08 20:26:34 +00:00
context : DEFAULT_CONTEXT . into ( ) ,
2018-03-12 14:19:46 +00:00
context_wait : DEFAULT_CONTEXT_WAIT ,
2019-03-13 16:07:53 +00:00
retrieve_sender_address : DEFAULT_RETRIEVE_SENDER_ADDRESS ,
2018-03-08 20:26:34 +00:00
}
}
}
2019-12-02 09:30:07 +00:00
#[ derive(Debug) ]
2021-12-14 18:40:27 +00:00
struct UdpReader ( Async < UdpSocket > ) ;
2019-12-02 09:30:07 +00:00
2018-07-06 07:19:59 +00:00
impl UdpReader {
2021-12-14 18:40:27 +00:00
fn new ( socket : Async < UdpSocket > ) -> Self {
2020-04-20 19:35:06 +00:00
UdpReader ( socket )
2018-07-06 07:19:59 +00:00
}
}
impl SocketRead for UdpReader {
const DO_TIMESTAMP : bool = true ;
2019-12-02 09:30:07 +00:00
fn read < ' buf > (
2020-04-20 19:35:06 +00:00
& ' buf mut self ,
2019-12-02 09:30:07 +00:00
buffer : & ' buf mut [ u8 ] ,
) -> BoxFuture < ' buf , io ::Result < ( usize , Option < std ::net ::SocketAddr > ) > > {
async move {
2020-04-20 19:35:06 +00:00
self . 0
2019-12-02 09:30:07 +00:00
. recv_from ( buffer )
. await
. map ( | ( read_size , saddr ) | ( read_size , Some ( saddr ) ) )
}
. boxed ( )
2018-07-06 07:19:59 +00:00
}
}
2022-06-24 09:48:04 +00:00
#[ derive(Clone, Debug) ]
struct UdpSrcPadHandler ;
2019-10-31 22:34:21 +00:00
2019-12-02 09:30:07 +00:00
impl PadSrcHandler for UdpSrcPadHandler {
type ElementImpl = UdpSrc ;
2018-03-06 09:38:27 +00:00
2022-10-12 10:35:20 +00:00
fn src_event ( & self , pad : & PadSrcRef , imp : & UdpSrc , event : gst ::Event ) -> bool {
2022-02-21 17:43:46 +00:00
gst ::log! ( CAT , obj : pad . gst_pad ( ) , " Handling {:?} " , event ) ;
2018-03-06 09:38:27 +00:00
2022-10-12 10:35:20 +00:00
use gst ::EventView ;
2018-03-15 19:17:01 +00:00
let ret = match event . view ( ) {
2022-10-12 10:35:20 +00:00
EventView ::FlushStart ( .. ) = > imp . task . flush_start ( ) . await_maybe_on_context ( ) . is_ok ( ) ,
EventView ::FlushStop ( .. ) = > imp . task . flush_stop ( ) . await_maybe_on_context ( ) . is_ok ( ) ,
2018-03-15 19:17:01 +00:00
EventView ::Reconfigure ( .. ) = > true ,
EventView ::Latency ( .. ) = > true ,
_ = > false ,
} ;
2018-03-06 09:38:27 +00:00
2018-03-15 19:17:01 +00:00
if ret {
2022-02-21 17:43:46 +00:00
gst ::log! ( CAT , obj : pad . gst_pad ( ) , " Handled {:?} " , event ) ;
2018-03-06 09:38:27 +00:00
} else {
2022-02-21 17:43:46 +00:00
gst ::log! ( CAT , obj : pad . gst_pad ( ) , " Didn't handle {:?} " , event ) ;
2018-03-06 09:38:27 +00:00
}
2019-12-02 09:30:07 +00:00
2020-03-06 13:51:05 +00:00
ret
2018-03-06 09:38:27 +00:00
}
2022-10-12 10:35:20 +00:00
fn src_query ( & self , pad : & PadSrcRef , imp : & UdpSrc , query : & mut gst ::QueryRef ) -> bool {
2022-02-21 17:43:46 +00:00
gst ::log! ( CAT , obj : pad . gst_pad ( ) , " Handling {:?} " , query ) ;
2018-03-06 09:38:27 +00:00
2022-10-12 10:35:20 +00:00
use gst ::QueryViewMut ;
2018-03-15 19:17:01 +00:00
let ret = match query . view_mut ( ) {
2022-01-19 13:07:45 +00:00
QueryViewMut ::Latency ( q ) = > {
2021-05-26 09:54:34 +00:00
q . set ( true , gst ::ClockTime ::ZERO , gst ::ClockTime ::NONE ) ;
2018-03-15 19:17:01 +00:00
true
}
2022-01-19 13:07:45 +00:00
QueryViewMut ::Scheduling ( q ) = > {
2018-03-15 19:17:01 +00:00
q . set ( gst ::SchedulingFlags ::SEQUENTIAL , 1 , - 1 , 0 ) ;
q . add_scheduling_modes ( & [ gst ::PadMode ::Push ] ) ;
true
}
2022-01-19 13:07:45 +00:00
QueryViewMut ::Caps ( q ) = > {
2022-10-12 10:35:20 +00:00
let caps = if let Some ( caps ) = imp . configured_caps . lock ( ) . unwrap ( ) . as_ref ( ) {
2021-04-12 12:49:54 +00:00
q . filter ( )
2018-03-15 19:17:01 +00:00
. map ( | f | f . intersect_with_mode ( caps , gst ::CapsIntersectMode ::First ) )
2019-02-21 18:12:09 +00:00
. unwrap_or_else ( | | caps . clone ( ) )
2018-03-15 19:17:01 +00:00
} else {
2021-04-12 12:49:54 +00:00
q . filter ( )
2018-03-15 19:17:01 +00:00
. map ( | f | f . to_owned ( ) )
2019-07-04 15:30:26 +00:00
. unwrap_or_else ( gst ::Caps ::new_any )
2018-03-15 19:17:01 +00:00
} ;
q . set_result ( & caps ) ;
true
}
_ = > false ,
2018-03-06 09:38:27 +00:00
} ;
2018-03-15 19:17:01 +00:00
if ret {
2022-02-21 17:43:46 +00:00
gst ::log! ( CAT , obj : pad . gst_pad ( ) , " Handled {:?} " , query ) ;
2018-03-15 19:17:01 +00:00
} else {
2022-02-21 17:43:46 +00:00
gst ::log! ( CAT , obj : pad . gst_pad ( ) , " Didn't handle {:?} " , query ) ;
2018-03-15 19:17:01 +00:00
}
2018-03-08 20:26:34 +00:00
2019-12-02 09:30:07 +00:00
ret
2018-03-26 14:49:42 +00:00
}
2019-12-02 09:30:07 +00:00
}
2018-03-26 14:49:42 +00:00
2020-04-20 19:35:06 +00:00
struct UdpSrcTask {
2020-11-14 17:09:42 +00:00
element : super ::UdpSrc ,
2022-06-24 09:48:04 +00:00
socket : Option < Socket < UdpReader > > ,
retrieve_sender_address : bool ,
need_initial_events : bool ,
need_segment : bool ,
2020-04-20 19:35:06 +00:00
}
impl UdpSrcTask {
2022-06-24 09:48:04 +00:00
fn new ( element : super ::UdpSrc ) -> Self {
2020-04-20 19:35:06 +00:00
UdpSrcTask {
2022-06-24 09:48:04 +00:00
element ,
socket : None ,
retrieve_sender_address : DEFAULT_RETRIEVE_SENDER_ADDRESS ,
need_initial_events : true ,
need_segment : true ,
2020-04-20 19:35:06 +00:00
}
}
}
impl TaskImpl for UdpSrcTask {
2022-08-10 18:10:08 +00:00
type Item = gst ::Buffer ;
2022-06-24 09:48:04 +00:00
fn prepare ( & mut self ) -> BoxFuture < '_ , Result < ( ) , gst ::ErrorMessage > > {
async move {
let udpsrc = self . element . imp ( ) ;
let mut settings = udpsrc . settings . lock ( ) . unwrap ( ) ;
gst ::debug! ( CAT , obj : & self . element , " Preparing Task " ) ;
self . retrieve_sender_address = settings . retrieve_sender_address ;
let socket = if let Some ( ref wrapped_socket ) = settings . socket {
let socket : UdpSocket ;
#[ cfg(unix) ]
{
socket = wrapped_socket . get ( )
}
#[ cfg(windows) ]
{
socket = wrapped_socket . get ( )
}
let socket = Async ::< UdpSocket > ::try_from ( socket ) . map_err ( | err | {
gst ::error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to setup Async socket: {} " , err ]
)
} ) ? ;
settings . used_socket = Some ( wrapped_socket . clone ( ) ) ;
socket
} else {
let addr : IpAddr = match settings . address {
None = > {
return Err ( gst ::error_msg! (
gst ::ResourceError ::Settings ,
[ " No address set " ]
) ) ;
}
Some ( ref addr ) = > match addr . parse ( ) {
Err ( err ) = > {
return Err ( gst ::error_msg! (
gst ::ResourceError ::Settings ,
[ " Invalid address '{}' set: {} " , addr , err ]
) ) ;
}
Ok ( addr ) = > addr ,
} ,
} ;
let port = settings . port ;
// TODO: TTL, multicast loopback, etc
let saddr = if addr . is_multicast ( ) {
let bind_addr = if addr . is_ipv4 ( ) {
IpAddr ::V4 ( Ipv4Addr ::UNSPECIFIED )
} else {
IpAddr ::V6 ( Ipv6Addr ::UNSPECIFIED )
} ;
let saddr = SocketAddr ::new ( bind_addr , port as u16 ) ;
gst ::debug! (
CAT ,
obj : & self . element ,
" Binding to {:?} for multicast group {:?} " ,
saddr ,
addr
) ;
saddr
} else {
let saddr = SocketAddr ::new ( addr , port as u16 ) ;
gst ::debug! ( CAT , obj : & self . element , " Binding to {:?} " , saddr ) ;
saddr
} ;
let socket = if addr . is_ipv4 ( ) {
socket2 ::Socket ::new (
socket2 ::Domain ::IPV4 ,
socket2 ::Type ::DGRAM ,
Some ( socket2 ::Protocol ::UDP ) ,
)
} else {
socket2 ::Socket ::new (
socket2 ::Domain ::IPV6 ,
socket2 ::Type ::DGRAM ,
Some ( socket2 ::Protocol ::UDP ) ,
)
}
. map_err ( | err | {
gst ::error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to create socket: {} " , err ]
)
} ) ? ;
socket . set_reuse_address ( settings . reuse ) . map_err ( | err | {
gst ::error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to set reuse_address: {} " , err ]
)
} ) ? ;
#[ cfg(unix) ]
{
socket . set_reuse_port ( settings . reuse ) . map_err ( | err | {
gst ::error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to set reuse_port: {} " , err ]
)
} ) ? ;
}
socket . bind ( & saddr . into ( ) ) . map_err ( | err | {
gst ::error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to bind socket: {} " , err ]
)
} ) ? ;
let socket = Async ::< UdpSocket > ::try_from ( socket ) . map_err ( | err | {
gst ::error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to setup Async socket: {} " , err ]
)
} ) ? ;
if addr . is_multicast ( ) {
// TODO: Multicast interface configuration, going to be tricky
match addr {
IpAddr ::V4 ( addr ) = > {
socket
. as_ref ( )
. join_multicast_v4 ( & addr , & Ipv4Addr ::new ( 0 , 0 , 0 , 0 ) )
. map_err ( | err | {
gst ::error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to join multicast group: {} " , err ]
)
} ) ? ;
}
IpAddr ::V6 ( addr ) = > {
socket . as_ref ( ) . join_multicast_v6 ( & addr , 0 ) . map_err ( | err | {
gst ::error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to join multicast group: {} " , err ]
)
} ) ? ;
}
}
}
settings . used_socket = Some ( wrap_socket ( & socket ) ? ) ;
socket
} ;
let port : i32 = socket . as_ref ( ) . local_addr ( ) . unwrap ( ) . port ( ) . into ( ) ;
if settings . port ! = port {
settings . port = port ;
drop ( settings ) ;
self . element . notify ( " port " ) ;
settings = udpsrc . settings . lock ( ) . unwrap ( ) ;
} ;
let buffer_pool = gst ::BufferPool ::new ( ) ;
let mut config = buffer_pool . config ( ) ;
config . set_params ( None , settings . mtu , 0 , 0 ) ;
buffer_pool . set_config ( config ) . map_err ( | err | {
gst ::error_msg! (
gst ::ResourceError ::Settings ,
[ " Failed to configure buffer pool {:?} " , err ]
)
} ) ? ;
self . socket = Some (
Socket ::try_new (
self . element . clone ( ) . upcast ( ) ,
buffer_pool ,
UdpReader ::new ( socket ) ,
)
. map_err ( | err | {
gst ::error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to prepare socket {:?} " , err ]
)
} ) ? ,
) ;
self . element . notify ( " used-socket " ) ;
Ok ( ( ) )
}
. boxed ( )
}
fn unprepare ( & mut self ) -> BoxFuture < '_ , ( ) > {
async move {
gst ::debug! ( CAT , obj : & self . element , " Unpreparing Task " ) ;
let udpsrc = self . element . imp ( ) ;
udpsrc . settings . lock ( ) . unwrap ( ) . used_socket = None ;
self . element . notify ( " used-socket " ) ;
}
. boxed ( )
}
2020-05-15 17:38:54 +00:00
fn start ( & mut self ) -> BoxFuture < '_ , Result < ( ) , gst ::ErrorMessage > > {
2020-04-20 19:35:06 +00:00
async move {
2022-02-21 17:43:46 +00:00
gst ::log! ( CAT , obj : & self . element , " Starting task " ) ;
2020-04-20 19:35:06 +00:00
self . socket
2022-06-24 09:48:04 +00:00
. as_mut ( )
. unwrap ( )
2021-05-26 09:54:34 +00:00
. set_clock ( self . element . clock ( ) , self . element . base_time ( ) ) ;
2022-02-21 17:43:46 +00:00
gst ::log! ( CAT , obj : & self . element , " Task started " ) ;
2020-05-15 17:38:54 +00:00
Ok ( ( ) )
2020-04-20 19:35:06 +00:00
}
. boxed ( )
}
2022-08-10 18:10:08 +00:00
fn try_next ( & mut self ) -> BoxFuture < '_ , Result < gst ::Buffer , gst ::FlowError > > {
2020-04-20 19:35:06 +00:00
async move {
2022-08-10 18:10:08 +00:00
self . socket
. as_mut ( )
. unwrap ( )
. try_next ( )
. await
. map ( | ( mut buffer , saddr ) | {
if let Some ( saddr ) = saddr {
if self . retrieve_sender_address {
NetAddressMeta ::add (
buffer . get_mut ( ) . unwrap ( ) ,
& gio ::InetSocketAddress ::from ( saddr ) ,
) ;
}
2022-06-24 09:48:04 +00:00
}
2022-08-10 18:10:08 +00:00
buffer
} )
. map_err ( | err | {
gst ::error! ( CAT , obj : & self . element , " Got error {:?} " , err ) ;
match err {
SocketError ::Gst ( err ) = > {
gst ::element_error! (
self . element ,
gst ::StreamError ::Failed ,
( " Internal data stream error " ) ,
[ " streaming stopped, reason {} " , err ]
) ;
}
SocketError ::Io ( err ) = > {
gst ::element_error! (
self . element ,
gst ::StreamError ::Failed ,
( " I/O error " ) ,
[ " streaming stopped, I/O error {} " , err ]
) ;
}
2020-04-20 19:35:06 +00:00
}
2022-08-10 18:10:08 +00:00
gst ::FlowError ::Error
} )
}
. boxed ( )
}
fn handle_item ( & mut self , buffer : gst ::Buffer ) -> BoxFuture < '_ , Result < ( ) , gst ::FlowError > > {
async {
gst ::log! ( CAT , obj : & self . element , " Handling {:?} " , buffer ) ;
let udpsrc = self . element . imp ( ) ;
if self . need_initial_events {
gst ::debug! ( CAT , obj : & self . element , " Pushing initial events " ) ;
let stream_id =
format! ( " {:08x} {:08x} " , rand ::random ::< u32 > ( ) , rand ::random ::< u32 > ( ) ) ;
let stream_start_evt = gst ::event ::StreamStart ::builder ( & stream_id )
. group_id ( gst ::GroupId ::next ( ) )
. build ( ) ;
udpsrc . src_pad . push_event ( stream_start_evt ) . await ;
let caps = udpsrc . settings . lock ( ) . unwrap ( ) . caps . clone ( ) ;
if let Some ( caps ) = caps {
udpsrc
. src_pad
. push_event ( gst ::event ::Caps ::new ( & caps ) )
. await ;
* udpsrc . configured_caps . lock ( ) . unwrap ( ) = Some ( caps ) ;
2020-04-20 19:35:06 +00:00
}
2022-08-10 18:10:08 +00:00
self . need_initial_events = false ;
}
if self . need_segment {
let segment_evt =
gst ::event ::Segment ::new ( & gst ::FormattedSegment ::< gst ::format ::Time > ::new ( ) ) ;
udpsrc . src_pad . push_event ( segment_evt ) . await ;
self . need_segment = false ;
}
let res = udpsrc . src_pad . push ( buffer ) . await . map ( drop ) ;
match res {
Ok ( _ ) = > gst ::log! ( CAT , obj : & self . element , " Successfully pushed buffer " ) ,
Err ( gst ::FlowError ::Flushing ) = > gst ::debug! ( CAT , obj : & self . element , " Flushing " ) ,
Err ( gst ::FlowError ::Eos ) = > {
gst ::debug! ( CAT , obj : & self . element , " EOS " ) ;
udpsrc . src_pad . push_event ( gst ::event ::Eos ::new ( ) ) . await ;
}
Err ( err ) = > {
gst ::error! ( CAT , obj : & self . element , " Got error {} " , err ) ;
gst ::element_error! (
self . element ,
gst ::StreamError ::Failed ,
( " Internal data stream error " ) ,
[ " streaming stopped, reason {} " , err ]
2020-11-10 17:31:41 +00:00
) ;
2020-04-20 19:35:06 +00:00
}
}
2022-08-10 18:10:08 +00:00
res
2020-04-20 19:35:06 +00:00
}
. boxed ( )
}
2020-05-15 17:38:54 +00:00
fn stop ( & mut self ) -> BoxFuture < '_ , Result < ( ) , gst ::ErrorMessage > > {
2020-04-20 19:35:06 +00:00
async move {
2022-02-21 17:43:46 +00:00
gst ::log! ( CAT , obj : & self . element , " Stopping task " ) ;
2022-06-24 09:48:04 +00:00
self . need_initial_events = true ;
self . need_segment = true ;
2022-02-21 17:43:46 +00:00
gst ::log! ( CAT , obj : & self . element , " Task stopped " ) ;
2020-05-15 17:38:54 +00:00
Ok ( ( ) )
2020-04-20 19:35:06 +00:00
}
. boxed ( )
}
2020-05-15 17:38:54 +00:00
fn flush_stop ( & mut self ) -> BoxFuture < '_ , Result < ( ) , gst ::ErrorMessage > > {
2020-04-20 19:35:06 +00:00
async move {
2022-02-21 17:43:46 +00:00
gst ::log! ( CAT , obj : & self . element , " Stopping task flush " ) ;
2022-06-24 09:48:04 +00:00
self . need_segment = true ;
2022-02-21 17:43:46 +00:00
gst ::log! ( CAT , obj : & self . element , " Stopped task flush " ) ;
2020-05-15 17:38:54 +00:00
Ok ( ( ) )
2020-04-20 19:35:06 +00:00
}
. boxed ( )
}
}
2020-11-14 17:09:42 +00:00
pub struct UdpSrc {
2019-12-02 09:30:07 +00:00
src_pad : PadSrc ,
2020-03-26 18:07:25 +00:00
task : Task ,
2022-06-24 09:48:04 +00:00
configured_caps : Mutex < Option < gst ::Caps > > ,
settings : Mutex < Settings > ,
2019-12-02 09:30:07 +00:00
}
2018-03-08 20:26:34 +00:00
2020-11-22 14:24:55 +00:00
static CAT : Lazy < gst ::DebugCategory > = Lazy ::new ( | | {
gst ::DebugCategory ::new (
2019-12-02 09:30:07 +00:00
" ts-udpsrc " ,
gst ::DebugColorFlags ::empty ( ) ,
Some ( " Thread-sharing UDP source " ) ,
2020-11-22 14:24:55 +00:00
)
} ) ;
2018-03-08 20:26:34 +00:00
2019-12-02 09:30:07 +00:00
impl UdpSrc {
2022-10-09 13:06:59 +00:00
fn prepare ( & self ) -> Result < ( ) , gst ::ErrorMessage > {
gst ::debug! ( CAT , imp : self , " Preparing " ) ;
2020-01-06 12:19:11 +00:00
2022-06-24 09:48:04 +00:00
let settings = self . settings . lock ( ) . unwrap ( ) ;
let context =
Context ::acquire ( & settings . context , settings . context_wait ) . map_err ( | err | {
2020-12-20 18:43:45 +00:00
gst ::error_msg! (
2018-11-05 11:43:38 +00:00
gst ::ResourceError ::OpenRead ,
2019-12-02 09:30:07 +00:00
[ " Failed to acquire Context: {} " , err ]
2018-11-05 11:43:38 +00:00
)
2020-01-07 19:19:46 +00:00
} ) ? ;
2022-06-24 09:48:04 +00:00
drop ( settings ) ;
2018-03-08 20:26:34 +00:00
2022-06-24 09:48:04 +00:00
* self . configured_caps . lock ( ) . unwrap ( ) = None ;
2020-04-20 19:35:06 +00:00
self . task
2022-10-09 13:06:59 +00:00
. prepare ( UdpSrcTask ::new ( self . instance ( ) . clone ( ) ) , context )
2022-08-05 12:44:50 +00:00
. block_on ( ) ? ;
2020-04-20 19:35:06 +00:00
2022-10-09 13:06:59 +00:00
gst ::debug! ( CAT , imp : self , " Prepared " ) ;
2018-03-08 20:26:34 +00:00
Ok ( ( ) )
}
2022-10-09 13:06:59 +00:00
fn unprepare ( & self ) {
gst ::debug! ( CAT , imp : self , " Unpreparing " ) ;
2022-08-05 12:44:50 +00:00
self . task . unprepare ( ) . block_on ( ) . unwrap ( ) ;
2022-10-09 13:06:59 +00:00
gst ::debug! ( CAT , imp : self , " Unprepared " ) ;
2020-03-06 13:51:05 +00:00
}
2022-10-09 13:06:59 +00:00
fn stop ( & self ) -> Result < ( ) , gst ::ErrorMessage > {
gst ::debug! ( CAT , imp : self , " Stopping " ) ;
2022-08-05 12:44:50 +00:00
self . task . stop ( ) . block_on ( ) ? ;
2022-10-09 13:06:59 +00:00
gst ::debug! ( CAT , imp : self , " Stopped " ) ;
2020-05-15 17:38:54 +00:00
Ok ( ( ) )
2018-03-08 20:26:34 +00:00
}
2022-10-09 13:06:59 +00:00
fn start ( & self ) -> Result < ( ) , gst ::ErrorMessage > {
gst ::debug! ( CAT , imp : self , " Starting " ) ;
2022-08-05 12:44:50 +00:00
self . task . start ( ) . block_on ( ) ? ;
2022-10-09 13:06:59 +00:00
gst ::debug! ( CAT , imp : self , " Started " ) ;
2020-05-15 17:38:54 +00:00
Ok ( ( ) )
2020-03-26 18:07:25 +00:00
}
2022-10-09 13:06:59 +00:00
fn pause ( & self ) -> Result < ( ) , gst ::ErrorMessage > {
gst ::debug! ( CAT , imp : self , " Pausing " ) ;
2022-08-10 18:10:08 +00:00
self . task . pause ( ) . block_on ( ) ? ;
2022-10-09 13:06:59 +00:00
gst ::debug! ( CAT , imp : self , " Paused " ) ;
2020-05-15 17:38:54 +00:00
Ok ( ( ) )
2018-03-08 20:26:34 +00:00
}
2018-03-06 09:38:27 +00:00
}
2021-03-07 16:22:24 +00:00
#[ glib::object_subclass ]
2018-12-06 11:03:04 +00:00
impl ObjectSubclass for UdpSrc {
const NAME : & 'static str = " RsTsUdpSrc " ;
2020-11-14 17:09:42 +00:00
type Type = super ::UdpSrc ;
2018-12-06 11:03:04 +00:00
type ParentType = gst ::Element ;
2020-11-14 17:09:42 +00:00
fn with_class ( klass : & Self ::Class ) -> Self {
2018-12-06 11:03:04 +00:00
Self {
2020-04-29 13:03:43 +00:00
src_pad : PadSrc ::new (
2021-04-20 12:58:11 +00:00
gst ::Pad ::from_template ( & klass . pad_template ( " src " ) . unwrap ( ) , Some ( " src " ) ) ,
2022-06-24 09:48:04 +00:00
UdpSrcPadHandler ,
2020-04-29 13:03:43 +00:00
) ,
2020-03-26 18:07:25 +00:00
task : Task ::default ( ) ,
2022-06-24 09:48:04 +00:00
configured_caps : Default ::default ( ) ,
settings : Default ::default ( ) ,
2018-12-06 11:03:04 +00:00
}
}
}
impl ObjectImpl for UdpSrc {
2021-01-21 18:21:29 +00:00
fn properties ( ) -> & 'static [ glib ::ParamSpec ] {
static PROPERTIES : Lazy < Vec < glib ::ParamSpec > > = Lazy ::new ( | | {
let mut properties = vec! [
2022-08-18 12:04:15 +00:00
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 ::ParamSpecString ::builder ( " address " )
. nick ( " Address " )
. blurb ( " Address/multicast group to listen on " )
. default_value ( DEFAULT_ADDRESS )
. build ( ) ,
glib ::ParamSpecInt ::builder ( " port " )
. nick ( " Port " )
. blurb ( " Port to listen on " )
. minimum ( 0 )
. maximum ( u16 ::MAX as i32 )
. default_value ( DEFAULT_PORT )
. build ( ) ,
glib ::ParamSpecBoolean ::builder ( " reuse " )
. nick ( " Reuse " )
. blurb ( " Allow reuse of the port " )
. default_value ( DEFAULT_REUSE )
. build ( ) ,
2022-09-05 08:45:47 +00:00
glib ::ParamSpecBoxed ::builder ::< gst ::Caps > ( " caps " )
2022-08-18 12:04:15 +00:00
. nick ( " Caps " )
. blurb ( " Caps to use " )
. build ( ) ,
glib ::ParamSpecUInt ::builder ( " mtu " )
. nick ( " MTU " )
. blurb ( " Maximum expected packet size. This directly defines the allocation size of the receive buffer pool " )
. maximum ( i32 ::MAX as u32 )
. default_value ( DEFAULT_MTU )
. build ( ) ,
glib ::ParamSpecBoolean ::builder ( " retrieve-sender-address " )
. nick ( " Retrieve sender address " )
. blurb ( " Whether to retrieve the sender address and add it to buffers as meta. Disabling this might result in minor performance improvements in certain scenarios " )
. default_value ( DEFAULT_RETRIEVE_SENDER_ADDRESS )
. build ( ) ,
2021-01-21 18:21:29 +00:00
] ;
#[ cfg(not(windows)) ]
{
2022-08-18 12:04:15 +00:00
properties . push (
2022-09-05 08:45:47 +00:00
glib ::ParamSpecObject ::builder ::< gio ::Socket > ( " socket " )
2022-08-18 12:04:15 +00:00
. nick ( " Socket " )
. blurb ( " Socket to use for UDP reception. (None == allocate) " )
. build ( ) ,
) ;
properties . push (
2022-09-05 08:45:47 +00:00
glib ::ParamSpecObject ::builder ::< gio ::Socket > ( " used-socket " )
2022-08-18 12:04:15 +00:00
. nick ( " Used Socket " )
. blurb ( " Socket currently in use for UDP reception. (None = no socket) " )
. read_only ( )
. build ( ) ,
) ;
2021-01-21 18:21:29 +00:00
}
2018-03-08 20:26:34 +00:00
2021-01-21 18:21:29 +00:00
properties
} ) ;
PROPERTIES . as_ref ( )
}
2022-10-09 13:06:59 +00:00
fn set_property ( & self , _id : usize , value : & glib ::Value , pspec : & glib ::ParamSpec ) {
2020-03-06 13:51:05 +00:00
let mut settings = self . settings . lock ( ) . unwrap ( ) ;
2021-04-12 12:49:54 +00:00
match pspec . name ( ) {
2021-01-21 18:21:29 +00:00
" address " = > {
2019-08-12 22:45:36 +00:00
settings . address = value . get ( ) . expect ( " type checked upstream " ) ;
2018-03-08 20:26:34 +00:00
}
2021-01-21 18:21:29 +00:00
" port " = > {
2021-04-25 12:41:22 +00:00
settings . port = value . get ( ) . expect ( " type checked upstream " ) ;
2018-03-08 20:26:34 +00:00
}
2021-01-21 18:21:29 +00:00
" reuse " = > {
2021-04-25 12:41:22 +00:00
settings . reuse = value . get ( ) . expect ( " type checked upstream " ) ;
2018-05-23 07:32:06 +00:00
}
2021-01-21 18:21:29 +00:00
" caps " = > {
2019-08-12 22:45:36 +00:00
settings . caps = value . get ( ) . expect ( " type checked upstream " ) ;
2018-03-08 20:26:34 +00:00
}
2021-01-21 18:21:29 +00:00
" mtu " = > {
2021-04-25 12:41:22 +00:00
settings . mtu = value . get ( ) . expect ( " type checked upstream " ) ;
2018-03-08 20:26:34 +00:00
}
2021-01-21 18:21:29 +00:00
" socket " = > {
2018-11-13 12:13:23 +00:00
settings . socket = value
2021-04-25 12:41:22 +00:00
. get ::< Option < gio ::Socket > > ( )
2019-08-12 22:45:36 +00:00
. expect ( " type checked upstream " )
2018-11-13 12:13:23 +00:00
. map ( | socket | GioSocketWrapper ::new ( & socket ) ) ;
}
2021-01-21 18:21:29 +00:00
" used-socket " = > {
2018-11-13 12:13:23 +00:00
unreachable! ( ) ;
}
2021-01-21 18:21:29 +00:00
" context " = > {
2019-08-12 22:45:36 +00:00
settings . context = value
2021-04-25 12:41:22 +00:00
. get ::< Option < String > > ( )
2019-08-12 22:45:36 +00:00
. expect ( " type checked upstream " )
2021-12-14 18:40:27 +00:00
. unwrap_or_else ( | | DEFAULT_CONTEXT . into ( ) ) ;
2018-03-08 20:26:34 +00:00
}
2021-01-21 18:21:29 +00:00
" context-wait " = > {
2021-05-26 09:54:34 +00:00
settings . context_wait = Duration ::from_millis (
value . get ::< u32 > ( ) . expect ( " type checked upstream " ) . into ( ) ,
) ;
2018-03-12 14:19:46 +00:00
}
2021-01-21 18:21:29 +00:00
" retrieve-sender-address " = > {
2021-04-25 12:41:22 +00:00
settings . retrieve_sender_address = value . get ( ) . expect ( " type checked upstream " ) ;
2019-03-13 16:07:53 +00:00
}
2018-03-08 20:26:34 +00:00
_ = > unimplemented! ( ) ,
}
}
2022-10-09 13:06:59 +00:00
fn property ( & self , _id : usize , pspec : & glib ::ParamSpec ) -> glib ::Value {
2020-03-06 13:51:05 +00:00
let settings = self . settings . lock ( ) . unwrap ( ) ;
2021-04-12 12:49:54 +00:00
match pspec . name ( ) {
2021-01-21 18:21:29 +00:00
" address " = > settings . address . to_value ( ) ,
" port " = > settings . port . to_value ( ) ,
" reuse " = > settings . reuse . to_value ( ) ,
" caps " = > settings . caps . to_value ( ) ,
" mtu " = > settings . mtu . to_value ( ) ,
" socket " = > settings
2020-01-02 21:32:52 +00:00
. socket
. as_ref ( )
. map ( GioSocketWrapper ::as_socket )
2020-11-19 15:55:57 +00:00
. to_value ( ) ,
2021-01-21 18:21:29 +00:00
" used-socket " = > settings
2020-01-02 21:32:52 +00:00
. used_socket
. as_ref ( )
. map ( GioSocketWrapper ::as_socket )
2020-11-19 15:55:57 +00:00
. to_value ( ) ,
2021-01-21 18:21:29 +00:00
" context " = > settings . context . to_value ( ) ,
2021-05-26 09:54:34 +00:00
" context-wait " = > ( settings . context_wait . as_millis ( ) as u32 ) . to_value ( ) ,
2021-01-21 18:21:29 +00:00
" retrieve-sender-address " = > settings . retrieve_sender_address . to_value ( ) ,
2018-03-08 20:26:34 +00:00
_ = > unimplemented! ( ) ,
}
}
2018-12-06 11:03:04 +00:00
2022-10-09 13:06:59 +00:00
fn constructed ( & self ) {
self . parent_constructed ( ) ;
2018-12-06 11:03:04 +00:00
2022-10-09 13:06:59 +00:00
let obj = self . instance ( ) ;
2020-11-14 17:09:42 +00:00
obj . add_pad ( self . src_pad . gst_pad ( ) ) . unwrap ( ) ;
2022-10-09 13:06:59 +00:00
obj . set_element_flags ( gst ::ElementFlags ::SOURCE ) ;
2018-12-06 11:03:04 +00:00
}
2018-03-08 20:26:34 +00:00
}
2018-03-06 09:38:27 +00:00
2021-10-23 08:57:31 +00:00
impl GstObjectImpl for UdpSrc { }
2018-12-06 11:03:04 +00:00
impl ElementImpl for UdpSrc {
2021-01-21 18:21:29 +00:00
fn metadata ( ) -> Option < & 'static gst ::subclass ::ElementMetadata > {
static ELEMENT_METADATA : Lazy < gst ::subclass ::ElementMetadata > = Lazy ::new ( | | {
gst ::subclass ::ElementMetadata ::new (
" Thread-sharing UDP source " ,
" Source/Network " ,
" Receives data over the network via UDP " ,
" Sebastian Dröge <sebastian@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 src_pad_template = gst ::PadTemplate ::new (
" src " ,
gst ::PadDirection ::Src ,
gst ::PadPresence ::Always ,
& caps ,
)
. unwrap ( ) ;
vec! [ src_pad_template ]
} ) ;
PAD_TEMPLATES . as_ref ( )
}
2018-03-06 09:38:27 +00:00
fn change_state (
& self ,
transition : gst ::StateChange ,
2019-01-11 23:45:05 +00:00
) -> Result < gst ::StateChangeSuccess , gst ::StateChangeError > {
2022-10-09 13:06:59 +00:00
gst ::trace! ( CAT , imp : self , " Changing state {:?} " , transition ) ;
2018-03-06 09:38:27 +00:00
match transition {
2019-01-11 23:45:05 +00:00
gst ::StateChange ::NullToReady = > {
2022-10-09 13:06:59 +00:00
self . prepare ( ) . map_err ( | err | {
self . post_error_message ( err ) ;
2019-11-30 18:51:31 +00:00
gst ::StateChangeError
} ) ? ;
}
2019-01-11 23:45:05 +00:00
gst ::StateChange ::PlayingToPaused = > {
2022-10-09 13:06:59 +00:00
self . pause ( ) . map_err ( | _ | gst ::StateChangeError ) ? ;
2019-01-11 23:45:05 +00:00
}
gst ::StateChange ::ReadyToNull = > {
2022-10-09 13:06:59 +00:00
self . unprepare ( ) ;
2019-01-11 23:45:05 +00:00
}
2018-03-06 09:38:27 +00:00
_ = > ( ) ,
}
2022-10-09 13:06:59 +00:00
let mut success = self . parent_change_state ( transition ) ? ;
2018-03-06 09:38:27 +00:00
match transition {
gst ::StateChange ::ReadyToPaused = > {
2019-01-11 23:45:05 +00:00
success = gst ::StateChangeSuccess ::NoPreroll ;
}
gst ::StateChange ::PausedToPlaying = > {
2022-10-09 13:06:59 +00:00
self . start ( ) . map_err ( | _ | gst ::StateChangeError ) ? ;
2018-03-06 09:38:27 +00:00
}
2020-01-23 14:56:11 +00:00
gst ::StateChange ::PlayingToPaused = > {
success = gst ::StateChangeSuccess ::NoPreroll ;
}
2018-03-08 20:26:34 +00:00
gst ::StateChange ::PausedToReady = > {
2022-10-09 13:06:59 +00:00
self . stop ( ) . map_err ( | _ | gst ::StateChangeError ) ? ;
2018-03-08 20:26:34 +00:00
}
2018-03-06 09:38:27 +00:00
_ = > ( ) ,
}
2019-01-11 23:45:05 +00:00
Ok ( success )
2018-03-06 09:38:27 +00:00
}
}