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 |