Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Side by Side Diff: webrtc/media/engine/webrtcvoiceengine.cc

Issue 2685893002: Support N unsignaled audio streams (Closed)
Patch Set: add histogram for # unsignaled audio streams Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 22 matching lines...) Expand all
33 #include "webrtc/media/base/mediaconstants.h" 33 #include "webrtc/media/base/mediaconstants.h"
34 #include "webrtc/media/base/streamparams.h" 34 #include "webrtc/media/base/streamparams.h"
35 #include "webrtc/media/engine/apm_helpers.h" 35 #include "webrtc/media/engine/apm_helpers.h"
36 #include "webrtc/media/engine/payload_type_mapper.h" 36 #include "webrtc/media/engine/payload_type_mapper.h"
37 #include "webrtc/media/engine/webrtcmediaengine.h" 37 #include "webrtc/media/engine/webrtcmediaengine.h"
38 #include "webrtc/media/engine/webrtcvoe.h" 38 #include "webrtc/media/engine/webrtcvoe.h"
39 #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" 39 #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
40 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h" 40 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h"
41 #include "webrtc/modules/audio_processing/include/audio_processing.h" 41 #include "webrtc/modules/audio_processing/include/audio_processing.h"
42 #include "webrtc/system_wrappers/include/field_trial.h" 42 #include "webrtc/system_wrappers/include/field_trial.h"
43 #include "webrtc/system_wrappers/include/metrics.h"
43 #include "webrtc/system_wrappers/include/trace.h" 44 #include "webrtc/system_wrappers/include/trace.h"
44 #include "webrtc/voice_engine/transmit_mixer.h" 45 #include "webrtc/voice_engine/transmit_mixer.h"
45 46
46 namespace cricket { 47 namespace cricket {
47 namespace { 48 namespace {
48 49
50 constexpr size_t kMaxUnsignaledRecvStreams = 50;
51
49 const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo | 52 const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo |
50 webrtc::kTraceWarning | webrtc::kTraceError | 53 webrtc::kTraceWarning | webrtc::kTraceError |
51 webrtc::kTraceCritical; 54 webrtc::kTraceCritical;
52 const int kElevatedTraceFilter = kDefaultTraceFilter | webrtc::kTraceStateInfo | 55 const int kElevatedTraceFilter = kDefaultTraceFilter | webrtc::kTraceStateInfo |
53 webrtc::kTraceInfo; 56 webrtc::kTraceInfo;
54 57
55 // On Windows Vista and newer, Microsoft introduced the concept of "Default 58 // On Windows Vista and newer, Microsoft introduced the concept of "Default
56 // Communications Device". This means that there are two types of default 59 // Communications Device". This means that there are two types of default
57 // devices (old Wave Audio style default and Default Communications Device). 60 // devices (old Wave Audio style default and Default Communications Device).
58 // 61 //
(...skipping 2171 matching lines...) Expand 10 before | Expand all | Expand 10 after
2230 if (!ValidateStreamParams(sp)) { 2233 if (!ValidateStreamParams(sp)) {
2231 return false; 2234 return false;
2232 } 2235 }
2233 2236
2234 const uint32_t ssrc = sp.first_ssrc(); 2237 const uint32_t ssrc = sp.first_ssrc();
2235 if (ssrc == 0) { 2238 if (ssrc == 0) {
2236 LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported."; 2239 LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported.";
2237 return false; 2240 return false;
2238 } 2241 }
2239 2242
2240 // If the default receive stream was created with this ssrc, we unmark it as 2243 // If this stream was previously received unsignaled, we promote it, possibly
2241 // being the default stream, and possibly recreate the AudioReceiveStream, if 2244 // recreating the AudioReceiveStream, if sync_label has changed.
2242 // sync_label has changed. 2245 if (MaybeDeregisterUnsignaledRecvStream(ssrc)) {
2243 if (IsDefaultRecvStream(ssrc)) {
2244 recv_streams_[ssrc]->MaybeRecreateAudioReceiveStream(sp.sync_label); 2246 recv_streams_[ssrc]->MaybeRecreateAudioReceiveStream(sp.sync_label);
2245 default_recv_ssrc_ = -1;
2246 return true; 2247 return true;
2247 } 2248 }
2248 2249
2249 if (GetReceiveChannelId(ssrc) != -1) { 2250 if (GetReceiveChannelId(ssrc) != -1) {
2250 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc; 2251 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
2251 return false; 2252 return false;
2252 } 2253 }
2253 2254
2254 // Create a new channel for receiving audio data. 2255 // Create a new channel for receiving audio data.
2255 const int channel = CreateVoEChannel(); 2256 const int channel = CreateVoEChannel();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2299 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2300 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2300 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; 2301 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
2301 2302
2302 const auto it = recv_streams_.find(ssrc); 2303 const auto it = recv_streams_.find(ssrc);
2303 if (it == recv_streams_.end()) { 2304 if (it == recv_streams_.end()) {
2304 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc 2305 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
2305 << " which doesn't exist."; 2306 << " which doesn't exist.";
2306 return false; 2307 return false;
2307 } 2308 }
2308 2309
2309 // Deregister default channel, if that's the one being destroyed. 2310 MaybeDeregisterUnsignaledRecvStream(ssrc);
2310 if (IsDefaultRecvStream(ssrc)) {
2311 default_recv_ssrc_ = -1;
2312 }
2313 2311
2314 const int channel = it->second->channel(); 2312 const int channel = it->second->channel();
2315 2313
2316 // Clean up and delete the receive stream+channel. 2314 // Clean up and delete the receive stream+channel.
2317 LOG(LS_INFO) << "Removing audio receive stream " << ssrc 2315 LOG(LS_INFO) << "Removing audio receive stream " << ssrc
2318 << " with VoiceEngine channel #" << channel << "."; 2316 << " with VoiceEngine channel #" << channel << ".";
2319 it->second->SetRawAudioSink(nullptr); 2317 it->second->SetRawAudioSink(nullptr);
2320 delete it->second; 2318 delete it->second;
2321 recv_streams_.erase(it); 2319 recv_streams_.erase(it);
2322 return DeleteVoEChannel(channel); 2320 return DeleteVoEChannel(channel);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2362 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2360 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2363 int highest = 0; 2361 int highest = 0;
2364 for (const auto& ch : recv_streams_) { 2362 for (const auto& ch : recv_streams_) {
2365 highest = std::max(GetOutputLevel(ch.second->channel()), highest); 2363 highest = std::max(GetOutputLevel(ch.second->channel()), highest);
2366 } 2364 }
2367 return highest; 2365 return highest;
2368 } 2366 }
2369 2367
2370 bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) { 2368 bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
2371 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2369 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2370 std::vector<uint32_t> ssrcs(1, ssrc);
2372 if (ssrc == 0) { 2371 if (ssrc == 0) {
2373 default_recv_volume_ = volume; 2372 default_recv_volume_ = volume;
2374 if (default_recv_ssrc_ == -1) { 2373 ssrcs = unsignaled_recv_ssrcs_;
2375 return true; 2374 }
2375 for (uint32_t ssrc : ssrcs) {
2376 const auto it = recv_streams_.find(ssrc);
2377 if (it == recv_streams_.end()) {
2378 LOG(LS_WARNING) << "SetOutputVolume: no recv stream " << ssrc;
2379 return false;
2376 } 2380 }
2377 ssrc = static_cast<uint32_t>(default_recv_ssrc_); 2381 it->second->SetOutputVolume(volume);
2382 LOG(LS_INFO) << "SetOutputVolume() to " << volume
2383 << " for recv stream with ssrc " << ssrc;
2378 } 2384 }
2379 const auto it = recv_streams_.find(ssrc);
2380 if (it == recv_streams_.end()) {
2381 LOG(LS_WARNING) << "SetOutputVolume: no recv stream" << ssrc;
2382 return false;
2383 }
2384 it->second->SetOutputVolume(volume);
2385 LOG(LS_INFO) << "SetOutputVolume() to " << volume
2386 << " for recv stream with ssrc " << ssrc;
2387 return true; 2385 return true;
2388 } 2386 }
2389 2387
2390 bool WebRtcVoiceMediaChannel::CanInsertDtmf() { 2388 bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
2391 return dtmf_payload_type_ ? true : false; 2389 return dtmf_payload_type_ ? true : false;
2392 } 2390 }
2393 2391
2394 bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event, 2392 bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event,
2395 int duration) { 2393 int duration) {
2396 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2394 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
(...skipping 30 matching lines...) Expand all
2427 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp, 2425 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2428 packet_time.not_before); 2426 packet_time.not_before);
2429 webrtc::PacketReceiver::DeliveryStatus delivery_result = 2427 webrtc::PacketReceiver::DeliveryStatus delivery_result =
2430 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO, 2428 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2431 packet->cdata(), packet->size(), 2429 packet->cdata(), packet->size(),
2432 webrtc_packet_time); 2430 webrtc_packet_time);
2433 if (delivery_result != webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC) { 2431 if (delivery_result != webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC) {
2434 return; 2432 return;
2435 } 2433 }
2436 2434
2437 // Create a default receive stream for this unsignalled and previously not 2435 // Create an unsignaled receive stream for this previously not received ssrc.
2438 // received ssrc. If there already is a default receive stream, delete it. 2436 // If there already is N unsignaled receive streams, delete the oldest.
2439 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208 2437 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208
2440 uint32_t ssrc = 0; 2438 uint32_t ssrc = 0;
2441 if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) { 2439 if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) {
2442 return; 2440 return;
2443 } 2441 }
2442 RTC_DCHECK(std::find(unsignaled_recv_ssrcs_.begin(),
2443 unsignaled_recv_ssrcs_.end(), ssrc) == unsignaled_recv_ssrcs_.end());
2444 2444
2445 // Add new stream.
2445 StreamParams sp; 2446 StreamParams sp;
2446 sp.ssrcs.push_back(ssrc); 2447 sp.ssrcs.push_back(ssrc);
2447 LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << "."; 2448 LOG(LS_INFO) << "Creating unsignaled receive stream for SSRC=" << ssrc;
2448 if (!AddRecvStream(sp)) { 2449 if (!AddRecvStream(sp)) {
2449 LOG(LS_WARNING) << "Could not create default receive stream."; 2450 LOG(LS_WARNING) << "Could not create unsignaled receive stream.";
2450 return; 2451 return;
2451 } 2452 }
2452 if (default_recv_ssrc_ != -1) { 2453 unsignaled_recv_ssrcs_.push_back(ssrc);
2453 LOG(LS_INFO) << "Removing default receive stream with ssrc " 2454 RTC_HISTOGRAM_COUNTS_LINEAR(
2454 << default_recv_ssrc_; 2455 "WebRTC.Audio.NumOfUnsignaledStreams", unsignaled_recv_ssrcs_.size(), 1,
2455 RTC_DCHECK_NE(ssrc, default_recv_ssrc_); 2456 100, 101);
2456 RemoveRecvStream(default_recv_ssrc_); 2457
2458 // Remove oldest unsignaled stream, if we have too many.
2459 if (unsignaled_recv_ssrcs_.size() > kMaxUnsignaledRecvStreams) {
2460 uint32_t remove_ssrc = unsignaled_recv_ssrcs_.front();
2461 LOG(LS_INFO) << "Removing unsignaled receive stream with SSRC="
2462 << remove_ssrc;
2463 RemoveRecvStream(remove_ssrc);
2457 } 2464 }
2458 default_recv_ssrc_ = ssrc; 2465 RTC_DCHECK_GE(kMaxUnsignaledRecvStreams, unsignaled_recv_ssrcs_.size());
2459 2466
2460 SetOutputVolume(default_recv_ssrc_, default_recv_volume_); 2467 SetOutputVolume(ssrc, default_recv_volume_);
2468
2469 // The default sink can only be attached to one stream at a time, so we hook
2470 // it up to the *latest* unsignaled stream we've seen, in order to support the
2471 // case where the SSRC of one unsignaled stream changes.
2461 if (default_sink_) { 2472 if (default_sink_) {
2473 for (uint32_t drop_ssrc : unsignaled_recv_ssrcs_) {
2474 auto it = recv_streams_.find(drop_ssrc);
2475 it->second->SetRawAudioSink(nullptr);
2476 }
2462 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink( 2477 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
2463 new ProxySink(default_sink_.get())); 2478 new ProxySink(default_sink_.get()));
2464 SetRawAudioSink(default_recv_ssrc_, std::move(proxy_sink)); 2479 SetRawAudioSink(ssrc, std::move(proxy_sink));
2465 } 2480 }
2481
2466 delivery_result = call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO, 2482 delivery_result = call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2467 packet->cdata(), 2483 packet->cdata(),
2468 packet->size(), 2484 packet->size(),
2469 webrtc_packet_time); 2485 webrtc_packet_time);
2470 RTC_DCHECK_NE(webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC, delivery_result); 2486 RTC_DCHECK_NE(webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC, delivery_result);
2471 } 2487 }
2472 2488
2473 void WebRtcVoiceMediaChannel::OnRtcpReceived( 2489 void WebRtcVoiceMediaChannel::OnRtcpReceived(
2474 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) { 2490 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
2475 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2491 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
2620 return true; 2636 return true;
2621 } 2637 }
2622 2638
2623 void WebRtcVoiceMediaChannel::SetRawAudioSink( 2639 void WebRtcVoiceMediaChannel::SetRawAudioSink(
2624 uint32_t ssrc, 2640 uint32_t ssrc,
2625 std::unique_ptr<webrtc::AudioSinkInterface> sink) { 2641 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
2626 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2642 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2627 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::SetRawAudioSink: ssrc:" << ssrc 2643 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::SetRawAudioSink: ssrc:" << ssrc
2628 << " " << (sink ? "(ptr)" : "NULL"); 2644 << " " << (sink ? "(ptr)" : "NULL");
2629 if (ssrc == 0) { 2645 if (ssrc == 0) {
2630 if (default_recv_ssrc_ != -1) { 2646 if (!unsignaled_recv_ssrcs_.empty()) {
2631 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink( 2647 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
2632 sink ? new ProxySink(sink.get()) : nullptr); 2648 sink ? new ProxySink(sink.get()) : nullptr);
2633 SetRawAudioSink(default_recv_ssrc_, std::move(proxy_sink)); 2649 SetRawAudioSink(unsignaled_recv_ssrcs_.back(), std::move(proxy_sink));
2634 } 2650 }
2635 default_sink_ = std::move(sink); 2651 default_sink_ = std::move(sink);
2636 return; 2652 return;
2637 } 2653 }
2638 const auto it = recv_streams_.find(ssrc); 2654 const auto it = recv_streams_.find(ssrc);
2639 if (it == recv_streams_.end()) { 2655 if (it == recv_streams_.end()) {
2640 LOG(LS_WARNING) << "SetRawAudioSink: no recv stream" << ssrc; 2656 LOG(LS_WARNING) << "SetRawAudioSink: no recv stream " << ssrc;
2641 return; 2657 return;
2642 } 2658 }
2643 it->second->SetRawAudioSink(std::move(sink)); 2659 it->second->SetRawAudioSink(std::move(sink));
2644 } 2660 }
2645 2661
2646 int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) { 2662 int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) {
2647 unsigned int ulevel = 0; 2663 unsigned int ulevel = 0;
2648 int ret = engine()->voe()->volume()->GetSpeechOutputLevel(channel, ulevel); 2664 int ret = engine()->voe()->volume()->GetSpeechOutputLevel(channel, ulevel);
2649 return (ret == 0) ? static_cast<int>(ulevel) : -1; 2665 return (ret == 0) ? static_cast<int>(ulevel) : -1;
2650 } 2666 }
2651 2667
2652 int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const { 2668 int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
2653 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2669 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2654 const auto it = recv_streams_.find(ssrc); 2670 const auto it = recv_streams_.find(ssrc);
2655 if (it != recv_streams_.end()) { 2671 if (it != recv_streams_.end()) {
2656 return it->second->channel(); 2672 return it->second->channel();
2657 } 2673 }
2658 return -1; 2674 return -1;
2659 } 2675 }
2660 2676
2661 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const { 2677 int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
2662 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); 2678 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2663 const auto it = send_streams_.find(ssrc); 2679 const auto it = send_streams_.find(ssrc);
2664 if (it != send_streams_.end()) { 2680 if (it != send_streams_.end()) {
2665 return it->second->channel(); 2681 return it->second->channel();
2666 } 2682 }
2667 return -1; 2683 return -1;
2668 } 2684 }
2685
2686 bool WebRtcVoiceMediaChannel::
2687 MaybeDeregisterUnsignaledRecvStream(uint32_t ssrc) {
2688 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2689 auto it = std::find(unsignaled_recv_ssrcs_.begin(),
2690 unsignaled_recv_ssrcs_.end(),
2691 ssrc);
2692 if (it != unsignaled_recv_ssrcs_.end()) {
2693 unsignaled_recv_ssrcs_.erase(it);
2694 return true;
2695 }
2696 return false;
2697 }
2669 } // namespace cricket 2698 } // namespace cricket
2670 2699
2671 #endif // HAVE_WEBRTC_VOICE 2700 #endif // HAVE_WEBRTC_VOICE
OLDNEW
« no previous file with comments | « webrtc/media/engine/webrtcvoiceengine.h ('k') | webrtc/media/engine/webrtcvoiceengine_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698