rtsp 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/ChangeLog.rdoc +10 -0
  2. data/Gemfile +1 -1
  3. data/README.rdoc +52 -38
  4. data/Rakefile +2 -8
  5. data/bin/rtsp_client +3 -3
  6. data/lib/rtsp/client.rb +69 -85
  7. data/lib/rtsp/message.rb +4 -5
  8. data/lib/rtsp/presentation.rb +1 -1
  9. data/lib/rtsp/session.rb +1 -1
  10. data/lib/rtsp/version.rb +1 -1
  11. data/rtsp.gemspec +13 -14
  12. data/spec/integration/client_use_spec.rb +206 -0
  13. data/spec/integration/coverage/index.html +1 -1
  14. data/spec/spec_helper.rb +2 -1
  15. data/spec/support/fake_rtsp_server.rb +1 -1
  16. data/spec/unit/rtsp/client_spec.rb +407 -0
  17. data/spec/{rtsp → unit/rtsp}/helpers_spec.rb +1 -1
  18. data/spec/{rtsp → unit/rtsp}/message_spec.rb +1 -1
  19. data/spec/{rtsp → unit/rtsp}/response_spec.rb +1 -1
  20. data/spec/{rtsp → unit/rtsp}/transport_parser_spec.rb +1 -1
  21. data/spec/{rtsp_spec.rb → unit/rtsp_spec.rb} +3 -3
  22. metadata +22 -185
  23. data/spec/rtsp/client_spec.rb +0 -326
  24. data/spec/rtsp/coverage/assets/0.7.1/application.css +0 -1110
  25. data/spec/rtsp/coverage/assets/0.7.1/application.js +0 -626
  26. data/spec/rtsp/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
  27. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
  28. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
  29. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
  30. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
  31. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
  32. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
  33. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
  34. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
  35. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
  36. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
  37. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
  38. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
  39. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
  40. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
  41. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
  42. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
  43. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
  44. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
  45. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
  46. data/spec/rtsp/coverage/assets/0.7.1/favicon_green.png +0 -0
  47. data/spec/rtsp/coverage/assets/0.7.1/favicon_red.png +0 -0
  48. data/spec/rtsp/coverage/assets/0.7.1/favicon_yellow.png +0 -0
  49. data/spec/rtsp/coverage/assets/0.7.1/loading.gif +0 -0
  50. data/spec/rtsp/coverage/assets/0.7.1/magnify.png +0 -0
  51. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  52. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  53. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  54. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  55. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  56. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  57. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  58. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  59. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
  60. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  61. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
  62. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
  63. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  64. data/spec/rtsp/coverage/index.html +0 -72
  65. data/spec/unit/rtsp/coverage/assets/0.7.1/application.css +0 -1110
  66. data/spec/unit/rtsp/coverage/assets/0.7.1/application.js +0 -626
  67. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
  68. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
  69. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
  70. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
  71. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
  72. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
  73. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
  74. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
  75. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
  76. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
  77. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
  78. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
  79. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
  80. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
  81. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
  82. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
  83. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
  84. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
  85. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
  86. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
  87. data/spec/unit/rtsp/coverage/assets/0.7.1/favicon_green.png +0 -0
  88. data/spec/unit/rtsp/coverage/assets/0.7.1/favicon_red.png +0 -0
  89. data/spec/unit/rtsp/coverage/assets/0.7.1/favicon_yellow.png +0 -0
  90. data/spec/unit/rtsp/coverage/assets/0.7.1/loading.gif +0 -0
  91. data/spec/unit/rtsp/coverage/assets/0.7.1/magnify.png +0 -0
  92. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  93. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  94. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  95. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  96. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  97. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  98. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  99. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  100. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
  101. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  102. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
  103. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
  104. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  105. data/spec/unit/rtsp/coverage/index.html +0 -72
@@ -75,7 +75,7 @@ module RTSP
75
75
  attr_reader :body
76
76
  attr_writer :rtsp_version
77
77
 
78
- # @param [Symbol] :method_type The RTSP method to build and send.
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] new_headers The headers to add to the Request. The 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.
@@ -33,7 +33,7 @@ module RTSP
33
33
  yield self if block_given?
34
34
  end
35
35
 
36
- # @param [RTSP::Stream] stream
36
+ # @yieldparam [RTSP::Stream]
37
37
  def add_stream(&block)
38
38
  stream = RTSP::Stream.new
39
39
  yield stream
@@ -37,7 +37,7 @@ module RTSP
37
37
  # * "The server is recording media data."
38
38
  attr_accessor :state
39
39
 
40
- # @param [RTSP::Stream]
40
+ # @param [RTSP::Stream] stream
41
41
  def initialize(stream)
42
42
  @stream = stream
43
43
  @session_id = Time.now.to_ntp
@@ -1,4 +1,4 @@
1
1
  module RTSP
2
2
  # rtsp version
3
- VERSION = "0.4.1"
3
+ VERSION = "0.4.2"
4
4
  end
@@ -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. At this point, it's up to you to parse
16
- the data from a play call, but we'll get there. ...eventually.
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 = %q{1.7.2}
25
+ s.rubygems_version = "1.7.2"
27
26
  s.test_files = Dir.glob("{spec,features}/**/*")
28
27
 
29
- s.add_runtime_dependency(%q<parslet>, [">= 1.1.0"])
30
- s.add_runtime_dependency(%q<rtp>, [">= 0.0.1"])
31
- s.add_runtime_dependency(%q<sdp>, ["~> 0.2.6"])
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(%q<bundler>)
34
- s.add_development_dependency(%q<cucumber>, [">= 1.1.0"])
35
- s.add_development_dependency(%q<rake>, [">= 0.8.7"])
36
- s.add_development_dependency(%q<rspec>, [">= 2.5.0"])
37
- s.add_development_dependency(%q<simplecov>, [">= 0.4.0"])
38
- s.add_development_dependency(%q<yard>, [">= 0.6.0"])
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-08T21:06:26-08:00">2012-11-08T21:06:26-08:00</abbr></div>
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">
@@ -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=10.221.222.186;source=10.221.222.235;client_port=9000-9001;server_port=6700-6701\r
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