Module: RTSP::SocatStreaming
Constant Summary collapse
- RTCP_SOURCE =
["80c80006072dee6ad42c300f76c3b928377e99e5006c461ba92d8a3" + "081ca0006072dee6a010e49583330444e2d41414a4248513600000000"]
- MP4_RTP_MAP =
"96 MP4V-ES/30000"
- MP4_FMTP =
"96 profile-level-id=5;config=000001b005000001b50900000100000" + "0012000c888ba9860fa22c087828307"
- H264_RTP_MAP =
"96 H264/90000"
- H264_FMTP =
"96 packetization-mode=1;profile-level-id=428032;" + "sprop-parameter-sets=Z0KAMtoAgAMEwAQAAjKAAAr8gYAAAYhMAABMS0IvfjAA" + "ADEJgAAJiWhF78CA,aM48gA=="
- SOCAT_OPTIONS =
"rcvbuf=2500000,sndbuf=2500000,sndtimeo=0.00001,rcvtimeo=0.00001"
- BLOCK_SIZE =
2000
- BSD_OPTIONS =
"setsockopt-int=0xffff:0x200:0x01"
Constants included from Global
Global::DEFAULT_RTSP_PORT, Global::DEFAULT_VERSION
Instance Attribute Summary collapse
-
#fmtp ⇒ Array<String>
Media format attributes.
-
#interface_ip ⇒ String
IP address of the interface of the RTSP streamer.
-
#pids ⇒ Hash
readonly
Hash of session IDs and pids.
-
#rtcp_source_identifier ⇒ String
RTCP source identifier.
-
#rtcp_threads ⇒ Hash
readonly
Hash of session IDs and RTCP threads.
-
#rtp_map ⇒ Array<String>
Media type attributes.
-
#rtp_sequence ⇒ Fixnum
RTP sequence number of the source stream.
-
#rtp_timestamp ⇒ Fixnum
RTP timestamp of the source stream.
-
#sessions ⇒ Hash
Hash of session IDs and SOCAT commands.
-
#source_ip ⇒ Array<String>
IP address of the source camera.
-
#source_port ⇒ Array<Fixnum>
Port where the source camera is streaming.
Attributes included from Global
#log, #log_level, #logger, #raise_errors
Instance Method Summary collapse
-
#description(multicast = false, stream_index = 1) ⇒ Object
Returns the default stream description.
-
#disconnect(sid) ⇒ Object
Disconnects the stream matching the session ID.
-
#generate_rtcp_source_id(friendly_name) ⇒ String
Generates a RTCP source ID based on the friendly name.
-
#parse_sequence_number(src_ip, src_port) ⇒ Array<Fixnum>
Parses the headers from an RTP stream.
-
#setup_streamer(sid, transport_url, index = 1, multicast = false) ⇒ Fixnum
Creates a RTP streamer using socat.
-
#start_streaming(sid) ⇒ Object
Start streaming for the requested session.
-
#stop_streaming(sid) ⇒ Object
Stop streaming for the requested session.
Methods included from Global
#log?, #raise_errors?, #reset_config!, #rtsp_version
Instance Attribute Details
#fmtp ⇒ Array<String>
Returns Media format attributes.
52 53 54 |
# File 'lib/rtsp/socat_streaming.rb', line 52 def fmtp @fmtp end |
#interface_ip ⇒ String
Returns IP address of the interface of the RTSP streamer.
37 38 39 |
# File 'lib/rtsp/socat_streaming.rb', line 37 def interface_ip @interface_ip end |
#pids ⇒ Hash (readonly)
Returns Hash of session IDs and pids.
25 26 27 |
# File 'lib/rtsp/socat_streaming.rb', line 25 def pids @pids end |
#rtcp_source_identifier ⇒ String
Returns RTCP source identifier.
46 47 48 |
# File 'lib/rtsp/socat_streaming.rb', line 46 def rtcp_source_identifier @rtcp_source_identifier end |
#rtcp_threads ⇒ Hash (readonly)
Returns Hash of session IDs and RTCP threads.
28 29 30 |
# File 'lib/rtsp/socat_streaming.rb', line 28 def rtcp_threads @rtcp_threads end |
#rtp_map ⇒ Array<String>
Returns Media type attributes.
49 50 51 |
# File 'lib/rtsp/socat_streaming.rb', line 49 def rtp_map @rtp_map end |
#rtp_sequence ⇒ Fixnum
Returns RTP sequence number of the source stream.
43 44 45 |
# File 'lib/rtsp/socat_streaming.rb', line 43 def rtp_sequence @rtp_sequence end |
#rtp_timestamp ⇒ Fixnum
Returns RTP timestamp of the source stream.
40 41 42 |
# File 'lib/rtsp/socat_streaming.rb', line 40 def @rtp_timestamp end |
#sessions ⇒ Hash
Returns Hash of session IDs and SOCAT commands.
22 23 24 |
# File 'lib/rtsp/socat_streaming.rb', line 22 def sessions @sessions end |
#source_ip ⇒ Array<String>
Returns IP address of the source camera.
31 32 33 |
# File 'lib/rtsp/socat_streaming.rb', line 31 def source_ip @source_ip end |
#source_port ⇒ Array<Fixnum>
Returns Port where the source camera is streaming.
34 35 36 |
# File 'lib/rtsp/socat_streaming.rb', line 34 def source_port @source_port end |
Instance Method Details
#description(multicast = false, stream_index = 1) ⇒ Object
Returns the default stream description.
@param multicast True if the description is for a multicast stream.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/rtsp/socat_streaming.rb', line 131 def description(multicast=false, stream_index=1) rtp_map = @rtp_map[stream_index - 1] || H264_RTP_MAP fmtp = @fmtp[stream_index - 1] || H264_FMTP <<EOF v=0\r o=- 1345481255966282 1 IN IP4 #{@interface_ip}\r s=Session streamed by "Streaming Server"\r i=stream1#{multicast ? 'm' : ''}\r t=0 0\r a=tool:LIVE555 Streaming Media v2007.07.09\r a=type:broadcast\r a=control:*\r a=range:npt=0-\r a=x-qt-text-nam:Session streamed by "Streaming Server"\r a=x-qt-text-inf:stream#{stream_index}#{multicast ? 'm' : ''}\r m=video #{multicast ? @source_port[stream_index - 1] : 0} RTP/AVP 96\r c=IN IP4 #{multicast ? "#{multicast_ip(stream_index)}/10" : "0.0.0.0"}\r a=rtpmap:#{rtp_map}\r a=fmtp:#{fmtp}\r a=control:track1\r EOF end |
#disconnect(sid) ⇒ Object
Disconnects the stream matching the session ID.
158 159 160 161 162 163 164 165 |
# File 'lib/rtsp/socat_streaming.rb', line 158 def disconnect sid pid = @pids[sid].to_i @pids.delete(sid) @sessions.delete(sid) Process.kill(9, pid) if pid > 1000 rescue Errno::ESRCH log "Tried to kill dead process: #{pid}" end |
#generate_rtcp_source_id(friendly_name) ⇒ String
Generates a RTCP source ID based on the friendly name. This ID is used in the RTCP communication with the client. The default RTCP_SOURCE
will be used if one is not provided.
60 61 62 63 |
# File 'lib/rtsp/socat_streaming.rb', line 60 def generate_rtcp_source_id friendly_name ["80c80006072dee6ad42c300f76c3b928377e99e5006c461ba92d8a3081ca0006072dee6a010e" + friendly_name.unpack("H*").first + "00000000"].pack("H*") end |
#parse_sequence_number(src_ip, src_port) ⇒ Array<Fixnum>
Parses the headers from an RTP stream.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/rtsp/socat_streaming.rb', line 172 def parse_sequence_number(src_ip, src_port) sock = UDPSocket.new ip = IPAddr.new(src_ip).hton + IPAddr.new("0.0.0.0").hton sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, ip) sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1) sock.bind(Socket::INADDR_ANY, src_port) begin data = sock.recv_nonblock(1500) rescue Errno::EAGAIN retry end sock.close packet = RTP::Packet.read(data) [packet["sequence_number"], packet["timestamp"]] end |
#setup_streamer(sid, transport_url, index = 1, multicast = false) ⇒ Fixnum
Creates a RTP streamer using socat.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/rtsp/socat_streaming.rb', line 71 def setup_streamer(sid, transport_url, index=1, multicast=false) dest_ip, dest_port = transport_url.split ":" unless multicast @rtcp_source_identifier ||= RTCP_SOURCE.pack("H*") local_port = multicast ? @source_port[index - 1] : free_port(true) unless multicast @rtcp_threads[sid] = Thread.start do s = UDPSocket.new s.bind(@interface_ip, local_port+1) loop do begin _, sender = s.recvfrom(36) s.send(@rtcp_source_identifier, 0, sender[3], sender[1]) end end end end @cleaner ||= Thread.start { cleanup_defunct } @processes ||= Sys::ProcTable.ps.map { |p| p.cmdline } if multicast @sessions[sid] = :multicast else @sessions[sid] = build_socat(dest_ip, dest_port, local_port, index) end local_port end |
#start_streaming(sid) ⇒ Object
Start streaming for the requested session.
110 111 112 |
# File 'lib/rtsp/socat_streaming.rb', line 110 def start_streaming sid spawn_socat(sid, @sessions[sid]) unless @sessions[sid] == :multicast end |
#stop_streaming(sid) ⇒ Object
Stop streaming for the requested session.
117 118 119 120 121 122 123 124 125 |
# File 'lib/rtsp/socat_streaming.rb', line 117 def stop_streaming sid if sid.nil? disconnect_all_streams else disconnect sid @rtcp_threads[sid].kill unless rtcp_threads[sid].nil? @rtcp_threads.delete sid end end |