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.
2019-12-02 09:30:07 +00:00
use futures ::future ::BoxFuture ;
2020-03-06 13:51:05 +00:00
use futures ::lock ::Mutex as FutMutex ;
2019-11-24 20:12:40 +00:00
use futures ::prelude ::* ;
2020-07-26 15:33:14 +00:00
use glib ::glib_object_subclass ;
2018-03-06 09:38:27 +00:00
use glib ::prelude ::* ;
2018-12-06 11:03:04 +00:00
use glib ::subclass ;
use glib ::subclass ::prelude ::* ;
2019-11-24 20:12:40 +00:00
2018-03-06 09:38:27 +00:00
use gst ::prelude ::* ;
2018-12-06 11:03:04 +00:00
use gst ::subclass ::prelude ::* ;
2019-11-24 20:12:40 +00:00
use gst ::{ gst_debug , gst_element_error , gst_error , gst_error_msg , gst_log , gst_trace } ;
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 ;
2019-12-02 09:30:07 +00:00
use std ::net ::{ IpAddr , Ipv4Addr , Ipv6Addr , SocketAddr } ;
2020-03-19 18:34:51 +00:00
use std ::sync ::Arc ;
2020-03-06 13:51:05 +00:00
use std ::sync ::Mutex as StdMutex ;
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 ::* ;
2020-04-20 19:35:06 +00:00
use crate ::runtime ::{ Context , PadSrc , PadSrcRef , PadSrcWeak , 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 " ) ;
const DEFAULT_PORT : i32 = 5000 ;
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 = " " ;
2018-03-12 14:19:46 +00:00
const DEFAULT_CONTEXT_WAIT : u32 = 0 ;
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 ,
2018-03-12 14:19:46 +00:00
context_wait : u32 ,
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-03-13 16:07:53 +00:00
static PROPERTIES : [ subclass ::Property ; 10 ] = [
2018-12-18 09:23:45 +00:00
subclass ::Property ( " address " , | name | {
2018-12-06 11:03:04 +00:00
glib ::ParamSpec ::string (
2018-12-18 09:23:45 +00:00
name ,
2018-12-06 11:03:04 +00:00
" Address " ,
" Address/multicast group to listen on " ,
DEFAULT_ADDRESS ,
glib ::ParamFlags ::READWRITE ,
)
} ) ,
2018-12-18 09:23:45 +00:00
subclass ::Property ( " port " , | name | {
2020-04-27 09:22:26 +00:00
glib ::ParamSpec ::int (
2018-12-18 09:23:45 +00:00
name ,
2018-12-06 11:03:04 +00:00
" Port " ,
" Port to listen on " ,
0 ,
2020-04-27 09:22:26 +00:00
u16 ::MAX as i32 ,
2018-12-06 11:03:04 +00:00
DEFAULT_PORT ,
glib ::ParamFlags ::READWRITE ,
)
} ) ,
2018-12-18 09:23:45 +00:00
subclass ::Property ( " reuse " , | name | {
2018-12-06 11:03:04 +00:00
glib ::ParamSpec ::boolean (
2018-12-18 09:23:45 +00:00
name ,
2018-12-06 11:03:04 +00:00
" Reuse " ,
" Allow reuse of the port " ,
DEFAULT_REUSE ,
glib ::ParamFlags ::READWRITE ,
)
} ) ,
2018-12-18 09:23:45 +00:00
subclass ::Property ( " caps " , | name | {
2018-12-06 11:03:04 +00:00
glib ::ParamSpec ::boxed (
2018-12-18 09:23:45 +00:00
name ,
2018-12-06 11:03:04 +00:00
" Caps " ,
" Caps to use " ,
gst ::Caps ::static_type ( ) ,
glib ::ParamFlags ::READWRITE ,
)
} ) ,
2018-12-18 09:23:45 +00:00
subclass ::Property ( " mtu " , | name | {
2018-12-06 11:03:04 +00:00
glib ::ParamSpec ::uint (
2018-12-18 09:23:45 +00:00
name ,
2018-12-06 11:03:04 +00:00
" MTU " ,
2020-04-27 09:22:26 +00:00
" Maximum expected packet size. This directly defines the allocation size of the receive buffer pool " ,
2018-12-06 11:03:04 +00:00
0 ,
2020-04-27 09:22:26 +00:00
i32 ::MAX as u32 ,
2018-12-06 11:03:04 +00:00
DEFAULT_MTU ,
glib ::ParamFlags ::READWRITE ,
)
} ) ,
2018-12-18 09:23:45 +00:00
subclass ::Property ( " socket " , | name | {
2018-12-06 11:03:04 +00:00
glib ::ParamSpec ::object (
2018-12-18 09:23:45 +00:00
name ,
2018-12-06 11:03:04 +00:00
" Socket " ,
" Socket to use for UDP reception. (None == allocate) " ,
gio ::Socket ::static_type ( ) ,
glib ::ParamFlags ::READWRITE ,
)
} ) ,
2018-12-18 09:23:45 +00:00
subclass ::Property ( " used-socket " , | name | {
2018-12-06 11:03:04 +00:00
glib ::ParamSpec ::object (
2018-12-18 09:23:45 +00:00
name ,
2018-12-06 11:03:04 +00:00
" Used Socket " ,
" Socket currently in use for UDP reception. (None = no socket) " ,
gio ::Socket ::static_type ( ) ,
glib ::ParamFlags ::READABLE ,
)
} ) ,
2018-12-18 09:23:45 +00:00
subclass ::Property ( " context " , | name | {
2018-12-06 11:03:04 +00:00
glib ::ParamSpec ::string (
2018-12-18 09:23:45 +00:00
name ,
2018-12-06 11:03:04 +00:00
" Context " ,
" Context name to share threads with " ,
Some ( DEFAULT_CONTEXT ) ,
glib ::ParamFlags ::READWRITE ,
)
} ) ,
2018-12-18 09:23:45 +00:00
subclass ::Property ( " context-wait " , | name | {
2018-12-06 11:03:04 +00:00
glib ::ParamSpec ::uint (
2018-12-18 09:23:45 +00:00
name ,
2018-12-06 11:03:04 +00:00
" Context Wait " ,
" Throttle poll loop to run at most once every this many ms " ,
0 ,
1000 ,
DEFAULT_CONTEXT_WAIT ,
glib ::ParamFlags ::READWRITE ,
)
} ) ,
2019-03-13 16:07:53 +00:00
subclass ::Property ( " retrieve-sender-address " , | name | {
glib ::ParamSpec ::boolean (
name ,
" Retrieve sender address " ,
" Whether to retrieve the sender address and add it to buffers as meta. Disabling this might result in minor performance improvements in certain scenarios " ,
2020-11-10 08:25:59 +00:00
DEFAULT_RETRIEVE_SENDER_ADDRESS ,
2019-03-13 16:07:53 +00:00
glib ::ParamFlags ::READWRITE ,
)
} ) ,
2018-03-08 20:26:34 +00:00
] ;
2019-12-02 09:30:07 +00:00
#[ derive(Debug) ]
2020-11-14 17:09:42 +00:00
struct UdpReader ( tokio ::net ::UdpSocket ) ;
2019-12-02 09:30:07 +00:00
2018-07-06 07:19:59 +00:00
impl UdpReader {
2019-11-30 18:51:31 +00:00
fn new ( socket : tokio ::net ::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
}
}
2019-12-02 09:30:07 +00:00
#[ derive(Debug) ]
2020-01-06 12:19:11 +00:00
struct UdpSrcPadHandlerState {
2019-12-02 09:30:07 +00:00
retrieve_sender_address : bool ,
2018-03-08 20:26:34 +00:00
need_initial_events : bool ,
2020-03-19 18:34:51 +00:00
need_segment : bool ,
2020-01-06 12:19:11 +00:00
caps : Option < gst ::Caps > ,
2018-03-06 09:38:27 +00:00
}
2020-01-06 12:19:11 +00:00
impl Default for UdpSrcPadHandlerState {
2019-12-02 09:30:07 +00:00
fn default ( ) -> Self {
2020-01-06 12:19:11 +00:00
UdpSrcPadHandlerState {
2019-12-02 09:30:07 +00:00
retrieve_sender_address : true ,
2018-03-08 20:26:34 +00:00
need_initial_events : true ,
2020-03-19 18:34:51 +00:00
need_segment : true ,
2020-01-06 12:19:11 +00:00
caps : None ,
2018-03-08 20:26:34 +00:00
}
2018-03-06 09:38:27 +00:00
}
}
2020-03-26 18:07:25 +00:00
#[ derive(Debug, Default) ]
2020-01-06 12:19:11 +00:00
struct UdpSrcPadHandlerInner {
2020-03-19 18:34:51 +00:00
state : FutMutex < UdpSrcPadHandlerState > ,
configured_caps : StdMutex < Option < gst ::Caps > > ,
}
2020-03-26 18:07:25 +00:00
#[ derive(Clone, Debug, Default) ]
2020-01-06 12:19:11 +00:00
struct UdpSrcPadHandler ( Arc < UdpSrcPadHandlerInner > ) ;
2019-12-02 09:30:07 +00:00
2020-01-06 12:19:11 +00:00
impl UdpSrcPadHandler {
2020-03-26 18:07:25 +00:00
fn prepare ( & self , caps : Option < gst ::Caps > , retrieve_sender_address : bool ) {
let mut state = self . 0. state . try_lock ( ) . expect ( " State locked elsewhere " ) ;
2020-03-19 18:34:51 +00:00
2020-03-26 18:07:25 +00:00
state . caps = caps ;
state . retrieve_sender_address = retrieve_sender_address ;
}
2020-03-19 18:34:51 +00:00
2020-04-20 19:35:06 +00:00
async fn reset_state ( & self ) {
* self . 0. state . lock ( ) . await = Default ::default ( ) ;
2020-03-19 18:34:51 +00:00
}
2020-04-20 19:35:06 +00:00
async fn set_need_segment ( & self ) {
self . 0. state . lock ( ) . await . need_segment = true ;
2020-03-06 13:51:05 +00:00
}
2019-12-02 09:30:07 +00:00
2020-11-14 17:09:42 +00:00
async fn push_prelude ( & self , pad : & PadSrcRef < '_ > , _element : & super ::UdpSrc ) {
2020-03-19 18:34:51 +00:00
let mut state = self . 0. state . lock ( ) . await ;
if state . need_initial_events {
2020-03-06 13:51:05 +00:00
gst_debug! ( CAT , obj : pad . gst_pad ( ) , " Pushing initial events " ) ;
let stream_id = format! ( " {:08x} {:08x} " , rand ::random ::< u32 > ( ) , rand ::random ::< u32 > ( ) ) ;
2020-06-24 22:33:57 +00:00
let stream_start_evt = gst ::event ::StreamStart ::builder ( & stream_id )
2020-03-19 18:34:51 +00:00
. group_id ( gst ::GroupId ::next ( ) )
. build ( ) ;
pad . push_event ( stream_start_evt ) . await ;
2020-03-06 13:51:05 +00:00
if let Some ( ref caps ) = state . caps {
2020-06-24 22:33:57 +00:00
pad . push_event ( gst ::event ::Caps ::new ( & caps ) ) . await ;
2020-03-19 18:34:51 +00:00
* self . 0. configured_caps . lock ( ) . unwrap ( ) = Some ( caps . clone ( ) ) ;
2019-12-02 09:30:07 +00:00
}
2020-03-06 13:51:05 +00:00
state . need_initial_events = false ;
2019-12-02 09:30:07 +00:00
}
2020-03-19 18:34:51 +00:00
if state . need_segment {
let segment_evt =
2020-06-24 22:33:57 +00:00
gst ::event ::Segment ::new ( & gst ::FormattedSegment ::< gst ::format ::Time > ::new ( ) ) ;
2020-03-19 18:34:51 +00:00
pad . push_event ( segment_evt ) . await ;
state . need_segment = false ;
2019-12-02 09:30:07 +00:00
}
}
2020-03-06 13:51:05 +00:00
async fn push_buffer (
& self ,
pad : & PadSrcRef < '_ > ,
2020-11-14 17:09:42 +00:00
element : & super ::UdpSrc ,
2020-03-06 13:51:05 +00:00
buffer : gst ::Buffer ,
) -> Result < gst ::FlowSuccess , gst ::FlowError > {
2020-03-19 18:34:51 +00:00
gst_log! ( CAT , obj : pad . gst_pad ( ) , " Handling {:?} " , buffer ) ;
2020-03-06 13:51:05 +00:00
self . push_prelude ( pad , element ) . await ;
pad . push ( buffer ) . await
}
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
2019-12-02 09:30:07 +00:00
fn src_event (
& self ,
2020-01-06 12:19:11 +00:00
pad : & PadSrcRef ,
2020-03-06 13:51:05 +00:00
udpsrc : & UdpSrc ,
2020-04-20 19:35:06 +00:00
_element : & gst ::Element ,
2019-12-02 09:30:07 +00:00
event : gst ::Event ,
2020-03-06 13:51:05 +00:00
) -> bool {
2020-01-06 12:19:11 +00:00
use gst ::EventView ;
gst_log! ( CAT , obj : pad . gst_pad ( ) , " Handling {:?} " , event ) ;
2018-03-06 09:38:27 +00:00
2018-03-15 19:17:01 +00:00
let ret = match event . view ( ) {
2020-05-15 17:38:54 +00:00
EventView ::FlushStart ( .. ) = > udpsrc . task . flush_start ( ) . is_ok ( ) ,
EventView ::FlushStop ( .. ) = > udpsrc . task . flush_stop ( ) . 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 {
2020-01-06 12:19:11 +00:00
gst_log! ( CAT , obj : pad . gst_pad ( ) , " Handled {:?} " , event ) ;
2018-03-06 09:38:27 +00:00
} else {
2020-01-06 12:19:11 +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
}
2018-12-06 11:03:04 +00:00
fn src_query (
& self ,
2020-01-06 12:19:11 +00:00
pad : & PadSrcRef ,
2019-12-02 09:30:07 +00:00
_udpsrc : & UdpSrc ,
2018-12-06 11:03:04 +00:00
_element : & gst ::Element ,
query : & mut gst ::QueryRef ,
) -> bool {
2020-01-06 12:19:11 +00:00
use gst ::QueryView ;
gst_log! ( CAT , obj : pad . gst_pad ( ) , " Handling {:?} " , query ) ;
2018-03-06 09:38:27 +00:00
2018-03-15 19:17:01 +00:00
let ret = match query . view_mut ( ) {
QueryView ::Latency ( ref mut q ) = > {
2020-01-23 15:09:40 +00:00
q . set ( true , 0. into ( ) , gst ::CLOCK_TIME_NONE ) ;
2018-03-15 19:17:01 +00:00
true
}
QueryView ::Scheduling ( ref mut q ) = > {
q . set ( gst ::SchedulingFlags ::SEQUENTIAL , 1 , - 1 , 0 ) ;
q . add_scheduling_modes ( & [ gst ::PadMode ::Push ] ) ;
true
}
QueryView ::Caps ( ref mut q ) = > {
2020-03-19 18:34:51 +00:00
let caps = if let Some ( caps ) = self . 0. configured_caps . lock ( ) . unwrap ( ) . as_ref ( ) {
2018-03-15 19:17:01 +00:00
q . get_filter ( )
. 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 {
q . get_filter ( )
. 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 {
2020-01-06 12:19:11 +00:00
gst_log! ( CAT , obj : pad . gst_pad ( ) , " Handled {:?} " , query ) ;
2018-03-15 19:17:01 +00:00
} else {
2020-01-06 12:19:11 +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 ,
2020-04-20 19:35:06 +00:00
src_pad : PadSrcWeak ,
src_pad_handler : UdpSrcPadHandler ,
socket : Socket < UdpReader > ,
}
impl UdpSrcTask {
fn new (
2020-11-14 17:09:42 +00:00
element : & super ::UdpSrc ,
2020-04-20 19:35:06 +00:00
src_pad : & PadSrc ,
src_pad_handler : & UdpSrcPadHandler ,
socket : Socket < UdpReader > ,
) -> Self {
UdpSrcTask {
element : element . clone ( ) ,
src_pad : src_pad . downgrade ( ) ,
src_pad_handler : src_pad_handler . clone ( ) ,
socket ,
}
}
}
impl TaskImpl for UdpSrcTask {
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 {
gst_log! ( CAT , obj : & self . element , " Starting task " ) ;
self . socket
. set_clock ( self . element . get_clock ( ) , Some ( self . element . get_base_time ( ) ) ) ;
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 ( )
}
fn iterate ( & mut self ) -> BoxFuture < '_ , Result < ( ) , gst ::FlowError > > {
async move {
let item = self . socket . next ( ) . await ;
let ( mut buffer , saddr ) = match item {
Some ( Ok ( ( buffer , saddr ) ) ) = > ( buffer , saddr ) ,
Some ( 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 ]
) ;
}
}
return Err ( gst ::FlowError ::Error ) ;
}
None = > {
gst_log! ( CAT , obj : & self . element , " SocketStream Stopped " ) ;
return Err ( gst ::FlowError ::Flushing ) ;
}
} ;
if let Some ( saddr ) = saddr {
if self
. src_pad_handler
. 0
. state
. lock ( )
. await
. retrieve_sender_address
{
2020-11-10 17:31:41 +00:00
NetAddressMeta ::add (
buffer . get_mut ( ) . unwrap ( ) ,
& gio ::InetSocketAddress ::from ( saddr ) ,
) ;
2020-04-20 19:35:06 +00:00
}
}
let pad = self . src_pad . upgrade ( ) . expect ( " PadSrc no longer exists " ) ;
let res = self
. src_pad_handler
. push_buffer ( & pad , & self . element , buffer )
. await ;
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 " ) ;
2020-06-24 22:33:57 +00:00
pad . push_event ( gst ::event ::Eos ::new ( ) ) . await ;
2020-04-20 19:35:06 +00:00
}
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 ]
) ;
}
}
res . map ( drop )
}
. 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 {
gst_log! ( CAT , obj : & self . element , " Stopping task " ) ;
self . src_pad_handler . reset_state ( ) . await ;
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 {
gst_log! ( CAT , obj : & self . element , " Stopping task flush " ) ;
self . src_pad_handler . set_need_segment ( ) . await ;
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
src_pad_handler : UdpSrcPadHandler ,
task : Task ,
2020-03-06 13:51:05 +00:00
settings : StdMutex < 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 {
2020-11-14 17:09:42 +00:00
fn prepare ( & self , element : & super ::UdpSrc ) -> Result < ( ) , gst ::ErrorMessage > {
2020-11-03 01:10:57 +00:00
let mut settings_guard = self . settings . lock ( ) . unwrap ( ) ;
2018-03-08 20:26:34 +00:00
2020-01-07 19:19:46 +00:00
gst_debug! ( CAT , obj : element , " Preparing " ) ;
2020-01-06 12:19:11 +00:00
2020-11-03 01:10:57 +00:00
let context = Context ::acquire ( & settings_guard . context , settings_guard . context_wait )
. map_err ( | err | {
2018-11-05 11:43:38 +00:00
gst_error_msg! (
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
} ) ? ;
2018-03-08 20:26:34 +00:00
2020-11-03 01:10:57 +00:00
let socket = if let Some ( ref wrapped_socket ) = settings_guard . socket {
2018-11-13 12:13:23 +00:00
use std ::net ::UdpSocket ;
2019-06-06 06:26:02 +00:00
let socket : UdpSocket ;
2018-11-13 12:13:23 +00:00
#[ cfg(unix) ]
{
socket = wrapped_socket . get ( )
}
#[ cfg(windows) ]
{
socket = wrapped_socket . get ( )
2018-03-16 18:24:36 +00:00
}
2018-11-13 12:13:23 +00:00
2020-01-07 19:19:46 +00:00
let socket = context . enter ( | | {
tokio ::net ::UdpSocket ::from_std ( socket ) . map_err ( | err | {
gst_error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to setup socket for tokio: {} " , err ]
)
} )
2019-11-30 18:51:31 +00:00
} ) ? ;
2018-11-13 12:13:23 +00:00
2020-11-03 01:10:57 +00:00
settings_guard . used_socket = Some ( wrapped_socket . clone ( ) ) ;
2018-11-13 12:13:23 +00:00
socket
} else {
2020-11-03 01:10:57 +00:00
let addr : IpAddr = match settings_guard . address {
2018-11-13 12:13:23 +00:00
None = > {
2018-03-16 18:24:36 +00:00
return Err ( gst_error_msg! (
gst ::ResourceError ::Settings ,
2018-11-13 12:13:23 +00:00
[ " No address set " ]
2018-12-04 17:01:40 +00:00
) ) ;
2018-03-16 18:24:36 +00:00
}
2018-11-13 12:13:23 +00:00
Some ( ref addr ) = > match addr . parse ( ) {
Err ( err ) = > {
return Err ( gst_error_msg! (
gst ::ResourceError ::Settings ,
[ " Invalid address '{}' set: {} " , addr , err ]
2018-12-04 17:01:40 +00:00
) ) ;
2018-11-13 12:13:23 +00:00
}
Ok ( addr ) = > addr ,
} ,
2018-03-08 20:26:34 +00:00
} ;
2020-11-03 01:10:57 +00:00
let port = settings_guard . port ;
2018-03-08 20:26:34 +00:00
2018-11-13 12:13:23 +00:00
// TODO: TTL, multicast loopback, etc
let saddr = if addr . is_multicast ( ) {
let bind_addr = if addr . is_ipv4 ( ) {
2019-11-30 18:51:31 +00:00
IpAddr ::V4 ( Ipv4Addr ::UNSPECIFIED )
2018-11-13 12:13:23 +00:00
} else {
2019-11-30 18:51:31 +00:00
IpAddr ::V6 ( Ipv6Addr ::UNSPECIFIED )
2018-11-13 12:13:23 +00:00
} ;
2018-05-23 07:32:06 +00:00
2018-11-13 12:13:23 +00:00
let saddr = SocketAddr ::new ( bind_addr , port as u16 ) ;
gst_debug! (
2019-10-31 22:34:21 +00:00
CAT ,
2020-01-07 19:19:46 +00:00
obj : element ,
2018-11-13 12:13:23 +00:00
" Binding to {:?} for multicast group {:?} " ,
saddr ,
addr
) ;
2018-05-23 07:32:06 +00:00
2018-11-13 12:13:23 +00:00
saddr
} else {
let saddr = SocketAddr ::new ( addr , port as u16 ) ;
2020-01-07 19:19:46 +00:00
gst_debug! ( CAT , obj : element , " Binding to {:?} " , saddr ) ;
2018-05-23 07:32:06 +00:00
2018-11-13 12:13:23 +00:00
saddr
} ;
2018-05-23 07:32:06 +00:00
2020-05-29 10:07:14 +00:00
let socket = if addr . is_ipv4 ( ) {
socket2 ::Socket ::new (
socket2 ::Domain ::ipv4 ( ) ,
socket2 ::Type ::dgram ( ) ,
Some ( socket2 ::Protocol ::udp ( ) ) ,
)
2018-11-13 12:13:23 +00:00
} else {
2020-05-29 10:07:14 +00:00
socket2 ::Socket ::new (
socket2 ::Domain ::ipv6 ( ) ,
socket2 ::Type ::dgram ( ) ,
Some ( socket2 ::Protocol ::udp ( ) ) ,
)
2018-11-13 12:13:23 +00:00
}
. map_err ( | err | {
gst_error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to create socket: {} " , err ]
)
} ) ? ;
2018-03-08 20:26:34 +00:00
2020-11-03 01:10:57 +00:00
socket
. set_reuse_address ( settings_guard . reuse )
. map_err ( | err | {
gst_error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to set reuse_address: {} " , err ]
)
} ) ? ;
2018-05-23 07:32:06 +00:00
2018-11-13 12:13:23 +00:00
#[ cfg(unix) ]
{
2020-11-03 01:10:57 +00:00
socket . set_reuse_port ( settings_guard . reuse ) . map_err ( | err | {
2018-11-13 12:13:23 +00:00
gst_error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to set reuse_port: {} " , err ]
)
} ) ? ;
}
2018-05-23 17:35:12 +00:00
2020-05-29 10:07:14 +00:00
socket . bind ( & saddr . into ( ) ) . map_err ( | err | {
2018-07-24 10:40:58 +00:00
gst_error_msg! (
gst ::ResourceError ::OpenRead ,
2018-11-13 12:13:23 +00:00
[ " Failed to bind socket: {} " , err ]
2018-07-24 10:40:58 +00:00
)
} ) ? ;
2018-05-23 17:35:12 +00:00
2020-01-07 19:19:46 +00:00
let socket = context . enter ( | | {
2020-05-29 10:07:14 +00:00
tokio ::net ::UdpSocket ::from_std ( socket . into ( ) ) . map_err ( | err | {
2020-01-07 19:19:46 +00:00
gst_error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to setup socket for tokio: {} " , err ]
)
} )
2019-11-30 18:51:31 +00:00
} ) ? ;
2018-11-13 12:13:23 +00:00
if addr . is_multicast ( ) {
// TODO: Multicast interface configuration, going to be tricky
match addr {
IpAddr ::V4 ( addr ) = > {
socket
2019-11-24 20:12:40 +00:00
. join_multicast_v4 ( addr , Ipv4Addr ::new ( 0 , 0 , 0 , 0 ) )
2018-11-13 12:13:23 +00:00
. map_err ( | err | {
gst_error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to join multicast group: {} " , err ]
)
} ) ? ;
}
IpAddr ::V6 ( addr ) = > {
socket . join_multicast_v6 ( & addr , 0 ) . map_err ( | err | {
2018-03-16 18:24:36 +00:00
gst_error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to join multicast group: {} " , err ]
)
} ) ? ;
2018-11-13 12:13:23 +00:00
}
2018-03-08 20:26:34 +00:00
}
2018-11-13 12:13:23 +00:00
}
2020-11-03 01:10:57 +00:00
settings_guard . used_socket = Some ( wrap_socket ( & socket ) ? ) ;
2018-11-13 12:13:23 +00:00
socket
} ;
2018-03-08 20:26:34 +00:00
2020-11-03 01:10:57 +00:00
let port : i32 = socket . local_addr ( ) . unwrap ( ) . port ( ) . into ( ) ;
let settings = if settings_guard . port ! = port {
settings_guard . port = port ;
let settings = settings_guard . clone ( ) ;
drop ( settings_guard ) ;
element . notify ( " port " ) ;
settings
} else {
let settings = settings_guard . clone ( ) ;
drop ( settings_guard ) ;
settings
} ;
2018-03-08 20:26:34 +00:00
let buffer_pool = gst ::BufferPool ::new ( ) ;
let mut config = buffer_pool . get_config ( ) ;
config . set_params ( None , settings . mtu , 0 , 0 ) ;
2019-11-30 18:51:31 +00:00
buffer_pool . set_config ( config ) . map_err ( | err | {
2018-03-16 18:24:36 +00:00
gst_error_msg! (
gst ::ResourceError ::Settings ,
2019-11-30 18:51:31 +00:00
[ " Failed to configure buffer pool {:?} " , err ]
2018-03-16 18:24:36 +00:00
)
} ) ? ;
2018-03-08 20:26:34 +00:00
2020-11-14 17:09:42 +00:00
let socket = Socket ::try_new (
element . clone ( ) . upcast ( ) ,
buffer_pool ,
UdpReader ::new ( socket ) ,
)
. map_err ( | err | {
gst_error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Failed to prepare socket {:?} " , err ]
)
} ) ? ;
2018-03-08 20:26:34 +00:00
2020-01-07 19:19:46 +00:00
element . notify ( " used-socket " ) ;
2019-11-30 18:51:31 +00:00
2020-03-26 18:07:25 +00:00
self . src_pad_handler
. prepare ( settings . caps , settings . retrieve_sender_address ) ;
2020-03-19 18:34:51 +00:00
2020-04-20 19:35:06 +00:00
self . task
. prepare (
UdpSrcTask ::new ( element , & self . src_pad , & self . src_pad_handler , socket ) ,
context ,
)
. map_err ( | err | {
gst_error_msg! (
gst ::ResourceError ::OpenRead ,
[ " Error preparing Task: {:?} " , err ]
)
} ) ? ;
2020-01-07 19:19:46 +00:00
gst_debug! ( CAT , obj : element , " Prepared " ) ;
2018-03-08 20:26:34 +00:00
Ok ( ( ) )
}
2020-11-14 17:09:42 +00:00
fn unprepare ( & self , element : & super ::UdpSrc ) {
2019-10-31 22:34:21 +00:00
gst_debug! ( CAT , obj : element , " Unpreparing " ) ;
2018-03-08 20:26:34 +00:00
2020-03-06 13:51:05 +00:00
self . settings . lock ( ) . unwrap ( ) . used_socket = None ;
element . notify ( " used-socket " ) ;
2018-11-13 12:13:23 +00:00
2020-03-26 18:07:25 +00:00
self . task . unprepare ( ) . unwrap ( ) ;
2020-03-06 13:51:05 +00:00
gst_debug! ( CAT , obj : element , " Unprepared " ) ;
}
2020-11-14 17:09:42 +00:00
fn stop ( & self , element : & super ::UdpSrc ) -> Result < ( ) , gst ::ErrorMessage > {
2020-03-06 13:51:05 +00:00
gst_debug! ( CAT , obj : element , " Stopping " ) ;
2020-05-15 17:38:54 +00:00
self . task . stop ( ) ? ;
2020-03-06 13:51:05 +00:00
gst_debug! ( CAT , obj : element , " Stopped " ) ;
2020-05-15 17:38:54 +00:00
Ok ( ( ) )
2018-03-08 20:26:34 +00:00
}
2020-11-14 17:09:42 +00:00
fn start ( & self , element : & super ::UdpSrc ) -> Result < ( ) , gst ::ErrorMessage > {
2020-03-26 18:07:25 +00:00
gst_debug! ( CAT , obj : element , " Starting " ) ;
2020-05-15 17:38:54 +00:00
self . task . start ( ) ? ;
2020-03-26 18:07:25 +00:00
gst_debug! ( CAT , obj : element , " Started " ) ;
2020-05-15 17:38:54 +00:00
Ok ( ( ) )
2020-03-26 18:07:25 +00:00
}
2020-11-14 17:09:42 +00:00
fn pause ( & self , element : & super ::UdpSrc ) -> Result < ( ) , gst ::ErrorMessage > {
2020-03-06 13:51:05 +00:00
gst_debug! ( CAT , obj : element , " Pausing " ) ;
2020-05-15 17:38:54 +00:00
self . task . pause ( ) ? ;
2019-12-02 09:30:07 +00:00
gst_debug! ( CAT , obj : element , " 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
}
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 ;
type Instance = gst ::subclass ::ElementInstanceStruct < Self > ;
type Class = subclass ::simple ::ClassStruct < Self > ;
glib_object_subclass! ( ) ;
2020-11-14 17:09:42 +00:00
fn class_init ( klass : & mut Self ::Class ) {
2018-12-06 11:03:04 +00:00
klass . set_metadata (
" Thread-sharing UDP source " ,
" Source/Network " ,
" Receives data over the network via UDP " ,
" Sebastian Dröge <sebastian@centricular.com> " ,
) ;
let caps = gst ::Caps ::new_any ( ) ;
let src_pad_template = gst ::PadTemplate ::new (
" src " ,
gst ::PadDirection ::Src ,
gst ::PadPresence ::Always ,
& caps ,
2019-01-29 15:26:40 +00:00
)
. unwrap ( ) ;
2018-12-06 11:03:04 +00:00
klass . add_pad_template ( src_pad_template ) ;
2019-02-07 08:21:08 +00:00
#[ cfg(not(windows)) ]
{
klass . install_properties ( & PROPERTIES ) ;
}
#[ cfg(windows) ]
{
let properties = PROPERTIES
. iter ( )
. filter ( | p | match * p {
subclass ::Property ( " socket " , .. ) | subclass ::Property ( " used-socket " , .. ) = > {
false
}
_ = > true ,
} )
. collect ::< Vec < _ > > ( ) ;
klass . install_properties ( properties . as_slice ( ) ) ;
}
2018-12-06 11:03:04 +00:00
}
2020-11-14 17:09:42 +00:00
fn with_class ( klass : & Self ::Class ) -> Self {
2020-04-29 13:03:43 +00:00
let src_pad_handler = UdpSrcPadHandler ::default ( ) ;
2018-12-06 11:03:04 +00:00
Self {
2020-04-29 13:03:43 +00:00
src_pad : PadSrc ::new (
2020-06-11 10:45:15 +00:00
gst ::Pad ::from_template ( & klass . get_pad_template ( " src " ) . unwrap ( ) , Some ( " src " ) ) ,
2020-04-29 13:03:43 +00:00
src_pad_handler . clone ( ) ,
) ,
src_pad_handler ,
2020-03-26 18:07:25 +00:00
task : Task ::default ( ) ,
2020-03-06 13:51:05 +00:00
settings : StdMutex ::new ( Settings ::default ( ) ) ,
2018-12-06 11:03:04 +00:00
}
}
}
impl ObjectImpl for UdpSrc {
2020-11-14 17:09:42 +00:00
fn set_property ( & self , _obj : & Self ::Type , id : usize , value : & glib ::Value ) {
2018-12-06 11:03:04 +00:00
let prop = & PROPERTIES [ id ] ;
2018-03-08 20:26:34 +00:00
2020-03-06 13:51:05 +00:00
let mut settings = self . settings . lock ( ) . unwrap ( ) ;
2018-03-08 20:26:34 +00:00
match * prop {
2018-12-06 11:03:04 +00:00
subclass ::Property ( " 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
}
2018-12-06 11:03:04 +00:00
subclass ::Property ( " port " , .. ) = > {
2019-08-12 22:45:36 +00:00
settings . port = value . get_some ( ) . expect ( " type checked upstream " ) ;
2018-03-08 20:26:34 +00:00
}
2018-12-06 11:03:04 +00:00
subclass ::Property ( " reuse " , .. ) = > {
2019-08-12 22:45:36 +00:00
settings . reuse = value . get_some ( ) . expect ( " type checked upstream " ) ;
2018-05-23 07:32:06 +00:00
}
2018-12-06 11:03:04 +00:00
subclass ::Property ( " 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
}
2018-12-06 11:03:04 +00:00
subclass ::Property ( " mtu " , .. ) = > {
2019-08-12 22:45:36 +00:00
settings . mtu = value . get_some ( ) . expect ( " type checked upstream " ) ;
2018-03-08 20:26:34 +00:00
}
2018-12-06 11:03:04 +00:00
subclass ::Property ( " socket " , .. ) = > {
2018-11-13 12:13:23 +00:00
settings . socket = value
. get ::< 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 ) ) ;
}
2018-12-06 11:03:04 +00:00
subclass ::Property ( " used-socket " , .. ) = > {
2018-11-13 12:13:23 +00:00
unreachable! ( ) ;
}
2018-12-06 11:03:04 +00:00
subclass ::Property ( " context " , .. ) = > {
2019-08-12 22:45:36 +00:00
settings . context = value
. get ( )
. expect ( " type checked upstream " )
. unwrap_or_else ( | | " " . into ( ) ) ;
2018-03-08 20:26:34 +00:00
}
2018-12-06 11:03:04 +00:00
subclass ::Property ( " context-wait " , .. ) = > {
2019-08-12 22:45:36 +00:00
settings . context_wait = value . get_some ( ) . expect ( " type checked upstream " ) ;
2018-03-12 14:19:46 +00:00
}
2019-03-13 16:07:53 +00:00
subclass ::Property ( " retrieve-sender-address " , .. ) = > {
2019-08-12 22:45:36 +00:00
settings . retrieve_sender_address = value . get_some ( ) . expect ( " type checked upstream " ) ;
2019-03-13 16:07:53 +00:00
}
2018-03-08 20:26:34 +00:00
_ = > unimplemented! ( ) ,
}
}
2020-11-19 15:55:57 +00:00
fn get_property ( & self , _obj : & Self ::Type , id : usize ) -> glib ::Value {
2018-12-06 11:03:04 +00:00
let prop = & PROPERTIES [ id ] ;
2018-03-08 20:26:34 +00:00
2020-03-06 13:51:05 +00:00
let settings = self . settings . lock ( ) . unwrap ( ) ;
2018-03-08 20:26:34 +00:00
match * prop {
2020-11-19 15:55:57 +00:00
subclass ::Property ( " address " , .. ) = > settings . address . to_value ( ) ,
subclass ::Property ( " port " , .. ) = > settings . port . to_value ( ) ,
subclass ::Property ( " reuse " , .. ) = > settings . reuse . to_value ( ) ,
subclass ::Property ( " caps " , .. ) = > settings . caps . to_value ( ) ,
subclass ::Property ( " mtu " , .. ) = > settings . mtu . to_value ( ) ,
subclass ::Property ( " 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 ( ) ,
subclass ::Property ( " 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 ( ) ,
subclass ::Property ( " context " , .. ) = > settings . context . to_value ( ) ,
subclass ::Property ( " context-wait " , .. ) = > settings . context_wait . to_value ( ) ,
2019-03-13 16:07:53 +00:00
subclass ::Property ( " retrieve-sender-address " , .. ) = > {
2020-11-19 15:55:57 +00:00
settings . retrieve_sender_address . to_value ( )
2019-03-13 16:07:53 +00:00
}
2018-03-08 20:26:34 +00:00
_ = > unimplemented! ( ) ,
}
}
2018-12-06 11:03:04 +00:00
2020-11-14 17:09:42 +00:00
fn constructed ( & self , obj : & Self ::Type ) {
2018-12-06 11:03:04 +00:00
self . parent_constructed ( obj ) ;
2020-11-14 17:09:42 +00:00
obj . add_pad ( self . src_pad . gst_pad ( ) ) . unwrap ( ) ;
2020-03-26 18:07:25 +00:00
2020-11-14 17:09:42 +00:00
crate ::set_element_flags ( obj , 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
2018-12-06 11:03:04 +00:00
impl ElementImpl for UdpSrc {
2018-03-06 09:38:27 +00:00
fn change_state (
& self ,
2020-11-14 17:09:42 +00:00
element : & Self ::Type ,
2018-03-06 09:38:27 +00:00
transition : gst ::StateChange ,
2019-01-11 23:45:05 +00:00
) -> Result < gst ::StateChangeSuccess , gst ::StateChangeError > {
2019-10-31 22:34:21 +00:00
gst_trace! ( CAT , obj : element , " Changing state {:?} " , transition ) ;
2018-03-06 09:38:27 +00:00
match transition {
2019-01-11 23:45:05 +00:00
gst ::StateChange ::NullToReady = > {
2020-03-06 13:51:05 +00:00
self . prepare ( element ) . map_err ( | err | {
2020-06-30 20:57:22 +00:00
element . 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 = > {
2020-05-15 17:38:54 +00:00
self . pause ( element ) . map_err ( | _ | gst ::StateChangeError ) ? ;
2019-01-11 23:45:05 +00:00
}
gst ::StateChange ::ReadyToNull = > {
2020-04-20 19:35:06 +00:00
self . unprepare ( element ) ;
2019-01-11 23:45:05 +00:00
}
2018-03-06 09:38:27 +00:00
_ = > ( ) ,
}
2019-01-11 23:45:05 +00:00
let mut success = self . parent_change_state ( element , 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 = > {
2020-05-15 17:38:54 +00:00
self . start ( element ) . 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 = > {
2020-05-15 17:38:54 +00:00
self . stop ( element ) . 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
}
}