Remove layer_sync from TL frame config.

This is instead derived from pattern_idx inside the frame config.

This also removes active_layer_ use from
ScreenshareLayers::PopulateCodecSpecific and instead ties the layer to
TemporalLayers::FrameConfig.

BUG=chromium:702017, webrtc:7349
R=sprang@webrtc.org

Review-Url: https://codereview.webrtc.org/2860063002
Cr-Commit-Position: refs/heads/master@{#18017}
This commit is contained in:
pbos
2017-05-04 06:39:04 -07:00
committed by Commit bot
parent 99ef6b7854
commit 51f083ccb2
5 changed files with 85 additions and 54 deletions

View File

@ -30,22 +30,17 @@ TemporalLayers::FrameConfig::FrameConfig() {}
TemporalLayers::FrameConfig::FrameConfig(TemporalLayers::BufferFlags last,
TemporalLayers::BufferFlags golden,
TemporalLayers::BufferFlags arf)
: FrameConfig(last, golden, arf, false, false) {}
: FrameConfig(last, golden, arf, false) {}
TemporalLayers::FrameConfig::FrameConfig(TemporalLayers::BufferFlags last,
TemporalLayers::BufferFlags golden,
TemporalLayers::BufferFlags arf,
int extra_flags)
: FrameConfig(last,
golden,
arf,
(extra_flags & kLayerSync) != 0,
(extra_flags & kFreezeEntropy) != 0) {}
FreezeEntropy)
: FrameConfig(last, golden, arf, true) {}
TemporalLayers::FrameConfig::FrameConfig(TemporalLayers::BufferFlags last,
TemporalLayers::BufferFlags golden,
TemporalLayers::BufferFlags arf,
bool layer_sync,
bool freeze_entropy)
: drop_frame(last == TemporalLayers::kNone &&
golden == TemporalLayers::kNone &&
@ -53,7 +48,6 @@ TemporalLayers::FrameConfig::FrameConfig(TemporalLayers::BufferFlags last,
last_buffer_flags(last),
golden_buffer_flags(golden),
arf_buffer_flags(arf),
layer_sync(layer_sync),
freeze_entropy(freeze_entropy) {}
namespace {
@ -90,6 +84,25 @@ std::vector<unsigned int> GetTemporalIds(size_t num_layers) {
return {0};
}
std::vector<bool> GetTemporalLayerSync(size_t num_layers) {
switch (num_layers) {
case 1:
return {false};
case 2:
return {false, true, false, false, false, false, false, false};
case 3:
return {false, true, true, false, false, false, false, false};
case 4:
return {false, true, true, true, true, true, false, true,
false, true, false, true, false, true, false, true};
default:
RTC_NOTREACHED();
break;
}
RTC_NOTREACHED();
return {false};
}
std::vector<TemporalLayers::FrameConfig> GetTemporalPattern(size_t num_layers) {
// For indexing in the patterns described below (which temporal layers they
// belong to), see the diagram above.
@ -118,9 +131,9 @@ std::vector<TemporalLayers::FrameConfig> GetTemporalPattern(size_t num_layers) {
return {TemporalLayers::FrameConfig(TemporalLayers::kReferenceAndUpdate,
TemporalLayers::kUpdate,
TemporalLayers::kReference),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kUpdate,
TemporalLayers::kReference, kLayerSync),
TemporalLayers::FrameConfig(TemporalLayers::kReference,
TemporalLayers::kUpdate,
TemporalLayers::kReference),
TemporalLayers::FrameConfig(TemporalLayers::kReferenceAndUpdate,
TemporalLayers::kNone,
TemporalLayers::kReference),
@ -138,7 +151,7 @@ std::vector<TemporalLayers::FrameConfig> GetTemporalPattern(size_t num_layers) {
TemporalLayers::kReference),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kReference,
TemporalLayers::kReference, kFreezeEntropy)};
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy)};
case 3:
// All layers can reference but not update the 'alt' buffer, this means
// that the 'alt' buffer reference is effectively the last keyframe.
@ -150,25 +163,25 @@ std::vector<TemporalLayers::FrameConfig> GetTemporalPattern(size_t num_layers) {
TemporalLayers::kReference),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kNone,
TemporalLayers::kReference, kLayerSync | kFreezeEntropy),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kUpdate,
TemporalLayers::kReference, kLayerSync),
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy),
TemporalLayers::FrameConfig(TemporalLayers::kReference,
TemporalLayers::kUpdate,
TemporalLayers::kReference),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kReference,
TemporalLayers::kReference, kFreezeEntropy),
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy),
TemporalLayers::FrameConfig(TemporalLayers::kReferenceAndUpdate,
TemporalLayers::kNone,
TemporalLayers::kReference),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kReference,
TemporalLayers::kReference, kFreezeEntropy),
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy),
TemporalLayers::FrameConfig(TemporalLayers::kReference,
TemporalLayers::kReferenceAndUpdate,
TemporalLayers::kReference),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kReference,
TemporalLayers::kReference, kFreezeEntropy)};
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy)};
case 4:
// TL0 references and updates only the 'last' buffer.
// TL1 references 'last' and updates and references 'golden'.
@ -179,49 +192,49 @@ std::vector<TemporalLayers::FrameConfig> GetTemporalPattern(size_t num_layers) {
TemporalLayers::kNone),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kReference,
TemporalLayers::kReference, kLayerSync | kFreezeEntropy),
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy),
TemporalLayers::FrameConfig(TemporalLayers::kReference,
TemporalLayers::kNone,
TemporalLayers::kUpdate, kLayerSync),
TemporalLayers::kUpdate),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kReference,
TemporalLayers::kReference, kLayerSync | kFreezeEntropy),
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy),
TemporalLayers::FrameConfig(TemporalLayers::kReference,
TemporalLayers::kUpdate,
TemporalLayers::kNone, kLayerSync),
TemporalLayers::kNone),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kReference,
TemporalLayers::kReference, kLayerSync | kFreezeEntropy),
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy),
TemporalLayers::FrameConfig(TemporalLayers::kReference,
TemporalLayers::kReference,
TemporalLayers::kReferenceAndUpdate),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kReference,
TemporalLayers::kReference, kLayerSync | kFreezeEntropy),
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy),
TemporalLayers::FrameConfig(TemporalLayers::kReferenceAndUpdate,
TemporalLayers::kNone,
TemporalLayers::kNone),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kReference,
TemporalLayers::kReference, kLayerSync | kFreezeEntropy),
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy),
TemporalLayers::FrameConfig(TemporalLayers::kReference,
TemporalLayers::kReference,
TemporalLayers::kReferenceAndUpdate),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kReference,
TemporalLayers::kReference, kLayerSync | kFreezeEntropy),
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy),
TemporalLayers::FrameConfig(TemporalLayers::kReference,
TemporalLayers::kReferenceAndUpdate,
TemporalLayers::kNone),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kReference,
TemporalLayers::kReference, kLayerSync | kFreezeEntropy),
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy),
TemporalLayers::FrameConfig(TemporalLayers::kReference,
TemporalLayers::kReference,
TemporalLayers::kReferenceAndUpdate),
TemporalLayers::FrameConfig(
TemporalLayers::kReference, TemporalLayers::kReference,
TemporalLayers::kReference, kLayerSync | kFreezeEntropy)};
TemporalLayers::kReference, TemporalLayers::kFreezeEntropy)};
default:
RTC_NOTREACHED();
break;
@ -237,11 +250,13 @@ DefaultTemporalLayers::DefaultTemporalLayers(int number_of_temporal_layers,
uint8_t initial_tl0_pic_idx)
: num_layers_(std::max(1, number_of_temporal_layers)),
temporal_ids_(GetTemporalIds(num_layers_)),
temporal_layer_sync_(GetTemporalLayerSync(num_layers_)),
temporal_pattern_(GetTemporalPattern(num_layers_)),
tl0_pic_idx_(initial_tl0_pic_idx),
pattern_idx_(255),
timestamp_(0),
last_base_layer_sync_(false) {
RTC_DCHECK_EQ(temporal_pattern_.size(), temporal_layer_sync_.size());
RTC_CHECK_GE(kMaxTemporalStreams, number_of_temporal_layers);
RTC_CHECK_GE(number_of_temporal_layers, 0);
RTC_CHECK_LE(number_of_temporal_layers, 4);
@ -339,7 +354,8 @@ void DefaultTemporalLayers::PopulateCodecSpecific(
} else {
vp8_info->temporalIdx = GetTemporalLayerId(tl_config);
vp8_info->layerSync = tl_config.layer_sync;
vp8_info->layerSync = temporal_layer_sync_[tl_config.pattern_idx %
temporal_layer_sync_.size()];
}
if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
// Regardless of pattern the frame after a base layer sync will always

View File

@ -53,6 +53,7 @@ class DefaultTemporalLayers : public TemporalLayers {
private:
const size_t num_layers_;
const std::vector<unsigned int> temporal_ids_;
const std::vector<bool> temporal_layer_sync_;
const std::vector<TemporalLayers::FrameConfig> temporal_pattern_;
uint8_t tl0_pic_idx_;

View File

@ -93,8 +93,10 @@ TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig(
if (number_of_temporal_layers_ <= 1) {
// No flags needed for 1 layer screenshare.
// TODO(pbos): Consider updating only last, and not all buffers.
return TemporalLayers::FrameConfig(kReferenceAndUpdate, kReferenceAndUpdate,
kReferenceAndUpdate);
TemporalLayers::FrameConfig tl_config(
kReferenceAndUpdate, kReferenceAndUpdate, kReferenceAndUpdate);
tl_config.pattern_idx = static_cast<int>(kTl1);
return tl_config;
}
const int64_t now_ms = clock_->TimeInMilliseconds();
@ -108,8 +110,7 @@ TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig(
stats_.first_frame_time_ms_ = now_ms;
int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
enum TemporalLayerState { kDrop, kTl0, kTl1, kTl1Sync };
enum TemporalLayerState layer_state = kDrop;
TemporalLayerState layer_state = kDrop;
if (active_layer_ == -1 ||
layers_[active_layer_].state != TemporalLayer::State::kDropped) {
if (last_emitted_tl0_timestamp_ != -1 &&
@ -163,27 +164,33 @@ TemporalLayers::FrameConfig ScreenshareLayers::UpdateLayerConfig(
layers_[0].UpdateDebt(ts_diff / 90);
layers_[1].UpdateDebt(ts_diff / 90);
last_timestamp_ = timestamp;
TemporalLayers::FrameConfig tl_config;
// TODO(pbos): Consider referencing but not updating the 'alt' buffer for all
// layers.
switch (layer_state) {
case kDrop:
return TemporalLayers::FrameConfig(kNone, kNone, kNone);
tl_config = TemporalLayers::FrameConfig(kNone, kNone, kNone);
break;
case kTl0:
// TL0 only references and updates 'last'.
return TemporalLayers::FrameConfig(kReferenceAndUpdate, kNone, kNone);
tl_config =
TemporalLayers::FrameConfig(kReferenceAndUpdate, kNone, kNone);
break;
case kTl1:
// TL1 references both 'last' and 'golden' but only updates 'golden'.
return TemporalLayers::FrameConfig(kReference, kReferenceAndUpdate,
kNone);
tl_config =
TemporalLayers::FrameConfig(kReference, kReferenceAndUpdate, kNone);
break;
case kTl1Sync:
// Predict from only TL0 to allow participants to switch to the high
// bitrate stream. Updates 'golden' so that TL1 can continue to refer to
// and update 'golden' from this point on.
return TemporalLayers::FrameConfig(kReference, kUpdate, kNone,
kLayerSync);
tl_config = TemporalLayers::FrameConfig(kReference, kUpdate, kNone);
break;
}
RTC_NOTREACHED();
return TemporalLayers::FrameConfig(kNone, kNone, kNone);
tl_config.pattern_idx = static_cast<int>(layer_state);
return tl_config;
}
std::vector<uint32_t> ScreenshareLayers::OnRatesUpdated(int bitrate_kbps,
@ -265,10 +272,20 @@ void ScreenshareLayers::PopulateCodecSpecific(
vp8_info->layerSync = false;
vp8_info->tl0PicIdx = kNoTl0PicIdx;
} else {
// TODO(pbos): Add active_layer_ to TemporalLayers::FrameConfig (as
// pattern_idx) and make function const.
RTC_DCHECK_NE(-1, active_layer_);
vp8_info->temporalIdx = active_layer_;
TemporalLayerState layer_state =
static_cast<TemporalLayerState>(tl_config.pattern_idx);
switch (layer_state) {
case kDrop:
RTC_NOTREACHED();
break;
case kTl0:
vp8_info->temporalIdx = 0;
break;
case kTl1:
case kTl1Sync:
vp8_info->temporalIdx = 1;
break;
}
if (frame_is_keyframe) {
vp8_info->temporalIdx = 0;
last_sync_timestamp_ = unwrapped_timestamp;

View File

@ -60,6 +60,8 @@ class ScreenshareLayers : public TemporalLayers {
uint8_t Tl0PicIdx() const override;
private:
enum TemporalLayerState { kDrop, kTl0, kTl1, kTl1Sync };
bool TimeToSync(int64_t timestamp) const;
uint32_t GetCodecTargetBitrateKbps() const;

View File

@ -24,11 +24,6 @@ namespace webrtc {
struct CodecSpecificInfoVP8;
// TODO(pbos): Remove along with layer_sync and freeze_entropy, they are
// derivable from picture_idx and should be exposed with
// TL::IsLayerSync(TL::FrameConfig).
enum TemporalFlags { kLayerSync = 1, kFreezeEntropy = 2 };
class TemporalLayers {
public:
enum BufferFlags {
@ -37,6 +32,7 @@ class TemporalLayers {
kUpdate = 2,
kReferenceAndUpdate = kReference | kUpdate,
};
enum FreezeEntropy { kFreezeEntropy };
struct FrameConfig {
FrameConfig();
@ -45,7 +41,7 @@ class TemporalLayers {
FrameConfig(BufferFlags last,
BufferFlags golden,
BufferFlags arf,
int extra_flags);
FreezeEntropy);
bool drop_frame;
BufferFlags last_buffer_flags;
@ -64,7 +60,6 @@ class TemporalLayers {
FrameConfig(BufferFlags last,
BufferFlags golden,
BufferFlags arf,
bool layer_sync,
bool freeze_entropy);
};