Chromium Code Reviews| 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..f9319d9ab9fe52521938183d3a32f598f3b0e830 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" |
| @@ -31,7 +35,8 @@ DefaultTemporalLayers::DefaultTemporalLayers(int numberOfTemporalLayers, |
| pattern_idx_(255), |
| timestamp_(0), |
| last_base_layer_sync_(false) { |
| - assert(kMaxTemporalStreams >= numberOfTemporalLayers); |
| + RTC_CHECK_GE(kMaxTemporalStreams, numberOfTemporalLayers); |
| + RTC_CHECK_GE(numberOfTemporalLayers, 0); |
| memset(temporal_ids_, 0, sizeof(temporal_ids_)); |
| memset(temporal_pattern_, 0, sizeof(temporal_pattern_)); |
| } |
| @@ -43,18 +48,49 @@ 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 bitrateKbit, |
|
stefan-webrtc
2016/11/02 10:26:35
Here too please :) Perhaps also change to kbps ins
sprang_webrtc
2016/11/02 13:28:32
Done.
|
| + int max_bitrate_kbit, |
| + 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 = |
| + bitrateKbit * 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; |
|
stefan-webrtc
2016/11/02 10:26:35
DCHECK that bitrates[i] > 0 after the subtraction,
sprang_webrtc
2016/11/02 13:28:32
Done.
|
| + sum = layer_bitrate; |
| + |
| + if (sum >= static_cast<uint32_t>(bitrateKbit)) { |
| + // 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]; |
|
stefan-webrtc
2016/11/02 10:26:35
Should we call this current_allocation_kbps_ or cu
sprang_webrtc
2016/11/02 13:28:32
They are new bitrates though, as the encoder has n
|
| cfg->ts_rate_decimator[0] = 1; |
| memcpy(cfg->ts_layer_id, temporal_ids_, |
| sizeof(unsigned int) * temporal_ids_length_); |
| @@ -69,8 +105,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 +131,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 +163,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 +192,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>>(); |
|
stefan-webrtc
2016/11/02 10:26:35
Why is this needed?
sprang_webrtc
2016/11/02 13:28:32
To not have to redo all this work for every frame.
stefan-webrtc
2016/11/03 13:34:58
Acknowledged.
|
| + |
| return true; |
| } |
| @@ -284,8 +323,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 |