| Index: webrtc/modules/video_coding/codecs/vp8/realtime_temporal_layers.cc
 | 
| diff --git a/webrtc/modules/video_coding/codecs/vp8/realtime_temporal_layers.cc b/webrtc/modules/video_coding/codecs/vp8/realtime_temporal_layers.cc
 | 
| index b9721cde1bcc6b6b9bb31a3962db0dfe0c3deb2f..a43bc900605dd3187899df48e9c5c153057f4b94 100644
 | 
| --- a/webrtc/modules/video_coding/codecs/vp8/realtime_temporal_layers.cc
 | 
| +++ b/webrtc/modules/video_coding/codecs/vp8/realtime_temporal_layers.cc
 | 
| @@ -12,6 +12,8 @@
 | 
|  
 | 
|  #include "vpx/vpx_encoder.h"
 | 
|  #include "vpx/vp8cx.h"
 | 
| +#include "webrtc/base/checks.h"
 | 
| +#include "webrtc/base/optional.h"
 | 
|  #include "webrtc/modules/video_coding/include/video_codec_interface.h"
 | 
|  #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h"
 | 
|  #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
 | 
| @@ -95,26 +97,20 @@ class RealTimeTemporalLayers : public TemporalLayers {
 | 
|          layer_ids_(NULL),
 | 
|          encode_flags_length_(0),
 | 
|          encode_flags_(NULL) {
 | 
| -    assert(max_temporal_layers_ >= 1);
 | 
| -    assert(max_temporal_layers_ <= 3);
 | 
| +    RTC_CHECK_GE(max_temporal_layers_, 1);
 | 
| +    RTC_CHECK_GE(max_temporal_layers_, 3);
 | 
|    }
 | 
|  
 | 
|    virtual ~RealTimeTemporalLayers() {}
 | 
|  
 | 
| -  bool ConfigureBitrates(int bitrate_kbit,
 | 
| -                         int max_bitrate_kbit,
 | 
| -                         int framerate,
 | 
| -                         vpx_codec_enc_cfg_t* cfg) override {
 | 
| +  std::vector<uint32_t> OnRatesUpdated(int bitrate_kbit,
 | 
| +                                       int max_bitrate_kbit,
 | 
| +                                       int framerate) override {
 | 
|      temporal_layers_ =
 | 
|          CalculateNumberOfTemporalLayers(temporal_layers_, framerate);
 | 
|      temporal_layers_ = std::min(temporal_layers_, max_temporal_layers_);
 | 
| -    assert(temporal_layers_ >= 1 && temporal_layers_ <= 3);
 | 
| -
 | 
| -    cfg->ts_number_layers = temporal_layers_;
 | 
| -    for (int tl = 0; tl < temporal_layers_; ++tl) {
 | 
| -      cfg->ts_target_bitrate[tl] =
 | 
| -          bitrate_kbit * kVp8LayerRateAlloction[temporal_layers_ - 1][tl];
 | 
| -    }
 | 
| +    RTC_CHECK_GE(temporal_layers_, 1);
 | 
| +    RTC_CHECK_LE(temporal_layers_, 3);
 | 
|  
 | 
|      switch (temporal_layers_) {
 | 
|        case 1: {
 | 
| @@ -125,9 +121,6 @@ class RealTimeTemporalLayers : public TemporalLayers {
 | 
|          static const int encode_flags[] = {kTemporalUpdateLastRefAll};
 | 
|          encode_flags_length_ = sizeof(encode_flags) / sizeof(*layer_ids);
 | 
|          encode_flags_ = encode_flags;
 | 
| -
 | 
| -        cfg->ts_rate_decimator[0] = 1;
 | 
| -        cfg->ts_periodicity = layer_ids_length_;
 | 
|        } break;
 | 
|  
 | 
|        case 2: {
 | 
| @@ -146,10 +139,6 @@ class RealTimeTemporalLayers : public TemporalLayers {
 | 
|              kTemporalUpdateNone};
 | 
|          encode_flags_length_ = sizeof(encode_flags) / sizeof(*layer_ids);
 | 
|          encode_flags_ = encode_flags;
 | 
| -
 | 
| -        cfg->ts_rate_decimator[0] = 2;
 | 
| -        cfg->ts_rate_decimator[1] = 1;
 | 
| -        cfg->ts_periodicity = layer_ids_length_;
 | 
|        } break;
 | 
|  
 | 
|        case 3: {
 | 
| @@ -168,19 +157,58 @@ class RealTimeTemporalLayers : public TemporalLayers {
 | 
|              kTemporalUpdateNone};
 | 
|          encode_flags_length_ = sizeof(encode_flags) / sizeof(*layer_ids);
 | 
|          encode_flags_ = encode_flags;
 | 
| -
 | 
| -        cfg->ts_rate_decimator[0] = 4;
 | 
| -        cfg->ts_rate_decimator[1] = 2;
 | 
| -        cfg->ts_rate_decimator[2] = 1;
 | 
| -        cfg->ts_periodicity = layer_ids_length_;
 | 
|        } break;
 | 
|  
 | 
|        default:
 | 
| -        assert(false);
 | 
| -        return false;
 | 
| +        RTC_NOTREACHED();
 | 
| +        return std::vector<uint32_t>();
 | 
| +    }
 | 
| +
 | 
| +    std::vector<uint32_t> bitrates;
 | 
| +    const int num_layers = std::max(1, temporal_layers_);
 | 
| +    for (int i = 0; i < num_layers; ++i) {
 | 
| +      float layer_bitrate =
 | 
| +          bitrate_kbit * 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];
 | 
| +      bitrates[i] -= sum;
 | 
| +      sum += layer_bitrate;
 | 
| +
 | 
| +      if (sum == static_cast<uint32_t>(bitrate_kbit)) {
 | 
| +        // Sum adds up; any subsequent layers will be 0.
 | 
| +        bitrates.resize(i);
 | 
| +        break;
 | 
| +      }
 | 
| +    }
 | 
| +
 | 
| +    return bitrates;
 | 
| +  }
 | 
| +
 | 
| +  bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) override {
 | 
| +    if (!new_bitrates_kbps_)
 | 
| +      return false;
 | 
| +
 | 
| +    cfg->ts_number_layers = temporal_layers_;
 | 
| +    for (int tl = 0; tl < temporal_layers_; ++tl) {
 | 
| +      cfg->ts_target_bitrate[tl] = (*new_bitrates_kbps_)[tl];
 | 
|      }
 | 
| +    new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>();
 | 
| +
 | 
| +    cfg->ts_periodicity = layer_ids_length_;
 | 
| +    int decimator = 1;
 | 
| +    for (int i = temporal_layers_ - 1; i >= 0; --i, decimator *= 2) {
 | 
| +      cfg->ts_rate_decimator[i] = decimator;
 | 
| +    }
 | 
| +
 | 
|      memcpy(cfg->ts_layer_id, layer_ids_,
 | 
|             sizeof(unsigned int) * layer_ids_length_);
 | 
| +
 | 
|      return true;
 | 
|    }
 | 
|  
 | 
| @@ -248,8 +276,6 @@ class RealTimeTemporalLayers : public TemporalLayers {
 | 
|  
 | 
|    void FrameEncoded(unsigned int size, uint32_t timestamp, int qp) override {}
 | 
|  
 | 
| -  bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) override { return false; }
 | 
| -
 | 
|   private:
 | 
|    int temporal_layers_;
 | 
|    int max_temporal_layers_;
 | 
| @@ -266,12 +292,19 @@ class RealTimeTemporalLayers : public TemporalLayers {
 | 
|    // Pattern of encode flags.
 | 
|    int encode_flags_length_;
 | 
|    const int* encode_flags_;
 | 
| +
 | 
| +  rtc::Optional<std::vector<uint32_t>> new_bitrates_kbps_;
 | 
|  };
 | 
|  }  // namespace
 | 
|  
 | 
|  TemporalLayers* RealTimeTemporalLayersFactory::Create(
 | 
| +    int simulcast_id,
 | 
|      int max_temporal_layers,
 | 
|      uint8_t initial_tl0_pic_idx) const {
 | 
| -  return new RealTimeTemporalLayers(max_temporal_layers, initial_tl0_pic_idx);
 | 
| +  TemporalLayers* tl =
 | 
| +      new RealTimeTemporalLayers(max_temporal_layers, initial_tl0_pic_idx);
 | 
| +  if (listener_)
 | 
| +    listener_->OnTemporalLayersCreated(simulcast_id, tl);
 | 
| +  return tl;
 | 
|  }
 | 
|  }  // namespace webrtc
 | 
| 
 |