| Index: webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.cc
 | 
| diff --git a/webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.cc b/webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.cc
 | 
| index e2ceb4a282c0bbf047a5872047777f87e8fdfea3..4f04743fc5d0359d62ff02117d9fe620e26fc309 100644
 | 
| --- a/webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.cc
 | 
| +++ b/webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.cc
 | 
| @@ -13,6 +13,10 @@
 | 
|  #include <stdlib.h>
 | 
|  #include <string.h>
 | 
|  
 | 
| +#include <algorithm>
 | 
| +#include <vector>
 | 
| +
 | 
| +#include "webrtc/base/checks.h"
 | 
|  #include "webrtc/modules/include/module_common_types.h"
 | 
|  #include "webrtc/modules/video_coding/include/video_codec_interface.h"
 | 
|  #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h"
 | 
| @@ -22,16 +26,17 @@
 | 
|  
 | 
|  namespace webrtc {
 | 
|  
 | 
| -DefaultTemporalLayers::DefaultTemporalLayers(int numberOfTemporalLayers,
 | 
| +DefaultTemporalLayers::DefaultTemporalLayers(int number_of_temporal_layers,
 | 
|                                               uint8_t initial_tl0_pic_idx)
 | 
| -    : number_of_temporal_layers_(numberOfTemporalLayers),
 | 
| +    : number_of_temporal_layers_(number_of_temporal_layers),
 | 
|        temporal_ids_length_(0),
 | 
|        temporal_pattern_length_(0),
 | 
|        tl0_pic_idx_(initial_tl0_pic_idx),
 | 
|        pattern_idx_(255),
 | 
|        timestamp_(0),
 | 
|        last_base_layer_sync_(false) {
 | 
| -  assert(kMaxTemporalStreams >= numberOfTemporalLayers);
 | 
| +  RTC_CHECK_GE(kMaxTemporalStreams, number_of_temporal_layers);
 | 
| +  RTC_CHECK_GE(number_of_temporal_layers, 0);
 | 
|    memset(temporal_ids_, 0, sizeof(temporal_ids_));
 | 
|    memset(temporal_pattern_, 0, sizeof(temporal_pattern_));
 | 
|  }
 | 
| @@ -43,18 +48,50 @@ int DefaultTemporalLayers::CurrentLayerId() const {
 | 
|    return temporal_ids_[index];
 | 
|  }
 | 
|  
 | 
| -bool DefaultTemporalLayers::ConfigureBitrates(int bitrateKbit,
 | 
| -                                              int max_bitrate_kbit,
 | 
| -                                              int framerate,
 | 
| -                                              vpx_codec_enc_cfg_t* cfg) {
 | 
| +std::vector<uint32_t> DefaultTemporalLayers::OnRatesUpdated(
 | 
| +    int bitrate_kbps,
 | 
| +    int max_bitrate_kbps,
 | 
| +    int framerate) {
 | 
| +  std::vector<uint32_t> bitrates;
 | 
| +  const int num_layers = std::max(1, number_of_temporal_layers_);
 | 
| +  for (int i = 0; i < num_layers; ++i) {
 | 
| +    float layer_bitrate =
 | 
| +        bitrate_kbps * kVp8LayerRateAlloction[num_layers - 1][i];
 | 
| +    bitrates.push_back(static_cast<uint32_t>(layer_bitrate + 0.5));
 | 
| +  }
 | 
| +  new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>(bitrates);
 | 
| +
 | 
| +  // Allocation table is of aggregates, transform to individual rates.
 | 
| +  uint32_t sum = 0;
 | 
| +  for (int i = 0; i < num_layers; ++i) {
 | 
| +    uint32_t layer_bitrate = bitrates[i];
 | 
| +    RTC_DCHECK_LE(sum, bitrates[i]);
 | 
| +    bitrates[i] -= sum;
 | 
| +    sum = layer_bitrate;
 | 
| +
 | 
| +    if (sum >= static_cast<uint32_t>(bitrate_kbps)) {
 | 
| +      // Sum adds up; any subsequent layers will be 0.
 | 
| +      bitrates.resize(i + 1);
 | 
| +      break;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  return bitrates;
 | 
| +}
 | 
| +
 | 
| +bool DefaultTemporalLayers::UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) {
 | 
| +  if (!new_bitrates_kbps_)
 | 
| +    return false;
 | 
| +
 | 
|    switch (number_of_temporal_layers_) {
 | 
|      case 0:
 | 
| +      FALLTHROUGH();
 | 
|      case 1:
 | 
|        temporal_ids_length_ = 1;
 | 
|        temporal_ids_[0] = 0;
 | 
|        cfg->ts_number_layers = number_of_temporal_layers_;
 | 
|        cfg->ts_periodicity = temporal_ids_length_;
 | 
| -      cfg->ts_target_bitrate[0] = bitrateKbit;
 | 
| +      cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0];
 | 
|        cfg->ts_rate_decimator[0] = 1;
 | 
|        memcpy(cfg->ts_layer_id, temporal_ids_,
 | 
|               sizeof(unsigned int) * temporal_ids_length_);
 | 
| @@ -69,8 +106,8 @@ bool DefaultTemporalLayers::ConfigureBitrates(int bitrateKbit,
 | 
|        cfg->ts_periodicity = temporal_ids_length_;
 | 
|        // Split stream 60% 40%.
 | 
|        // Bitrate API for VP8 is the agregated bitrate for all lower layers.
 | 
| -      cfg->ts_target_bitrate[0] = bitrateKbit * kVp8LayerRateAlloction[1][0];
 | 
| -      cfg->ts_target_bitrate[1] = bitrateKbit;
 | 
| +      cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0];
 | 
| +      cfg->ts_target_bitrate[1] = (*new_bitrates_kbps_)[1];
 | 
|        cfg->ts_rate_decimator[0] = 2;
 | 
|        cfg->ts_rate_decimator[1] = 1;
 | 
|        memcpy(cfg->ts_layer_id, temporal_ids_,
 | 
| @@ -95,9 +132,9 @@ bool DefaultTemporalLayers::ConfigureBitrates(int bitrateKbit,
 | 
|        cfg->ts_periodicity = temporal_ids_length_;
 | 
|        // Split stream 40% 20% 40%.
 | 
|        // Bitrate API for VP8 is the agregated bitrate for all lower layers.
 | 
| -      cfg->ts_target_bitrate[0] = bitrateKbit * kVp8LayerRateAlloction[2][0];
 | 
| -      cfg->ts_target_bitrate[1] = bitrateKbit * kVp8LayerRateAlloction[2][1];
 | 
| -      cfg->ts_target_bitrate[2] = bitrateKbit;
 | 
| +      cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0];
 | 
| +      cfg->ts_target_bitrate[1] = (*new_bitrates_kbps_)[1];
 | 
| +      cfg->ts_target_bitrate[2] = (*new_bitrates_kbps_)[2];
 | 
|        cfg->ts_rate_decimator[0] = 4;
 | 
|        cfg->ts_rate_decimator[1] = 2;
 | 
|        cfg->ts_rate_decimator[2] = 1;
 | 
| @@ -127,10 +164,10 @@ bool DefaultTemporalLayers::ConfigureBitrates(int bitrateKbit,
 | 
|        // Bitrate API for VP8 is the agregated bitrate for all lower layers.
 | 
|        cfg->ts_number_layers = 4;
 | 
|        cfg->ts_periodicity = temporal_ids_length_;
 | 
| -      cfg->ts_target_bitrate[0] = bitrateKbit * kVp8LayerRateAlloction[3][0];
 | 
| -      cfg->ts_target_bitrate[1] = bitrateKbit * kVp8LayerRateAlloction[3][1];
 | 
| -      cfg->ts_target_bitrate[2] = bitrateKbit * kVp8LayerRateAlloction[3][2];
 | 
| -      cfg->ts_target_bitrate[3] = bitrateKbit;
 | 
| +      cfg->ts_target_bitrate[0] = (*new_bitrates_kbps_)[0];
 | 
| +      cfg->ts_target_bitrate[1] = (*new_bitrates_kbps_)[1];
 | 
| +      cfg->ts_target_bitrate[2] = (*new_bitrates_kbps_)[2];
 | 
| +      cfg->ts_target_bitrate[3] = (*new_bitrates_kbps_)[3];
 | 
|        cfg->ts_rate_decimator[0] = 8;
 | 
|        cfg->ts_rate_decimator[1] = 4;
 | 
|        cfg->ts_rate_decimator[2] = 2;
 | 
| @@ -156,9 +193,12 @@ bool DefaultTemporalLayers::ConfigureBitrates(int bitrateKbit,
 | 
|        temporal_pattern_[15] = kTemporalUpdateNone;
 | 
|        break;
 | 
|      default:
 | 
| -      assert(false);
 | 
| +      RTC_NOTREACHED();
 | 
|        return false;
 | 
|    }
 | 
| +
 | 
| +  new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>();
 | 
| +
 | 
|    return true;
 | 
|  }
 | 
|  
 | 
| @@ -284,8 +324,18 @@ void DefaultTemporalLayers::PopulateCodecSpecific(
 | 
|  }
 | 
|  
 | 
|  TemporalLayers* TemporalLayersFactory::Create(
 | 
| +    int simulcast_id,
 | 
|      int temporal_layers,
 | 
|      uint8_t initial_tl0_pic_idx) const {
 | 
| -  return new DefaultTemporalLayers(temporal_layers, initial_tl0_pic_idx);
 | 
| +  TemporalLayers* tl =
 | 
| +      new DefaultTemporalLayers(temporal_layers, initial_tl0_pic_idx);
 | 
| +  if (listener_)
 | 
| +    listener_->OnTemporalLayersCreated(simulcast_id, tl);
 | 
| +  return tl;
 | 
| +}
 | 
| +
 | 
| +void TemporalLayersFactory::SetListener(TemporalLayersListener* listener) {
 | 
| +  listener_ = listener;
 | 
|  }
 | 
| +
 | 
|  }  // namespace webrtc
 | 
| 
 |