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