Storing raw audio sink for default audio track.

BUG=webrtc:5250

Committed: https://crrev.com/e591f9377f33f3f725a30faecd1bef1a71fa6b99
Cr-Commit-Position: refs/heads/master@{#11230}

Review URL: https://codereview.webrtc.org/1551813002

Cr-Commit-Position: refs/heads/master@{#11275}
This commit is contained in:
deadbeef 2016-01-15 09:20:04 -08:00 committed by Commit bot
parent 1567d0bd98
commit 884f58523a
6 changed files with 91 additions and 2 deletions

View File

@ -2084,8 +2084,12 @@ TEST_F(PeerConnectionInterfaceTest, SdpWithoutMsidCreatesDefaultStream) {
ASSERT_EQ(1u, observer_.remote_streams()->count());
ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
EXPECT_EQ("defaulta0", remote_stream->GetAudioTracks()[0]->id());
EXPECT_EQ(MediaStreamTrackInterface::kLive,
remote_stream->GetAudioTracks()[0]->state());
ASSERT_EQ(1u, remote_stream->GetVideoTracks().size());
EXPECT_EQ("defaultv0", remote_stream->GetVideoTracks()[0]->id());
EXPECT_EQ(MediaStreamTrackInterface::kLive,
remote_stream->GetVideoTracks()[0]->state());
}
// This tests that a default MediaStream is created if a remote session

View File

@ -89,6 +89,7 @@ class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream {
void SetStats(const webrtc::AudioReceiveStream::Stats& stats);
int received_packets() const { return received_packets_; }
void IncrementReceivedPackets();
const webrtc::AudioSinkInterface* sink() const { return sink_.get(); }
private:
// webrtc::ReceiveStream implementation.

View File

@ -132,6 +132,16 @@ const int kMaxTelephoneEventCode = 255;
const int kMinTelephoneEventDuration = 100;
const int kMaxTelephoneEventDuration = 60000; // Actual limit is 2^16
class ProxySink : public webrtc::AudioSinkInterface {
public:
ProxySink(AudioSinkInterface* sink) : sink_(sink) { RTC_DCHECK(sink); }
void OnData(const Data& audio) override { sink_->OnData(audio); }
private:
webrtc::AudioSinkInterface* sink_;
};
bool ValidateStreamParams(const StreamParams& sp) {
if (sp.ssrcs.empty()) {
LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString();
@ -2191,6 +2201,11 @@ void WebRtcVoiceMediaChannel::OnPacketReceived(
}
default_recv_ssrc_ = ssrc;
SetOutputVolume(default_recv_ssrc_, default_recv_volume_);
if (default_sink_) {
rtc::scoped_ptr<webrtc::AudioSinkInterface> proxy_sink(
new ProxySink(default_sink_.get()));
SetRawAudioSink(default_recv_ssrc_, std::move(proxy_sink));
}
}
// Forward packet to Call. If the SSRC is unknown we'll return after this.
@ -2419,7 +2434,17 @@ void WebRtcVoiceMediaChannel::SetRawAudioSink(
uint32_t ssrc,
rtc::scoped_ptr<webrtc::AudioSinkInterface> sink) {
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::SetRawAudioSink";
LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::SetRawAudioSink: ssrc:" << ssrc
<< " " << (sink ? "(ptr)" : "NULL");
if (ssrc == 0) {
if (default_recv_ssrc_ != -1) {
rtc::scoped_ptr<webrtc::AudioSinkInterface> proxy_sink(
sink ? new ProxySink(sink.get()) : nullptr);
SetRawAudioSink(default_recv_ssrc_, std::move(proxy_sink));
}
default_sink_ = std::move(sink);
return;
}
const auto it = recv_streams_.find(ssrc);
if (it == recv_streams_.end()) {
LOG(LS_WARNING) << "SetRawAudioSink: no recv stream" << ssrc;

View File

@ -272,6 +272,8 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
int64_t default_recv_ssrc_ = -1;
// Volume for unsignalled stream, which may be set before the stream exists.
double default_recv_volume_ = 1.0;
// Sink for unsignalled stream, which may be set before the stream exists.
rtc::scoped_ptr<webrtc::AudioSinkInterface> default_sink_;
// Default SSRC to use for RTCP receiver reports in case of no signaled
// send streams. See: https://code.google.com/p/webrtc/issues/detail?id=4740
// and https://code.google.com/p/chromium/issues/detail?id=547661

View File

@ -72,6 +72,11 @@ class FakeVoEWrapper : public cricket::VoEWrapper {
};
} // namespace
class FakeAudioSink : public webrtc::AudioSinkInterface {
public:
void OnData(const Data& audio) override {}
};
class WebRtcVoiceEngineTestFake : public testing::Test {
public:
WebRtcVoiceEngineTestFake()
@ -125,6 +130,12 @@ class WebRtcVoiceEngineTestFake : public testing::Test {
return *send_stream;
}
const cricket::FakeAudioReceiveStream& GetRecvStream(uint32_t ssrc) {
const auto* recv_stream = call_.GetAudioReceiveStream(ssrc);
EXPECT_TRUE(recv_stream);
return *recv_stream;
}
const webrtc::AudioSendStream::Config& GetSendStreamConfig(uint32_t ssrc) {
const auto* send_stream = call_.GetAudioSendStream(ssrc);
EXPECT_TRUE(send_stream);
@ -3105,6 +3116,52 @@ TEST_F(WebRtcVoiceEngineTestFake, AssociateChannelResetUponDeleteChannnel) {
EXPECT_EQ(voe_.GetAssociateSendChannel(recv_ch), -1);
}
TEST_F(WebRtcVoiceEngineTestFake, SetRawAudioSink) {
EXPECT_TRUE(SetupEngine());
rtc::scoped_ptr<FakeAudioSink> fake_sink_1(new FakeAudioSink());
rtc::scoped_ptr<FakeAudioSink> fake_sink_2(new FakeAudioSink());
// Setting the sink before a recv stream exists should do nothing.
channel_->SetRawAudioSink(kSsrc1, std::move(fake_sink_1));
EXPECT_TRUE(
channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrc1)));
EXPECT_EQ(nullptr, GetRecvStream(kSsrc1).sink());
// Now try actually setting the sink.
channel_->SetRawAudioSink(kSsrc1, std::move(fake_sink_2));
EXPECT_NE(nullptr, GetRecvStream(kSsrc1).sink());
// Now try resetting it.
channel_->SetRawAudioSink(kSsrc1, nullptr);
EXPECT_EQ(nullptr, GetRecvStream(kSsrc1).sink());
}
TEST_F(WebRtcVoiceEngineTestFake, SetRawAudioSinkDefaultRecvStream) {
EXPECT_TRUE(SetupEngine());
rtc::scoped_ptr<FakeAudioSink> fake_sink_1(new FakeAudioSink());
rtc::scoped_ptr<FakeAudioSink> fake_sink_2(new FakeAudioSink());
// Should be able to set a default sink even when no stream exists.
channel_->SetRawAudioSink(0, std::move(fake_sink_1));
// Create default channel and ensure it's assigned the default sink.
DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
EXPECT_NE(nullptr, GetRecvStream(0x01).sink());
// Try resetting the default sink.
channel_->SetRawAudioSink(0, nullptr);
EXPECT_EQ(nullptr, GetRecvStream(0x01).sink());
// Try setting the default sink while the default stream exists.
channel_->SetRawAudioSink(0, std::move(fake_sink_2));
EXPECT_NE(nullptr, GetRecvStream(0x01).sink());
// If we remove and add a default stream, it should get the same sink.
EXPECT_TRUE(channel_->RemoveRecvStream(0x01));
DeliverPacket(kPcmuFrame, sizeof(kPcmuFrame));
EXPECT_NE(nullptr, GetRecvStream(0x01).sink());
}
// Tests that the library initializes and shuts down properly.
TEST(WebRtcVoiceEngineTest, StartupShutdown) {
cricket::WebRtcVoiceEngine engine;

View File

@ -112,7 +112,7 @@ class AudioReceiveStream : public ReceiveStream {
// Sets an audio sink that receives unmixed audio from the receive stream.
// Ownership of the sink is passed to the stream and can be used by the
// caller to do lifetime management (i.e. when the sink's dtor is called).
// Only one sink can be set and passing a null sink, clears an existing one.
// Only one sink can be set and passing a null sink clears an existing one.
// NOTE: Audio must still somehow be pulled through AudioTransport for audio
// to stream through this sink. In practice, this happens if mixed audio
// is being pulled+rendered and/or if audio is being pulled for the purposes