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/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
|