| Index: webrtc/call/call_unittest.cc
|
| diff --git a/webrtc/call/call_unittest.cc b/webrtc/call/call_unittest.cc
|
| index 564f6bd0323e014771266f9ec432b099758ef18b..bbc3d646c8a0d753ef71c70bb50f2bdfa7d2b34c 100644
|
| --- a/webrtc/call/call_unittest.cc
|
| +++ b/webrtc/call/call_unittest.cc
|
| @@ -13,13 +13,16 @@
|
| #include <memory>
|
| #include <utility>
|
|
|
| +#include "webrtc/api/test/mock_audio_mixer.h"
|
| #include "webrtc/base/ptr_util.h"
|
| #include "webrtc/call/audio_state.h"
|
| #include "webrtc/call/call.h"
|
| #include "webrtc/call/fake_rtp_transport_controller_send.h"
|
| #include "webrtc/logging/rtc_event_log/rtc_event_log.h"
|
| +#include "webrtc/modules/audio_device/include/mock_audio_device.h"
|
| #include "webrtc/modules/audio_mixer/audio_mixer_impl.h"
|
| #include "webrtc/modules/congestion_controller/include/mock/mock_send_side_congestion_controller.h"
|
| +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
|
| #include "webrtc/test/gtest.h"
|
| #include "webrtc/test/mock_audio_decoder_factory.h"
|
| #include "webrtc/test/mock_transport.h"
|
| @@ -134,6 +137,7 @@ TEST(CallTest, CreateDestroy_AssociateAudioSendReceiveStreams_RecvFirst) {
|
| rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory(
|
| new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>);
|
| CallHelper call(decoder_factory);
|
| + ::testing::NiceMock<MockRtpRtcp> mock_rtp_rtcp;
|
|
|
| constexpr int kRecvChannelId = 101;
|
|
|
| @@ -151,6 +155,8 @@ TEST(CallTest, CreateDestroy_AssociateAudioSendReceiveStreams_RecvFirst) {
|
| [](const std::map<int, SdpAudioFormat>& codecs) {
|
| EXPECT_THAT(codecs, testing::IsEmpty());
|
| }));
|
| + EXPECT_CALL(*channel_proxy, GetRtpRtcp(testing::_, testing::_))
|
| + .WillRepeatedly(testing::SetArgPointee<0>(&mock_rtp_rtcp));
|
| // If being called for the send channel, save a pointer to the channel
|
| // proxy for later.
|
| if (channel_id == kRecvChannelId) {
|
| @@ -186,6 +192,7 @@ TEST(CallTest, CreateDestroy_AssociateAudioSendReceiveStreams_SendFirst) {
|
| rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory(
|
| new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>);
|
| CallHelper call(decoder_factory);
|
| + ::testing::NiceMock<MockRtpRtcp> mock_rtp_rtcp;
|
|
|
| constexpr int kRecvChannelId = 101;
|
|
|
| @@ -203,6 +210,8 @@ TEST(CallTest, CreateDestroy_AssociateAudioSendReceiveStreams_SendFirst) {
|
| [](const std::map<int, SdpAudioFormat>& codecs) {
|
| EXPECT_THAT(codecs, testing::IsEmpty());
|
| }));
|
| + EXPECT_CALL(*channel_proxy, GetRtpRtcp(testing::_, testing::_))
|
| + .WillRepeatedly(testing::SetArgPointee<0>(&mock_rtp_rtcp));
|
| // If being called for the send channel, save a pointer to the channel
|
| // proxy for later.
|
| if (channel_id == kRecvChannelId) {
|
| @@ -333,4 +342,69 @@ TEST(CallTest, MockSendSideCongestionControllerExample) {
|
| call->SetBitrateConfig(bitrate_config);
|
| }
|
|
|
| +TEST(CallTest, RecreatingAudioStreamWithSameSsrcReusesRtpState) {
|
| + constexpr uint32_t kSSRC = 12345;
|
| + testing::NiceMock<test::MockAudioDeviceModule> mock_adm;
|
| + // Reply with a 10ms timer every time TimeUntilNextProcess is called to
|
| + // avoid entering a tight loop on the process thread.
|
| + EXPECT_CALL(mock_adm, TimeUntilNextProcess())
|
| + .WillRepeatedly(testing::Return(10));
|
| + rtc::scoped_refptr<test::MockAudioMixer> mock_mixer(
|
| + new rtc::RefCountedObject<test::MockAudioMixer>);
|
| +
|
| + // There's similar functionality in cricket::VoEWrapper but it's not reachable
|
| + // from here. Since we're working on removing VoE interfaces, I doubt it's
|
| + // worth making VoEWrapper more easily available.
|
| + struct ScopedVoiceEngine {
|
| + ScopedVoiceEngine()
|
| + : voe(VoiceEngine::Create()),
|
| + base(VoEBase::GetInterface(voe)) {}
|
| + ~ScopedVoiceEngine() {
|
| + base->Release();
|
| + EXPECT_TRUE(VoiceEngine::Delete(voe));
|
| + }
|
| +
|
| + VoiceEngine* voe;
|
| + VoEBase* base;
|
| + };
|
| + ScopedVoiceEngine voice_engine;
|
| +
|
| + voice_engine.base->Init(&mock_adm);
|
| + AudioState::Config audio_state_config;
|
| + audio_state_config.voice_engine = voice_engine.voe;
|
| + audio_state_config.audio_mixer = mock_mixer;
|
| + auto audio_state = AudioState::Create(audio_state_config);
|
| + RtcEventLogNullImpl event_log;
|
| + Call::Config call_config(&event_log);
|
| + call_config.audio_state = audio_state;
|
| + std::unique_ptr<Call> call(Call::Create(call_config));
|
| +
|
| + auto create_stream_and_get_rtp_state = [&](uint32_t ssrc) {
|
| + AudioSendStream::Config config(nullptr);
|
| + config.rtp.ssrc = ssrc;
|
| + config.voe_channel_id = voice_engine.base->CreateChannel();
|
| + AudioSendStream* stream = call->CreateAudioSendStream(config);
|
| + VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine.voe);
|
| + auto channel_proxy = voe_impl->GetChannelProxy(config.voe_channel_id);
|
| + RtpRtcp* rtp_rtcp = nullptr;
|
| + RtpReceiver* rtp_receiver = nullptr; // Unused but required for call.
|
| + channel_proxy->GetRtpRtcp(&rtp_rtcp, &rtp_receiver);
|
| + const RtpState rtp_state = rtp_rtcp->GetRtpState();
|
| + call->DestroyAudioSendStream(stream);
|
| + voice_engine.base->DeleteChannel(config.voe_channel_id);
|
| + return rtp_state;
|
| + };
|
| +
|
| + const RtpState rtp_state1 = create_stream_and_get_rtp_state(kSSRC);
|
| + const RtpState rtp_state2 = create_stream_and_get_rtp_state(kSSRC);
|
| +
|
| + EXPECT_EQ(rtp_state1.sequence_number, rtp_state2.sequence_number);
|
| + EXPECT_EQ(rtp_state1.start_timestamp, rtp_state2.start_timestamp);
|
| + EXPECT_EQ(rtp_state1.timestamp, rtp_state2.timestamp);
|
| + EXPECT_EQ(rtp_state1.capture_time_ms, rtp_state2.capture_time_ms);
|
| + EXPECT_EQ(rtp_state1.last_timestamp_time_ms,
|
| + rtp_state2.last_timestamp_time_ms);
|
| + EXPECT_EQ(rtp_state1.media_has_been_sent, rtp_state2.media_has_been_sent);
|
| +}
|
| +
|
| } // namespace webrtc
|
|
|