Björn Terelius | 987ef48 | 2020-03-05 15:52:10 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 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 |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
| 11 | #include "api/stats/rtc_stats_collector_callback.h" |
| 12 | #include "api/stats/rtcstats_objects.h" |
| 13 | #include "pc/test/mock_peer_connection_observers.h" |
| 14 | #include "test/field_trial.h" |
| 15 | #include "test/gtest.h" |
| 16 | #include "test/peer_scenario/peer_scenario.h" |
| 17 | #include "test/peer_scenario/peer_scenario_client.h" |
| 18 | |
| 19 | namespace webrtc { |
| 20 | namespace test { |
| 21 | |
| 22 | // TODO(terelius): Use fake encoder and enable on Android once |
| 23 | // https://bugs.chromium.org/p/webrtc/issues/detail?id=11408 is fixed. |
| 24 | #if defined(WEBRTC_ANDROID) |
| 25 | #define MAYBE_NoBweChangeFromVideoUnmute DISABLED_NoBweChangeFromVideoUnmute |
| 26 | #else |
| 27 | #define MAYBE_NoBweChangeFromVideoUnmute NoBweChangeFromVideoUnmute |
| 28 | #endif |
| 29 | TEST(GoogCcPeerScenarioTest, MAYBE_NoBweChangeFromVideoUnmute) { |
| 30 | // If transport wide sequence numbers are used for audio, and the call |
| 31 | // switches from audio only to video only, there will be a sharp change in |
| 32 | // packets sizes. This will create a change in propagation time which might be |
| 33 | // detected as an overuse. Using separate overuse detectors for audio and |
| 34 | // video avoids the issue. |
| 35 | std::string audio_twcc_trials( |
| 36 | "WebRTC-Audio-SendSideBwe/Enabled/" // |
| 37 | "WebRTC-SendSideBwe-WithOverhead/Enabled/" // |
| 38 | "WebRTC-Audio-AlrProbing/Disabled/"); |
| 39 | std::string separate_audio_video( |
| 40 | "WebRTC-Bwe-SeparateAudioPackets/" |
| 41 | "enabled:true,packet_threshold:15,time_threshold:1000ms/"); |
| 42 | ScopedFieldTrials field_trial(audio_twcc_trials + separate_audio_video); |
| 43 | PeerScenario s(*test_info_); |
| 44 | auto* caller = s.CreateClient(PeerScenarioClient::Config()); |
| 45 | auto* callee = s.CreateClient(PeerScenarioClient::Config()); |
| 46 | |
| 47 | BuiltInNetworkBehaviorConfig net_conf; |
| 48 | net_conf.link_capacity_kbps = 350; |
| 49 | net_conf.queue_delay_ms = 50; |
| 50 | auto send_node = s.net()->CreateEmulatedNode(net_conf); |
| 51 | auto ret_node = s.net()->CreateEmulatedNode(net_conf); |
| 52 | |
| 53 | PeerScenarioClient::VideoSendTrackConfig video_conf; |
| 54 | video_conf.generator.squares_video->framerate = 15; |
| 55 | auto video = caller->CreateVideo("VIDEO", video_conf); |
| 56 | auto audio = caller->CreateAudio("AUDIO", cricket::AudioOptions()); |
| 57 | |
| 58 | // Start ICE and exchange SDP. |
| 59 | s.SimpleConnection(caller, callee, {send_node}, {ret_node}); |
| 60 | |
| 61 | // Limit the encoder bitrate to ensure that there are no actual BWE overuses. |
| 62 | ASSERT_EQ(caller->pc()->GetSenders().size(), 2u); // 2 senders. |
| 63 | int num_video_streams = 0; |
| 64 | for (auto& rtp_sender : caller->pc()->GetSenders()) { |
| 65 | auto parameters = rtp_sender->GetParameters(); |
| 66 | ASSERT_EQ(parameters.encodings.size(), 1u); // 1 stream per sender. |
| 67 | for (auto& encoding_parameters : parameters.encodings) { |
| 68 | if (encoding_parameters.ssrc == video.sender->ssrc()) { |
| 69 | num_video_streams++; |
| 70 | encoding_parameters.max_bitrate_bps = 220000; |
| 71 | encoding_parameters.max_framerate = 15; |
| 72 | } |
| 73 | } |
| 74 | rtp_sender->SetParameters(parameters); |
| 75 | } |
| 76 | ASSERT_EQ(num_video_streams, 1); // Exactly 1 video stream. |
| 77 | |
| 78 | auto get_bwe = [&] { |
| 79 | rtc::scoped_refptr<webrtc::MockRTCStatsCollectorCallback> callback( |
| 80 | new rtc::RefCountedObject<webrtc::MockRTCStatsCollectorCallback>()); |
| 81 | caller->pc()->GetStats(callback); |
| 82 | s.net()->time_controller()->Wait([&] { return callback->called(); }); |
| 83 | auto stats = |
| 84 | callback->report()->GetStatsOfType<RTCIceCandidatePairStats>()[0]; |
| 85 | return DataRate::BitsPerSec(*stats->available_outgoing_bitrate); |
| 86 | }; |
| 87 | |
| 88 | s.ProcessMessages(TimeDelta::Seconds(15)); |
| 89 | const DataRate initial_bwe = get_bwe(); |
| 90 | EXPECT_GE(initial_bwe, DataRate::KilobitsPerSec(300)); |
| 91 | |
| 92 | // 10 seconds audio only. Bandwidth should not drop. |
| 93 | video.capturer->Stop(); |
| 94 | s.ProcessMessages(TimeDelta::Seconds(10)); |
| 95 | EXPECT_GE(get_bwe(), initial_bwe); |
| 96 | |
| 97 | // Resume video but stop audio. Bandwidth should not drop. |
| 98 | video.capturer->Start(); |
| 99 | RTCError status = caller->pc()->RemoveTrackNew(audio.sender); |
| 100 | ASSERT_TRUE(status.ok()); |
| 101 | audio.track->set_enabled(false); |
| 102 | for (int i = 0; i < 10; i++) { |
| 103 | s.ProcessMessages(TimeDelta::Seconds(1)); |
| 104 | EXPECT_GE(get_bwe(), initial_bwe); |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | } // namespace test |
| 109 | } // namespace webrtc |