rtsp 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog.rdoc +10 -0
- data/Gemfile +1 -1
- data/README.rdoc +52 -38
- data/Rakefile +2 -8
- data/bin/rtsp_client +3 -3
- data/lib/rtsp/client.rb +69 -85
- data/lib/rtsp/message.rb +4 -5
- data/lib/rtsp/presentation.rb +1 -1
- data/lib/rtsp/session.rb +1 -1
- data/lib/rtsp/version.rb +1 -1
- data/rtsp.gemspec +13 -14
- data/spec/integration/client_use_spec.rb +206 -0
- data/spec/integration/coverage/index.html +1 -1
- data/spec/spec_helper.rb +2 -1
- data/spec/support/fake_rtsp_server.rb +1 -1
- data/spec/unit/rtsp/client_spec.rb +407 -0
- data/spec/{rtsp → unit/rtsp}/helpers_spec.rb +1 -1
- data/spec/{rtsp → unit/rtsp}/message_spec.rb +1 -1
- data/spec/{rtsp → unit/rtsp}/response_spec.rb +1 -1
- data/spec/{rtsp → unit/rtsp}/transport_parser_spec.rb +1 -1
- data/spec/{rtsp_spec.rb → unit/rtsp_spec.rb} +3 -3
- metadata +22 -185
- data/spec/rtsp/client_spec.rb +0 -326
- data/spec/rtsp/coverage/assets/0.7.1/application.css +0 -1110
- data/spec/rtsp/coverage/assets/0.7.1/application.js +0 -626
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/favicon_green.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/favicon_red.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/favicon_yellow.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/loading.gif +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/magnify.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/spec/rtsp/coverage/index.html +0 -72
- data/spec/unit/rtsp/coverage/assets/0.7.1/application.css +0 -1110
- data/spec/unit/rtsp/coverage/assets/0.7.1/application.js +0 -626
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/favicon_green.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/favicon_red.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/favicon_yellow.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/loading.gif +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/magnify.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/spec/unit/rtsp/coverage/index.html +0 -72
data/ChangeLog.rdoc
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
=== 0.4.2 / 2012-11-14
|
|
2
|
+
|
|
3
|
+
* Bug fixes
|
|
4
|
+
* {gh-17}[https://github.com/turboladen/rtsp/issues/17] Can now parse HTTP
|
|
5
|
+
responses (some servers may send HTTP responses to RTSP requests).
|
|
6
|
+
* Other
|
|
7
|
+
* Turned logging off by default. To enable, simply do <tt>RTSP::Client.log = true</tt>
|
|
8
|
+
* Updated to work with RTP 0.1.0.
|
|
9
|
+
* Can now inspect RTP packets during #play.
|
|
10
|
+
|
|
1
11
|
=== 0.4.1 / 2012-11-14
|
|
2
12
|
|
|
3
13
|
* gh-16: Can now parse Session IDs to be alpha characters. Thanks @greywolf-colorado!
|
data/Gemfile
CHANGED
data/README.rdoc
CHANGED
|
@@ -2,48 +2,47 @@
|
|
|
2
2
|
|
|
3
3
|
* https://github.com/turboladen/rtsp
|
|
4
4
|
|
|
5
|
+
{<img src="https://secure.travis-ci.org/turboladen/rtsp.png" alt="Build Status" />}[https://travis-ci.org/turboladen/rtsp]
|
|
6
|
+
|
|
5
7
|
== DESCRIPTION:
|
|
6
8
|
|
|
7
9
|
This library intends to follow the RTSP RFC document (2326) to allow for working
|
|
8
|
-
with RTSP servers.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
For more information
|
|
10
|
+
with RTSP servers. By way of {rtp}[https://github.com/turboladen/rtp], you can
|
|
11
|
+
either inspect the RTP packets as they come across the wire or use the file
|
|
12
|
+
that the data got saved to.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
For more information:
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
* RTSP: {http://tools.ietf.org/html/rfc2326}[http://tools.ietf.org/html/rfc2326]
|
|
17
|
+
* RTP: {http://tools.ietf.org/html/rfc3550}[http://tools.ietf.org/html/rfc3550]
|
|
18
|
+
* SDP: {http://tools.ietf.org/html/rfc4566}[http://tools.ietf.org/html/rfc4566]
|
|
16
19
|
|
|
17
20
|
== FEATURES/PROBLEMS:
|
|
18
21
|
|
|
19
22
|
* All standard RTSP methods supported except REDIRECT.
|
|
20
|
-
* Captures RTP data to a file,
|
|
21
|
-
* One client object can only handle 1 stream; use a client per stream until this
|
|
22
|
-
gets implemented.
|
|
23
|
-
* Only handles unicast,
|
|
24
|
-
* RTSP exceptions are all
|
|
23
|
+
* Captures RTP data to a file, or yields if a block is passed to #play.
|
|
24
|
+
* One client object can only handle 1 stream; use a client per stream until this
|
|
25
|
+
functionality gets implemented.
|
|
26
|
+
* Only handles unicast, TCP RTSP communication.
|
|
27
|
+
* RTSP exceptions are all {RTSP::Error}s.
|
|
25
28
|
|
|
26
29
|
== SYNOPSIS:
|
|
27
30
|
|
|
28
31
|
=== Basic Usage
|
|
29
32
|
|
|
30
|
-
RTSP::Client.log? # =>
|
|
31
|
-
RTSP::Client.log =
|
|
32
|
-
client = RTSP::Client.new "rtsp://64.202.98.91/sa.sdp"
|
|
33
|
-
|
|
34
|
-
capturer.rtp_port = 8554
|
|
35
|
-
capturer.rtp_file = File.open("captured_stuff.rtp", "wb")
|
|
36
|
-
end
|
|
37
|
-
|
|
33
|
+
RTSP::Client.log? # => false
|
|
34
|
+
RTSP::Client.log = true
|
|
35
|
+
client = RTSP::Client.new "rtsp://64.202.98.91/sa.sdp"
|
|
36
|
+
|
|
38
37
|
client.server_uri # => #<URI::Generic:0x00000100ba4db0 URL:rtsp://64.202.98.91:554/sa.sdp>
|
|
39
38
|
client.session_state # => :init
|
|
40
39
|
client.cseq # => 1
|
|
41
40
|
client.connection.do_capture # => true
|
|
42
41
|
client.connection.interleave # => false
|
|
43
|
-
client.connection.timeout # =>
|
|
44
|
-
client.capturer.
|
|
45
|
-
client.capturer.rtp_port # =>
|
|
46
|
-
client.capturer.
|
|
42
|
+
client.connection.timeout # => 30
|
|
43
|
+
client.capturer.ip_addressing_type # => :unicast
|
|
44
|
+
client.capturer.rtp_port # => 6970
|
|
45
|
+
client.capturer.capture_file # => #<File:/var/folders/tg/j9jxvvfs4qn9cg4vztzyy2gc0000gp/T/rtp_capture.raw-59901-1l8dgv2>
|
|
47
46
|
client.capturer.transport_protocol # => :UDP
|
|
48
47
|
|
|
49
48
|
response = client.options
|
|
@@ -66,7 +65,6 @@ gets implemented.
|
|
|
66
65
|
client.cseq # => 4
|
|
67
66
|
client.session_state # => :ready
|
|
68
67
|
|
|
69
|
-
|
|
70
68
|
response = client.play(client.aggregate_control_track)
|
|
71
69
|
response.range # => "npt=now="
|
|
72
70
|
resposne.rtp_info # => "url=rtsp://64.202.98.91:554/sa.sdp/trackID=1"
|
|
@@ -86,7 +84,31 @@ gets implemented.
|
|
|
86
84
|
client.session_state # => :init
|
|
87
85
|
|
|
88
86
|
# Check the streamed file's contents
|
|
89
|
-
puts client.capturer.
|
|
87
|
+
puts client.capturer.capture_file # => (Lots of data)
|
|
88
|
+
|
|
89
|
+
=== RTP packet inspection
|
|
90
|
+
|
|
91
|
+
As of RTP 0.1.0, you can now inspect and use packets as they come across the
|
|
92
|
+
wire:
|
|
93
|
+
|
|
94
|
+
client = RTSP::Client.new "rtsp://64.202.98.91/sa.sdp"
|
|
95
|
+
client.describe
|
|
96
|
+
client.setup(client.media_control_tracks.first)
|
|
97
|
+
payload_file = File.new('rtp.data', 'wb')
|
|
98
|
+
|
|
99
|
+
client.play(client.aggregate_control_track) do |packet|
|
|
100
|
+
puts "packet is a #{packet.class}"
|
|
101
|
+
puts "RTP seqence: #{packet.sequence_number}"
|
|
102
|
+
puts "RTP payload type: #{packet.payload_type}"
|
|
103
|
+
|
|
104
|
+
# Let's save the payload data while we're at it...
|
|
105
|
+
payload_file.write(packet.rtp_payload)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
payload_file.close
|
|
109
|
+
|
|
110
|
+
Take a look at the {RTP::Packet docs}[http://rdoc.info/gems/rtp/RTP/Packet] for
|
|
111
|
+
more information.
|
|
90
112
|
|
|
91
113
|
=== CLI App
|
|
92
114
|
|
|
@@ -116,20 +138,12 @@ As usual, get help by:
|
|
|
116
138
|
== REQUIREMENTS:
|
|
117
139
|
|
|
118
140
|
* (Tested) Rubies
|
|
119
|
-
* 1.9.2
|
|
141
|
+
* 1.9.2
|
|
142
|
+
* 1.9.3
|
|
120
143
|
* RubyGems
|
|
121
|
-
* sdp
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* code_statistics, '~> 0.2.13'
|
|
125
|
-
* metric_fu, '>= 2.0.0'
|
|
126
|
-
* ore, '~> 0.7.2'
|
|
127
|
-
* ore-core, '~> 0.1.0'
|
|
128
|
-
* ore-tasks, '~> 0.3.0'
|
|
129
|
-
* rake, '~> 0.8.7'
|
|
130
|
-
* rspec, '~> 2.5.0'
|
|
131
|
-
* simplecov, '>= 0.4.0'
|
|
132
|
-
* yard, '~> 0.6.0'
|
|
144
|
+
* sdp
|
|
145
|
+
* rtp
|
|
146
|
+
* parslet
|
|
133
147
|
|
|
134
148
|
== INSTALL:
|
|
135
149
|
|
data/Rakefile
CHANGED
|
@@ -2,22 +2,16 @@ require 'bundler/gem_tasks'
|
|
|
2
2
|
require 'rspec/core/rake_task'
|
|
3
3
|
require 'yard'
|
|
4
4
|
|
|
5
|
-
RSpec::Core::RakeTask.new
|
|
6
|
-
t.rspec_opts = ['--format', 'documentation', '--color']
|
|
7
|
-
end
|
|
5
|
+
RSpec::Core::RakeTask.new
|
|
8
6
|
|
|
9
7
|
namespace :spec do
|
|
10
8
|
RSpec::Core::RakeTask.new(:warnings) do |t|
|
|
11
9
|
t.ruby_opts = "-w"
|
|
12
|
-
t.rspec_opts = ['--format', 'documentation', '--color']
|
|
13
10
|
end
|
|
14
11
|
end
|
|
15
12
|
task :default => :spec
|
|
16
13
|
task :test => :spec # for `gem test`
|
|
17
14
|
|
|
18
15
|
YARD::Rake::YardocTask.new do |t|
|
|
19
|
-
t.options = [
|
|
16
|
+
t.options = %w[--verbose]
|
|
20
17
|
end
|
|
21
|
-
|
|
22
|
-
# Load all extra rake tasks
|
|
23
|
-
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].each { |ext| load ext }
|
data/bin/rtsp_client
CHANGED
|
@@ -11,7 +11,7 @@ optparse = OptionParser.new do |opts|
|
|
|
11
11
|
# Turn on logging
|
|
12
12
|
RTSP::Client.configure { |c| c.log = false }
|
|
13
13
|
opts.on('-d', '--debug', "Turn on RTSP::Client logging.") do
|
|
14
|
-
RTSP::Client.
|
|
14
|
+
RTSP::Client.log = true
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
#----------------------------------------------------------------------------
|
|
@@ -50,8 +50,8 @@ optparse = OptionParser.new do |opts|
|
|
|
50
50
|
exit
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
rtsp_client = RTSP::Client.new(url) do |
|
|
54
|
-
capturer.
|
|
53
|
+
rtsp_client = RTSP::Client.new(url) do |_, capturer|
|
|
54
|
+
capturer.capture_file = File.open("#{Dir.pwd}/rtsp_client_stream.rtp", "wb")
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
begin
|
data/lib/rtsp/client.rb
CHANGED
|
@@ -79,7 +79,7 @@ module RTSP
|
|
|
79
79
|
attr_accessor :connection
|
|
80
80
|
|
|
81
81
|
# Use to get/set an object for capturing received data.
|
|
82
|
-
#
|
|
82
|
+
#
|
|
83
83
|
# @return [RTP::Receiver]
|
|
84
84
|
attr_accessor :capturer
|
|
85
85
|
|
|
@@ -112,21 +112,16 @@ module RTSP
|
|
|
112
112
|
@connection = Struct::Connection.new
|
|
113
113
|
@capturer = RTP::Receiver.new
|
|
114
114
|
|
|
115
|
-
yield(connection, capturer) if block_given?
|
|
116
|
-
|
|
117
|
-
@connection.server_url
|
|
118
|
-
@server_uri
|
|
119
|
-
@connection.timeout
|
|
120
|
-
@connection.socket
|
|
121
|
-
@connection.do_capture
|
|
122
|
-
@connection.interleave
|
|
123
|
-
|
|
124
|
-
@
|
|
125
|
-
@capturer.broadcast_type ||= :unicast
|
|
126
|
-
@capturer.rtp_file ||= Tempfile.new(RTP::Receiver::DEFAULT_CAPFILE_NAME)
|
|
127
|
-
|
|
128
|
-
@play_thread = nil
|
|
129
|
-
@cseq = 1
|
|
115
|
+
yield(@connection, @capturer) if block_given?
|
|
116
|
+
|
|
117
|
+
@connection.server_url = server_url || @connection.server_url
|
|
118
|
+
@server_uri = build_resource_uri_from(@connection.server_url)
|
|
119
|
+
@connection.timeout ||= 30
|
|
120
|
+
@connection.socket ||= TCPSocket.new(@server_uri.host, @server_uri.port)
|
|
121
|
+
@connection.do_capture ||= true
|
|
122
|
+
@connection.interleave ||= false
|
|
123
|
+
|
|
124
|
+
@cseq = 1
|
|
130
125
|
reset_state
|
|
131
126
|
end
|
|
132
127
|
|
|
@@ -153,18 +148,16 @@ module RTSP
|
|
|
153
148
|
response = Timeout::timeout(@connection.timeout) do
|
|
154
149
|
@connection.socket.send(message.to_s, 0)
|
|
155
150
|
socket_data = @connection.socket.recvfrom MAX_BYTES_TO_RECEIVE
|
|
151
|
+
|
|
152
|
+
RTSP::Client.log "Received response:"
|
|
153
|
+
socket_data.first.each_line { |line| RTSP::Client.log line.strip }
|
|
154
|
+
|
|
156
155
|
RTSP::Response.new socket_data.first
|
|
157
156
|
end
|
|
158
157
|
rescue Timeout::Error
|
|
159
158
|
raise RTSP::Error, "Request took more than #{@connection.timeout} seconds to send."
|
|
160
159
|
end
|
|
161
160
|
|
|
162
|
-
RTSP::Client.log "Received response:"
|
|
163
|
-
|
|
164
|
-
if response
|
|
165
|
-
response.to_s.each_line { |line| RTSP::Client.log line.strip }
|
|
166
|
-
end
|
|
167
|
-
|
|
168
161
|
response
|
|
169
162
|
end
|
|
170
163
|
|
|
@@ -235,8 +228,8 @@ module RTSP
|
|
|
235
228
|
# @return [String] The String to use with the Transport header.
|
|
236
229
|
# @see http://tools.ietf.org/html/rfc2326#page-58 RFC 2326, Section 12.39.
|
|
237
230
|
def request_transport
|
|
238
|
-
value = "RTP/AVP;#{@capturer.
|
|
239
|
-
value << "#{@capturer.rtp_port}-#{@capturer.
|
|
231
|
+
value = "RTP/AVP;#{@capturer.ip_addressing_type};client_port="
|
|
232
|
+
value << "#{@capturer.rtp_port}-#{@capturer.rtcp_port}\r\n"
|
|
240
233
|
end
|
|
241
234
|
|
|
242
235
|
# Sends the SETUP request, then sets +@session+ to the value returned in the
|
|
@@ -260,14 +253,14 @@ module RTSP
|
|
|
260
253
|
|
|
261
254
|
@session = response.session
|
|
262
255
|
parser = RTSP::TransportParser.new
|
|
263
|
-
@transport = parser.parse
|
|
256
|
+
@transport = parser.parse(response.transport)
|
|
264
257
|
|
|
265
258
|
unless @transport[:transport_protocol].nil?
|
|
266
259
|
@capturer.transport_protocol = @transport[:transport_protocol]
|
|
267
260
|
end
|
|
268
261
|
|
|
269
|
-
@capturer.rtp_port
|
|
270
|
-
@capturer.
|
|
262
|
+
@capturer.rtp_port = @transport[:client_port][:rtp].to_i
|
|
263
|
+
@capturer.ip_address = @transport[:destination].to_s
|
|
271
264
|
end
|
|
272
265
|
end
|
|
273
266
|
|
|
@@ -281,7 +274,7 @@ module RTSP
|
|
|
281
274
|
# @raise [RTSP::Error] If +#play+ is called but the session hasn't yet been
|
|
282
275
|
# set up via +#setup+.
|
|
283
276
|
# @see http://tools.ietf.org/html/rfc2326#page-34 RFC 2326, Section 10.5.
|
|
284
|
-
def play(track, additional_headers={})
|
|
277
|
+
def play(track, additional_headers={}, &block)
|
|
285
278
|
message = RTSP::Message.play(track).with_headers({
|
|
286
279
|
cseq: @cseq, session: @session[:session_id] })
|
|
287
280
|
message.add_headers additional_headers
|
|
@@ -291,16 +284,8 @@ module RTSP
|
|
|
291
284
|
raise RTSP::Error, "Session not set up yet. Run #setup first."
|
|
292
285
|
end
|
|
293
286
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
unless @capturer.running?
|
|
298
|
-
@play_thread = Thread.new do
|
|
299
|
-
@capturer.run
|
|
300
|
-
end
|
|
301
|
-
end
|
|
302
|
-
end
|
|
303
|
-
|
|
287
|
+
RTSP::Client.log "Capturing RTP data on port #{@transport[:client_port][:rtp]}"
|
|
288
|
+
@capturer.start(&block)
|
|
304
289
|
@session_state = :playing
|
|
305
290
|
end
|
|
306
291
|
end
|
|
@@ -313,7 +298,7 @@ module RTSP
|
|
|
313
298
|
# @see http://tools.ietf.org/html/rfc2326#page-36 RFC 2326, Section 10.6.
|
|
314
299
|
def pause(track, additional_headers={})
|
|
315
300
|
message = RTSP::Message.pause(track).with_headers({
|
|
316
|
-
|
|
301
|
+
cseq: @cseq, session: @session[:session_id] })
|
|
317
302
|
message.add_headers additional_headers
|
|
318
303
|
|
|
319
304
|
request(message) do
|
|
@@ -336,23 +321,11 @@ module RTSP
|
|
|
336
321
|
message.add_headers additional_headers
|
|
337
322
|
|
|
338
323
|
request(message) do
|
|
324
|
+
@capturer.stop
|
|
339
325
|
reset_state
|
|
340
|
-
|
|
341
|
-
if @play_thread
|
|
342
|
-
@capturer.stop
|
|
343
|
-
@capturer.rtp_file.close
|
|
344
|
-
@play_thread.exit
|
|
345
|
-
end
|
|
346
326
|
end
|
|
347
327
|
end
|
|
348
328
|
|
|
349
|
-
# Sets state related variables back to their starting values;
|
|
350
|
-
# +@session_state+ is set to +:init+; +@session+ is set to 0.
|
|
351
|
-
def reset_state
|
|
352
|
-
@session_state = :init
|
|
353
|
-
@session = {}
|
|
354
|
-
end
|
|
355
|
-
|
|
356
329
|
# Sends the GET_PARAMETERS request.
|
|
357
330
|
#
|
|
358
331
|
# @param [String] track The presentation or media track to ping.
|
|
@@ -361,8 +334,7 @@ module RTSP
|
|
|
361
334
|
# @return [RTSP::Response]
|
|
362
335
|
# @see http://tools.ietf.org/html/rfc2326#page-37 RFC 2326, Section 10.8.
|
|
363
336
|
def get_parameter(track, body="", additional_headers={})
|
|
364
|
-
message = RTSP::Message.get_parameter(track).with_headers({
|
|
365
|
-
cseq: @cseq })
|
|
337
|
+
message = RTSP::Message.get_parameter(track).with_headers({ cseq: @cseq })
|
|
366
338
|
message.add_headers additional_headers
|
|
367
339
|
message.body = body
|
|
368
340
|
|
|
@@ -377,8 +349,7 @@ module RTSP
|
|
|
377
349
|
# @return [RTSP::Response]
|
|
378
350
|
# @see http://tools.ietf.org/html/rfc2326#page-38 RFC 2326, Section 10.9.
|
|
379
351
|
def set_parameter(track, parameters, additional_headers={})
|
|
380
|
-
message = RTSP::Message.set_parameter(track).with_headers({
|
|
381
|
-
cseq: @cseq })
|
|
352
|
+
message = RTSP::Message.set_parameter(track).with_headers({ cseq: @cseq })
|
|
382
353
|
message.add_headers additional_headers
|
|
383
354
|
message.body = parameters
|
|
384
355
|
|
|
@@ -404,7 +375,7 @@ module RTSP
|
|
|
404
375
|
# then increments +@cseq+ by 1. Handles any exceptions raised during the
|
|
405
376
|
# Request.
|
|
406
377
|
#
|
|
407
|
-
# @param [
|
|
378
|
+
# @param [RTSP::Message] message
|
|
408
379
|
# @yield [RTSP::Response]
|
|
409
380
|
# @return [RTSP::Response]
|
|
410
381
|
# @raise [RTSP::Error] All 4xx & 5xx response codes & their messages.
|
|
@@ -434,15 +405,6 @@ module RTSP
|
|
|
434
405
|
response
|
|
435
406
|
end
|
|
436
407
|
|
|
437
|
-
# Ensures that +@session+ is set before continuing on.
|
|
438
|
-
#
|
|
439
|
-
# @raise [RTSP::Error] Raises if @session isn't set.
|
|
440
|
-
def ensure_session
|
|
441
|
-
if @session.empty?
|
|
442
|
-
raise RTSP::Error, "Session number not retrieved from server yet. Run SETUP first."
|
|
443
|
-
end
|
|
444
|
-
end
|
|
445
|
-
|
|
446
408
|
# Extracts the URL associated with the "control" attribute from the main
|
|
447
409
|
# section of the session description.
|
|
448
410
|
#
|
|
@@ -478,24 +440,31 @@ module RTSP
|
|
|
478
440
|
tracks
|
|
479
441
|
end
|
|
480
442
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
#
|
|
443
|
+
private
|
|
444
|
+
|
|
445
|
+
# Sets state related variables back to their starting values;
|
|
446
|
+
# +@session_state+ is set to +:init+; +@session+ is set to 0.
|
|
447
|
+
def reset_state
|
|
448
|
+
@session_state = :init
|
|
449
|
+
@session = {}
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
# Takes the methods returned from the Public header from an OPTIONS response
|
|
453
|
+
# and puts them to an Array.
|
|
484
454
|
#
|
|
485
|
-
# @param [
|
|
486
|
-
#
|
|
487
|
-
#
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
raise RTSP::Error, message
|
|
492
|
-
end
|
|
455
|
+
# @param [String] method_list The string returned from the server containing
|
|
456
|
+
# the list of methods it supports.
|
|
457
|
+
# @return [Array<Symbol>] The list of methods as symbols.
|
|
458
|
+
# @see #options
|
|
459
|
+
def extract_supported_methods_from method_list
|
|
460
|
+
method_list.downcase.split(', ').map { |m| m.to_sym }
|
|
493
461
|
end
|
|
494
462
|
|
|
495
463
|
# Compares the session number passed in to the current client session
|
|
496
464
|
# number ( +@session+ ) and raises if they're not equal. If that's the case,
|
|
497
465
|
# the server responded to a different request.
|
|
498
466
|
#
|
|
467
|
+
# @todo Remove this--it's not used.
|
|
499
468
|
# @param [Fixnum] server_session Session number returned by the server.
|
|
500
469
|
# @raise [RTSP::Error] If the server returns a Session value that's different
|
|
501
470
|
# from what the client sent.
|
|
@@ -506,15 +475,30 @@ module RTSP
|
|
|
506
475
|
end
|
|
507
476
|
end
|
|
508
477
|
|
|
509
|
-
#
|
|
510
|
-
# and
|
|
478
|
+
# Compares the sequence number passed in to the current client sequence
|
|
479
|
+
# number ( +@cseq+ ) and raises if they're not equal. If that's the case, the
|
|
480
|
+
# server responded to a different request.
|
|
511
481
|
#
|
|
512
|
-
# @param [
|
|
513
|
-
#
|
|
514
|
-
#
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
482
|
+
# @param [Fixnum] server_cseq Sequence number returned by the server.
|
|
483
|
+
# @raise [RTSP::Error] If the server returns a CSeq value that's different
|
|
484
|
+
# from what the client sent.
|
|
485
|
+
def compare_sequence_number server_cseq
|
|
486
|
+
if @cseq != server_cseq
|
|
487
|
+
message = "Sequence number mismatch. Client: #{@cseq}, Server: #{server_cseq}"
|
|
488
|
+
raise RTSP::Error, message
|
|
489
|
+
end
|
|
518
490
|
end
|
|
491
|
+
|
|
492
|
+
# Ensures that +@session+ is set before continuing on.
|
|
493
|
+
#
|
|
494
|
+
# @raise [RTSP::Error] Raises if @session isn't set.
|
|
495
|
+
def ensure_session
|
|
496
|
+
if @session.empty?
|
|
497
|
+
raise RTSP::Error, "Session number not retrieved from server yet. Run SETUP first."
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
|
|
519
501
|
end
|
|
520
502
|
end
|
|
503
|
+
|
|
504
|
+
RTSP::Client.log = false
|