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:
@ -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" ]
|
||||
|
||||
72
webrtc/audio/audio_send_stream.cc
Normal file
72
webrtc/audio/audio_send_stream.cc
Normal 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
|
||||
43
webrtc/audio/audio_send_stream.h
Normal file
43
webrtc/audio/audio_send_stream.h
Normal 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_
|
||||
34
webrtc/audio/audio_send_stream_unittest.cc
Normal file
34
webrtc/audio/audio_send_stream_unittest.cc
Normal 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
|
||||
@ -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',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
@ -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.
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
104
webrtc/call/call_unittest.cc
Normal file
104
webrtc/call/call_unittest.cc
Normal 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
|
||||
@ -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',
|
||||
|
||||
Reference in New Issue
Block a user