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}
diff --git a/webrtc/audio/BUILD.gn b/webrtc/audio/BUILD.gn
index db0791f..c6f4b6b 100644
--- a/webrtc/audio/BUILD.gn
+++ b/webrtc/audio/BUILD.gn
@@ -12,6 +12,8 @@
   sources = [
     "audio_receive_stream.cc",
     "audio_receive_stream.h",
+    "audio_send_stream.cc",
+    "audio_send_stream.h",
   ]
 
   configs += [ "..:common_config" ]
diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc
new file mode 100644
index 0000000..0d0c072
--- /dev/null
+++ b/webrtc/audio/audio_send_stream.cc
@@ -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
diff --git a/webrtc/audio/audio_send_stream.h b/webrtc/audio/audio_send_stream.h
new file mode 100644
index 0000000..54046fc
--- /dev/null
+++ b/webrtc/audio/audio_send_stream.h
@@ -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_
diff --git a/webrtc/audio/audio_send_stream_unittest.cc b/webrtc/audio/audio_send_stream_unittest.cc
new file mode 100644
index 0000000..e5d73ff
--- /dev/null
+++ b/webrtc/audio/audio_send_stream_unittest.cc
@@ -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
diff --git a/webrtc/audio/webrtc_audio.gypi b/webrtc/audio/webrtc_audio.gypi
index 42f91ac..40ccff6 100644
--- a/webrtc/audio/webrtc_audio.gypi
+++ b/webrtc/audio/webrtc_audio.gypi
@@ -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',
     ],
   },
 }
diff --git a/webrtc/audio_send_stream.h b/webrtc/audio_send_stream.h
index 2fb288f..b96a8ef 100644
--- a/webrtc/audio_send_stream.h
+++ b/webrtc/audio_send_stream.h
@@ -45,7 +45,8 @@
       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 @@
     // 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.
   };
diff --git a/webrtc/call/call.cc b/webrtc/call/call.cc
index a32a823..6d9bf40 100644
--- a/webrtc/call/call.cc
+++ b/webrtc/call/call.cc
@@ -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 @@
   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 @@
       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() {
-  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 @@
 
 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 @@
     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 @@
   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 @@
   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);
     }
diff --git a/webrtc/call/call_unittest.cc b/webrtc/call/call_unittest.cc
new file mode 100644
index 0000000..9adecc3
--- /dev/null
+++ b/webrtc/call/call_unittest.cc
@@ -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
diff --git a/webrtc/webrtc_tests.gypi b/webrtc/webrtc_tests.gypi
index 0823500..0e245c5 100644
--- a/webrtc/webrtc_tests.gypi
+++ b/webrtc/webrtc_tests.gypi
@@ -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',