1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/protocol/rtsp/controller/RtspControllerChild.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,526 @@ 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 "RtspControllerChild.h" 1.11 +#include "RtspMetaData.h" 1.12 +#include "mozilla/dom/TabChild.h" 1.13 +#include "mozilla/net/NeckoChild.h" 1.14 +#include "nsITabChild.h" 1.15 +#include "nsILoadContext.h" 1.16 +#include "nsNetUtil.h" 1.17 +#include "mozilla/ipc/InputStreamUtils.h" 1.18 +#include "mozilla/ipc/URIUtils.h" 1.19 +#include "nsStringStream.h" 1.20 +#include "prlog.h" 1.21 + 1.22 +PRLogModuleInfo* gRtspChildLog = nullptr; 1.23 +#undef LOG 1.24 +#define LOG(args) PR_LOG(gRtspChildLog, PR_LOG_DEBUG, args) 1.25 + 1.26 +const uint32_t kRtspTotalTracks = 2; 1.27 +using namespace mozilla::ipc; 1.28 + 1.29 +namespace mozilla { 1.30 +namespace net { 1.31 + 1.32 +NS_IMPL_ADDREF(RtspControllerChild) 1.33 + 1.34 +NS_IMETHODIMP_(nsrefcnt) RtspControllerChild::Release() 1.35 +{ 1.36 + NS_PRECONDITION(0 != mRefCnt, "dup release"); 1.37 + // Enable this to find non-threadsafe destructors: 1.38 + // NS_ASSERT_OWNINGTHREAD(RtspControllerChild); 1.39 + --mRefCnt; 1.40 + NS_LOG_RELEASE(this, mRefCnt, "RtspControllerChild"); 1.41 + 1.42 + if (mRefCnt == 1 && mIPCOpen) { 1.43 + Send__delete__(this); 1.44 + return mRefCnt; 1.45 + } 1.46 + 1.47 + if (mRefCnt == 0) { 1.48 + mRefCnt = 1; /* stabilize */ 1.49 + delete this; 1.50 + return 0; 1.51 + } 1.52 + return mRefCnt; 1.53 +} 1.54 + 1.55 +NS_INTERFACE_MAP_BEGIN(RtspControllerChild) 1.56 + NS_INTERFACE_MAP_ENTRY(nsIStreamingProtocolController) 1.57 + NS_INTERFACE_MAP_ENTRY(nsIStreamingProtocolListener) 1.58 + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamingProtocolController) 1.59 +NS_INTERFACE_MAP_END 1.60 + 1.61 +//----------------------------------------------------------------------------- 1.62 +// RtspControllerChild methods 1.63 +//----------------------------------------------------------------------------- 1.64 +RtspControllerChild::RtspControllerChild(nsIChannel *channel) 1.65 + : mIPCOpen(false) 1.66 + , mIPCAllowed(false) 1.67 + , mChannel(channel) 1.68 + , mTotalTracks(0) 1.69 + , mSuspendCount(0) 1.70 +{ 1.71 +#if defined(PR_LOGGING) 1.72 + if (!gRtspChildLog) 1.73 + gRtspChildLog = PR_NewLogModule("nsRtspChild"); 1.74 +#endif 1.75 + AddIPDLReference(); 1.76 + gNeckoChild->SendPRtspControllerConstructor(this); 1.77 +} 1.78 + 1.79 +RtspControllerChild::~RtspControllerChild() 1.80 +{ 1.81 + LOG(("RtspControllerChild::~RtspControllerChild()")); 1.82 +} 1.83 + 1.84 +void 1.85 +RtspControllerChild::ReleaseChannel() 1.86 +{ 1.87 + static_cast<RtspChannelChild*>(mChannel.get())->ReleaseController(); 1.88 +} 1.89 + 1.90 +bool 1.91 +RtspControllerChild::OKToSendIPC() 1.92 +{ 1.93 + MOZ_ASSERT(NS_IsMainThread()); 1.94 + if (mIPCOpen == false) { 1.95 + return false; 1.96 + } 1.97 + return mIPCAllowed; 1.98 +} 1.99 + 1.100 +void 1.101 +RtspControllerChild::AllowIPC() 1.102 +{ 1.103 + MOZ_ASSERT(NS_IsMainThread()); 1.104 + mIPCAllowed = true; 1.105 +} 1.106 + 1.107 +void 1.108 +RtspControllerChild::DisallowIPC() 1.109 +{ 1.110 + MOZ_ASSERT(NS_IsMainThread()); 1.111 + mIPCAllowed = false; 1.112 +} 1.113 + 1.114 +//----------------------------------------------------------------------------- 1.115 +// RtspControllerChild::PRtspControllerChild 1.116 +//----------------------------------------------------------------------------- 1.117 +bool 1.118 +RtspControllerChild::RecvOnMediaDataAvailable( 1.119 + const uint8_t& index, 1.120 + const nsCString& data, 1.121 + const uint32_t& length, 1.122 + const uint32_t& offset, 1.123 + const InfallibleTArray<RtspMetadataParam>& metaArray) 1.124 +{ 1.125 + nsRefPtr<RtspMetaData> meta = new RtspMetaData(); 1.126 + nsresult rv = meta->DeserializeRtspMetaData(metaArray); 1.127 + NS_ENSURE_SUCCESS(rv, true); 1.128 + 1.129 + if (mListener) { 1.130 + mListener->OnMediaDataAvailable(index, data, length, offset, meta.get()); 1.131 + } 1.132 + return true; 1.133 +} 1.134 + 1.135 +void 1.136 +RtspControllerChild::AddMetaData( 1.137 + already_AddRefed<nsIStreamingProtocolMetaData>&& meta) 1.138 +{ 1.139 + nsCOMPtr<nsIStreamingProtocolMetaData> data = meta; 1.140 + mMetaArray.AppendElement(data); 1.141 +} 1.142 + 1.143 +int 1.144 +RtspControllerChild::GetMetaDataLength() 1.145 +{ 1.146 + return mMetaArray.Length(); 1.147 +} 1.148 + 1.149 +bool 1.150 +RtspControllerChild::RecvOnConnected( 1.151 + const uint8_t& index, 1.152 + const InfallibleTArray<RtspMetadataParam>& metaArray) 1.153 +{ 1.154 + // Deserialize meta data. 1.155 + nsRefPtr<RtspMetaData> meta = new RtspMetaData(); 1.156 + nsresult rv = meta->DeserializeRtspMetaData(metaArray); 1.157 + NS_ENSURE_SUCCESS(rv, true); 1.158 + meta->GetTotalTracks(&mTotalTracks); 1.159 + if (mTotalTracks <= 0) { 1.160 + LOG(("RtspControllerChild::RecvOnConnected invalid tracks %d", mTotalTracks)); 1.161 + // Set the default value. 1.162 + mTotalTracks = kRtspTotalTracks; 1.163 + } 1.164 + AddMetaData(meta.forget().downcast<nsIStreamingProtocolMetaData>()); 1.165 + 1.166 + // Notify the listener when meta data of tracks are available. 1.167 + if ((static_cast<uint32_t>(index) + 1) == mTotalTracks) { 1.168 + // The controller provide |GetTrackMetaData| method for his client. 1.169 + if (mListener) { 1.170 + mListener->OnConnected(index, nullptr); 1.171 + } 1.172 + } 1.173 + return true; 1.174 +} 1.175 + 1.176 +bool 1.177 +RtspControllerChild::RecvOnDisconnected( 1.178 + const uint8_t& index, 1.179 + const nsresult& reason) 1.180 +{ 1.181 + DisallowIPC(); 1.182 + LOG(("RtspControllerChild::RecvOnDisconnected for track %d reason = 0x%x", index, reason)); 1.183 + if (mListener) { 1.184 + mListener->OnDisconnected(index, reason); 1.185 + } 1.186 + ReleaseChannel(); 1.187 + return true; 1.188 +} 1.189 + 1.190 +bool 1.191 +RtspControllerChild::RecvAsyncOpenFailed(const nsresult& reason) 1.192 +{ 1.193 + DisallowIPC(); 1.194 + LOG(("RtspControllerChild::RecvAsyncOpenFailed reason = 0x%x", reason)); 1.195 + if (mListener) { 1.196 + mListener->OnDisconnected(0, NS_ERROR_CONNECTION_REFUSED); 1.197 + } 1.198 + ReleaseChannel(); 1.199 + return true; 1.200 +} 1.201 + 1.202 +void 1.203 +RtspControllerChild::AddIPDLReference() 1.204 +{ 1.205 + NS_ABORT_IF_FALSE(!mIPCOpen, 1.206 + "Attempt to retain more than one IPDL reference"); 1.207 + mIPCOpen = true; 1.208 + AllowIPC(); 1.209 + AddRef(); 1.210 +} 1.211 + 1.212 +void 1.213 +RtspControllerChild::ReleaseIPDLReference() 1.214 +{ 1.215 + NS_ABORT_IF_FALSE(mIPCOpen, "Attempt to release nonexistent IPDL reference"); 1.216 + mIPCOpen = false; 1.217 + DisallowIPC(); 1.218 + Release(); 1.219 +} 1.220 + 1.221 +NS_IMETHODIMP 1.222 +RtspControllerChild::GetTrackMetaData( 1.223 + uint8_t index, 1.224 + nsIStreamingProtocolMetaData **result) 1.225 +{ 1.226 + if (GetMetaDataLength() <= 0 || index >= GetMetaDataLength()) { 1.227 + LOG(("RtspControllerChild:: meta data is not available")); 1.228 + return NS_ERROR_NOT_INITIALIZED; 1.229 + } 1.230 + LOG(("RtspControllerChild::GetTrackMetaData() %d", index)); 1.231 + NS_IF_ADDREF(*result = mMetaArray[index]); 1.232 + return NS_OK; 1.233 +} 1.234 + 1.235 +enum IPCEvent 1.236 +{ 1.237 + SendNoneEvent = 0, 1.238 + SendPlayEvent, 1.239 + SendPauseEvent, 1.240 + SendSeekEvent, 1.241 + SendResumeEvent, 1.242 + SendSuspendEvent, 1.243 + SendStopEvent 1.244 +}; 1.245 + 1.246 +class SendIPCEvent : public nsRunnable 1.247 +{ 1.248 +public: 1.249 + SendIPCEvent(RtspControllerChild *aController, IPCEvent aEvent) 1.250 + : mController(aController) 1.251 + , mEvent(aEvent) 1.252 + , mSeekTime(0) 1.253 + { 1.254 + } 1.255 + 1.256 + SendIPCEvent(RtspControllerChild *aController, 1.257 + IPCEvent aEvent, 1.258 + uint64_t aSeekTime) 1.259 + : mController(aController) 1.260 + , mEvent(aEvent) 1.261 + , mSeekTime(aSeekTime) 1.262 + { 1.263 + } 1.264 + 1.265 + NS_IMETHOD Run() 1.266 + { 1.267 + MOZ_ASSERT(NS_IsMainThread()); 1.268 + if (mController->OKToSendIPC() == false) { 1.269 + // Don't send any more IPC events; no guarantee that parent objects are 1.270 + // still alive. 1.271 + return NS_ERROR_FAILURE; 1.272 + } 1.273 + bool rv = true; 1.274 + 1.275 + if (mEvent == SendPlayEvent) { 1.276 + rv = mController->SendPlay(); 1.277 + } else if (mEvent == SendPauseEvent) { 1.278 + rv = mController->SendPause(); 1.279 + } else if (mEvent == SendSeekEvent) { 1.280 + rv = mController->SendSeek(mSeekTime); 1.281 + } else if (mEvent == SendResumeEvent) { 1.282 + rv = mController->SendResume(); 1.283 + } else if (mEvent == SendSuspendEvent) { 1.284 + rv = mController->SendSuspend(); 1.285 + } else if (mEvent == SendStopEvent) { 1.286 + rv = mController->SendStop(); 1.287 + } else { 1.288 + LOG(("RtspControllerChild::SendIPCEvent")); 1.289 + } 1.290 + if (!rv) { 1.291 + return NS_ERROR_FAILURE; 1.292 + } 1.293 + return NS_OK; 1.294 + } 1.295 +private: 1.296 + nsRefPtr<RtspControllerChild> mController; 1.297 + IPCEvent mEvent; 1.298 + uint64_t mSeekTime; 1.299 +}; 1.300 + 1.301 +//----------------------------------------------------------------------------- 1.302 +// RtspControllerChild::nsIStreamingProtocolController 1.303 +//----------------------------------------------------------------------------- 1.304 +NS_IMETHODIMP 1.305 +RtspControllerChild::Play(void) 1.306 +{ 1.307 + LOG(("RtspControllerChild::Play()")); 1.308 + 1.309 + if (NS_IsMainThread()) { 1.310 + if (!OKToSendIPC() || !SendPlay()) { 1.311 + return NS_ERROR_FAILURE; 1.312 + } 1.313 + } else { 1.314 + nsresult rv = NS_DispatchToMainThread( 1.315 + new SendIPCEvent(this, SendPlayEvent)); 1.316 + NS_ENSURE_SUCCESS(rv, rv); 1.317 + } 1.318 + 1.319 + return NS_OK; 1.320 +} 1.321 + 1.322 +NS_IMETHODIMP 1.323 +RtspControllerChild::Pause(void) 1.324 +{ 1.325 + LOG(("RtspControllerChild::Pause()")); 1.326 + 1.327 + if (NS_IsMainThread()) { 1.328 + if (!OKToSendIPC() || !SendPause()) { 1.329 + return NS_ERROR_FAILURE; 1.330 + } 1.331 + } else { 1.332 + nsresult rv = NS_DispatchToMainThread( 1.333 + new SendIPCEvent(this, SendPauseEvent)); 1.334 + NS_ENSURE_SUCCESS(rv, rv); 1.335 + } 1.336 + 1.337 + return NS_OK; 1.338 +} 1.339 + 1.340 +NS_IMETHODIMP 1.341 +RtspControllerChild::Resume(void) 1.342 +{ 1.343 + LOG(("RtspControllerChild::Resume()")); 1.344 + NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED); 1.345 + 1.346 + if (!--mSuspendCount) { 1.347 + if (NS_IsMainThread()) { 1.348 + if (!OKToSendIPC() || !SendResume()) { 1.349 + return NS_ERROR_FAILURE; 1.350 + } 1.351 + } else { 1.352 + nsresult rv = NS_DispatchToMainThread( 1.353 + new SendIPCEvent(this, SendResumeEvent)); 1.354 + NS_ENSURE_SUCCESS(rv, rv); 1.355 + } 1.356 + } 1.357 + 1.358 + return NS_OK; 1.359 +} 1.360 + 1.361 +NS_IMETHODIMP 1.362 +RtspControllerChild::Suspend(void) 1.363 +{ 1.364 + LOG(("RtspControllerChild::Suspend()")); 1.365 + 1.366 + if (!mSuspendCount++) { 1.367 + if (NS_IsMainThread()) { 1.368 + if (!OKToSendIPC() || !SendSuspend()) { 1.369 + return NS_ERROR_FAILURE; 1.370 + } 1.371 + } else { 1.372 + nsresult rv = NS_DispatchToMainThread( 1.373 + new SendIPCEvent(this, SendSuspendEvent)); 1.374 + NS_ENSURE_SUCCESS(rv, rv); 1.375 + } 1.376 + } 1.377 + 1.378 + return NS_OK; 1.379 +} 1.380 + 1.381 +NS_IMETHODIMP 1.382 +RtspControllerChild::Seek(uint64_t seekTimeUs) 1.383 +{ 1.384 + LOG(("RtspControllerChild::Seek() %llu", seekTimeUs)); 1.385 + 1.386 + if (NS_IsMainThread()) { 1.387 + if (!OKToSendIPC() || !SendSeek(seekTimeUs)) { 1.388 + return NS_ERROR_FAILURE; 1.389 + } 1.390 + } else { 1.391 + nsresult rv = NS_DispatchToMainThread( 1.392 + new SendIPCEvent(this, SendSeekEvent, seekTimeUs)); 1.393 + NS_ENSURE_SUCCESS(rv, rv); 1.394 + } 1.395 + 1.396 + return NS_OK; 1.397 +} 1.398 + 1.399 +NS_IMETHODIMP 1.400 +RtspControllerChild::Stop() 1.401 +{ 1.402 + LOG(("RtspControllerChild::Stop()")); 1.403 + 1.404 + if (NS_IsMainThread()) { 1.405 + if (!OKToSendIPC() || !SendStop()) { 1.406 + return NS_ERROR_FAILURE; 1.407 + } 1.408 + DisallowIPC(); 1.409 + } else { 1.410 + nsresult rv = NS_DispatchToMainThread( 1.411 + new SendIPCEvent(this, SendStopEvent)); 1.412 + NS_ENSURE_SUCCESS(rv, rv); 1.413 + } 1.414 + 1.415 + return NS_OK; 1.416 +} 1.417 + 1.418 +NS_IMETHODIMP 1.419 +RtspControllerChild::GetTotalTracks(uint8_t *aTracks) 1.420 +{ 1.421 + NS_ENSURE_ARG_POINTER(aTracks); 1.422 + *aTracks = kRtspTotalTracks; 1.423 + if (mTotalTracks) { 1.424 + *aTracks = mTotalTracks; 1.425 + } 1.426 + LOG(("RtspControllerChild::GetTracks() %d", *aTracks)); 1.427 + return NS_OK; 1.428 +} 1.429 + 1.430 +//----------------------------------------------------------------------------- 1.431 +// RtspControllerChild::nsIStreamingProtocolListener 1.432 +//----------------------------------------------------------------------------- 1.433 +NS_IMETHODIMP 1.434 +RtspControllerChild::OnMediaDataAvailable(uint8_t index, 1.435 + const nsACString & data, 1.436 + uint32_t length, 1.437 + uint32_t offset, 1.438 + nsIStreamingProtocolMetaData *meta) 1.439 +{ 1.440 + LOG(("RtspControllerChild::OnMediaDataAvailable()")); 1.441 + return NS_ERROR_NOT_IMPLEMENTED; 1.442 +} 1.443 + 1.444 +NS_IMETHODIMP 1.445 +RtspControllerChild::OnConnected(uint8_t index, 1.446 + nsIStreamingProtocolMetaData *meta) 1.447 + 1.448 +{ 1.449 + LOG(("RtspControllerChild::OnConnected()")); 1.450 + return NS_ERROR_NOT_IMPLEMENTED; 1.451 +} 1.452 + 1.453 +NS_IMETHODIMP 1.454 +RtspControllerChild::OnDisconnected(uint8_t index, 1.455 + nsresult reason) 1.456 +{ 1.457 + LOG(("RtspControllerChild::OnDisconnected() reason = 0x%x", reason)); 1.458 + return NS_ERROR_NOT_IMPLEMENTED; 1.459 +} 1.460 + 1.461 +//----------------------------------------------------------------------------- 1.462 +// RtspControllerChild::nsIStreamingProtocoController 1.463 +//----------------------------------------------------------------------------- 1.464 +NS_IMETHODIMP 1.465 +RtspControllerChild::Init(nsIURI *aURI) 1.466 +{ 1.467 + nsresult rv; 1.468 + 1.469 + if (!aURI) { 1.470 + LOG(("RtspControllerChild::Init() - invalid URI")); 1.471 + return NS_ERROR_NOT_INITIALIZED; 1.472 + } 1.473 + 1.474 + nsAutoCString host; 1.475 + int32_t port = -1; 1.476 + 1.477 + rv = aURI->GetAsciiHost(host); 1.478 + if (NS_FAILED(rv)) return rv; 1.479 + 1.480 + // Reject the URL if it doesn't specify a host 1.481 + if (host.IsEmpty()) 1.482 + return NS_ERROR_MALFORMED_URI; 1.483 + 1.484 + rv = aURI->GetPort(&port); 1.485 + if (NS_FAILED(rv)) return rv; 1.486 + 1.487 + rv = aURI->GetAsciiSpec(mSpec); 1.488 + if (NS_FAILED(rv)) return rv; 1.489 + 1.490 + if (!strncmp(mSpec.get(), "rtsp:", 5) == 0) 1.491 + return NS_ERROR_UNEXPECTED; 1.492 + 1.493 + mURI = aURI; 1.494 + 1.495 + return NS_OK; 1.496 +} 1.497 + 1.498 +NS_IMETHODIMP 1.499 +RtspControllerChild::AsyncOpen(nsIStreamingProtocolListener *aListener) 1.500 +{ 1.501 + LOG(("RtspControllerChild::AsyncOpen()")); 1.502 + if (!aListener) { 1.503 + LOG(("RtspControllerChild::AsyncOpen() - invalid listener")); 1.504 + return NS_ERROR_NOT_INITIALIZED; 1.505 + } 1.506 + mListener = aListener; 1.507 + 1.508 + if (!mChannel) { 1.509 + LOG(("RtspControllerChild::AsyncOpen() - invalid URI")); 1.510 + return NS_ERROR_NOT_INITIALIZED; 1.511 + } 1.512 + 1.513 + nsCOMPtr<nsIURI> uri; 1.514 + URIParams uriParams; 1.515 + mChannel->GetURI(getter_AddRefs(uri)); 1.516 + if (!uri) { 1.517 + LOG(("RtspControllerChild::AsyncOpen() - invalid URI")); 1.518 + return NS_ERROR_NOT_INITIALIZED; 1.519 + } 1.520 + SerializeURI(uri, uriParams); 1.521 + 1.522 + if (!OKToSendIPC() || !SendAsyncOpen(uriParams)) { 1.523 + return NS_ERROR_FAILURE; 1.524 + } 1.525 + return NS_OK; 1.526 +} 1.527 + 1.528 +} // namespace net 1.529 +} // namespace mozilla