| Index: webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc | 
| diff --git a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc | 
| index 0ca7eeabe91bf9d1a3a331e94a04d11e3773d92b..97f08462bf6db25fdd941ea2ecf0069ce55e7c78 100644 | 
| --- a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc | 
| +++ b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc | 
| @@ -112,42 +112,72 @@ int VP9EncoderImpl::Release() { | 
| return WEBRTC_VIDEO_CODEC_OK; | 
| } | 
|  | 
| +bool VP9EncoderImpl::ExplicitlyConfiguredSpatialLayers() const { | 
| +  // We check target_bitrate_bps of the 0th layer to see if the spatial layers | 
| +  // (i.e. bitrates) were explicitly configured. | 
| +  return num_spatial_layers_ > 1 && | 
| +         codec_.spatialLayers[0].target_bitrate_bps > 0; | 
| +} | 
| + | 
| bool VP9EncoderImpl::SetSvcRates() { | 
| -  float rate_ratio[VPX_MAX_LAYERS] = {0}; | 
| -  float total = 0; | 
| uint8_t i = 0; | 
|  | 
| -  for (i = 0; i < num_spatial_layers_; ++i) { | 
| -    if (svc_internal_.svc_params.scaling_factor_num[i] <= 0 || | 
| -        svc_internal_.svc_params.scaling_factor_den[i] <= 0) { | 
| +  if (ExplicitlyConfiguredSpatialLayers()) { | 
| +    if (num_temporal_layers_ > 1) { | 
| +      LOG(LS_ERROR) << "Multiple temporal layers when manually specifying " | 
| +                       "spatial layers not implemented yet!"; | 
| return false; | 
| } | 
| -    rate_ratio[i] = static_cast<float>( | 
| -        svc_internal_.svc_params.scaling_factor_num[i]) / | 
| -        svc_internal_.svc_params.scaling_factor_den[i]; | 
| -    total += rate_ratio[i]; | 
| -  } | 
| - | 
| -  for (i = 0; i < num_spatial_layers_; ++i) { | 
| -    config_->ss_target_bitrate[i] = static_cast<unsigned int>( | 
| -        config_->rc_target_bitrate * rate_ratio[i] / total); | 
| -    if (num_temporal_layers_ == 1) { | 
| -      config_->layer_target_bitrate[i] = config_->ss_target_bitrate[i]; | 
| -    } else if (num_temporal_layers_ == 2) { | 
| -      config_->layer_target_bitrate[i * num_temporal_layers_] = | 
| -          config_->ss_target_bitrate[i] * 2 / 3; | 
| -      config_->layer_target_bitrate[i * num_temporal_layers_ + 1] = | 
| -          config_->ss_target_bitrate[i]; | 
| -    } else if (num_temporal_layers_ == 3) { | 
| -      config_->layer_target_bitrate[i * num_temporal_layers_] = | 
| -          config_->ss_target_bitrate[i] / 2; | 
| -      config_->layer_target_bitrate[i * num_temporal_layers_ + 1] = | 
| -          config_->layer_target_bitrate[i * num_temporal_layers_] + | 
| -          (config_->ss_target_bitrate[i] / 4); | 
| -      config_->layer_target_bitrate[i * num_temporal_layers_ + 2] = | 
| -          config_->ss_target_bitrate[i]; | 
| -    } else { | 
| -      return false; | 
| +    int total_bitrate_bps = 0; | 
| +    for (i = 0; i < num_spatial_layers_; ++i) | 
| +      total_bitrate_bps += codec_.spatialLayers[i].target_bitrate_bps; | 
| +    // If total bitrate differs now from what has been specified at the | 
| +    // beginning, update the bitrates in the same ratio as before. | 
| +    for (i = 0; i < num_spatial_layers_; ++i) { | 
| +      config_->ss_target_bitrate[i] = config_->layer_target_bitrate[i] = | 
| +          static_cast<int>(static_cast<int64_t>(config_->rc_target_bitrate) * | 
| +                           codec_.spatialLayers[i].target_bitrate_bps / | 
| +                           total_bitrate_bps); | 
| +    } | 
| +  } else { | 
| +    float rate_ratio[VPX_MAX_LAYERS] = {0}; | 
| +    float total = 0; | 
| + | 
| +    for (i = 0; i < num_spatial_layers_; ++i) { | 
| +      if (svc_internal_.svc_params.scaling_factor_num[i] <= 0 || | 
| +          svc_internal_.svc_params.scaling_factor_den[i] <= 0) { | 
| +        LOG(LS_ERROR) << "Scaling factors not specified!"; | 
| +        return false; | 
| +      } | 
| +      rate_ratio[i] = | 
| +          static_cast<float>(svc_internal_.svc_params.scaling_factor_num[i]) / | 
| +          svc_internal_.svc_params.scaling_factor_den[i]; | 
| +      total += rate_ratio[i]; | 
| +    } | 
| + | 
| +    for (i = 0; i < num_spatial_layers_; ++i) { | 
| +      config_->ss_target_bitrate[i] = static_cast<unsigned int>( | 
| +          config_->rc_target_bitrate * rate_ratio[i] / total); | 
| +      if (num_temporal_layers_ == 1) { | 
| +        config_->layer_target_bitrate[i] = config_->ss_target_bitrate[i]; | 
| +      } else if (num_temporal_layers_ == 2) { | 
| +        config_->layer_target_bitrate[i * num_temporal_layers_] = | 
| +            config_->ss_target_bitrate[i] * 2 / 3; | 
| +        config_->layer_target_bitrate[i * num_temporal_layers_ + 1] = | 
| +            config_->ss_target_bitrate[i]; | 
| +      } else if (num_temporal_layers_ == 3) { | 
| +        config_->layer_target_bitrate[i * num_temporal_layers_] = | 
| +            config_->ss_target_bitrate[i] / 2; | 
| +        config_->layer_target_bitrate[i * num_temporal_layers_ + 1] = | 
| +            config_->layer_target_bitrate[i * num_temporal_layers_] + | 
| +            (config_->ss_target_bitrate[i] / 4); | 
| +        config_->layer_target_bitrate[i * num_temporal_layers_ + 2] = | 
| +            config_->ss_target_bitrate[i]; | 
| +      } else { | 
| +        LOG(LS_ERROR) << "Unsupported number of temporal layers: " | 
| +                      << num_temporal_layers_; | 
| +        return false; | 
| +      } | 
| } | 
| } | 
|  | 
| @@ -349,14 +379,24 @@ int VP9EncoderImpl::NumberOfThreads(int width, | 
| int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) { | 
| config_->ss_number_layers = num_spatial_layers_; | 
|  | 
| -  int scaling_factor_num = 256; | 
| -  for (int i = num_spatial_layers_ - 1; i >= 0; --i) { | 
| -    svc_internal_.svc_params.max_quantizers[i] = config_->rc_max_quantizer; | 
| -    svc_internal_.svc_params.min_quantizers[i] = config_->rc_min_quantizer; | 
| -    // 1:2 scaling in each dimension. | 
| -    svc_internal_.svc_params.scaling_factor_num[i] = scaling_factor_num; | 
| -    svc_internal_.svc_params.scaling_factor_den[i] = 256; | 
| -    scaling_factor_num /= 2; | 
| +  if (ExplicitlyConfiguredSpatialLayers()) { | 
| +    for (int i = 0; i < num_spatial_layers_; ++i) { | 
| +      const auto& layer = codec_.spatialLayers[i]; | 
| +      svc_internal_.svc_params.max_quantizers[i] = config_->rc_max_quantizer; | 
| +      svc_internal_.svc_params.min_quantizers[i] = config_->rc_min_quantizer; | 
| +      svc_internal_.svc_params.scaling_factor_num[i] = layer.scaling_factor_num; | 
| +      svc_internal_.svc_params.scaling_factor_den[i] = layer.scaling_factor_den; | 
| +    } | 
| +  } else { | 
| +    int scaling_factor_num = 256; | 
| +    for (int i = num_spatial_layers_ - 1; i >= 0; --i) { | 
| +      svc_internal_.svc_params.max_quantizers[i] = config_->rc_max_quantizer; | 
| +      svc_internal_.svc_params.min_quantizers[i] = config_->rc_min_quantizer; | 
| +      // 1:2 scaling in each dimension. | 
| +      svc_internal_.svc_params.scaling_factor_num[i] = scaling_factor_num; | 
| +      svc_internal_.svc_params.scaling_factor_den[i] = 256; | 
| +      scaling_factor_num /= 2; | 
| +    } | 
| } | 
|  | 
| if (!SetSvcRates()) { | 
|  |