1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/protocol/rtsp/controller/RtspController.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,373 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set sw=2 ts=8 et tw=80 : */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "RtspController.h" 1.11 +#include "RtspMetaData.h" 1.12 +#include "nsIURI.h" 1.13 +#include "nsICryptoHash.h" 1.14 +#include "nsIRunnable.h" 1.15 +#include "nsIPrefBranch.h" 1.16 +#include "nsIPrefService.h" 1.17 +#include "nsICancelable.h" 1.18 +#include "nsIStreamConverterService.h" 1.19 +#include "nsIIOService2.h" 1.20 +#include "nsIProtocolProxyService.h" 1.21 +#include "nsIProxyInfo.h" 1.22 +#include "nsIProxiedChannel.h" 1.23 + 1.24 +#include "nsAutoPtr.h" 1.25 +#include "nsStandardURL.h" 1.26 +#include "nsNetCID.h" 1.27 +#include "nsServiceManagerUtils.h" 1.28 +#include "nsXPIDLString.h" 1.29 +#include "nsCRT.h" 1.30 +#include "nsThreadUtils.h" 1.31 +#include "nsError.h" 1.32 +#include "nsStringStream.h" 1.33 +#include "nsAlgorithm.h" 1.34 +#include "nsProxyRelease.h" 1.35 +#include "nsNetUtil.h" 1.36 +#include "mozilla/Attributes.h" 1.37 +#include "mozilla/Telemetry.h" 1.38 +#include "mozilla/TimeStamp.h" 1.39 +#include "prlog.h" 1.40 + 1.41 +#include "plbase64.h" 1.42 +#include "prmem.h" 1.43 +#include "prnetdb.h" 1.44 +#include "zlib.h" 1.45 +#include <algorithm> 1.46 +#include "nsDebug.h" 1.47 + 1.48 +extern PRLogModuleInfo* gRtspLog; 1.49 +#undef LOG 1.50 +#define LOG(args) PR_LOG(gRtspLog, PR_LOG_DEBUG, args) 1.51 + 1.52 +namespace mozilla { 1.53 +namespace net { 1.54 + 1.55 +NS_IMPL_ISUPPORTS(RtspController, 1.56 + nsIStreamingProtocolController) 1.57 + 1.58 +RtspController::RtspController(nsIChannel *channel) 1.59 + : mState(INIT) 1.60 +{ 1.61 + LOG(("RtspController::RtspController()")); 1.62 +} 1.63 + 1.64 +RtspController::~RtspController() 1.65 +{ 1.66 + LOG(("RtspController::~RtspController()")); 1.67 + if (mRtspSource.get()) { 1.68 + mRtspSource.clear(); 1.69 + } 1.70 +} 1.71 + 1.72 +NS_IMETHODIMP 1.73 +RtspController::GetTrackMetaData(uint8_t index, 1.74 + nsIStreamingProtocolMetaData * *_retval) 1.75 +{ 1.76 + LOG(("RtspController::GetTrackMetaData()")); 1.77 + return NS_OK; 1.78 +} 1.79 + 1.80 +NS_IMETHODIMP 1.81 +RtspController::Play(void) 1.82 +{ 1.83 + LOG(("RtspController::Play()")); 1.84 + if (!mRtspSource.get()) { 1.85 + MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!"); 1.86 + return NS_ERROR_NOT_INITIALIZED; 1.87 + } 1.88 + 1.89 + if (mState != CONNECTED) { 1.90 + return NS_ERROR_NOT_CONNECTED; 1.91 + } 1.92 + 1.93 + mRtspSource->play(); 1.94 + return NS_OK; 1.95 +} 1.96 + 1.97 +NS_IMETHODIMP 1.98 +RtspController::Pause(void) 1.99 +{ 1.100 + LOG(("RtspController::Pause()")); 1.101 + if (!mRtspSource.get()) { 1.102 + MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!"); 1.103 + return NS_ERROR_NOT_INITIALIZED; 1.104 + } 1.105 + 1.106 + if (mState != CONNECTED) { 1.107 + return NS_ERROR_NOT_CONNECTED; 1.108 + } 1.109 + 1.110 + mRtspSource->pause(); 1.111 + return NS_OK; 1.112 +} 1.113 + 1.114 +NS_IMETHODIMP 1.115 +RtspController::Resume(void) 1.116 +{ 1.117 + LOG(("RtspController::Resume()")); 1.118 + if (!mRtspSource.get()) { 1.119 + MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!"); 1.120 + return NS_ERROR_NOT_INITIALIZED; 1.121 + } 1.122 + 1.123 + if (mState != CONNECTED) { 1.124 + return NS_ERROR_NOT_CONNECTED; 1.125 + } 1.126 + 1.127 + mRtspSource->play(); 1.128 + return NS_OK; 1.129 +} 1.130 + 1.131 +NS_IMETHODIMP 1.132 +RtspController::Suspend(void) 1.133 +{ 1.134 + LOG(("RtspController::Suspend()")); 1.135 + if (!mRtspSource.get()) { 1.136 + MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!"); 1.137 + return NS_ERROR_NOT_INITIALIZED; 1.138 + } 1.139 + 1.140 + if (mState != CONNECTED) { 1.141 + return NS_ERROR_NOT_CONNECTED; 1.142 + } 1.143 + 1.144 + mRtspSource->pause(); 1.145 + return NS_OK; 1.146 +} 1.147 + 1.148 +NS_IMETHODIMP 1.149 +RtspController::Seek(uint64_t seekTimeUs) 1.150 +{ 1.151 + LOG(("RtspController::Seek() %llu", seekTimeUs)); 1.152 + if (!mRtspSource.get()) { 1.153 + MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!"); 1.154 + return NS_ERROR_NOT_INITIALIZED; 1.155 + } 1.156 + 1.157 + if (mState != CONNECTED) { 1.158 + return NS_ERROR_NOT_CONNECTED; 1.159 + } 1.160 + 1.161 + mRtspSource->seek(seekTimeUs); 1.162 + return NS_OK; 1.163 +} 1.164 + 1.165 +NS_IMETHODIMP 1.166 +RtspController::Stop() 1.167 +{ 1.168 + LOG(("RtspController::Stop()")); 1.169 + mState = INIT; 1.170 + if (!mRtspSource.get()) { 1.171 + MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!"); 1.172 + return NS_ERROR_NOT_INITIALIZED; 1.173 + } 1.174 + 1.175 + mRtspSource->stop(); 1.176 + return NS_OK; 1.177 +} 1.178 + 1.179 +NS_IMETHODIMP 1.180 +RtspController::GetTotalTracks(uint8_t *aTracks) 1.181 +{ 1.182 + LOG(("RtspController::GetTotalTracks()")); 1.183 + return NS_ERROR_NOT_IMPLEMENTED; 1.184 +} 1.185 + 1.186 +NS_IMETHODIMP 1.187 +RtspController::AsyncOpen(nsIStreamingProtocolListener *aListener) 1.188 +{ 1.189 + if (!aListener) { 1.190 + LOG(("RtspController::AsyncOpen() illegal listener")); 1.191 + return NS_ERROR_NOT_INITIALIZED; 1.192 + } 1.193 + 1.194 + mListener = aListener; 1.195 + 1.196 + if (!mURI) { 1.197 + LOG(("RtspController::AsyncOpen() illegal URI")); 1.198 + return NS_ERROR_ILLEGAL_VALUE; 1.199 + } 1.200 + 1.201 + nsAutoCString uriSpec; 1.202 + mURI->GetSpec(uriSpec); 1.203 + LOG(("RtspController AsyncOpen uri=%s", uriSpec.get())); 1.204 + 1.205 + if (!mRtspSource.get()) { 1.206 + mRtspSource = new android::RTSPSource(this, uriSpec.get(), false, 0); 1.207 + } 1.208 + // Connect to Rtsp Server. 1.209 + mRtspSource->start(); 1.210 + 1.211 + return NS_OK; 1.212 +} 1.213 + 1.214 +class SendMediaDataTask : public nsRunnable 1.215 +{ 1.216 +public: 1.217 + SendMediaDataTask(nsIStreamingProtocolListener *listener, 1.218 + uint8_t index, 1.219 + const nsACString & data, 1.220 + uint32_t length, 1.221 + uint32_t offset, 1.222 + nsIStreamingProtocolMetaData *meta) 1.223 + : mIndex(index) 1.224 + , mLength(length) 1.225 + , mOffset(offset) 1.226 + , mMetaData(meta) 1.227 + , mListener(listener) 1.228 + { 1.229 + mData.Assign(data); 1.230 + } 1.231 + 1.232 + NS_IMETHOD Run() 1.233 + { 1.234 + MOZ_ASSERT(NS_IsMainThread()); 1.235 + mListener->OnMediaDataAvailable(mIndex, mData, mLength, 1.236 + mOffset, mMetaData); 1.237 + return NS_OK; 1.238 + } 1.239 + 1.240 +private: 1.241 + uint8_t mIndex; 1.242 + nsCString mData; 1.243 + uint32_t mLength; 1.244 + uint32_t mOffset; 1.245 + nsRefPtr<nsIStreamingProtocolMetaData> mMetaData; 1.246 + nsCOMPtr<nsIStreamingProtocolListener> mListener; 1.247 +}; 1.248 + 1.249 +NS_IMETHODIMP 1.250 +RtspController::OnMediaDataAvailable(uint8_t index, 1.251 + const nsACString & data, 1.252 + uint32_t length, 1.253 + uint32_t offset, 1.254 + nsIStreamingProtocolMetaData *meta) 1.255 +{ 1.256 + if (mListener && mState == CONNECTED) { 1.257 + nsRefPtr<SendMediaDataTask> task = 1.258 + new SendMediaDataTask(mListener, index, data, length, offset, meta); 1.259 + return NS_DispatchToMainThread(task); 1.260 + } 1.261 + return NS_ERROR_NOT_AVAILABLE; 1.262 +} 1.263 + 1.264 +class SendOnConnectedTask : public nsRunnable 1.265 +{ 1.266 +public: 1.267 + SendOnConnectedTask(nsIStreamingProtocolListener *listener, 1.268 + uint8_t index, 1.269 + nsIStreamingProtocolMetaData *meta) 1.270 + : mListener(listener) 1.271 + , mIndex(index) 1.272 + , mMetaData(meta) 1.273 + { } 1.274 + 1.275 + NS_IMETHOD Run() 1.276 + { 1.277 + MOZ_ASSERT(NS_IsMainThread()); 1.278 + mListener->OnConnected(mIndex, mMetaData); 1.279 + return NS_OK; 1.280 + } 1.281 + 1.282 +private: 1.283 + nsCOMPtr<nsIStreamingProtocolListener> mListener; 1.284 + uint8_t mIndex; 1.285 + nsRefPtr<nsIStreamingProtocolMetaData> mMetaData; 1.286 +}; 1.287 + 1.288 + 1.289 +NS_IMETHODIMP 1.290 +RtspController::OnConnected(uint8_t index, 1.291 + nsIStreamingProtocolMetaData *meta) 1.292 +{ 1.293 + LOG(("RtspController::OnConnected()")); 1.294 + mState = CONNECTED; 1.295 + if (mListener) { 1.296 + nsRefPtr<SendOnConnectedTask> task = 1.297 + new SendOnConnectedTask(mListener, index, meta); 1.298 + return NS_DispatchToMainThread(task); 1.299 + } 1.300 + return NS_ERROR_NOT_AVAILABLE; 1.301 +} 1.302 + 1.303 +class SendOnDisconnectedTask : public nsRunnable 1.304 +{ 1.305 +public: 1.306 + SendOnDisconnectedTask(nsIStreamingProtocolListener *listener, 1.307 + uint8_t index, 1.308 + nsresult reason) 1.309 + : mListener(listener) 1.310 + , mIndex(index) 1.311 + , mReason(reason) 1.312 + { } 1.313 + 1.314 + NS_IMETHOD Run() 1.315 + { 1.316 + MOZ_ASSERT(NS_IsMainThread()); 1.317 + mListener->OnDisconnected(mIndex, mReason); 1.318 + return NS_OK; 1.319 + } 1.320 + 1.321 +private: 1.322 + nsCOMPtr<nsIStreamingProtocolListener> mListener; 1.323 + uint8_t mIndex; 1.324 + nsresult mReason; 1.325 +}; 1.326 + 1.327 +NS_IMETHODIMP 1.328 +RtspController::OnDisconnected(uint8_t index, 1.329 + nsresult reason) 1.330 +{ 1.331 + LOG(("RtspController::OnDisconnected() for track %d reason = 0x%x", index, reason)); 1.332 + mState = DISCONNECTED; 1.333 + if (mListener) { 1.334 + nsRefPtr<SendOnDisconnectedTask> task = 1.335 + new SendOnDisconnectedTask(mListener, index, reason); 1.336 + // Break the cycle reference between the Listener (RtspControllerParent) and 1.337 + // us. 1.338 + mListener = nullptr; 1.339 + return NS_DispatchToMainThread(task); 1.340 + } 1.341 + return NS_ERROR_NOT_AVAILABLE; 1.342 +} 1.343 + 1.344 +NS_IMETHODIMP 1.345 +RtspController::Init(nsIURI *aURI) 1.346 +{ 1.347 + nsresult rv; 1.348 + 1.349 + if (!aURI) { 1.350 + LOG(("RtspController::Init() - invalid URI")); 1.351 + return NS_ERROR_NOT_INITIALIZED; 1.352 + } 1.353 + 1.354 + nsAutoCString host; 1.355 + int32_t port = -1; 1.356 + 1.357 + rv = aURI->GetAsciiHost(host); 1.358 + if (NS_FAILED(rv)) return rv; 1.359 + 1.360 + // Reject the URL if it doesn't specify a host 1.361 + if (host.IsEmpty()) 1.362 + return NS_ERROR_MALFORMED_URI; 1.363 + 1.364 + rv = aURI->GetPort(&port); 1.365 + if (NS_FAILED(rv)) return rv; 1.366 + 1.367 + rv = aURI->GetAsciiSpec(mSpec); 1.368 + if (NS_FAILED(rv)) return rv; 1.369 + 1.370 + mURI = aURI; 1.371 + 1.372 + return NS_OK; 1.373 +} 1.374 + 1.375 +} // namespace mozilla::net 1.376 +} // namespace mozilla