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, request, 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.
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/rtsp/socat_streaming.rb', line 144 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.
171 172 173 174 175 176 177 178 |
# File 'lib/rtsp/socat_streaming.rb', line 171 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.
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/rtsp/socat_streaming.rb', line 185 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, request, 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 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/rtsp/socat_streaming.rb', line 71 def setup_streamer(sid, request, index=1, multicast=false) transport_url = request.transport_url 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 if request.transport.include?('cleint_port') /client_port=(?<p1>\d*)-(?<p2>\d*)/ =~ request.transport dest_port = p1 if dest_port == "64000" @sessions[sid] = :multicast else puts "Request malformed client-port not found #{request.transport}" if dest_port.nil? raise "Request malformed client-port not found #{request.transport}" if dest_port.nil? @sessions[sid] = build_socat(@source_ip[index - 1], dest_port.to_i, local_port, index) end else @sessions[sid] = :multicast end 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.
123 124 125 |
# File 'lib/rtsp/socat_streaming.rb', line 123 def start_streaming sid spawn_socat(sid, @sessions[sid]) unless @sessions[sid] == :multicast end |
#stop_streaming(sid) ⇒ Object
Stop streaming for the requested session.
130 131 132 133 134 135 136 137 138 |
# File 'lib/rtsp/socat_streaming.rb', line 130 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 |