rtsp 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- 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/lib/rtsp/message.rb
CHANGED
@@ -75,7 +75,7 @@ module RTSP
|
|
75
75
|
attr_reader :body
|
76
76
|
attr_writer :rtsp_version
|
77
77
|
|
78
|
-
# @param [Symbol]
|
78
|
+
# @param [Symbol] method_type The RTSP method to build and send.
|
79
79
|
# @param [String] request_uri The URL to communicate to.
|
80
80
|
def initialize(method_type, request_uri)
|
81
81
|
@method_type = method_type
|
@@ -88,7 +88,7 @@ module RTSP
|
|
88
88
|
# Adds the header and its value to the list of headers for the message.
|
89
89
|
#
|
90
90
|
# @param [Symbol] type The header type.
|
91
|
-
# @param [] value The value to set the header field to.
|
91
|
+
# @param [*] value The value to set the header field to.
|
92
92
|
def header(type, value)
|
93
93
|
if type.is_a? Symbol
|
94
94
|
headers[type] = value
|
@@ -124,8 +124,7 @@ module RTSP
|
|
124
124
|
#
|
125
125
|
# @example Simple header
|
126
126
|
# RTSP::Message.options("192.168.1.10").with_body("The body!")
|
127
|
-
# @param [Hash]
|
128
|
-
# key will be capitalized; if
|
127
|
+
# @param [Hash] new_body The new body to add to the request.
|
129
128
|
def with_body(new_body)
|
130
129
|
add_body new_body
|
131
130
|
|
@@ -249,7 +248,7 @@ module RTSP
|
|
249
248
|
|
250
249
|
# Turns header values into a single string.
|
251
250
|
#
|
252
|
-
# @param [] values The header values to put to string.
|
251
|
+
# @param [*] values The header values to put to string.
|
253
252
|
# @param [String] separator The character to use to separate multiple
|
254
253
|
# values that define a header.
|
255
254
|
# @return [String] The header values as a single string.
|
data/lib/rtsp/presentation.rb
CHANGED
data/lib/rtsp/session.rb
CHANGED
data/lib/rtsp/version.rb
CHANGED
data/rtsp.gemspec
CHANGED
@@ -9,12 +9,11 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.version = RTSP::VERSION
|
10
10
|
|
11
11
|
s.homepage = %q{https://github.com/turboladen/rtsp}
|
12
|
-
s.authors = ["Steve Loveless, Mike Kirby", "Sujin Philip"]
|
12
|
+
s.authors = ["Steve Loveless", "Mike Kirby", "Sujin Philip"]
|
13
13
|
s.summary = %q{Library to allow RTSP streaming from RTSP-enabled devices.}
|
14
14
|
s.description = %q{This library intends to follow the RTSP RFC document (2326)
|
15
|
-
to allow for working with RTSP servers.
|
16
|
-
|
17
|
-
For more information see: http://www.ietf.org/rfc/rfc2326.txt}
|
15
|
+
to allow for working with RTSP servers. For more information see:
|
16
|
+
http://www.ietf.org/rfc/rfc2326.txt}
|
18
17
|
s.email = %w{steve.loveless@gmail.com}
|
19
18
|
s.licenses = %w{MIT}
|
20
19
|
|
@@ -23,17 +22,17 @@ For more information see: http://www.ietf.org/rfc/rfc2326.txt}
|
|
23
22
|
%w(.gemtest rtsp.gemspec Gemfile Rakefile)
|
24
23
|
s.extra_rdoc_files = %w{ChangeLog.rdoc LICENSE.rdoc README.rdoc}
|
25
24
|
s.require_paths = %w{lib}
|
26
|
-
s.rubygems_version =
|
25
|
+
s.rubygems_version = "1.7.2"
|
27
26
|
s.test_files = Dir.glob("{spec,features}/**/*")
|
28
27
|
|
29
|
-
s.add_runtime_dependency
|
30
|
-
s.add_runtime_dependency
|
31
|
-
s.add_runtime_dependency
|
28
|
+
s.add_runtime_dependency "parslet", ">= 1.1.0"
|
29
|
+
s.add_runtime_dependency "rtp", ">= 0.1.1"
|
30
|
+
s.add_runtime_dependency "sdp", "~> 0.2.6"
|
32
31
|
|
33
|
-
s.add_development_dependency
|
34
|
-
s.add_development_dependency
|
35
|
-
s.add_development_dependency
|
36
|
-
s.add_development_dependency
|
37
|
-
s.add_development_dependency
|
38
|
-
s.add_development_dependency
|
32
|
+
s.add_development_dependency "bundler"
|
33
|
+
s.add_development_dependency "cucumber", ">= 1.1.0"
|
34
|
+
s.add_development_dependency "rake", ">= 0.8.7"
|
35
|
+
s.add_development_dependency "rspec", ">= 2.5.0"
|
36
|
+
s.add_development_dependency "simplecov", ">= 0.4.0"
|
37
|
+
s.add_development_dependency "yard", ">= 0.6.0"
|
39
38
|
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'sdp'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'rtsp/client'
|
4
|
+
|
5
|
+
describe "Client use" do
|
6
|
+
subject do
|
7
|
+
fake_rtsp_server = FakeRTSPServer.new
|
8
|
+
|
9
|
+
RTSP::Client.new('http://localhost') do |connection|
|
10
|
+
connection.socket = fake_rtsp_server
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#options" do
|
15
|
+
it "extracts the server's supported methods" do
|
16
|
+
subject.options
|
17
|
+
subject.supported_methods.should ==
|
18
|
+
[:describe, :setup, :teardown, :play, :pause]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns a Response" do
|
22
|
+
response = subject.options
|
23
|
+
response.should be_a RTSP::Response
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#describe" do
|
28
|
+
before do
|
29
|
+
@response = subject.describe
|
30
|
+
end
|
31
|
+
|
32
|
+
it "extracts the aggregate control track" do
|
33
|
+
subject.aggregate_control_track.should == "rtsp://64.202.98.91:554/sa.sdp/"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "extracts the media control tracks" do
|
37
|
+
subject.media_control_tracks.should == ["rtsp://64.202.98.91:554/sa.sdp/trackID=1"]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "extracts the SDP object" do
|
41
|
+
subject.instance_variable_get(:@session_description).should ==
|
42
|
+
@response.body
|
43
|
+
end
|
44
|
+
|
45
|
+
it "extracts the Content-Base header" do
|
46
|
+
subject.instance_variable_get(:@content_base).should ==
|
47
|
+
URI.parse("rtsp://64.202.98.91:554/sa.sdp/")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns a Response" do
|
51
|
+
@response.should be_a RTSP::Response
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#announce" do
|
56
|
+
it "returns a Response" do
|
57
|
+
sdp = SDP::Description.new
|
58
|
+
subject.setup("rtsp://localhost/another_track")
|
59
|
+
response = subject.announce("rtsp://localhost/another_track", sdp)
|
60
|
+
response.should be_a RTSP::Response
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#setup" do
|
65
|
+
after do
|
66
|
+
subject.teardown("rtsp://localhost/some_track")
|
67
|
+
end
|
68
|
+
|
69
|
+
it "extracts the session number" do
|
70
|
+
subject.session.should be_empty
|
71
|
+
subject.setup("rtsp://localhost/some_track")
|
72
|
+
subject.session[:session_id].should == "1234567890"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "changes the session_state to :ready" do
|
76
|
+
subject.setup("rtsp://localhost/some_track")
|
77
|
+
subject.session_state.should == :ready
|
78
|
+
end
|
79
|
+
|
80
|
+
it "extracts the transport header info" do
|
81
|
+
subject.instance_variable_get(:@transport).should be_nil
|
82
|
+
subject.setup("rtsp://localhost/some_track")
|
83
|
+
subject.instance_variable_get(:@transport).should == {
|
84
|
+
streaming_protocol: "RTP",
|
85
|
+
profile: "AVP",
|
86
|
+
broadcast_type: "unicast",
|
87
|
+
destination: "127.0.0.1",
|
88
|
+
source: "10.221.222.235",
|
89
|
+
client_port: { rtp: "9000", rtcp: "9001" },
|
90
|
+
server_port: { rtp: "6700", rtcp: "6701" }
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
it "returns a Response" do
|
95
|
+
response = subject.setup("rtsp://localhost/some_track")
|
96
|
+
response.should be_a RTSP::Response
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#play" do
|
101
|
+
before do
|
102
|
+
subject.setup("rtsp://localhost/some_track")
|
103
|
+
end
|
104
|
+
|
105
|
+
after do
|
106
|
+
subject.teardown('rtsp://localhost/some_track')
|
107
|
+
end
|
108
|
+
|
109
|
+
it "changes the session_state to :playing" do
|
110
|
+
subject.play("rtsp://localhost/some_track")
|
111
|
+
subject.session_state.should == :playing
|
112
|
+
end
|
113
|
+
|
114
|
+
it "returns a Response" do
|
115
|
+
RTSP::Client.log = true
|
116
|
+
RTP::Logger.log = true
|
117
|
+
response = subject.play("rtsp://localhost/some_track")
|
118
|
+
response.should be_a RTSP::Response
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "#pause" do
|
123
|
+
before :each do
|
124
|
+
subject.setup("rtsp://localhost/some_track")
|
125
|
+
end
|
126
|
+
|
127
|
+
after do
|
128
|
+
subject.teardown('rtsp://localhost/some_track')
|
129
|
+
end
|
130
|
+
|
131
|
+
it "changes the session_state from :playing to :ready" do
|
132
|
+
subject.play("rtsp://localhost/some_track")
|
133
|
+
subject.pause("rtsp://localhost/some_track")
|
134
|
+
subject.session_state.should == :ready
|
135
|
+
end
|
136
|
+
|
137
|
+
it "changes the session_state from :recording to :ready" do
|
138
|
+
subject.record("rtsp://localhost/some_track")
|
139
|
+
subject.pause("rtsp://localhost/some_track")
|
140
|
+
subject.session_state.should == :ready
|
141
|
+
end
|
142
|
+
|
143
|
+
it "returns a Response" do
|
144
|
+
response = subject.pause("rtsp://localhost/some_track")
|
145
|
+
response.should be_a RTSP::Response
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "#teardown" do
|
150
|
+
before do
|
151
|
+
subject.setup("rtsp://localhost/some_track")
|
152
|
+
end
|
153
|
+
|
154
|
+
it "changes the session_state to :init" do
|
155
|
+
subject.session_state.should_not == :init
|
156
|
+
subject.teardown("rtsp://localhost/some_track")
|
157
|
+
subject.session_state.should == :init
|
158
|
+
end
|
159
|
+
|
160
|
+
it "changes the session_id back to 0" do
|
161
|
+
subject.session.should_not be_empty
|
162
|
+
subject.teardown("rtsp://localhost/some_track")
|
163
|
+
subject.session.should be_empty
|
164
|
+
end
|
165
|
+
|
166
|
+
it "returns a Response" do
|
167
|
+
response = subject.teardown("rtsp://localhost/some_track")
|
168
|
+
response.should be_a RTSP::Response
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "#get_parameter" do
|
173
|
+
it "returns a Response" do
|
174
|
+
response = subject.get_parameter("rtsp://localhost/some_track", "ping!")
|
175
|
+
response.should be_a RTSP::Response
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe "#set_parameter" do
|
180
|
+
it "returns a Response" do
|
181
|
+
response = subject.set_parameter("rtsp://localhost/some_track", "ping!")
|
182
|
+
response.should be_a RTSP::Response
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe "#record" do
|
187
|
+
before :each do
|
188
|
+
subject.setup("rtsp://localhost/some_track")
|
189
|
+
end
|
190
|
+
|
191
|
+
after do
|
192
|
+
subject.teardown('rtsp://localhost/some_track')
|
193
|
+
end
|
194
|
+
|
195
|
+
it "returns a Response" do
|
196
|
+
response = subject.record("rtsp://localhost/some_track")
|
197
|
+
response.is_a?(RTSP::Response).should be_true
|
198
|
+
end
|
199
|
+
|
200
|
+
it "changes the session_state to :recording" do
|
201
|
+
subject.session_state.should == :ready
|
202
|
+
subject.record("rtsp://localhost/some_track")
|
203
|
+
subject.session_state.should == :recording
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
@@ -14,7 +14,7 @@
|
|
14
14
|
<img src="./assets/0.7.1/loading.gif" alt="loading"/>
|
15
15
|
</div>
|
16
16
|
<div id="wrapper" style="display:none;">
|
17
|
-
<div class="timestamp">Generated <abbr class="timeago" title="2012-11-
|
17
|
+
<div class="timestamp">Generated <abbr class="timeago" title="2012-11-20T18:37:28-08:00">2012-11-20T18:37:28-08:00</abbr></div>
|
18
18
|
<ul class="group_tabs"></ul>
|
19
19
|
|
20
20
|
<div id="content">
|
data/spec/spec_helper.rb
CHANGED
@@ -4,10 +4,11 @@ SimpleCov.start do
|
|
4
4
|
add_filter "/spec/"
|
5
5
|
end
|
6
6
|
|
7
|
-
require 'rspec'
|
8
7
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
9
8
|
require 'rtsp'
|
10
9
|
|
10
|
+
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f }
|
11
|
+
|
11
12
|
OPTIONS_RESPONSE = %Q{RTSP/1.0 200 OK\r
|
12
13
|
CSeq: 1\r
|
13
14
|
Date: Fri, Jan 28 2011 01:14:42 GMT\r
|
@@ -66,7 +66,7 @@ class FakeRTSPServer
|
|
66
66
|
%Q{RTSP/1.0 200 OK\r
|
67
67
|
CSeq: #{@cseq}\r
|
68
68
|
Date: #{Time.now.httpdate}\r
|
69
|
-
Transport: RTP/AVP;unicast;destination=
|
69
|
+
Transport: RTP/AVP;unicast;destination=127.0.0.1;source=10.221.222.235;client_port=9000-9001;server_port=6700-6701\r
|
70
70
|
Session: #{@session}\r
|
71
71
|
\r\n}
|
72
72
|
end
|
@@ -0,0 +1,407 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rtsp/client'
|
3
|
+
|
4
|
+
RTSP::Client.log = false
|
5
|
+
RTP::Logger.log = false
|
6
|
+
|
7
|
+
|
8
|
+
describe RTSP::Client do
|
9
|
+
subject do
|
10
|
+
mock_socket = double 'MockSocket'
|
11
|
+
|
12
|
+
RTSP::Client.new("rtsp://localhost") do |connection|
|
13
|
+
connection.socket = mock_socket
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#initialize" do
|
18
|
+
it "sets cseq to 1" do
|
19
|
+
subject.cseq.should == 1
|
20
|
+
end
|
21
|
+
|
22
|
+
it "sets session_state to :init" do
|
23
|
+
subject.session_state.should == :init
|
24
|
+
end
|
25
|
+
|
26
|
+
it "sets server_uri to be a URI containing the first init param + 554" do
|
27
|
+
subject.server_uri.should be_a(URI)
|
28
|
+
subject.server_uri.to_s.should == "rtsp://localhost:554"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe ".configure" do
|
33
|
+
around do |example|
|
34
|
+
RTSP::Client.reset_config!
|
35
|
+
example.run
|
36
|
+
RTSP::Client.reset_config!
|
37
|
+
RTSP::Client.log = false
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "log" do
|
41
|
+
it "should default to true" do
|
42
|
+
RTSP::Client.log?.should be_true
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should set whether to log RTSP requests/responses" do
|
46
|
+
RTSP::Client.configure { |config| config.log = false }
|
47
|
+
RTSP::Client.log?.should be_false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "logger" do
|
52
|
+
it "should set the logger to use" do
|
53
|
+
MyLogger = Class.new
|
54
|
+
RTSP::Client.configure { |config| config.logger = MyLogger }
|
55
|
+
RTSP::Client.logger.should == MyLogger
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should default to Logger writing to STDOUT" do
|
59
|
+
RTSP::Client.logger.should be_a(Logger)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "log_level" do
|
64
|
+
it "should default to :debug" do
|
65
|
+
RTSP::Client.log_level.should == :debug
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should set the log level to use" do
|
69
|
+
RTSP::Client.configure { |config| config.log_level = :info }
|
70
|
+
RTSP::Client.log_level.should == :info
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it "handles empty non-existent CSeq header" do
|
76
|
+
pending
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#server_url" do
|
80
|
+
it "allows for changing the server URL on the fly" do
|
81
|
+
subject.server_uri.to_s.should == "rtsp://localhost:554"
|
82
|
+
subject.server_url = "rtsp://localhost:8080"
|
83
|
+
subject.server_uri.to_s.should == "rtsp://localhost:8080"
|
84
|
+
subject.server_uri.should be_a URI
|
85
|
+
end
|
86
|
+
|
87
|
+
it "raises when passing in something other than a String" do
|
88
|
+
subject.server_uri.to_s.should == "rtsp://localhost:554"
|
89
|
+
expect { subject.server_url = [] }.to raise_error
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#options" do
|
94
|
+
let(:message) do
|
95
|
+
m = double "RTSP::Message"
|
96
|
+
m.should_receive(:with_headers).with(cseq: 1).and_return m
|
97
|
+
m.should_receive(:add_headers).with({})
|
98
|
+
|
99
|
+
m
|
100
|
+
end
|
101
|
+
|
102
|
+
let(:response) do
|
103
|
+
double "RTSP::Response", public: [:a_method]
|
104
|
+
end
|
105
|
+
|
106
|
+
it "creates a RTSP::Message.options from @server_uri" do
|
107
|
+
RTSP::Message.should_receive(:options).with('rtsp://localhost:554').
|
108
|
+
and_return message
|
109
|
+
subject.should_receive(:request).with(message).and_yield(response)
|
110
|
+
subject.should_receive(:extract_supported_methods_from).with [:a_method]
|
111
|
+
subject.options
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "#describe" do
|
116
|
+
let(:message) do
|
117
|
+
m = double "RTSP::Message"
|
118
|
+
m.should_receive(:with_headers).with(cseq: 1).and_return m
|
119
|
+
m.should_receive(:add_headers).with({})
|
120
|
+
|
121
|
+
m
|
122
|
+
end
|
123
|
+
|
124
|
+
let(:response) do
|
125
|
+
r = double "RTSP::Response"
|
126
|
+
r.should_receive(:body).and_return "the body"
|
127
|
+
r.should_receive(:content_base).and_return "content"
|
128
|
+
|
129
|
+
r
|
130
|
+
end
|
131
|
+
|
132
|
+
before do
|
133
|
+
RTSP::Message.should_receive(:describe).with('rtsp://localhost:554').
|
134
|
+
and_return message
|
135
|
+
subject.should_receive(:request).with(message).and_yield(response)
|
136
|
+
subject.should_receive(:build_resource_uri_from).with("content").
|
137
|
+
and_return "content"
|
138
|
+
subject.should_receive(:media_control_tracks).and_return 'media'
|
139
|
+
subject.should_receive(:aggregate_control_track).and_return 'aggregate'
|
140
|
+
|
141
|
+
subject.describe
|
142
|
+
end
|
143
|
+
|
144
|
+
it "extracts @session_description, @content_base, and tracks" do
|
145
|
+
subject.instance_variable_get(:@session_description).should == 'the body'
|
146
|
+
subject.instance_variable_get(:@content_base).should == 'content'
|
147
|
+
subject.instance_variable_get(:@media_control_tracks).should == 'media'
|
148
|
+
subject.instance_variable_get(:@aggregate_control_track).should == 'aggregate'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "#announce" do
|
153
|
+
let(:message) do
|
154
|
+
message = double "RTSP::Message"
|
155
|
+
message.should_receive(:with_headers).with(cseq: 1).and_return message
|
156
|
+
message.should_receive(:add_headers).with({})
|
157
|
+
message.should_receive(:body=).with('description')
|
158
|
+
|
159
|
+
message
|
160
|
+
end
|
161
|
+
|
162
|
+
let(:description) { double "SDP::Description", to_s: "description" }
|
163
|
+
let(:url) { 'rtsp://neato:9000' }
|
164
|
+
|
165
|
+
it "creates and sends an announce request with request_url and description" do
|
166
|
+
RTSP::Message.should_receive(:announce).with(url).and_return message
|
167
|
+
subject.should_receive(:request).with(message)
|
168
|
+
subject.announce(url, description)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "#setup" do
|
173
|
+
let(:message) do
|
174
|
+
subject.stub(:request_transport).and_return "transport"
|
175
|
+
message = double "RTSP::Message"
|
176
|
+
message.should_receive(:with_headers).
|
177
|
+
with(cseq: 1, transport: "transport").and_return message
|
178
|
+
message.should_receive(:add_headers).with({})
|
179
|
+
|
180
|
+
message
|
181
|
+
end
|
182
|
+
|
183
|
+
let(:track_url) { 'rtsp://server/track1' }
|
184
|
+
let(:response) do
|
185
|
+
r = double "RTSP::Response"
|
186
|
+
r.should_receive(:session).and_return session
|
187
|
+
r.should_receive(:transport).and_return transport
|
188
|
+
|
189
|
+
r
|
190
|
+
end
|
191
|
+
|
192
|
+
let(:transport) do
|
193
|
+
t = double "@transport"
|
194
|
+
t.should_receive(:[]).with(:transport_protocol).twice.and_return "RTP"
|
195
|
+
t.stub_chain(:[], :[]).and_return 1
|
196
|
+
t.should_receive(:[]).with(:destination).and_return "destination"
|
197
|
+
|
198
|
+
t
|
199
|
+
end
|
200
|
+
|
201
|
+
let(:transport_parser) { double "RTSP::TransportParser", parse: transport }
|
202
|
+
let(:session) { 1 }
|
203
|
+
|
204
|
+
before do
|
205
|
+
RTSP::Message.should_receive(:setup).with(track_url).and_return message
|
206
|
+
subject.should_receive(:request).with(message).and_yield response
|
207
|
+
RTSP::TransportParser.stub(:new).and_return transport_parser
|
208
|
+
|
209
|
+
subject.setup(track_url)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "changes session_state to :ready" do
|
213
|
+
subject.session_state.should == :ready
|
214
|
+
end
|
215
|
+
|
216
|
+
it "sets the capturer's transport_protocol to what was requested in the transport header" do
|
217
|
+
subject.capturer.transport_protocol.should == "RTP"
|
218
|
+
end
|
219
|
+
|
220
|
+
it "sets the capturer's rtp_port to what was requested in the transport header" do
|
221
|
+
subject.capturer.rtp_port.should == 1
|
222
|
+
end
|
223
|
+
|
224
|
+
it "sets the capturer's ip_address to what was requested in the transport header" do
|
225
|
+
subject.capturer.ip_address.should == "destination"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "#play" do
|
230
|
+
let(:fake_capturer) { double "RTP::Receiver" }
|
231
|
+
|
232
|
+
let(:transport) do
|
233
|
+
t = double "@transport"
|
234
|
+
t.stub_chain(:[], :[])
|
235
|
+
|
236
|
+
t
|
237
|
+
end
|
238
|
+
|
239
|
+
before do
|
240
|
+
subject.capturer = fake_capturer
|
241
|
+
subject.instance_variable_set(:@transport, transport)
|
242
|
+
subject.instance_variable_set(:@session_state, :ready)
|
243
|
+
subject.should_receive(:request).and_yield
|
244
|
+
end
|
245
|
+
|
246
|
+
context "@session_state is :ready" do
|
247
|
+
before do
|
248
|
+
fake_capturer.should_receive(:start)
|
249
|
+
end
|
250
|
+
|
251
|
+
it "changes the session_state to :playing" do
|
252
|
+
subject.play("rtsp://localhost/some_track")
|
253
|
+
|
254
|
+
subject.session_state.should == :playing
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context "@session_state is not :ready" do
|
259
|
+
before do
|
260
|
+
subject.instance_variable_set(:@session_state, :pants)
|
261
|
+
end
|
262
|
+
|
263
|
+
it "raises an error" do
|
264
|
+
expect {
|
265
|
+
subject.play("rtsp://localhost/some_track")
|
266
|
+
}.to raise_error RTSP::Error
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
describe "#pause" do
|
272
|
+
let(:message) do
|
273
|
+
m = double "RTSP::Message"
|
274
|
+
m.should_receive(:with_headers).with(cseq: 1, session: 1).and_return m
|
275
|
+
m.should_receive(:add_headers).with({})
|
276
|
+
|
277
|
+
m
|
278
|
+
end
|
279
|
+
|
280
|
+
before do
|
281
|
+
RTSP::Message.should_receive(:pause).and_return message
|
282
|
+
subject.instance_variable_set(:@session, { session_id: 1 })
|
283
|
+
subject.should_receive(:request).with(message).and_yield
|
284
|
+
end
|
285
|
+
|
286
|
+
context "@session_state is :playing" do
|
287
|
+
before do
|
288
|
+
subject.instance_variable_set(:@session_state, :playing)
|
289
|
+
|
290
|
+
subject.pause('rtsp://localhost/some_track')
|
291
|
+
end
|
292
|
+
|
293
|
+
it "sets @session_state to :ready" do
|
294
|
+
subject.instance_variable_get(:@session_state).should == :ready
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
context "@session_state is not :playing" do
|
299
|
+
before do
|
300
|
+
subject.instance_variable_set(:@session_state, :pants)
|
301
|
+
|
302
|
+
subject.pause('rtsp://localhost/some_track')
|
303
|
+
end
|
304
|
+
|
305
|
+
it "doesn't change @session_state" do
|
306
|
+
subject.instance_variable_get(:@session_state).should == :pants
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
describe "#teardown" do
|
312
|
+
let(:message) do
|
313
|
+
m = double "RTSP::Message"
|
314
|
+
m.should_receive(:with_headers).with(cseq: 1, session: 1).and_return m
|
315
|
+
m.should_receive(:add_headers).with({})
|
316
|
+
|
317
|
+
m
|
318
|
+
end
|
319
|
+
|
320
|
+
before do
|
321
|
+
RTSP::Message.should_receive(:teardown).and_return message
|
322
|
+
subject.instance_variable_set(:@session, { session_id: 1 })
|
323
|
+
subject.instance_variable_set(:@session_state, :playing)
|
324
|
+
subject.should_receive(:request).with(message).and_yield
|
325
|
+
subject.capturer.should_receive(:stop)
|
326
|
+
|
327
|
+
subject.teardown('rtsp://localhost/some_track')
|
328
|
+
end
|
329
|
+
|
330
|
+
it "sets @session_state back to :init" do
|
331
|
+
subject.instance_variable_get(:@session_state).should == :init
|
332
|
+
end
|
333
|
+
|
334
|
+
it "clears the session info" do
|
335
|
+
subject.instance_variable_get(:@session).should == {}
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
describe "#get_parameter" do
|
340
|
+
let(:message) do
|
341
|
+
m = double "RTSP::Message"
|
342
|
+
m.should_receive(:with_headers).with(cseq: 1).and_return m
|
343
|
+
m.should_receive(:add_headers).with({})
|
344
|
+
m.should_receive(:body=).with(body)
|
345
|
+
|
346
|
+
m
|
347
|
+
end
|
348
|
+
|
349
|
+
let(:body) { "body" }
|
350
|
+
|
351
|
+
it "sends the request" do
|
352
|
+
RTSP::Message.should_receive(:get_parameter).and_return message
|
353
|
+
subject.should_receive(:request).with(message)
|
354
|
+
|
355
|
+
subject.get_parameter('rtsp://localhost/some_track', body)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
describe "#set_parameter" do
|
360
|
+
let(:message) do
|
361
|
+
m = double "RTSP::Message"
|
362
|
+
m.should_receive(:with_headers).with(cseq: 1).and_return m
|
363
|
+
m.should_receive(:add_headers).with({})
|
364
|
+
m.should_receive(:body=).with(body)
|
365
|
+
|
366
|
+
m
|
367
|
+
end
|
368
|
+
|
369
|
+
let(:body) { "body" }
|
370
|
+
|
371
|
+
it "sends the request" do
|
372
|
+
RTSP::Message.should_receive(:set_parameter).and_return message
|
373
|
+
subject.should_receive(:request).with(message)
|
374
|
+
|
375
|
+
subject.set_parameter('rtsp://localhost/some_track', body)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
describe "#record" do
|
380
|
+
let(:message) do
|
381
|
+
m = double "RTSP::Message"
|
382
|
+
m.should_receive(:with_headers).with(cseq: 1, session: 1).and_return m
|
383
|
+
m.should_receive(:add_headers).with({})
|
384
|
+
|
385
|
+
m
|
386
|
+
end
|
387
|
+
|
388
|
+
before do
|
389
|
+
RTSP::Message.should_receive(:record).and_return message
|
390
|
+
subject.instance_variable_set(:@session, { session_id: 1 })
|
391
|
+
subject.instance_variable_set(:@session_state, :playing)
|
392
|
+
subject.should_receive(:request).with(message).and_yield
|
393
|
+
|
394
|
+
subject.record('rtsp://localhost/some_track')
|
395
|
+
end
|
396
|
+
|
397
|
+
it "sets @session_state to :recording" do
|
398
|
+
subject.instance_variable_get(:@session_state).should == :recording
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
describe "#send_message" do
|
403
|
+
it "raises if the send takes longer than the timeout" do
|
404
|
+
pending "until I figure out how to test the time out raises"
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|