Move ownership of vie_encoders and vie_channels into the channel group.

BUG=4323
R=mflodman@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/44369004

Cr-Commit-Position: refs/heads/master@{#8647}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8647 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/video_engine/vie_base_impl.cc b/webrtc/video_engine/vie_base_impl.cc
index 4b977de..ca7fd50 100644
--- a/webrtc/video_engine/vie_base_impl.cc
+++ b/webrtc/video_engine/vie_base_impl.cc
@@ -211,7 +211,7 @@
 
     // Deregister the ViEEncoder if no other channel is using it.
     ViEEncoder* vie_encoder = cs.Encoder(video_channel);
-    if (cs.ChannelUsingViEEncoder(video_channel) == false) {
+    if (!cs.ChannelUsingViEEncoder(video_channel)) {
       ViEInputManagerScoped is(*(shared_data_.input_manager()));
       ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
       if (provider) {
diff --git a/webrtc/video_engine/vie_channel_group.cc b/webrtc/video_engine/vie_channel_group.cc
index c91c9a9..afa2d8b 100644
--- a/webrtc/video_engine/vie_channel_group.cc
+++ b/webrtc/video_engine/vie_channel_group.cc
@@ -10,6 +10,7 @@
 
 #include "webrtc/video_engine/vie_channel_group.h"
 
+#include "webrtc/base/checks.h"
 #include "webrtc/base/thread_annotations.h"
 #include "webrtc/common.h"
 #include "webrtc/experiments.h"
@@ -20,9 +21,11 @@
 #include "webrtc/system_wrappers/interface/logging.h"
 #include "webrtc/video_engine/call_stats.h"
 #include "webrtc/video_engine/encoder_state_feedback.h"
+#include "webrtc/video_engine/payload_router.h"
 #include "webrtc/video_engine/vie_channel.h"
 #include "webrtc/video_engine/vie_encoder.h"
 #include "webrtc/video_engine/vie_remb.h"
+#include "webrtc/voice_engine/include/voe_video_sync.h"
 
 namespace webrtc {
 namespace {
@@ -151,7 +154,7 @@
     own_config_.reset(new Config);
     config_ = own_config_.get();
   }
-  assert(config_);  // Must have a valid config pointer here.
+  DCHECK(config_);  // Must have a valid config pointer here.
 
   remote_bitrate_estimator_.reset(
       new WrappingBitrateEstimator(remb_.get(),
@@ -170,44 +173,248 @@
   process_thread_->DeRegisterModule(call_stats_.get());
   process_thread_->DeRegisterModule(remote_bitrate_estimator_.get());
   call_stats_->DeregisterStatsObserver(remote_bitrate_estimator_.get());
-  assert(channels_.empty());
-  assert(!remb_->InUse());
+  DCHECK(channels_.empty());
+  DCHECK(channel_map_.empty());
+  DCHECK(!remb_->InUse());
+  DCHECK(vie_encoder_map_.empty());
+}
+
+bool ChannelGroup::CreateSendChannel(int channel_id,
+                                     int engine_id,
+                                     int number_of_cores,
+                                     bool disable_default_encoder) {
+  rtc::scoped_ptr<ViEEncoder> vie_encoder(new ViEEncoder(
+      channel_id, number_of_cores, *config_, *process_thread_,
+      bitrate_allocator_.get(), bitrate_controller_.get(), false));
+  if (!vie_encoder->Init()) {
+    return false;
+  }
+  ViEEncoder* encoder = vie_encoder.get();
+  if (!CreateChannel(channel_id, engine_id, number_of_cores,
+                     vie_encoder.release(), true, disable_default_encoder)) {
+    return false;
+  }
+  ViEChannel* channel = channel_map_[channel_id];
+  // Connect the encoder with the send packet router, to enable sending.
+  encoder->StartThreadsAndSetSharedMembers(channel->send_payload_router(),
+                                           channel->vcm_protection_callback());
+
+  // Register the ViEEncoder to get key frame requests for this channel.
+  unsigned int ssrc = 0;
+  int stream_idx = 0;
+  channel->GetLocalSSRC(stream_idx, &ssrc);
+  encoder_state_feedback_->AddEncoder(ssrc, encoder);
+  std::list<unsigned int> ssrcs;
+  ssrcs.push_back(ssrc);
+  encoder->SetSsrcs(ssrcs);
+  return true;
+}
+
+bool ChannelGroup::CreateReceiveChannel(int channel_id,
+                                        int engine_id,
+                                        int base_channel_id,
+                                        int number_of_cores,
+                                        bool disable_default_encoder) {
+  ViEEncoder* encoder = GetEncoder(base_channel_id);
+  return CreateChannel(channel_id, engine_id, number_of_cores, encoder, false,
+                       disable_default_encoder);
+}
+
+bool ChannelGroup::CreateChannel(int channel_id,
+                                 int engine_id,
+                                 int number_of_cores,
+                                 ViEEncoder* vie_encoder,
+                                 bool sender,
+                                 bool disable_default_encoder) {
+  DCHECK(vie_encoder);
+
+  rtc::scoped_ptr<ViEChannel> channel(new ViEChannel(
+      channel_id, engine_id, number_of_cores, *config_, *process_thread_,
+      encoder_state_feedback_->GetRtcpIntraFrameObserver(),
+      bitrate_controller_->CreateRtcpBandwidthObserver(),
+      remote_bitrate_estimator_.get(), call_stats_->rtcp_rtt_stats(),
+      vie_encoder->GetPacedSender(), sender, disable_default_encoder));
+  if (channel->Init() != 0) {
+    return false;
+  }
+  if (!disable_default_encoder) {
+    VideoCodec encoder;
+    if (vie_encoder->GetEncoder(&encoder) != 0) {
+      return false;
+    }
+    if (sender && channel->SetSendCodec(encoder) != 0) {
+      return false;
+    }
+  }
+
+  // Register the channel to receive stats updates.
+  call_stats_->RegisterStatsObserver(channel->GetStatsObserver());
+
+  // Store the channel, add it to the channel group and save the vie_encoder.
+  channel_map_[channel_id] = channel.release();
+  vie_encoder_map_[channel_id] = vie_encoder;
+
+  return true;
+}
+
+void ChannelGroup::DeleteChannel(int channel_id) {
+  ViEChannel* vie_channel = PopChannel(channel_id);
+
+  ViEEncoder* vie_encoder = GetEncoder(channel_id);
+  DCHECK(vie_encoder != NULL);
+
+  call_stats_->DeregisterStatsObserver(vie_channel->GetStatsObserver());
+  SetChannelRembStatus(channel_id, false, false, vie_channel);
+
+  // If we're owning the encoder, remove the feedback and stop all encoding
+  // threads and processing. This must be done before deleting the channel.
+  if (vie_encoder->channel_id() == channel_id) {
+    encoder_state_feedback_->RemoveEncoder(vie_encoder);
+    vie_encoder->StopThreadsAndRemoveSharedMembers();
+  }
+
+  unsigned int remote_ssrc = 0;
+  vie_channel->GetRemoteSSRC(&remote_ssrc);
+  RemoveChannel(channel_id);
+  remote_bitrate_estimator_->RemoveStream(remote_ssrc);
+
+  // Check if other channels are using the same encoder.
+  if (OtherChannelsUsingEncoder(channel_id)) {
+    vie_encoder = NULL;
+  } else {
+    // Delete later when we've released the critsect.
+  }
+
+  // We can't erase the item before we've checked for other channels using
+  // same ViEEncoder.
+  PopEncoder(channel_id);
+
+  delete vie_channel;
+  // Leave the write critsect before deleting the objects.
+  // Deleting a channel can cause other objects, such as renderers, to be
+  // deleted, which might take time.
+  // If statment just to show that this object is not always deleted.
+  if (vie_encoder) {
+    LOG(LS_VERBOSE) << "ViEEncoder deleted for channel " << channel_id;
+    delete vie_encoder;
+  }
+
+  LOG(LS_VERBOSE) << "Channel deleted " << channel_id;
 }
 
 void ChannelGroup::AddChannel(int channel_id) {
   channels_.insert(channel_id);
 }
 
-void ChannelGroup::RemoveChannel(int channel_id, unsigned int ssrc) {
+void ChannelGroup::RemoveChannel(int channel_id) {
   channels_.erase(channel_id);
-  remote_bitrate_estimator_->RemoveStream(ssrc);
 }
 
-bool ChannelGroup::HasChannel(int channel_id) {
+bool ChannelGroup::HasChannel(int channel_id) const {
   return channels_.find(channel_id) != channels_.end();
 }
 
-bool ChannelGroup::Empty() {
+bool ChannelGroup::Empty() const {
   return channels_.empty();
 }
 
-BitrateAllocator* ChannelGroup::GetBitrateAllocator() {
-  return bitrate_allocator_.get();
+ViEChannel* ChannelGroup::GetChannel(int channel_id) const {
+  ChannelMap::const_iterator it = channel_map_.find(channel_id);
+  if (it == channel_map_.end()) {
+    LOG(LS_ERROR) << "Channel doesn't exist " << channel_id;
+    return NULL;
+  }
+  return it->second;
 }
 
-BitrateController* ChannelGroup::GetBitrateController() {
+ViEEncoder* ChannelGroup::GetEncoder(int channel_id) const {
+  EncoderMap::const_iterator it = vie_encoder_map_.find(channel_id);
+  if (it == vie_encoder_map_.end()) {
+    printf("No encoder found: %d\n", channel_id);
+    return NULL;
+  }
+  return it->second;
+}
+
+ViEChannel* ChannelGroup::PopChannel(int channel_id) {
+  ChannelMap::iterator c_it = channel_map_.find(channel_id);
+  DCHECK(c_it != channel_map_.end());
+  ViEChannel* channel = c_it->second;
+  channel_map_.erase(c_it);
+
+  return channel;
+}
+
+ViEEncoder* ChannelGroup::PopEncoder(int channel_id) {
+  EncoderMap::iterator e_it = vie_encoder_map_.find(channel_id);
+  DCHECK(e_it != vie_encoder_map_.end());
+  ViEEncoder* encoder = e_it->second;
+  vie_encoder_map_.erase(e_it);
+
+  return encoder;
+}
+
+std::vector<int> ChannelGroup::GetChannelIds() const {
+  std::vector<int> ids;
+  for (auto channel : channel_map_)
+    ids.push_back(channel.first);
+  return ids;
+}
+
+bool ChannelGroup::OtherChannelsUsingEncoder(int channel_id) const {
+  EncoderMap::const_iterator orig_it = vie_encoder_map_.find(channel_id);
+  if (orig_it == vie_encoder_map_.end()) {
+    // No ViEEncoder for this channel.
+    return false;
+  }
+
+  // Loop through all other channels to see if anyone points at the same
+  // ViEEncoder.
+  for (EncoderMap::const_iterator comp_it = vie_encoder_map_.begin();
+       comp_it != vie_encoder_map_.end(); ++comp_it) {
+    // Make sure we're not comparing the same channel with itself.
+    if (comp_it->first != channel_id) {
+      if (comp_it->second == orig_it->second) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+void ChannelGroup::SetSyncInterface(VoEVideoSync* sync_interface) {
+  for (auto channel : channel_map_) {
+    channel.second->SetVoiceChannel(-1, sync_interface);
+  }
+}
+
+void ChannelGroup::GetChannelsUsingEncoder(int channel_id,
+                                           ChannelList* channels) const {
+  EncoderMap::const_iterator orig_it = vie_encoder_map_.find(channel_id);
+
+  for (ChannelMap::const_iterator c_it = channel_map_.begin();
+       c_it != channel_map_.end(); ++c_it) {
+    EncoderMap::const_iterator comp_it = vie_encoder_map_.find(c_it->first);
+    DCHECK(comp_it != vie_encoder_map_.end());
+    if (comp_it->second == orig_it->second) {
+      channels->push_back(c_it->second);
+    }
+  }
+}
+
+BitrateController* ChannelGroup::GetBitrateController() const {
   return bitrate_controller_.get();
 }
 
-RemoteBitrateEstimator* ChannelGroup::GetRemoteBitrateEstimator() {
+RemoteBitrateEstimator* ChannelGroup::GetRemoteBitrateEstimator() const {
   return remote_bitrate_estimator_.get();
 }
 
-CallStats* ChannelGroup::GetCallStats() {
+CallStats* ChannelGroup::GetCallStats() const {
   return call_stats_.get();
 }
 
-EncoderStateFeedback* ChannelGroup::GetEncoderStateFeedback() {
+EncoderStateFeedback* ChannelGroup::GetEncoderStateFeedback() const {
   return encoder_state_feedback_.get();
 }
 
diff --git a/webrtc/video_engine/vie_channel_group.h b/webrtc/video_engine/vie_channel_group.h
index 9a2fd2a..a5fad41 100644
--- a/webrtc/video_engine/vie_channel_group.h
+++ b/webrtc/video_engine/vie_channel_group.h
@@ -11,7 +11,10 @@
 #ifndef WEBRTC_VIDEO_ENGINE_VIE_CHANNEL_GROUP_H_
 #define WEBRTC_VIDEO_ENGINE_VIE_CHANNEL_GROUP_H_
 
+#include <list>
+#include <map>
 #include <set>
+#include <vector>
 
 #include "webrtc/base/scoped_ptr.h"
 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
@@ -27,6 +30,9 @@
 class ViEChannel;
 class ViEEncoder;
 class VieRemb;
+class VoEVideoSync;
+
+typedef std::list<ViEChannel*> ChannelList;
 
 // Channel group contains data common for several channels. All channels in the
 // group are assumed to send/receive data to the same end-point.
@@ -34,22 +40,37 @@
  public:
   ChannelGroup(ProcessThread* process_thread, const Config* config);
   ~ChannelGroup();
-
+  bool CreateSendChannel(int channel_id,
+                         int engine_id,
+                         int number_of_cores,
+                         bool disable_default_encoder);
+  bool CreateReceiveChannel(int channel_id,
+                            int engine_id,
+                            int base_channel_id,
+                            int number_of_cores,
+                            bool disable_default_encoder);
+  void DeleteChannel(int channel_id);
   void AddChannel(int channel_id);
-  void RemoveChannel(int channel_id, unsigned int ssrc);
-  bool HasChannel(int channel_id);
-  bool Empty();
+  void RemoveChannel(int channel_id);
+  bool HasChannel(int channel_id) const;
+  bool Empty() const;
+  ViEChannel* GetChannel(int channel_id) const;
+  ViEEncoder* GetEncoder(int channel_id) const;
+  std::vector<int> GetChannelIds() const;
+  bool OtherChannelsUsingEncoder(int channel_id) const;
+  void GetChannelsUsingEncoder(int channel_id, ChannelList* channels) const;
+
+  void SetSyncInterface(VoEVideoSync* sync_interface);
 
   void SetChannelRembStatus(int channel_id,
                             bool sender,
                             bool receiver,
                             ViEChannel* channel);
 
-  BitrateAllocator* GetBitrateAllocator();
-  BitrateController* GetBitrateController();
-  CallStats* GetCallStats();
-  RemoteBitrateEstimator* GetRemoteBitrateEstimator();
-  EncoderStateFeedback* GetEncoderStateFeedback();
+  BitrateController* GetBitrateController() const;
+  CallStats* GetCallStats() const;
+  RemoteBitrateEstimator* GetRemoteBitrateEstimator() const;
+  EncoderStateFeedback* GetEncoderStateFeedback() const;
 
   // Implements BitrateObserver.
   void OnNetworkChanged(uint32_t target_bitrate_bps,
@@ -57,7 +78,18 @@
                         int64_t rtt) override;
 
  private:
+  typedef std::map<int, ViEChannel*> ChannelMap;
   typedef std::set<int> ChannelSet;
+  typedef std::map<int, ViEEncoder*> EncoderMap;
+
+  bool CreateChannel(int channel_id,
+                     int engine_id,
+                     int number_of_cores,
+                     ViEEncoder* vie_encoder,
+                     bool sender,
+                     bool disable_default_encoder);
+  ViEChannel* PopChannel(int channel_id);
+  ViEEncoder* PopEncoder(int channel_id);
 
   rtc::scoped_ptr<VieRemb> remb_;
   rtc::scoped_ptr<BitrateAllocator> bitrate_allocator_;
@@ -66,6 +98,9 @@
   rtc::scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
   rtc::scoped_ptr<EncoderStateFeedback> encoder_state_feedback_;
   ChannelSet channels_;
+  ChannelMap channel_map_;
+  // Maps Channel id -> ViEEncoder.
+  EncoderMap vie_encoder_map_;
   const Config* config_;
   // Placeholder for the case where this owns the config.
   rtc::scoped_ptr<Config> own_config_;
diff --git a/webrtc/video_engine/vie_channel_manager.cc b/webrtc/video_engine/vie_channel_manager.cc
index 85c60e9..4c4c66f 100644
--- a/webrtc/video_engine/vie_channel_manager.cc
+++ b/webrtc/video_engine/vie_channel_manager.cc
@@ -20,8 +20,8 @@
 #include "webrtc/system_wrappers/interface/logging.h"
 #include "webrtc/video_engine/call_stats.h"
 #include "webrtc/video_engine/encoder_state_feedback.h"
-#include "webrtc/video_engine/payload_router.h"
 #include "webrtc/video_engine/vie_channel.h"
+#include "webrtc/video_engine/vie_channel_group.h"
 #include "webrtc/video_engine/vie_defines.h"
 #include "webrtc/video_engine/vie_encoder.h"
 #include "webrtc/video_engine/vie_remb.h"
@@ -29,28 +29,28 @@
 
 namespace webrtc {
 
-ViEChannelManager::ViEChannelManager(
-    int engine_id,
-    int number_of_cores,
-    const Config& config)
+ViEChannelManager::ViEChannelManager(int engine_id,
+                                     int number_of_cores,
+                                     const Config& config)
     : channel_id_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
       engine_id_(engine_id),
       number_of_cores_(number_of_cores),
       free_channel_ids_(new bool[kViEMaxNumberOfChannels]),
       free_channel_ids_size_(kViEMaxNumberOfChannels),
       voice_sync_interface_(NULL),
-      module_process_thread_(NULL),
-      engine_config_(config) {
+      module_process_thread_(NULL) {
   for (int idx = 0; idx < free_channel_ids_size_; idx++) {
     free_channel_ids_[idx] = true;
   }
 }
 
 ViEChannelManager::~ViEChannelManager() {
-  while (channel_map_.size() > 0) {
-    ChannelMap::iterator it = channel_map_.begin();
-    // DeleteChannel will erase this channel from the map and invalidate |it|.
-    DeleteChannel(it->first);
+  while (!channel_groups_.empty()) {
+    // The channel group is deleted by DeleteChannel when all its channels have
+    // been deleted.
+    for (int channel_id : channel_groups_.front()->GetChannelIds()) {
+      DeleteChannel(channel_id);
+    }
   }
 
   if (voice_sync_interface_) {
@@ -66,8 +66,6 @@
     free_channel_ids_size_ = 0;
   }
   assert(channel_groups_.empty());
-  assert(channel_map_.empty());
-  assert(vie_encoder_map_.empty());
 }
 
 void ViEChannelManager::SetModuleProcessThread(
@@ -87,53 +85,18 @@
   }
 
   // Create a new channel group and add this channel.
-  ChannelGroup* group = new ChannelGroup(module_process_thread_,
-                                         channel_group_config);
-  BitrateAllocator* bitrate_allocator = group->GetBitrateAllocator();
-  BitrateController* bitrate_controller = group->GetBitrateController();
-  ViEEncoder* vie_encoder = new ViEEncoder(
-      new_channel_id, number_of_cores_, engine_config_, *module_process_thread_,
-      bitrate_allocator, bitrate_controller, false);
+  rtc::scoped_ptr<ChannelGroup> group(
+      new ChannelGroup(module_process_thread_, channel_group_config));
 
-  RtcpBandwidthObserver* bandwidth_observer =
-      bitrate_controller->CreateRtcpBandwidthObserver();
-  RemoteBitrateEstimator* remote_bitrate_estimator =
-      group->GetRemoteBitrateEstimator();
-  EncoderStateFeedback* encoder_state_feedback =
-      group->GetEncoderStateFeedback();
-  RtcpRttStats* rtcp_rtt_stats =
-      group->GetCallStats()->rtcp_rtt_stats();
-
-  if (!(vie_encoder->Init() &&
-        CreateChannelObject(new_channel_id, vie_encoder, bandwidth_observer,
-                            remote_bitrate_estimator, rtcp_rtt_stats,
-                            encoder_state_feedback->GetRtcpIntraFrameObserver(),
-                            true, false))) {
-    delete vie_encoder;
-    vie_encoder = NULL;
+  if (!group->CreateSendChannel(new_channel_id, engine_id_, number_of_cores_,
+                                false)) {
     ReturnChannelId(new_channel_id);
-    delete group;
     return -1;
   }
-  // Connect the encoder with the send packet router, to enable sending.
-  vie_encoder->StartThreadsAndSetSharedMembers(
-      channel_map_[new_channel_id]->send_payload_router(),
-      channel_map_[new_channel_id]->vcm_protection_callback());
 
-  // Add ViEEncoder to EncoderFeedBackObserver.
-  unsigned int ssrc = 0;
-  int idx = 0;
-  channel_map_[new_channel_id]->GetLocalSSRC(idx, &ssrc);
-  encoder_state_feedback->AddEncoder(ssrc, vie_encoder);
-  std::list<unsigned int> ssrcs;
-  ssrcs.push_back(ssrc);
-  vie_encoder->SetSsrcs(ssrcs);
   *channel_id = new_channel_id;
   group->AddChannel(*channel_id);
-  channel_groups_.push_back(group);
-  // Register the channel to receive stats updates.
-  group->GetCallStats()->RegisterStatsObserver(
-      channel_map_[new_channel_id]->GetStatsObserver());
+  channel_groups_.push_back(group.release());
   return 0;
 }
 
@@ -151,77 +114,27 @@
   if (new_channel_id == -1) {
     return -1;
   }
-  BitrateAllocator* bitrate_allocator = channel_group->GetBitrateAllocator();
-  BitrateController* bitrate_controller = channel_group->GetBitrateController();
-  RtcpBandwidthObserver* bandwidth_observer =
-      bitrate_controller->CreateRtcpBandwidthObserver();
-  RemoteBitrateEstimator* remote_bitrate_estimator =
-      channel_group->GetRemoteBitrateEstimator();
-  EncoderStateFeedback* encoder_state_feedback =
-      channel_group->GetEncoderStateFeedback();
-    RtcpRttStats* rtcp_rtt_stats =
-        channel_group->GetCallStats()->rtcp_rtt_stats();
-
-  ViEEncoder* vie_encoder = NULL;
   if (sender) {
-    // We need to create a new ViEEncoder.
-    vie_encoder =
-        new ViEEncoder(new_channel_id, number_of_cores_, engine_config_,
-                       *module_process_thread_, bitrate_allocator,
-                       bitrate_controller, disable_default_encoder);
-    if (!(vie_encoder->Init() &&
-        CreateChannelObject(
-            new_channel_id,
-            vie_encoder,
-            bandwidth_observer,
-            remote_bitrate_estimator,
-            rtcp_rtt_stats,
-            encoder_state_feedback->GetRtcpIntraFrameObserver(),
-            sender,
-            disable_default_encoder))) {
-      delete vie_encoder;
-      vie_encoder = NULL;
+    if (!channel_group->CreateSendChannel(new_channel_id, engine_id_,
+                                          number_of_cores_,
+                                          disable_default_encoder)) {
+      ReturnChannelId(new_channel_id);
+      return -1;
     }
-    // Connect the encoder with the send packet router, to enable sending.
-    vie_encoder->StartThreadsAndSetSharedMembers(
-        channel_map_[new_channel_id]->send_payload_router(),
-        channel_map_[new_channel_id]->vcm_protection_callback());
-
-    // Register the ViEEncoder to get key frame requests for this channel.
-    unsigned int ssrc = 0;
-    int stream_idx = 0;
-    channel_map_[new_channel_id]->GetLocalSSRC(stream_idx, &ssrc);
-    encoder_state_feedback->AddEncoder(ssrc, vie_encoder);
   } else {
-    vie_encoder = ViEEncoderPtr(original_channel);
-    assert(vie_encoder);
-    if (!CreateChannelObject(
-        new_channel_id,
-        vie_encoder,
-        bandwidth_observer,
-        remote_bitrate_estimator,
-        rtcp_rtt_stats,
-        encoder_state_feedback->GetRtcpIntraFrameObserver(),
-        sender,
-        disable_default_encoder)) {
-      vie_encoder = NULL;
+    if (!channel_group->CreateReceiveChannel(new_channel_id, engine_id_,
+                                             original_channel, number_of_cores_,
+                                             disable_default_encoder)) {
+      ReturnChannelId(new_channel_id);
+      return -1;
     }
   }
-  if (!vie_encoder) {
-    ReturnChannelId(new_channel_id);
-    return -1;
-  }
   *channel_id = new_channel_id;
   channel_group->AddChannel(*channel_id);
-  // Register the channel to receive stats updates.
-  channel_group->GetCallStats()->RegisterStatsObserver(
-      channel_map_[new_channel_id]->GetStatsObserver());
   return 0;
 }
 
 int ViEChannelManager::DeleteChannel(int channel_id) {
-  ViEChannel* vie_channel = NULL;
-  ViEEncoder* vie_encoder = NULL;
   ChannelGroup* group = NULL;
   {
     // Write lock to make sure no one is using the channel.
@@ -230,47 +143,11 @@
     // Protect the maps.
     CriticalSectionScoped cs(channel_id_critsect_);
 
-    ChannelMap::iterator c_it = channel_map_.find(channel_id);
-    if (c_it == channel_map_.end()) {
-      // No such channel.
-      return -1;
-    }
-    vie_channel = c_it->second;
-    channel_map_.erase(c_it);
-
-    ReturnChannelId(channel_id);
-
-    // Find the encoder object.
-    EncoderMap::iterator e_it = vie_encoder_map_.find(channel_id);
-    assert(e_it != vie_encoder_map_.end());
-    vie_encoder = e_it->second;
-
     group = FindGroup(channel_id);
-    group->GetCallStats()->DeregisterStatsObserver(
-        vie_channel->GetStatsObserver());
-    group->SetChannelRembStatus(channel_id, false, false, vie_channel);
-
-    // If we're owning the encoder, remove the feedback and stop all encoding
-    // threads and processing. This must be done before deleting the channel.
-    if (vie_encoder->channel_id() == channel_id) {
-      group->GetEncoderStateFeedback()->RemoveEncoder(vie_encoder);
-      vie_encoder->StopThreadsAndRemoveSharedMembers();
-    }
-
-    unsigned int remote_ssrc = 0;
-    vie_channel->GetRemoteSSRC(&remote_ssrc);
-    group->RemoveChannel(channel_id, remote_ssrc);
-
-    // Check if other channels are using the same encoder.
-    if (ChannelUsingViEEncoder(channel_id)) {
-      vie_encoder = NULL;
-    } else {
-      // Delete later when we've released the critsect.
-    }
-
-    // We can't erase the item before we've checked for other channels using
-    // same ViEEncoder.
-    vie_encoder_map_.erase(e_it);
+    if (group == NULL)
+      return -1;
+    ReturnChannelId(channel_id);
+    group->DeleteChannel(channel_id);
 
     if (group->Empty()) {
       channel_groups_.remove(group);
@@ -278,15 +155,6 @@
       group = NULL;  // Prevent group from being deleted.
     }
   }
-  delete vie_channel;
-  // Leave the write critsect before deleting the objects.
-  // Deleting a channel can cause other objects, such as renderers, to be
-  // deleted, which might take time.
-  // If statment just to show that this object is not always deleted.
-  if (vie_encoder) {
-    LOG(LS_VERBOSE) << "ViEEncoder deleted for channel " << channel_id;
-    delete vie_encoder;
-  }
   // If statment just to show that this object is not always deleted.
   if (group) {
     // Delete the group if empty last since the encoder holds a pointer to the
@@ -294,7 +162,6 @@
     LOG(LS_VERBOSE) << "Channel group deleted for channel " << channel_id;
     delete group;
   }
-  LOG(LS_VERBOSE) << "Channel deleted " << channel_id;
   return 0;
 }
 
@@ -313,9 +180,8 @@
     }
   }
 
-  for (ChannelMap::iterator it = channel_map_.begin(); it != channel_map_.end();
-       ++it) {
-    it->second->SetVoiceChannel(-1, sync_interface);
+  for (ChannelGroup* group : channel_groups_) {
+    group->SetSyncInterface(sync_interface);
   }
   if (voice_sync_interface_) {
     voice_sync_interface_->Release();
@@ -422,66 +288,21 @@
   return true;
 }
 
-bool ViEChannelManager::CreateChannelObject(
-    int channel_id,
-    ViEEncoder* vie_encoder,
-    RtcpBandwidthObserver* bandwidth_observer,
-    RemoteBitrateEstimator* remote_bitrate_estimator,
-    RtcpRttStats* rtcp_rtt_stats,
-    RtcpIntraFrameObserver* intra_frame_observer,
-    bool sender,
-    bool disable_default_encoder) {
-  PacedSender* paced_sender = vie_encoder->GetPacedSender();
-
-  ViEChannel* vie_channel = new ViEChannel(channel_id, engine_id_,
-                                           number_of_cores_,
-                                           engine_config_,
-                                           *module_process_thread_,
-                                           intra_frame_observer,
-                                           bandwidth_observer,
-                                           remote_bitrate_estimator,
-                                           rtcp_rtt_stats,
-                                           paced_sender,
-                                           sender,
-                                           disable_default_encoder);
-  if (vie_channel->Init() != 0) {
-    delete vie_channel;
-    return false;
-  }
-  if (!disable_default_encoder) {
-    VideoCodec encoder;
-    if (vie_encoder->GetEncoder(&encoder) != 0) {
-      delete vie_channel;
-      return false;
-    }
-    if (sender && vie_channel->SetSendCodec(encoder) != 0) {
-      delete vie_channel;
-      return false;
-    }
-  }
-  // Store the channel, add it to the channel group and save the vie_encoder.
-  channel_map_[channel_id] = vie_channel;
-  vie_encoder_map_[channel_id] = vie_encoder;
-  return true;
-}
-
 ViEChannel* ViEChannelManager::ViEChannelPtr(int channel_id) const {
   CriticalSectionScoped cs(channel_id_critsect_);
-  ChannelMap::const_iterator it = channel_map_.find(channel_id);
-  if (it == channel_map_.end()) {
-    LOG(LS_ERROR) << "Channel doesn't exist " << channel_id;
+  ChannelGroup* group = FindGroup(channel_id);
+  if (group == NULL)
     return NULL;
-  }
-  return it->second;
+  return group->GetChannel(channel_id);
 }
 
 ViEEncoder* ViEChannelManager::ViEEncoderPtr(int video_channel_id) const {
   CriticalSectionScoped cs(channel_id_critsect_);
-  EncoderMap::const_iterator it = vie_encoder_map_.find(video_channel_id);
-  if (it == vie_encoder_map_.end()) {
+  ChannelGroup* group = FindGroup(video_channel_id);
+  if (group == NULL) {
     return NULL;
   }
-  return it->second;
+  return group->GetEncoder(video_channel_id);
 }
 
 int ViEChannelManager::FreeChannelId() {
@@ -517,39 +338,20 @@
 
 bool ViEChannelManager::ChannelUsingViEEncoder(int channel_id) const {
   CriticalSectionScoped cs(channel_id_critsect_);
-  EncoderMap::const_iterator orig_it = vie_encoder_map_.find(channel_id);
-  if (orig_it == vie_encoder_map_.end()) {
-    // No ViEEncoder for this channel.
+  ChannelGroup* group = FindGroup(channel_id);
+  if (group == NULL) {
     return false;
   }
-
-  // Loop through all other channels to see if anyone points at the same
-  // ViEEncoder.
-  for (EncoderMap::const_iterator comp_it = vie_encoder_map_.begin();
-       comp_it != vie_encoder_map_.end(); ++comp_it) {
-    // Make sure we're not comparing the same channel with itself.
-    if (comp_it->first != channel_id) {
-      if (comp_it->second == orig_it->second) {
-        return true;
-      }
-    }
-  }
-  return false;
+  return group->OtherChannelsUsingEncoder(channel_id);
 }
 
 void ViEChannelManager::ChannelsUsingViEEncoder(int channel_id,
                                                 ChannelList* channels) const {
   CriticalSectionScoped cs(channel_id_critsect_);
-  EncoderMap::const_iterator orig_it = vie_encoder_map_.find(channel_id);
-
-  for (ChannelMap::const_iterator c_it = channel_map_.begin();
-       c_it != channel_map_.end(); ++c_it) {
-    EncoderMap::const_iterator comp_it = vie_encoder_map_.find(c_it->first);
-    assert(comp_it != vie_encoder_map_.end());
-    if (comp_it->second == orig_it->second) {
-      channels->push_back(c_it->second);
-    }
-  }
+  ChannelGroup* group = FindGroup(channel_id);
+  if (group == NULL)
+    return;
+  group->GetChannelsUsingEncoder(channel_id, channels);
 }
 
 ViEChannelManagerScoped::ViEChannelManagerScoped(
diff --git a/webrtc/video_engine/vie_channel_manager.h b/webrtc/video_engine/vie_channel_manager.h
index e6f6c96..c4a19b5 100644
--- a/webrtc/video_engine/vie_channel_manager.h
+++ b/webrtc/video_engine/vie_channel_manager.h
@@ -14,17 +14,16 @@
 #include <list>
 #include <map>
 
-#include "webrtc/base/scoped_ptr.h"
 #include "webrtc/engine_configurations.h"
 #include "webrtc/typedefs.h"
 #include "webrtc/video_engine/include/vie_rtp_rtcp.h"
-#include "webrtc/video_engine/vie_channel_group.h"
 #include "webrtc/video_engine/vie_defines.h"
 #include "webrtc/video_engine/vie_manager_base.h"
 #include "webrtc/video_engine/vie_remb.h"
 
 namespace webrtc {
 
+class ChannelGroup;
 class Config;
 class CriticalSectionWrapper;
 class ProcessThread;
@@ -36,8 +35,6 @@
 
 typedef std::list<ChannelGroup*> ChannelGroups;
 typedef std::list<ViEChannel*> ChannelList;
-typedef std::map<int, ViEChannel*> ChannelMap;
-typedef std::map<int, ViEEncoder*> EncoderMap;
 
 class ViEChannelManager: private ViEManagerBase {
   friend class ViEChannelManagerScoped;
@@ -90,17 +87,6 @@
                                     uint32_t* estimated_bandwidth) const;
 
  private:
-  // Creates a channel object connected to |vie_encoder|. Assumed to be called
-  // protected.
-  bool CreateChannelObject(int channel_id,
-                           ViEEncoder* vie_encoder,
-                           RtcpBandwidthObserver* bandwidth_observer,
-                           RemoteBitrateEstimator* remote_bitrate_estimator,
-                           RtcpRttStats* rtcp_rtt_stats,
-                           RtcpIntraFrameObserver* intra_frame_observer,
-                           bool sender,
-                           bool disable_default_encoder);
-
   // Used by ViEChannelScoped, forcing a manager user to use scoped.
   // Returns a pointer to the channel with id 'channel_id'.
   ViEChannel* ViEChannelPtr(int channel_id) const;
@@ -128,8 +114,6 @@
   int engine_id_;
   int number_of_cores_;
 
-  // TODO(mflodman) Make part of channel group.
-  ChannelMap channel_map_;
   bool* free_channel_ids_;
   int free_channel_ids_size_;
 
@@ -137,12 +121,9 @@
   std::list<ChannelGroup*> channel_groups_;
 
   // TODO(mflodman) Make part of channel group.
-  // Maps Channel id -> ViEEncoder.
-  EncoderMap vie_encoder_map_;
   VoEVideoSync* voice_sync_interface_;
 
   ProcessThread* module_process_thread_;
-  const Config& engine_config_;
 };
 
 class ViEChannelManagerScoped: private ViEManagerScopedBase {