Add webrtc::AudioSendStream and methods on webrtc::Call to create and delete AudioSendStreams.

AudioSendStream will be replacing the send side of VoiceEngine channels and associated APIs. Hence, they will be used transform recorded audio into RTP/RTCP packets that can be transmitted to another party, according to given parameters.

BUG=webrtc:4690

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

Cr-Commit-Position: refs/heads/master@{#10307}
This commit is contained in:
solenberg
2015-10-16 14:35:07 -07:00
committed by Commit bot
parent 9781152e04
commit c7a8b08a7c
9 changed files with 309 additions and 15 deletions

View File

@ -12,6 +12,8 @@ source_set("audio") {
sources = [
"audio_receive_stream.cc",
"audio_receive_stream.h",
"audio_send_stream.cc",
"audio_send_stream.h",
]
configs += [ "..:common_config" ]

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/audio/audio_send_stream.h"
#include <string>
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
namespace webrtc {
std::string AudioSendStream::Config::Rtp::ToString() const {
std::stringstream ss;
ss << "{ssrc: " << ssrc;
ss << ", extensions: [";
for (size_t i = 0; i < extensions.size(); ++i) {
ss << extensions[i].ToString();
if (i != extensions.size() - 1)
ss << ", ";
}
ss << ']';
ss << '}';
return ss.str();
}
std::string AudioSendStream::Config::ToString() const {
std::stringstream ss;
ss << "{rtp: " << rtp.ToString();
ss << ", voe_channel_id: " << voe_channel_id;
// TODO(solenberg): Encoder config.
ss << ", cng_payload_type: " << cng_payload_type;
ss << ", red_payload_type: " << red_payload_type;
ss << '}';
return ss.str();
}
namespace internal {
AudioSendStream::AudioSendStream(const webrtc::AudioSendStream::Config& config)
: config_(config) {
LOG(LS_INFO) << "AudioSendStream: " << config_.ToString();
RTC_DCHECK(config.voe_channel_id != -1);
}
AudioSendStream::~AudioSendStream() {
LOG(LS_INFO) << "~AudioSendStream: " << config_.ToString();
}
webrtc::AudioSendStream::Stats AudioSendStream::GetStats() const {
return webrtc::AudioSendStream::Stats();
}
void AudioSendStream::Start() {
}
void AudioSendStream::Stop() {
}
void AudioSendStream::SignalNetworkState(NetworkState state) {
}
bool AudioSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
return false;
}
} // namespace internal
} // namespace webrtc

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_AUDIO_AUDIO_SEND_STREAM_H_
#define WEBRTC_AUDIO_AUDIO_SEND_STREAM_H_
#include "webrtc/audio_send_stream.h"
namespace webrtc {
namespace internal {
class AudioSendStream : public webrtc::AudioSendStream {
public:
explicit AudioSendStream(const webrtc::AudioSendStream::Config& config);
~AudioSendStream() override;
// webrtc::SendStream implementation.
void Start() override;
void Stop() override;
void SignalNetworkState(NetworkState state) override;
bool DeliverRtcp(const uint8_t* packet, size_t length) override;
// webrtc::AudioSendStream implementation.
webrtc::AudioSendStream::Stats GetStats() const override;
const webrtc::AudioSendStream::Config& config() const {
return config_;
}
private:
const webrtc::AudioSendStream::Config config_;
};
} // namespace internal
} // namespace webrtc
#endif // WEBRTC_AUDIO_AUDIO_SEND_STREAM_H_

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/audio/audio_send_stream.h"
namespace webrtc {
TEST(AudioSendStreamTest, ConfigToString) {
const int kAbsSendTimeId = 3;
AudioSendStream::Config config(nullptr);
config.rtp.ssrc = 1234;
config.rtp.extensions.push_back(
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeId));
config.voe_channel_id = 1;
config.cng_payload_type = 42;
config.red_payload_type = 17;
EXPECT_GT(config.ToString().size(), 0u);
}
TEST(AudioSendStreamTest, ConstructDestruct) {
AudioSendStream::Config config(nullptr);
config.voe_channel_id = 1;
internal::AudioSendStream send_stream(config);
}
} // namespace webrtc

View File

@ -16,6 +16,8 @@
'webrtc_audio_sources': [
'audio/audio_receive_stream.cc',
'audio/audio_receive_stream.h',
'audio/audio_send_stream.cc',
'audio/audio_send_stream.h',
],
},
}

View File

@ -45,7 +45,8 @@ class AudioSendStream : public SendStream {
std::vector<RtpExtension> extensions;
} rtp;
// Transport for outgoing packets.
// Transport for outgoing packets. The transport is expected to exist for
// the entire life of the AudioSendStream and is owned by the API client.
Transport* send_transport = nullptr;
// Underlying VoiceEngine handle, used to map AudioSendStream to lower-level
@ -54,7 +55,10 @@ class AudioSendStream : public SendStream {
// of Call.
int voe_channel_id = -1;
rtc::scoped_ptr<AudioEncoder> encoder;
// Ownership of the encoder object is transferred to Call when the config is
// passed to Call::CreateAudioSendStream().
// TODO(solenberg): Implement, once we configure codecs through the new API.
// rtc::scoped_ptr<AudioEncoder> encoder;
int cng_payload_type = -1; // pt, or -1 to disable Comfort Noise Generator.
int red_payload_type = -1; // pt, or -1 to disable REDundant coding.
};

View File

@ -14,6 +14,7 @@
#include <vector>
#include "webrtc/audio/audio_receive_stream.h"
#include "webrtc/audio/audio_send_stream.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/thread_annotations.h"
@ -103,6 +104,7 @@ class Call : public webrtc::Call, public PacketReceiver {
bool network_enabled_ GUARDED_BY(network_enabled_crit_);
rtc::scoped_ptr<RWLockWrapper> receive_crit_;
// Audio and Video receive streams are owned by the client that creates them.
std::map<uint32_t, AudioReceiveStream*> audio_receive_ssrcs_
GUARDED_BY(receive_crit_);
std::map<uint32_t, VideoReceiveStream*> video_receive_ssrcs_
@ -113,6 +115,8 @@ class Call : public webrtc::Call, public PacketReceiver {
GUARDED_BY(receive_crit_);
rtc::scoped_ptr<RWLockWrapper> send_crit_;
// Audio and Video send streams are owned by the client that creates them.
std::map<uint32_t, AudioSendStream*> audio_send_ssrcs_ GUARDED_BY(send_crit_);
std::map<uint32_t, VideoSendStream*> video_send_ssrcs_ GUARDED_BY(send_crit_);
std::set<VideoSendStream*> video_send_streams_ GUARDED_BY(send_crit_);
@ -164,11 +168,12 @@ Call::Call(const Call::Config& config)
}
Call::~Call() {
RTC_CHECK_EQ(0u, video_send_ssrcs_.size());
RTC_CHECK_EQ(0u, video_send_streams_.size());
RTC_CHECK_EQ(0u, audio_receive_ssrcs_.size());
RTC_CHECK_EQ(0u, video_receive_ssrcs_.size());
RTC_CHECK_EQ(0u, video_receive_streams_.size());
RTC_CHECK(audio_send_ssrcs_.empty());
RTC_CHECK(video_send_ssrcs_.empty());
RTC_CHECK(video_send_streams_.empty());
RTC_CHECK(audio_receive_ssrcs_.empty());
RTC_CHECK(video_receive_ssrcs_.empty());
RTC_CHECK(video_receive_streams_.empty());
module_process_thread_->Stop();
Trace::ReturnTrace();
@ -178,14 +183,36 @@ PacketReceiver* Call::Receiver() { return this; }
webrtc::AudioSendStream* Call::CreateAudioSendStream(
const webrtc::AudioSendStream::Config& config) {
// TODO(pbos): When adding AudioSendStream, add both TRACE_EVENT0 and config
// logging to AudioSendStream constructor.
return nullptr;
TRACE_EVENT0("webrtc", "Call::CreateAudioSendStream");
AudioSendStream* send_stream = new AudioSendStream(config);
{
rtc::CritScope lock(&network_enabled_crit_);
WriteLockScoped write_lock(*send_crit_);
RTC_DCHECK(audio_send_ssrcs_.find(config.rtp.ssrc) ==
audio_send_ssrcs_.end());
audio_send_ssrcs_[config.rtp.ssrc] = send_stream;
if (!network_enabled_)
send_stream->SignalNetworkState(kNetworkDown);
}
return send_stream;
}
void Call::DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) {
// TODO(pbos): When adding AudioSendStream, add both TRACE_EVENT0 and config
// logging to AudioSendStream destructor.
TRACE_EVENT0("webrtc", "Call::DestroyAudioSendStream");
RTC_DCHECK(send_stream != nullptr);
send_stream->Stop();
webrtc::internal::AudioSendStream* audio_send_stream =
static_cast<webrtc::internal::AudioSendStream*>(send_stream);
{
WriteLockScoped write_lock(*send_crit_);
size_t num_deleted = audio_send_ssrcs_.erase(
audio_send_stream->config().rtp.ssrc);
RTC_DCHECK(num_deleted == 1);
}
delete audio_send_stream;
}
webrtc::AudioReceiveStream* Call::CreateAudioReceiveStream(
@ -207,8 +234,8 @@ void Call::DestroyAudioReceiveStream(
webrtc::AudioReceiveStream* receive_stream) {
TRACE_EVENT0("webrtc", "Call::DestroyAudioReceiveStream");
RTC_DCHECK(receive_stream != nullptr);
AudioReceiveStream* audio_receive_stream =
static_cast<AudioReceiveStream*>(receive_stream);
webrtc::internal::AudioReceiveStream* audio_receive_stream =
static_cast<webrtc::internal::AudioReceiveStream*>(receive_stream);
{
WriteLockScoped write_lock(*receive_crit_);
size_t num_deleted = audio_receive_ssrcs_.erase(
@ -362,6 +389,7 @@ Call::Stats Call::GetStats() const {
stats.pacer_delay_ms = channel_group_->GetPacerQueuingDelayMs();
{
ReadLockScoped read_lock(*send_crit_);
// TODO(solenberg): Add audio send streams.
for (const auto& kv : video_send_ssrcs_) {
int rtt_ms = kv.second->GetRtt();
if (rtt_ms > 0)
@ -401,6 +429,9 @@ void Call::SignalNetworkState(NetworkState state) {
channel_group_->SignalNetworkState(state);
{
ReadLockScoped write_lock(*send_crit_);
for (auto& kv : audio_send_ssrcs_) {
kv.second->SignalNetworkState(state);
}
for (auto& kv : video_send_ssrcs_) {
kv.second->SignalNetworkState(state);
}

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <list>
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/call.h"
namespace {
struct CallHelper {
CallHelper() {
webrtc::Call::Config config;
// TODO(solenberg): Fill in with VoiceEngine* etc.
call_.reset(webrtc::Call::Create(config));
}
webrtc::Call* operator->() { return call_.get(); }
private:
rtc::scoped_ptr<webrtc::Call> call_;
};
} // namespace
namespace webrtc {
TEST(CallTest, ConstructDestruct) {
CallHelper call;
}
TEST(CallTest, CreateDestroy_AudioSendStream) {
CallHelper call;
AudioSendStream::Config config(nullptr);
config.rtp.ssrc = 42;
config.voe_channel_id = 123;
AudioSendStream* stream = call->CreateAudioSendStream(config);
EXPECT_NE(stream, nullptr);
call->DestroyAudioSendStream(stream);
}
TEST(CallTest, CreateDestroy_AudioReceiveStream) {
CallHelper call;
AudioReceiveStream::Config config;
config.rtp.remote_ssrc = 42;
config.voe_channel_id = 123;
AudioReceiveStream* stream = call->CreateAudioReceiveStream(config);
EXPECT_NE(stream, nullptr);
call->DestroyAudioReceiveStream(stream);
}
TEST(CallTest, CreateDestroy_AudioSendStreams) {
CallHelper call;
AudioSendStream::Config config(nullptr);
config.voe_channel_id = 123;
std::list<AudioSendStream*> streams;
for (int i = 0; i < 2; ++i) {
for (uint32_t ssrc = 0; ssrc < 1234567; ssrc += 34567) {
config.rtp.ssrc = ssrc;
AudioSendStream* stream = call->CreateAudioSendStream(config);
EXPECT_NE(stream, nullptr);
if (ssrc & 1) {
streams.push_back(stream);
} else {
streams.push_front(stream);
}
}
for (auto s : streams) {
call->DestroyAudioSendStream(s);
}
streams.clear();
}
}
TEST(CallTest, CreateDestroy_AudioReceiveStreams) {
CallHelper call;
AudioReceiveStream::Config config;
config.voe_channel_id = 123;
std::list<AudioReceiveStream*> streams;
for (int i = 0; i < 2; ++i) {
for (uint32_t ssrc = 0; ssrc < 1234567; ssrc += 34567) {
config.rtp.remote_ssrc = ssrc;
AudioReceiveStream* stream = call->CreateAudioReceiveStream(config);
EXPECT_NE(stream, nullptr);
if (ssrc & 1) {
streams.push_back(stream);
} else {
streams.push_front(stream);
}
}
for (auto s : streams) {
call->DestroyAudioReceiveStream(s);
}
streams.clear();
}
}
} // namespace webrtc

View File

@ -146,12 +146,14 @@
],
},
{
# TODO(pbos): Add separate target webrtc_audio_tests and move files there.
# TODO(solenberg): Rename to webrtc_call_tests.
'target_name': 'video_engine_tests',
'type': '<(gtest_target_type)',
'sources': [
'audio/audio_receive_stream_unittest.cc',
'audio/audio_send_stream_unittest.cc',
'call/bitrate_estimator_tests.cc',
'call/call_unittest.cc',
'call/packet_injection_tests.cc',
'test/common_unittest.cc',
'test/testsupport/metrics/video_metrics_unittest.cc',