| Index: webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h
 | 
| diff --git a/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h b/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h
 | 
| index 56ad3a710d29528e30ec6d65636bf2062d2c5b36..1740153252cfd8b40bd6a44e70e66f007ca9103f 100644
 | 
| --- a/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h
 | 
| +++ b/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h
 | 
| @@ -12,6 +12,7 @@
 | 
|  #define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_SIMULCAST_UNITTEST_H_
 | 
|  
 | 
|  #include <algorithm>
 | 
| +#include <map>
 | 
|  #include <memory>
 | 
|  #include <vector>
 | 
|  
 | 
| @@ -20,6 +21,7 @@
 | 
|  #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
 | 
|  #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
 | 
|  #include "webrtc/modules/video_coding/include/mock/mock_video_codec_interface.h"
 | 
| +#include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h"
 | 
|  #include "webrtc/test/gtest.h"
 | 
|  #include "webrtc/video_frame.h"
 | 
|  
 | 
| @@ -147,83 +149,6 @@ class Vp8TestDecodedImageCallback : public DecodedImageCallback {
 | 
|    int decoded_frames_;
 | 
|  };
 | 
|  
 | 
| -class SkipEncodingUnusedStreamsTest {
 | 
| - public:
 | 
| -  std::vector<unsigned int> RunTest(VP8Encoder* encoder,
 | 
| -                                    VideoCodec* settings,
 | 
| -                                    uint32_t target_bitrate) {
 | 
| -    SpyingTemporalLayersFactory spy_factory;
 | 
| -    settings->VP8()->tl_factory = &spy_factory;
 | 
| -    EXPECT_EQ(0, encoder->InitEncode(settings, 1, 1200));
 | 
| -
 | 
| -    encoder->SetRates(target_bitrate, 30);
 | 
| -
 | 
| -    std::vector<unsigned int> configured_bitrates;
 | 
| -    for (std::vector<TemporalLayers*>::const_iterator it =
 | 
| -             spy_factory.spying_layers_.begin();
 | 
| -         it != spy_factory.spying_layers_.end(); ++it) {
 | 
| -      configured_bitrates.push_back(
 | 
| -          static_cast<SpyingTemporalLayers*>(*it)->configured_bitrate_);
 | 
| -    }
 | 
| -    return configured_bitrates;
 | 
| -  }
 | 
| -
 | 
| -  class SpyingTemporalLayers : public TemporalLayers {
 | 
| -   public:
 | 
| -    explicit SpyingTemporalLayers(TemporalLayers* layers)
 | 
| -        : configured_bitrate_(0), layers_(layers) {}
 | 
| -
 | 
| -    virtual ~SpyingTemporalLayers() { delete layers_; }
 | 
| -
 | 
| -    int EncodeFlags(uint32_t timestamp) override {
 | 
| -      return layers_->EncodeFlags(timestamp);
 | 
| -    }
 | 
| -
 | 
| -    bool ConfigureBitrates(int bitrate_kbit,
 | 
| -                           int max_bitrate_kbit,
 | 
| -                           int framerate,
 | 
| -                           vpx_codec_enc_cfg_t* cfg) override {
 | 
| -      configured_bitrate_ = bitrate_kbit;
 | 
| -      return layers_->ConfigureBitrates(bitrate_kbit, max_bitrate_kbit,
 | 
| -                                        framerate, cfg);
 | 
| -    }
 | 
| -
 | 
| -    void PopulateCodecSpecific(bool base_layer_sync,
 | 
| -                               CodecSpecificInfoVP8* vp8_info,
 | 
| -                               uint32_t timestamp) override {
 | 
| -      layers_->PopulateCodecSpecific(base_layer_sync, vp8_info, timestamp);
 | 
| -    }
 | 
| -
 | 
| -    void FrameEncoded(unsigned int size, uint32_t timestamp, int qp) override {
 | 
| -      layers_->FrameEncoded(size, timestamp, qp);
 | 
| -    }
 | 
| -
 | 
| -    int CurrentLayerId() const override { return layers_->CurrentLayerId(); }
 | 
| -
 | 
| -    bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) override {
 | 
| -      return false;
 | 
| -    }
 | 
| -
 | 
| -    int configured_bitrate_;
 | 
| -    TemporalLayers* layers_;
 | 
| -  };
 | 
| -
 | 
| -  class SpyingTemporalLayersFactory : public TemporalLayersFactory {
 | 
| -   public:
 | 
| -    virtual ~SpyingTemporalLayersFactory() {}
 | 
| -    TemporalLayers* Create(int temporal_layers,
 | 
| -                           uint8_t initial_tl0_pic_idx) const override {
 | 
| -      SpyingTemporalLayers* layers =
 | 
| -          new SpyingTemporalLayers(TemporalLayersFactory::Create(
 | 
| -              temporal_layers, initial_tl0_pic_idx));
 | 
| -      spying_layers_.push_back(layers);
 | 
| -      return layers;
 | 
| -    }
 | 
| -
 | 
| -    mutable std::vector<TemporalLayers*> spying_layers_;
 | 
| -  };
 | 
| -};
 | 
| -
 | 
|  class TestVp8Simulcast : public ::testing::Test {
 | 
|   public:
 | 
|    TestVp8Simulcast(VP8Encoder* encoder, VP8Decoder* decoder)
 | 
| @@ -265,7 +190,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|  
 | 
|    static void DefaultSettings(VideoCodec* settings,
 | 
|                                const int* temporal_layer_profile) {
 | 
| -    assert(settings);
 | 
| +    RTC_CHECK(settings);
 | 
|      memset(settings, 0, sizeof(VideoCodec));
 | 
|      strncpy(settings->plName, "VP8", 4);
 | 
|      settings->codecType = kVideoCodecVP8;
 | 
| @@ -315,12 +240,18 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|    }
 | 
|  
 | 
|   protected:
 | 
| -  virtual void SetUp() { SetUpCodec(kDefaultTemporalLayerProfile); }
 | 
| +  void SetUp() override { SetUpCodec(kDefaultTemporalLayerProfile); }
 | 
|  
 | 
| -  virtual void SetUpCodec(const int* temporal_layer_profile) {
 | 
| +  void TearDown() override {
 | 
| +    encoder_->Release();
 | 
| +    decoder_->Release();
 | 
| +  }
 | 
| +
 | 
| +  void SetUpCodec(const int* temporal_layer_profile) {
 | 
|      encoder_->RegisterEncodeCompleteCallback(&encoder_callback_);
 | 
|      decoder_->RegisterDecodeCompleteCallback(&decoder_callback_);
 | 
|      DefaultSettings(&settings_, temporal_layer_profile);
 | 
| +    SetUpRateAllocator();
 | 
|      EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200));
 | 
|      EXPECT_EQ(0, decoder_->InitDecode(&settings_, 1));
 | 
|      int half_width = (kDefaultWidth + 1) / 2;
 | 
| @@ -331,9 +262,16 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|          new VideoFrame(input_buffer_, 0, 0, webrtc::kVideoRotation_0));
 | 
|    }
 | 
|  
 | 
| -  virtual void TearDown() {
 | 
| -    encoder_->Release();
 | 
| -    decoder_->Release();
 | 
| +  void SetUpRateAllocator() {
 | 
| +    TemporalLayersFactory* tl_factory = new TemporalLayersFactory();
 | 
| +    rate_allocator_.reset(new SimulcastRateAllocator(
 | 
| +        settings_, std::unique_ptr<TemporalLayersFactory>(tl_factory)));
 | 
| +    settings_.VP8()->tl_factory = tl_factory;
 | 
| +  }
 | 
| +
 | 
| +  void SetRates(uint32_t bitrate_kbps, uint32_t fps) {
 | 
| +    encoder_->SetRateAllocation(
 | 
| +        rate_allocator_->GetAllocation(bitrate_kbps * 1000, fps), fps);
 | 
|    }
 | 
|  
 | 
|    void ExpectStreams(FrameType frame_type, int expected_video_streams) {
 | 
| @@ -396,7 +334,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|    // We currently expect all active streams to generate a key frame even though
 | 
|    // a key frame was only requested for some of them.
 | 
|    void TestKeyFrameRequestsOnAllStreams() {
 | 
| -    encoder_->SetRates(kMaxBitrates[2], 30);  // To get all three streams.
 | 
| +    SetRates(kMaxBitrates[2], 30);  // To get all three streams.
 | 
|      std::vector<FrameType> frame_types(kNumberOfSimulcastStreams,
 | 
|                                         kVideoFrameDelta);
 | 
|      ExpectStreams(kVideoFrameKey, kNumberOfSimulcastStreams);
 | 
| @@ -431,7 +369,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|  
 | 
|    void TestPaddingAllStreams() {
 | 
|      // We should always encode the base layer.
 | 
| -    encoder_->SetRates(kMinBitrates[0] - 1, 30);
 | 
| +    SetRates(kMinBitrates[0] - 1, 30);
 | 
|      std::vector<FrameType> frame_types(kNumberOfSimulcastStreams,
 | 
|                                         kVideoFrameDelta);
 | 
|      ExpectStreams(kVideoFrameKey, 1);
 | 
| @@ -444,7 +382,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|  
 | 
|    void TestPaddingTwoStreams() {
 | 
|      // We have just enough to get only the first stream and padding for two.
 | 
| -    encoder_->SetRates(kMinBitrates[0], 30);
 | 
| +    SetRates(kMinBitrates[0], 30);
 | 
|      std::vector<FrameType> frame_types(kNumberOfSimulcastStreams,
 | 
|                                         kVideoFrameDelta);
 | 
|      ExpectStreams(kVideoFrameKey, 1);
 | 
| @@ -458,7 +396,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|    void TestPaddingTwoStreamsOneMaxedOut() {
 | 
|      // We are just below limit of sending second stream, so we should get
 | 
|      // the first stream maxed out (at |maxBitrate|), and padding for two.
 | 
| -    encoder_->SetRates(kTargetBitrates[0] + kMinBitrates[1] - 1, 30);
 | 
| +    SetRates(kTargetBitrates[0] + kMinBitrates[1] - 1, 30);
 | 
|      std::vector<FrameType> frame_types(kNumberOfSimulcastStreams,
 | 
|                                         kVideoFrameDelta);
 | 
|      ExpectStreams(kVideoFrameKey, 1);
 | 
| @@ -471,7 +409,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|  
 | 
|    void TestPaddingOneStream() {
 | 
|      // We have just enough to send two streams, so padding for one stream.
 | 
| -    encoder_->SetRates(kTargetBitrates[0] + kMinBitrates[1], 30);
 | 
| +    SetRates(kTargetBitrates[0] + kMinBitrates[1], 30);
 | 
|      std::vector<FrameType> frame_types(kNumberOfSimulcastStreams,
 | 
|                                         kVideoFrameDelta);
 | 
|      ExpectStreams(kVideoFrameKey, 2);
 | 
| @@ -485,8 +423,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|    void TestPaddingOneStreamTwoMaxedOut() {
 | 
|      // We are just below limit of sending third stream, so we should get
 | 
|      // first stream's rate maxed out at |targetBitrate|, second at |maxBitrate|.
 | 
| -    encoder_->SetRates(
 | 
| -        kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] - 1, 30);
 | 
| +    SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] - 1, 30);
 | 
|      std::vector<FrameType> frame_types(kNumberOfSimulcastStreams,
 | 
|                                         kVideoFrameDelta);
 | 
|      ExpectStreams(kVideoFrameKey, 2);
 | 
| @@ -499,8 +436,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|  
 | 
|    void TestSendAllStreams() {
 | 
|      // We have just enough to send all streams.
 | 
| -    encoder_->SetRates(
 | 
| -        kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2], 30);
 | 
| +    SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2], 30);
 | 
|      std::vector<FrameType> frame_types(kNumberOfSimulcastStreams,
 | 
|                                         kVideoFrameDelta);
 | 
|      ExpectStreams(kVideoFrameKey, 3);
 | 
| @@ -513,7 +449,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|  
 | 
|    void TestDisablingStreams() {
 | 
|      // We should get three media streams.
 | 
| -    encoder_->SetRates(kMaxBitrates[0] + kMaxBitrates[1] + kMaxBitrates[2], 30);
 | 
| +    SetRates(kMaxBitrates[0] + kMaxBitrates[1] + kMaxBitrates[2], 30);
 | 
|      std::vector<FrameType> frame_types(kNumberOfSimulcastStreams,
 | 
|                                         kVideoFrameDelta);
 | 
|      ExpectStreams(kVideoFrameKey, 3);
 | 
| @@ -524,36 +460,33 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|      EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types));
 | 
|  
 | 
|      // We should only get two streams and padding for one.
 | 
| -    encoder_->SetRates(
 | 
| -        kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30);
 | 
| +    SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30);
 | 
|      ExpectStreams(kVideoFrameDelta, 2);
 | 
|      input_frame_->set_timestamp(input_frame_->timestamp() + 3000);
 | 
|      EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types));
 | 
|  
 | 
|      // We should only get the first stream and padding for two.
 | 
| -    encoder_->SetRates(kTargetBitrates[0] + kMinBitrates[1] / 2, 30);
 | 
| +    SetRates(kTargetBitrates[0] + kMinBitrates[1] / 2, 30);
 | 
|      ExpectStreams(kVideoFrameDelta, 1);
 | 
|      input_frame_->set_timestamp(input_frame_->timestamp() + 3000);
 | 
|      EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types));
 | 
|  
 | 
|      // We don't have enough bitrate for the thumbnail stream, but we should get
 | 
|      // it anyway with current configuration.
 | 
| -    encoder_->SetRates(kTargetBitrates[0] - 1, 30);
 | 
| +    SetRates(kTargetBitrates[0] - 1, 30);
 | 
|      ExpectStreams(kVideoFrameDelta, 1);
 | 
|      input_frame_->set_timestamp(input_frame_->timestamp() + 3000);
 | 
|      EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types));
 | 
|  
 | 
|      // We should only get two streams and padding for one.
 | 
| -    encoder_->SetRates(
 | 
| -        kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30);
 | 
| +    SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30);
 | 
|      // We get a key frame because a new stream is being enabled.
 | 
|      ExpectStreams(kVideoFrameKey, 2);
 | 
|      input_frame_->set_timestamp(input_frame_->timestamp() + 3000);
 | 
|      EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types));
 | 
|  
 | 
|      // We should get all three streams.
 | 
| -    encoder_->SetRates(
 | 
| -        kTargetBitrates[0] + kTargetBitrates[1] + kTargetBitrates[2], 30);
 | 
| +    SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kTargetBitrates[2], 30);
 | 
|      // We get a key frame because a new stream is being enabled.
 | 
|      ExpectStreams(kVideoFrameKey, 3);
 | 
|      input_frame_->set_timestamp(input_frame_->timestamp() + 3000);
 | 
| @@ -590,10 +523,11 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|          settings_.width;
 | 
|      settings_.simulcastStream[settings_.numberOfSimulcastStreams - 1].height =
 | 
|          settings_.height;
 | 
| +    SetUpRateAllocator();
 | 
|      EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200));
 | 
|  
 | 
|      // Encode one frame and verify.
 | 
| -    encoder_->SetRates(kMaxBitrates[0] + kMaxBitrates[1], 30);
 | 
| +    SetRates(kMaxBitrates[0] + kMaxBitrates[1], 30);
 | 
|      std::vector<FrameType> frame_types(kNumberOfSimulcastStreams,
 | 
|                                         kVideoFrameDelta);
 | 
|      EXPECT_CALL(
 | 
| @@ -611,8 +545,9 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|      DefaultSettings(&settings_, kDefaultTemporalLayerProfile);
 | 
|      // Start at the lowest bitrate for enabling base stream.
 | 
|      settings_.startBitrate = kMinBitrates[0];
 | 
| +    SetUpRateAllocator();
 | 
|      EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200));
 | 
| -    encoder_->SetRates(settings_.startBitrate, 30);
 | 
| +    SetRates(settings_.startBitrate, 30);
 | 
|      ExpectStreams(kVideoFrameKey, 1);
 | 
|      // Resize |input_frame_| to the new resolution.
 | 
|      half_width = (settings_.width + 1) / 2;
 | 
| @@ -634,7 +569,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|      Vp8TestEncodedImageCallback encoder_callback;
 | 
|      encoder_->RegisterEncodeCompleteCallback(&encoder_callback);
 | 
|  
 | 
| -    encoder_->SetRates(kMaxBitrates[2], 30);  // To get all three streams.
 | 
| +    SetRates(kMaxBitrates[2], 30);  // To get all three streams.
 | 
|  
 | 
|      EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL));
 | 
|      int picture_id = -1;
 | 
| @@ -703,7 +638,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|      encoder_->RegisterEncodeCompleteCallback(&encoder_callback);
 | 
|      decoder_->RegisterDecodeCompleteCallback(&decoder_callback);
 | 
|  
 | 
| -    encoder_->SetRates(kMaxBitrates[2], 30);  // To get all three streams.
 | 
| +    SetRates(kMaxBitrates[2], 30);  // To get all three streams.
 | 
|  
 | 
|      // Set color.
 | 
|      int plane_offset[kNumOfPlanes];
 | 
| @@ -777,7 +712,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|    void TestSaptioTemporalLayers333PatternEncoder() {
 | 
|      Vp8TestEncodedImageCallback encoder_callback;
 | 
|      encoder_->RegisterEncodeCompleteCallback(&encoder_callback);
 | 
| -    encoder_->SetRates(kMaxBitrates[2], 30);  // To get all three streams.
 | 
| +    SetRates(kMaxBitrates[2], 30);  // To get all three streams.
 | 
|  
 | 
|      int expected_temporal_idx[3] = {-1, -1, -1};
 | 
|      bool expected_layer_sync[3] = {false, false, false};
 | 
| @@ -846,7 +781,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|      SetUpCodec(temporal_layer_profile);
 | 
|      Vp8TestEncodedImageCallback encoder_callback;
 | 
|      encoder_->RegisterEncodeCompleteCallback(&encoder_callback);
 | 
| -    encoder_->SetRates(kMaxBitrates[2], 30);  // To get all three streams.
 | 
| +    SetRates(kMaxBitrates[2], 30);  // To get all three streams.
 | 
|  
 | 
|      int expected_temporal_idx[3] = {-1, -1, -1};
 | 
|      bool expected_layer_sync[3] = {false, false, false};
 | 
| @@ -905,7 +840,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|      encoder_->RegisterEncodeCompleteCallback(&encoder_callback);
 | 
|      decoder_->RegisterDecodeCompleteCallback(&decoder_callback);
 | 
|  
 | 
| -    encoder_->SetRates(kMaxBitrates[2], 30);  // To get all three streams.
 | 
| +    SetRates(kMaxBitrates[2], 30);  // To get all three streams.
 | 
|      // Setting two (possibly) problematic use cases for stride:
 | 
|      // 1. stride > width 2. stride_y != stride_uv/2
 | 
|      int stride_y = kDefaultWidth + 20;
 | 
| @@ -941,30 +876,6 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|      EXPECT_EQ(2, decoder_callback.DecodedFrames());
 | 
|    }
 | 
|  
 | 
| -  void TestSkipEncodingUnusedStreams() {
 | 
| -    SkipEncodingUnusedStreamsTest test;
 | 
| -    std::vector<unsigned int> configured_bitrate =
 | 
| -        test.RunTest(encoder_.get(), &settings_,
 | 
| -                     1);  // Target bit rate 1, to force all streams but the
 | 
| -                          // base one to be exceeding bandwidth constraints.
 | 
| -    EXPECT_EQ(static_cast<size_t>(kNumberOfSimulcastStreams),
 | 
| -              configured_bitrate.size());
 | 
| -
 | 
| -    unsigned int min_bitrate =
 | 
| -        std::max(settings_.simulcastStream[0].minBitrate, settings_.minBitrate);
 | 
| -    int stream = 0;
 | 
| -    for (std::vector<unsigned int>::const_iterator it =
 | 
| -             configured_bitrate.begin();
 | 
| -         it != configured_bitrate.end(); ++it) {
 | 
| -      if (stream == 0) {
 | 
| -        EXPECT_EQ(min_bitrate, *it);
 | 
| -      } else {
 | 
| -        EXPECT_EQ(0u, *it);
 | 
| -      }
 | 
| -      ++stream;
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
|    std::unique_ptr<VP8Encoder> encoder_;
 | 
|    MockEncodedImageCallback encoder_callback_;
 | 
|    std::unique_ptr<VP8Decoder> decoder_;
 | 
| @@ -972,6 +883,7 @@ class TestVp8Simulcast : public ::testing::Test {
 | 
|    VideoCodec settings_;
 | 
|    rtc::scoped_refptr<I420Buffer> input_buffer_;
 | 
|    std::unique_ptr<VideoFrame> input_frame_;
 | 
| +  std::unique_ptr<SimulcastRateAllocator> rate_allocator_;
 | 
|  };
 | 
|  
 | 
|  }  // namespace testing
 | 
| 
 |