Revert "Enables/disables simulcast streams by allocating a bitrate of 0 to the spatial layer."

This reverts commit 18c4261339dc76b220e7c805e36b4ea6f3dd161d.

Reason for revert: Broke internal tests

Original change's description:
> Enables/disables simulcast streams by allocating a bitrate of 0 to the spatial layer.
> 
> Creates VideoStreams & VideoCodec.simulcastStreams with an active field, and then allocates 0 bitrate to simulcast streams that are inactive. This turns off the encoder for specific simulcast streams.
> 
> Bug: webrtc:8653
> Change-Id: Id93b03dcd8d1191a7d3300bd77882c8af96ee469
> Reviewed-on: https://webrtc-review.googlesource.com/37740
> Reviewed-by: Stefan Holmer <stefan@webrtc.org>
> Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
> Reviewed-by: Erik Språng <sprang@webrtc.org>
> Commit-Queue: Seth Hampson <shampson@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#21646}

TBR=deadbeef@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,shampson@webrtc.org

Change-Id: I0aeb743cbd2e8d564aa732c937587c25a4c49b09
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:8653
Reviewed-on: https://webrtc-review.googlesource.com/39883
Reviewed-by: Lu Liu <lliuu@webrtc.org>
Commit-Queue: Lu Liu <lliuu@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21647}
This commit is contained in:
Lu Liu
2018-01-17 00:28:14 +00:00
committed by Commit Bot
parent 18c4261339
commit 0f17f9ce28
18 changed files with 76 additions and 516 deletions

View File

@ -37,92 +37,56 @@ void SimulcastRateAllocator::OnTemporalLayersCreated(int simulcast_id,
BitrateAllocation SimulcastRateAllocator::GetAllocation(
uint32_t total_bitrate_bps,
uint32_t framerate) {
BitrateAllocation allocated_bitrates_bps;
DistributeAllocationToSimulcastLayers(total_bitrate_bps,
&allocated_bitrates_bps);
DistributeAllocationToTemporalLayers(framerate, &allocated_bitrates_bps);
return allocated_bitrates_bps;
}
void SimulcastRateAllocator::DistributeAllocationToSimulcastLayers(
uint32_t total_bitrate_bps,
BitrateAllocation* allocated_bitrates_bps) {
uint32_t left_to_allocate = total_bitrate_bps;
if (codec_.maxBitrate && codec_.maxBitrate * 1000 < left_to_allocate)
left_to_allocate = codec_.maxBitrate * 1000;
BitrateAllocation allocated_bitrates_bps;
if (codec_.numberOfSimulcastStreams == 0) {
// No simulcast, just set the target as this has been capped already.
if (codec_.active) {
allocated_bitrates_bps->SetBitrate(
0, 0, std::max(codec_.minBitrate * 1000, left_to_allocate));
allocated_bitrates_bps.SetBitrate(
0, 0, std::max(codec_.minBitrate * 1000, left_to_allocate));
} else {
// Always allocate enough bitrate for the minimum bitrate of the first
// layer. Suspending below min bitrate is controlled outside the codec
// implementation and is not overridden by this.
left_to_allocate =
std::max(codec_.simulcastStream[0].minBitrate * 1000, left_to_allocate);
// Begin by allocating bitrate to simulcast streams, putting all bitrate in
// temporal layer 0. We'll then distribute this bitrate, across potential
// temporal layers, when stream allocation is done.
// Allocate up to the target bitrate for each simulcast layer.
size_t layer = 0;
for (; layer < codec_.numberOfSimulcastStreams; ++layer) {
const SimulcastStream& stream = codec_.simulcastStream[layer];
if (left_to_allocate < stream.minBitrate * 1000)
break;
uint32_t allocation =
std::min(left_to_allocate, stream.targetBitrate * 1000);
allocated_bitrates_bps.SetBitrate(layer, 0, allocation);
RTC_DCHECK_LE(allocation, left_to_allocate);
left_to_allocate -= allocation;
}
return;
}
// Find the first active layer. We don't allocate to inactive layers.
size_t active_layer = 0;
for (; active_layer < codec_.numberOfSimulcastStreams; ++active_layer) {
if (codec_.simulcastStream[active_layer].active) {
// Found the first active layer.
break;
// Next, try allocate remaining bitrate, up to max bitrate, in top stream.
// TODO(sprang): Allocate up to max bitrate for all layers once we have a
// better idea of possible performance implications.
if (left_to_allocate > 0) {
size_t active_layer = layer - 1;
const SimulcastStream& stream = codec_.simulcastStream[active_layer];
uint32_t bitrate_bps =
allocated_bitrates_bps.GetSpatialLayerSum(active_layer);
uint32_t allocation =
std::min(left_to_allocate, stream.maxBitrate * 1000 - bitrate_bps);
bitrate_bps += allocation;
RTC_DCHECK_LE(allocation, left_to_allocate);
left_to_allocate -= allocation;
allocated_bitrates_bps.SetBitrate(active_layer, 0, bitrate_bps);
}
}
// All streams could be inactive, and nothing more to do.
if (active_layer == codec_.numberOfSimulcastStreams) {
return;
}
// Always allocate enough bitrate for the minimum bitrate of the first
// active layer. Suspending below min bitrate is controlled outside the
// codec implementation and is not overridden by this.
left_to_allocate = std::max(
codec_.simulcastStream[active_layer].minBitrate * 1000, left_to_allocate);
// Begin by allocating bitrate to simulcast streams, putting all bitrate in
// temporal layer 0. We'll then distribute this bitrate, across potential
// temporal layers, when stream allocation is done.
size_t top_active_layer = active_layer;
// Allocate up to the target bitrate for each active simulcast layer.
for (; active_layer < codec_.numberOfSimulcastStreams; ++active_layer) {
const SimulcastStream& stream = codec_.simulcastStream[active_layer];
if (!stream.active) {
continue;
}
// If we can't allocate to the current layer we can't allocate to higher
// layers because they require a higher minimum bitrate.
if (left_to_allocate < stream.minBitrate * 1000) {
break;
}
// We are allocating to this layer so it is the current active allocation.
top_active_layer = active_layer;
uint32_t allocation =
std::min(left_to_allocate, stream.targetBitrate * 1000);
allocated_bitrates_bps->SetBitrate(active_layer, 0, allocation);
RTC_DCHECK_LE(allocation, left_to_allocate);
left_to_allocate -= allocation;
}
// Next, try allocate remaining bitrate, up to max bitrate, in top active
// stream.
// TODO(sprang): Allocate up to max bitrate for all layers once we have a
// better idea of possible performance implications.
if (left_to_allocate > 0) {
const SimulcastStream& stream = codec_.simulcastStream[top_active_layer];
uint32_t bitrate_bps =
allocated_bitrates_bps->GetSpatialLayerSum(top_active_layer);
uint32_t allocation =
std::min(left_to_allocate, stream.maxBitrate * 1000 - bitrate_bps);
bitrate_bps += allocation;
RTC_DCHECK_LE(allocation, left_to_allocate);
left_to_allocate -= allocation;
allocated_bitrates_bps->SetBitrate(top_active_layer, 0, bitrate_bps);
}
}
void SimulcastRateAllocator::DistributeAllocationToTemporalLayers(
uint32_t framerate,
BitrateAllocation* allocated_bitrates_bps) {
const int num_spatial_streams =
std::max(1, static_cast<int>(codec_.numberOfSimulcastStreams));
@ -130,21 +94,16 @@ void SimulcastRateAllocator::DistributeAllocationToTemporalLayers(
// available temporal layers.
for (int simulcast_id = 0; simulcast_id < num_spatial_streams;
++simulcast_id) {
// TODO(shampson): Consider adding a continue here if the simulcast stream
// is inactive. Currently this is not added because the call
// below to OnRatesUpdated changes the TemporalLayer's
// state.
auto tl_it = temporal_layers_.find(simulcast_id);
if (tl_it == temporal_layers_.end())
continue; // TODO(sprang): If > 1 SS, assume default TL alloc?
uint32_t target_bitrate_kbps =
allocated_bitrates_bps->GetBitrate(simulcast_id, 0) / 1000;
allocated_bitrates_bps.GetBitrate(simulcast_id, 0) / 1000;
const uint32_t expected_allocated_bitrate_kbps = target_bitrate_kbps;
RTC_DCHECK_EQ(
target_bitrate_kbps,
allocated_bitrates_bps->GetSpatialLayerSum(simulcast_id) / 1000);
allocated_bitrates_bps.GetSpatialLayerSum(simulcast_id) / 1000);
const int num_temporal_streams = std::max<uint8_t>(
1, codec_.numberOfSimulcastStreams == 0
? codec_.VP8().numberOfTemporalLayers
@ -178,14 +137,14 @@ void SimulcastRateAllocator::DistributeAllocationToTemporalLayers(
uint64_t tl_allocation_sum_kbps = 0;
for (size_t tl_index = 0; tl_index < tl_allocation.size(); ++tl_index) {
uint32_t layer_rate_kbps = tl_allocation[tl_index];
if (layer_rate_kbps > 0) {
allocated_bitrates_bps->SetBitrate(simulcast_id, tl_index,
layer_rate_kbps * 1000);
}
allocated_bitrates_bps.SetBitrate(simulcast_id, tl_index,
layer_rate_kbps * 1000);
tl_allocation_sum_kbps += layer_rate_kbps;
}
RTC_DCHECK_LE(tl_allocation_sum_kbps, expected_allocated_bitrate_kbps);
}
return allocated_bitrates_bps;
}
uint32_t SimulcastRateAllocator::GetPreferredBitrateBps(uint32_t framerate) {

View File

@ -39,12 +39,6 @@ class SimulcastRateAllocator : public VideoBitrateAllocator,
const VideoCodec& GetCodec() const;
private:
void DistributeAllocationToSimulcastLayers(
uint32_t total_bitrate_bps,
BitrateAllocation* allocated_bitrates_bps);
void DistributeAllocationToTemporalLayers(
uint32_t framerate,
BitrateAllocation* allocated_bitrates_bps);
const VideoCodec codec_;
std::map<uint32_t, TemporalLayers*> temporal_layers_;
std::unique_ptr<TemporalLayersFactory> tl_factory_;

View File

@ -203,7 +203,6 @@ class TestVp8Simulcast : public ::testing::Test {
settings->width = kDefaultWidth;
settings->height = kDefaultHeight;
settings->numberOfSimulcastStreams = kNumberOfSimulcastStreams;
settings->active = true;
ASSERT_EQ(3, kNumberOfSimulcastStreams);
settings->timing_frame_thresholds = {kDefaultTimingFramesDelayMs,
kDefaultOutlierFrameSizePercent};
@ -239,7 +238,6 @@ class TestVp8Simulcast : public ::testing::Test {
stream->targetBitrate = target_bitrate;
stream->numberOfTemporalLayers = num_temporal_layers;
stream->qpMax = 45;
stream->active = true;
}
protected:
@ -284,22 +282,10 @@ class TestVp8Simulcast : public ::testing::Test {
rate_allocator_->GetAllocation(bitrate_kbps * 1000, fps), fps);
}
void UpdateActiveStreams(const std::vector<bool> active_streams) {
ASSERT_EQ(static_cast<int>(active_streams.size()),
kNumberOfSimulcastStreams);
for (size_t i = 0; i < active_streams.size(); ++i) {
settings_.simulcastStream[i].active = active_streams[i];
}
// Re initialize the allocator and encoder with the new settings.
SetUpRateAllocator();
EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200));
}
void ExpectStreams(FrameType frame_type,
const std::vector<bool> expected_streams_active) {
ASSERT_EQ(static_cast<int>(expected_streams_active.size()),
kNumberOfSimulcastStreams);
if (expected_streams_active[0]) {
void ExpectStreams(FrameType frame_type, int expected_video_streams) {
ASSERT_GE(expected_video_streams, 0);
ASSERT_LE(expected_video_streams, kNumberOfSimulcastStreams);
if (expected_video_streams >= 1) {
EXPECT_CALL(
encoder_callback_,
OnEncodedImage(
@ -311,7 +297,7 @@ class TestVp8Simulcast : public ::testing::Test {
.WillRepeatedly(Return(EncodedImageCallback::Result(
EncodedImageCallback::Result::OK, 0)));
}
if (expected_streams_active[1]) {
if (expected_video_streams >= 2) {
EXPECT_CALL(
encoder_callback_,
OnEncodedImage(
@ -323,7 +309,7 @@ class TestVp8Simulcast : public ::testing::Test {
.WillRepeatedly(Return(EncodedImageCallback::Result(
EncodedImageCallback::Result::OK, 0)));
}
if (expected_streams_active[2]) {
if (expected_video_streams >= 3) {
EXPECT_CALL(
encoder_callback_,
OnEncodedImage(
@ -337,16 +323,6 @@ class TestVp8Simulcast : public ::testing::Test {
}
}
void ExpectStreams(FrameType frame_type, int expected_video_streams) {
ASSERT_GE(expected_video_streams, 0);
ASSERT_LE(expected_video_streams, kNumberOfSimulcastStreams);
std::vector<bool> expected_streams_active(kNumberOfSimulcastStreams, false);
for (int i = 0; i < expected_video_streams; ++i) {
expected_streams_active[i] = true;
}
ExpectStreams(frame_type, expected_streams_active);
}
void VerifyTemporalIdxAndSyncForAllSpatialLayers(
Vp8TestEncodedImageCallback* encoder_callback,
const int* expected_temporal_idx,
@ -525,43 +501,6 @@ class TestVp8Simulcast : public ::testing::Test {
EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types));
}
void TestActiveStreams() {
const int kEnoughBitrateAllStreams =
kMaxBitrates[0] + kMaxBitrates[1] + kMaxBitrates[2];
std::vector<FrameType> frame_types(kNumberOfSimulcastStreams,
kVideoFrameDelta);
// TODO(shampson): Currently turning off the base stream causes unexpected
// behavior in the libvpx encoder. The libvpx encoder labels key frames
// based upon the base stream. If the base stream is never enabled, it
// will continue to spit out encoded images labeled as key frames for the
// other streams that are enabled. Once this is fixed in libvpx, update this
// test to reflect that change.
// Only turn on the the base stream.
std::vector<bool> active_streams = {true, false, false};
UpdateActiveStreams(active_streams);
SetRates(kEnoughBitrateAllStreams, 30);
ExpectStreams(kVideoFrameKey, active_streams);
input_frame_->set_timestamp(input_frame_->timestamp() + 3000);
EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types));
ExpectStreams(kVideoFrameDelta, active_streams);
input_frame_->set_timestamp(input_frame_->timestamp() + 3000);
EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types));
// Turn off only the middle stream.
active_streams = {true, false, true};
UpdateActiveStreams(active_streams);
SetRates(kEnoughBitrateAllStreams, 30);
ExpectStreams(kVideoFrameKey, active_streams);
input_frame_->set_timestamp(input_frame_->timestamp() + 3000);
EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types));
ExpectStreams(kVideoFrameDelta, active_streams);
input_frame_->set_timestamp(input_frame_->timestamp() + 3000);
EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types));
}
void SwitchingToOneStream(int width, int height) {
// Disable all streams except the last and set the bitrate of the last to
// 100 kbps. This verifies the way GTP switches to screenshare mode.

View File

@ -55,10 +55,6 @@ TEST_F(TestVp8Impl, TestDisablingStreams) {
TestVp8Simulcast::TestDisablingStreams();
}
TEST_F(TestVp8Impl, TestActiveStreams) {
TestVp8Simulcast::TestActiveStreams();
}
TEST_F(TestVp8Impl, TestSwitchingToOneStream) {
TestVp8Simulcast::TestSwitchingToOneStream();
}