void PeerConnectionMedia::BeginIceRestart(const std::string& ufrag, const std::string& pwd) { ASSERT_ON_THREAD(mMainThread); if (IsIceRestarting()) { return; } bool default_address_only = GetPrefDefaultAddressOnly(); RefPtr<NrIceCtx> new_ctx = mIceCtxHdlr->CreateCtx(ufrag, pwd, default_address_only); RUN_ON_THREAD(GetSTSThread(), WrapRunnable( RefPtr<PeerConnectionMedia>(this), &PeerConnectionMedia::BeginIceRestart_s, new_ctx), NS_DISPATCH_NORMAL); mIceRestartState = ICE_RESTART_PROVISIONAL; }
void PeerConnectionMedia::SelfDestruct() { ASSERT_ON_THREAD(mMainThread); CSFLogDebug(logTag, "%s: ", __FUNCTION__); // Shut down the media for (uint32_t i=0; i < mLocalSourceStreams.Length(); ++i) { mLocalSourceStreams[i]->DetachMedia_m(); } for (uint32_t i=0; i < mRemoteSourceStreams.Length(); ++i) { mRemoteSourceStreams[i]->DetachMedia_m(); } // Shutdown the transport (async) RUN_ON_THREAD(mSTSThread, WrapRunnable( this, &PeerConnectionMedia::ShutdownMediaTransport_s), NS_DISPATCH_NORMAL); CSFLogDebug(logTag, "%s: Media shut down", __FUNCTION__); }
// callback while receiving UDP packet NS_IMETHODIMP NrSocketIpc::CallListenerReceivedData(const nsACString &type, const nsACString &host, uint16_t port, uint8_t *data, uint32_t data_length) { ASSERT_ON_THREAD(main_thread_); MOZ_ASSERT(type.EqualsLiteral("ondata")); PRNetAddr addr; memset(&addr, 0, sizeof(addr)); { ReentrantMonitorAutoEnter mon(monitor_); if (PR_SUCCESS != PR_StringToNetAddr(host.BeginReading(), &addr)) { err_ = true; MOZ_ASSERT(false, "Failed to convert remote host to PRNetAddr"); return NS_OK; } // Use PR_IpAddrNull to avoid address being reset to 0. if (PR_SUCCESS != PR_SetNetAddr(PR_IpAddrNull, addr.raw.family, port, &addr)) { err_ = true; MOZ_ASSERT(false, "Failed to set port in PRNetAddr"); return NS_OK; } } nsAutoPtr<DataBuffer> buf(new DataBuffer(data, data_length)); RefPtr<nr_udp_message> msg(new nr_udp_message(addr, buf)); RUN_ON_THREAD(sts_thread_, mozilla::WrapRunnable(nsRefPtr<NrSocketIpc>(this), &NrSocketIpc::recv_callback_s, msg), NS_DISPATCH_NORMAL); return NS_OK; }
bool PeerConnectionMedia::UpdateFilterFromRemoteDescription_m( int level, nsAutoPtr<mozilla::MediaPipelineFilter> filter) { ASSERT_ON_THREAD(mMainThread); RefPtr<mozilla::MediaPipeline> receive; for (size_t i = 0; !receive && i < mRemoteSourceStreams.Length(); ++i) { receive = mRemoteSourceStreams[i]->GetPipelineByLevel_m(level); } RefPtr<mozilla::MediaPipeline> transmit; for (size_t i = 0; !transmit && i < mLocalSourceStreams.Length(); ++i) { transmit = mLocalSourceStreams[i]->GetPipelineByLevel_m(level); } if (receive && transmit) { // GetPipelineByLevel_m will return nullptr if shutdown is in progress; // since shutdown is initiated in main, and involves a dispatch to STS // before the pipelines are released, our dispatch to STS will complete // before any release can happen due to a shutdown that hasn't started yet. RUN_ON_THREAD(GetSTSThread(), WrapRunnableNM( &UpdateFilterFromRemoteDescription_s, receive, transmit, filter ), NS_DISPATCH_NORMAL); return true; } else { CSFLogWarn(logTag, "Could not locate level %d to update filter", static_cast<int>(level)); } return false; }
void MediaEngineWebRTCMicrophoneSource::Process(int channel, webrtc::ProcessingTypes type, sample *audio10ms, int length, int samplingFreq, bool isStereo) { // On initial capture, throw away all far-end data except the most recent sample // since it's already irrelevant and we want to keep avoid confusing the AEC far-end // input code with "old" audio. if (!mStarted) { mStarted = true; while (gFarendObserver->Size() > 1) { free(gFarendObserver->Pop()); // only call if size() > 0 } } while (gFarendObserver->Size() > 0) { FarEndAudioChunk *buffer = gFarendObserver->Pop(); // only call if size() > 0 if (buffer) { int length = buffer->mSamples; int res = mVoERender->ExternalPlayoutData(buffer->mData, gFarendObserver->PlayoutFrequency(), gFarendObserver->PlayoutChannels(), mPlayoutDelay, length); free(buffer); if (res == -1) { return; } } } MonitorAutoLock lock(mMonitor); if (mState != kStarted) return; uint32_t len = mSources.Length(); for (uint32_t i = 0; i < len; i++) { RefPtr<SharedBuffer> buffer = SharedBuffer::Create(length * sizeof(sample)); sample* dest = static_cast<sample*>(buffer->Data()); memcpy(dest, audio10ms, length * sizeof(sample)); nsAutoPtr<AudioSegment> segment(new AudioSegment()); nsAutoTArray<const sample*,1> channels; channels.AppendElement(dest); segment->AppendFrames(buffer.forget(), channels, length); TimeStamp insertTime; segment->GetStartTime(insertTime); if (mSources[i]) { // Make sure we include the stream and the track. // The 0:1 is a flag to note when we've done the final insert for a given input block. LogTime(AsyncLatencyLogger::AudioTrackInsertion, LATENCY_STREAM_ID(mSources[i].get(), mTrackID), (i+1 < len) ? 0 : 1, insertTime); // This is safe from any thread, and is safe if the track is Finished // or Destroyed. // Note: due to evil magic, the nsAutoPtr<AudioSegment>'s ownership transfers to // the Runnable (AutoPtr<> = AutoPtr<>) RUN_ON_THREAD(mThread, WrapRunnable(mSources[i], &SourceMediaStream::AppendToTrack, mTrackID, segment, (AudioSegment *) nullptr), NS_DISPATCH_NORMAL); } } return; }
nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_servers, const std::vector<NrIceTurnServer>& turn_servers) { // TODO([email protected]): need some way to set not offerer later // Looks like a bug in the NrIceCtx API. mIceCtx = NrIceCtx::Create("PC:" + mParent->GetName(), true); if(!mIceCtx) { CSFLogError(logTag, "%s: Failed to create Ice Context", __FUNCTION__); return NS_ERROR_FAILURE; } nsresult rv; if (NS_FAILED(rv = mIceCtx->SetStunServers(stun_servers))) { CSFLogError(logTag, "%s: Failed to set stun servers", __FUNCTION__); return rv; } // Give us a way to globally turn off TURN support #ifdef MOZILLA_INTERNAL_API bool disabled = Preferences::GetBool("media.peerconnection.turn.disable", false); #else bool disabled = false; #endif if (!disabled) { if (NS_FAILED(rv = mIceCtx->SetTurnServers(turn_servers))) { CSFLogError(logTag, "%s: Failed to set turn servers", __FUNCTION__); return rv; } } else if (turn_servers.size() != 0) { CSFLogError(logTag, "%s: Setting turn servers disabled", __FUNCTION__); } if (NS_FAILED(rv = mDNSResolver->Init())) { CSFLogError(logTag, "%s: Failed to initialize dns resolver", __FUNCTION__); return rv; } if (NS_FAILED(rv = mIceCtx->SetResolver(mDNSResolver->AllocateResolver()))) { CSFLogError(logTag, "%s: Failed to get dns resolver", __FUNCTION__); return rv; } mIceCtx->SignalGatheringStateChange.connect( this, &PeerConnectionMedia::IceGatheringStateChange_s); mIceCtx->SignalConnectionStateChange.connect( this, &PeerConnectionMedia::IceConnectionStateChange_s); // Create three streams to start with. // One each for audio, video and DataChannel // TODO: this will be re-visited RefPtr<NrIceMediaStream> audioStream = mIceCtx->CreateStream((mParent->GetName()+": stream1/audio").c_str(), 2); RefPtr<NrIceMediaStream> videoStream = mIceCtx->CreateStream((mParent->GetName()+": stream2/video").c_str(), 2); RefPtr<NrIceMediaStream> dcStream = mIceCtx->CreateStream((mParent->GetName()+": stream3/data").c_str(), 2); if (!audioStream) { CSFLogError(logTag, "%s: audio stream is NULL", __FUNCTION__); return NS_ERROR_FAILURE; } else { mIceStreams.push_back(audioStream); } if (!videoStream) { CSFLogError(logTag, "%s: video stream is NULL", __FUNCTION__); return NS_ERROR_FAILURE; } else { mIceStreams.push_back(videoStream); } if (!dcStream) { CSFLogError(logTag, "%s: datachannel stream is NULL", __FUNCTION__); return NS_ERROR_FAILURE; } else { mIceStreams.push_back(dcStream); } // TODO([email protected]): This is not connected to the PCCimpl. // Will need to do that later. for (std::size_t i=0; i<mIceStreams.size(); i++) { mIceStreams[i]->SignalReady.connect(this, &PeerConnectionMedia::IceStreamReady); } // TODO([email protected]): When we have a generic error reporting mechanism, // figure out how to report that StartGathering failed. Bug 827982. RUN_ON_THREAD(mIceCtx->thread(), WrapRunnable(mIceCtx, &NrIceCtx::StartGathering), NS_DISPATCH_NORMAL); return NS_OK; }
nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_servers) { mMainThread = mParent->GetMainThread(); mSTSThread = mParent->GetSTSThread(); // TODO([email protected]): need some way to set not offerer later // Looks like a bug in the NrIceCtx API. mIceCtx = NrIceCtx::Create("PC:" + mParent->GetHandle(), true); if(!mIceCtx) { CSFLogError(logTag, "%s: Failed to create Ice Context", __FUNCTION__); return NS_ERROR_FAILURE; } nsresult rv; if (NS_FAILED(rv = mIceCtx->SetStunServers(stun_servers))) { CSFLogError(logTag, "%s: Failed to set stun servers", __FUNCTION__); return rv; } if (NS_FAILED(rv = mDNSResolver->Init())) { CSFLogError(logTag, "%s: Failed to initialize dns resolver", __FUNCTION__); return rv; } if (NS_FAILED(rv = mIceCtx->SetResolver(mDNSResolver->AllocateResolver()))) { CSFLogError(logTag, "%s: Failed to get dns resolver", __FUNCTION__); return rv; } mIceCtx->SignalGatheringCompleted.connect(this, &PeerConnectionMedia::IceGatheringCompleted); mIceCtx->SignalCompleted.connect(this, &PeerConnectionMedia::IceCompleted); mIceCtx->SignalFailed.connect(this, &PeerConnectionMedia::IceFailed); // Create three streams to start with. // One each for audio, video and DataChannel // TODO: this will be re-visited RefPtr<NrIceMediaStream> audioStream = mIceCtx->CreateStream("stream1", 2); RefPtr<NrIceMediaStream> videoStream = mIceCtx->CreateStream("stream2", 2); RefPtr<NrIceMediaStream> dcStream = mIceCtx->CreateStream("stream3", 2); if (!audioStream) { CSFLogError(logTag, "%s: audio stream is NULL", __FUNCTION__); return NS_ERROR_FAILURE; } else { mIceStreams.push_back(audioStream); } if (!videoStream) { CSFLogError(logTag, "%s: video stream is NULL", __FUNCTION__); return NS_ERROR_FAILURE; } else { mIceStreams.push_back(videoStream); } if (!dcStream) { CSFLogError(logTag, "%s: datachannel stream is NULL", __FUNCTION__); return NS_ERROR_FAILURE; } else { mIceStreams.push_back(dcStream); } // TODO([email protected]): This is not connected to the PCCimpl. // Will need to do that later. for (std::size_t i=0; i<mIceStreams.size(); i++) { mIceStreams[i]->SignalReady.connect(this, &PeerConnectionMedia::IceStreamReady); } // TODO([email protected]): When we have a generic error reporting mechanism, // figure out how to report that StartGathering failed. Bug 827982. RUN_ON_THREAD(mIceCtx->thread(), WrapRunnable(mIceCtx, &NrIceCtx::StartGathering), NS_DISPATCH_NORMAL); return NS_OK; }