netwerk/protocol/rtsp/controller/RtspController.cpp

branch
TOR_BUG_9701
changeset 14
925c144e1f1f
equal deleted inserted replaced
-1:000000000000 0:d122dfe0e4dc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 : */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "RtspController.h"
8 #include "RtspMetaData.h"
9 #include "nsIURI.h"
10 #include "nsICryptoHash.h"
11 #include "nsIRunnable.h"
12 #include "nsIPrefBranch.h"
13 #include "nsIPrefService.h"
14 #include "nsICancelable.h"
15 #include "nsIStreamConverterService.h"
16 #include "nsIIOService2.h"
17 #include "nsIProtocolProxyService.h"
18 #include "nsIProxyInfo.h"
19 #include "nsIProxiedChannel.h"
20
21 #include "nsAutoPtr.h"
22 #include "nsStandardURL.h"
23 #include "nsNetCID.h"
24 #include "nsServiceManagerUtils.h"
25 #include "nsXPIDLString.h"
26 #include "nsCRT.h"
27 #include "nsThreadUtils.h"
28 #include "nsError.h"
29 #include "nsStringStream.h"
30 #include "nsAlgorithm.h"
31 #include "nsProxyRelease.h"
32 #include "nsNetUtil.h"
33 #include "mozilla/Attributes.h"
34 #include "mozilla/Telemetry.h"
35 #include "mozilla/TimeStamp.h"
36 #include "prlog.h"
37
38 #include "plbase64.h"
39 #include "prmem.h"
40 #include "prnetdb.h"
41 #include "zlib.h"
42 #include <algorithm>
43 #include "nsDebug.h"
44
45 extern PRLogModuleInfo* gRtspLog;
46 #undef LOG
47 #define LOG(args) PR_LOG(gRtspLog, PR_LOG_DEBUG, args)
48
49 namespace mozilla {
50 namespace net {
51
52 NS_IMPL_ISUPPORTS(RtspController,
53 nsIStreamingProtocolController)
54
55 RtspController::RtspController(nsIChannel *channel)
56 : mState(INIT)
57 {
58 LOG(("RtspController::RtspController()"));
59 }
60
61 RtspController::~RtspController()
62 {
63 LOG(("RtspController::~RtspController()"));
64 if (mRtspSource.get()) {
65 mRtspSource.clear();
66 }
67 }
68
69 NS_IMETHODIMP
70 RtspController::GetTrackMetaData(uint8_t index,
71 nsIStreamingProtocolMetaData * *_retval)
72 {
73 LOG(("RtspController::GetTrackMetaData()"));
74 return NS_OK;
75 }
76
77 NS_IMETHODIMP
78 RtspController::Play(void)
79 {
80 LOG(("RtspController::Play()"));
81 if (!mRtspSource.get()) {
82 MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
83 return NS_ERROR_NOT_INITIALIZED;
84 }
85
86 if (mState != CONNECTED) {
87 return NS_ERROR_NOT_CONNECTED;
88 }
89
90 mRtspSource->play();
91 return NS_OK;
92 }
93
94 NS_IMETHODIMP
95 RtspController::Pause(void)
96 {
97 LOG(("RtspController::Pause()"));
98 if (!mRtspSource.get()) {
99 MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
100 return NS_ERROR_NOT_INITIALIZED;
101 }
102
103 if (mState != CONNECTED) {
104 return NS_ERROR_NOT_CONNECTED;
105 }
106
107 mRtspSource->pause();
108 return NS_OK;
109 }
110
111 NS_IMETHODIMP
112 RtspController::Resume(void)
113 {
114 LOG(("RtspController::Resume()"));
115 if (!mRtspSource.get()) {
116 MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
117 return NS_ERROR_NOT_INITIALIZED;
118 }
119
120 if (mState != CONNECTED) {
121 return NS_ERROR_NOT_CONNECTED;
122 }
123
124 mRtspSource->play();
125 return NS_OK;
126 }
127
128 NS_IMETHODIMP
129 RtspController::Suspend(void)
130 {
131 LOG(("RtspController::Suspend()"));
132 if (!mRtspSource.get()) {
133 MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
134 return NS_ERROR_NOT_INITIALIZED;
135 }
136
137 if (mState != CONNECTED) {
138 return NS_ERROR_NOT_CONNECTED;
139 }
140
141 mRtspSource->pause();
142 return NS_OK;
143 }
144
145 NS_IMETHODIMP
146 RtspController::Seek(uint64_t seekTimeUs)
147 {
148 LOG(("RtspController::Seek() %llu", seekTimeUs));
149 if (!mRtspSource.get()) {
150 MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
151 return NS_ERROR_NOT_INITIALIZED;
152 }
153
154 if (mState != CONNECTED) {
155 return NS_ERROR_NOT_CONNECTED;
156 }
157
158 mRtspSource->seek(seekTimeUs);
159 return NS_OK;
160 }
161
162 NS_IMETHODIMP
163 RtspController::Stop()
164 {
165 LOG(("RtspController::Stop()"));
166 mState = INIT;
167 if (!mRtspSource.get()) {
168 MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
169 return NS_ERROR_NOT_INITIALIZED;
170 }
171
172 mRtspSource->stop();
173 return NS_OK;
174 }
175
176 NS_IMETHODIMP
177 RtspController::GetTotalTracks(uint8_t *aTracks)
178 {
179 LOG(("RtspController::GetTotalTracks()"));
180 return NS_ERROR_NOT_IMPLEMENTED;
181 }
182
183 NS_IMETHODIMP
184 RtspController::AsyncOpen(nsIStreamingProtocolListener *aListener)
185 {
186 if (!aListener) {
187 LOG(("RtspController::AsyncOpen() illegal listener"));
188 return NS_ERROR_NOT_INITIALIZED;
189 }
190
191 mListener = aListener;
192
193 if (!mURI) {
194 LOG(("RtspController::AsyncOpen() illegal URI"));
195 return NS_ERROR_ILLEGAL_VALUE;
196 }
197
198 nsAutoCString uriSpec;
199 mURI->GetSpec(uriSpec);
200 LOG(("RtspController AsyncOpen uri=%s", uriSpec.get()));
201
202 if (!mRtspSource.get()) {
203 mRtspSource = new android::RTSPSource(this, uriSpec.get(), false, 0);
204 }
205 // Connect to Rtsp Server.
206 mRtspSource->start();
207
208 return NS_OK;
209 }
210
211 class SendMediaDataTask : public nsRunnable
212 {
213 public:
214 SendMediaDataTask(nsIStreamingProtocolListener *listener,
215 uint8_t index,
216 const nsACString & data,
217 uint32_t length,
218 uint32_t offset,
219 nsIStreamingProtocolMetaData *meta)
220 : mIndex(index)
221 , mLength(length)
222 , mOffset(offset)
223 , mMetaData(meta)
224 , mListener(listener)
225 {
226 mData.Assign(data);
227 }
228
229 NS_IMETHOD Run()
230 {
231 MOZ_ASSERT(NS_IsMainThread());
232 mListener->OnMediaDataAvailable(mIndex, mData, mLength,
233 mOffset, mMetaData);
234 return NS_OK;
235 }
236
237 private:
238 uint8_t mIndex;
239 nsCString mData;
240 uint32_t mLength;
241 uint32_t mOffset;
242 nsRefPtr<nsIStreamingProtocolMetaData> mMetaData;
243 nsCOMPtr<nsIStreamingProtocolListener> mListener;
244 };
245
246 NS_IMETHODIMP
247 RtspController::OnMediaDataAvailable(uint8_t index,
248 const nsACString & data,
249 uint32_t length,
250 uint32_t offset,
251 nsIStreamingProtocolMetaData *meta)
252 {
253 if (mListener && mState == CONNECTED) {
254 nsRefPtr<SendMediaDataTask> task =
255 new SendMediaDataTask(mListener, index, data, length, offset, meta);
256 return NS_DispatchToMainThread(task);
257 }
258 return NS_ERROR_NOT_AVAILABLE;
259 }
260
261 class SendOnConnectedTask : public nsRunnable
262 {
263 public:
264 SendOnConnectedTask(nsIStreamingProtocolListener *listener,
265 uint8_t index,
266 nsIStreamingProtocolMetaData *meta)
267 : mListener(listener)
268 , mIndex(index)
269 , mMetaData(meta)
270 { }
271
272 NS_IMETHOD Run()
273 {
274 MOZ_ASSERT(NS_IsMainThread());
275 mListener->OnConnected(mIndex, mMetaData);
276 return NS_OK;
277 }
278
279 private:
280 nsCOMPtr<nsIStreamingProtocolListener> mListener;
281 uint8_t mIndex;
282 nsRefPtr<nsIStreamingProtocolMetaData> mMetaData;
283 };
284
285
286 NS_IMETHODIMP
287 RtspController::OnConnected(uint8_t index,
288 nsIStreamingProtocolMetaData *meta)
289 {
290 LOG(("RtspController::OnConnected()"));
291 mState = CONNECTED;
292 if (mListener) {
293 nsRefPtr<SendOnConnectedTask> task =
294 new SendOnConnectedTask(mListener, index, meta);
295 return NS_DispatchToMainThread(task);
296 }
297 return NS_ERROR_NOT_AVAILABLE;
298 }
299
300 class SendOnDisconnectedTask : public nsRunnable
301 {
302 public:
303 SendOnDisconnectedTask(nsIStreamingProtocolListener *listener,
304 uint8_t index,
305 nsresult reason)
306 : mListener(listener)
307 , mIndex(index)
308 , mReason(reason)
309 { }
310
311 NS_IMETHOD Run()
312 {
313 MOZ_ASSERT(NS_IsMainThread());
314 mListener->OnDisconnected(mIndex, mReason);
315 return NS_OK;
316 }
317
318 private:
319 nsCOMPtr<nsIStreamingProtocolListener> mListener;
320 uint8_t mIndex;
321 nsresult mReason;
322 };
323
324 NS_IMETHODIMP
325 RtspController::OnDisconnected(uint8_t index,
326 nsresult reason)
327 {
328 LOG(("RtspController::OnDisconnected() for track %d reason = 0x%x", index, reason));
329 mState = DISCONNECTED;
330 if (mListener) {
331 nsRefPtr<SendOnDisconnectedTask> task =
332 new SendOnDisconnectedTask(mListener, index, reason);
333 // Break the cycle reference between the Listener (RtspControllerParent) and
334 // us.
335 mListener = nullptr;
336 return NS_DispatchToMainThread(task);
337 }
338 return NS_ERROR_NOT_AVAILABLE;
339 }
340
341 NS_IMETHODIMP
342 RtspController::Init(nsIURI *aURI)
343 {
344 nsresult rv;
345
346 if (!aURI) {
347 LOG(("RtspController::Init() - invalid URI"));
348 return NS_ERROR_NOT_INITIALIZED;
349 }
350
351 nsAutoCString host;
352 int32_t port = -1;
353
354 rv = aURI->GetAsciiHost(host);
355 if (NS_FAILED(rv)) return rv;
356
357 // Reject the URL if it doesn't specify a host
358 if (host.IsEmpty())
359 return NS_ERROR_MALFORMED_URI;
360
361 rv = aURI->GetPort(&port);
362 if (NS_FAILED(rv)) return rv;
363
364 rv = aURI->GetAsciiSpec(mSpec);
365 if (NS_FAILED(rv)) return rv;
366
367 mURI = aURI;
368
369 return NS_OK;
370 }
371
372 } // namespace mozilla::net
373 } // namespace mozilla

mercurial