VideoStreamEncoder report VideoLayersAllocation for simulcast
Adds support for Vp8 simulcast. Bug: webrtc:12000 Change-Id: Ib24fd0542642b023ec35f7a7bdc4880d72365edf Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/187341 Commit-Queue: Per Kjellander <perkj@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Cr-Commit-Position: refs/heads/master@{#32416}
This commit is contained in:

committed by
Commit Bot

parent
4244b5f6b4
commit
a94348440b
@ -21,7 +21,6 @@ rtc_library("video_rtp_headers") {
|
|||||||
"hdr_metadata.h",
|
"hdr_metadata.h",
|
||||||
"video_content_type.cc",
|
"video_content_type.cc",
|
||||||
"video_content_type.h",
|
"video_content_type.h",
|
||||||
"video_layers_allocation.h",
|
|
||||||
"video_rotation.h",
|
"video_rotation.h",
|
||||||
"video_timing.cc",
|
"video_timing.cc",
|
||||||
"video_timing.h",
|
"video_timing.h",
|
||||||
@ -182,6 +181,13 @@ rtc_library("video_bitrate_allocation") {
|
|||||||
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc_source_set("video_layers_allocation") {
|
||||||
|
visibility = [ "*" ]
|
||||||
|
sources = [ "video_layers_allocation.h" ]
|
||||||
|
deps = [ "../units:data_rate" ]
|
||||||
|
absl_deps = [ "//third_party/abseil-cpp/absl/container:inlined_vector" ]
|
||||||
|
}
|
||||||
|
|
||||||
rtc_library("video_bitrate_allocator") {
|
rtc_library("video_bitrate_allocator") {
|
||||||
visibility = [ "*" ]
|
visibility = [ "*" ]
|
||||||
sources = [
|
sources = [
|
||||||
@ -264,6 +270,7 @@ rtc_source_set("video_stream_encoder") {
|
|||||||
":video_bitrate_allocator_factory",
|
":video_bitrate_allocator_factory",
|
||||||
":video_codec_constants",
|
":video_codec_constants",
|
||||||
":video_frame",
|
":video_frame",
|
||||||
|
":video_layers_allocation",
|
||||||
"..:rtp_parameters",
|
"..:rtp_parameters",
|
||||||
"..:scoped_refptr",
|
"..:scoped_refptr",
|
||||||
"../:fec_controller_api",
|
"../:fec_controller_api",
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "api/scoped_refptr.h"
|
#include "api/scoped_refptr.h"
|
||||||
#include "api/units/data_rate.h"
|
#include "api/units/data_rate.h"
|
||||||
#include "api/video/video_bitrate_allocator.h"
|
#include "api/video/video_bitrate_allocator.h"
|
||||||
|
#include "api/video/video_layers_allocation.h"
|
||||||
#include "api/video/video_sink_interface.h"
|
#include "api/video/video_sink_interface.h"
|
||||||
#include "api/video/video_source_interface.h"
|
#include "api/video/video_source_interface.h"
|
||||||
#include "api/video_codecs/video_encoder.h"
|
#include "api/video_codecs/video_encoder.h"
|
||||||
@ -52,6 +53,9 @@ class VideoStreamEncoderInterface : public rtc::VideoSinkInterface<VideoFrame> {
|
|||||||
|
|
||||||
virtual void OnBitrateAllocationUpdated(
|
virtual void OnBitrateAllocationUpdated(
|
||||||
const VideoBitrateAllocation& allocation) = 0;
|
const VideoBitrateAllocation& allocation) = 0;
|
||||||
|
|
||||||
|
virtual void OnVideoLayersAllocationUpdated(
|
||||||
|
VideoLayersAllocation allocation) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the resource is overusing, the VideoStreamEncoder will try to reduce
|
// If the resource is overusing, the VideoStreamEncoder will try to reduce
|
||||||
|
@ -110,6 +110,7 @@ rtc_library("rtp_rtcp_format") {
|
|||||||
"../../api/transport/rtp:dependency_descriptor",
|
"../../api/transport/rtp:dependency_descriptor",
|
||||||
"../../api/units:time_delta",
|
"../../api/units:time_delta",
|
||||||
"../../api/video:video_frame",
|
"../../api/video:video_frame",
|
||||||
|
"../../api/video:video_layers_allocation",
|
||||||
"../../api/video:video_rtp_headers",
|
"../../api/video:video_rtp_headers",
|
||||||
"../../common_video",
|
"../../common_video",
|
||||||
"../../rtc_base:checks",
|
"../../rtc_base:checks",
|
||||||
@ -278,6 +279,7 @@ rtc_library("rtp_rtcp") {
|
|||||||
"../../api/video:video_codec_constants",
|
"../../api/video:video_codec_constants",
|
||||||
"../../api/video:video_frame",
|
"../../api/video:video_frame",
|
||||||
"../../api/video:video_frame_type",
|
"../../api/video:video_frame_type",
|
||||||
|
"../../api/video:video_layers_allocation",
|
||||||
"../../api/video:video_rtp_headers",
|
"../../api/video:video_rtp_headers",
|
||||||
"../../api/video_codecs:video_codecs_api",
|
"../../api/video_codecs:video_codecs_api",
|
||||||
"../../call:rtp_interfaces",
|
"../../call:rtp_interfaces",
|
||||||
@ -537,6 +539,7 @@ if (rtc_include_tests) {
|
|||||||
"../../api/video:video_bitrate_allocator",
|
"../../api/video:video_bitrate_allocator",
|
||||||
"../../api/video:video_codec_constants",
|
"../../api/video:video_codec_constants",
|
||||||
"../../api/video:video_frame",
|
"../../api/video:video_frame",
|
||||||
|
"../../api/video:video_layers_allocation",
|
||||||
"../../api/video:video_rtp_headers",
|
"../../api/video:video_rtp_headers",
|
||||||
"../../api/video_codecs:video_codecs_api",
|
"../../api/video_codecs:video_codecs_api",
|
||||||
"../../call:rtp_receiver",
|
"../../call:rtp_receiver",
|
||||||
|
@ -226,6 +226,7 @@ rtc_library("video_stream_encoder_impl") {
|
|||||||
"../api/video:video_bitrate_allocator_factory",
|
"../api/video:video_bitrate_allocator_factory",
|
||||||
"../api/video:video_codec_constants",
|
"../api/video:video_codec_constants",
|
||||||
"../api/video:video_frame",
|
"../api/video:video_frame",
|
||||||
|
"../api/video:video_layers_allocation",
|
||||||
"../api/video:video_rtp_headers",
|
"../api/video:video_rtp_headers",
|
||||||
"../api/video:video_stream_encoder",
|
"../api/video:video_stream_encoder",
|
||||||
"../api/video_codecs:video_codecs_api",
|
"../api/video_codecs:video_codecs_api",
|
||||||
|
@ -472,6 +472,20 @@ void VideoSendStreamImpl::OnBitrateAllocationUpdated(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoSendStreamImpl::OnVideoLayersAllocationUpdated(
|
||||||
|
VideoLayersAllocation allocation) {
|
||||||
|
if (!worker_queue_->IsCurrent()) {
|
||||||
|
auto ptr = weak_ptr_;
|
||||||
|
worker_queue_->PostTask([allocation = std::move(allocation), ptr] {
|
||||||
|
if (!ptr.get())
|
||||||
|
return;
|
||||||
|
ptr->OnVideoLayersAllocationUpdated(allocation);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO(bugs.webrtc.org/12000): Implement
|
||||||
|
}
|
||||||
|
|
||||||
void VideoSendStreamImpl::SignalEncoderActive() {
|
void VideoSendStreamImpl::SignalEncoderActive() {
|
||||||
RTC_DCHECK_RUN_ON(worker_queue_);
|
RTC_DCHECK_RUN_ON(worker_queue_);
|
||||||
if (rtp_video_sender_->IsActive()) {
|
if (rtp_video_sender_->IsActive()) {
|
||||||
|
@ -121,6 +121,8 @@ class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
|
|||||||
|
|
||||||
void OnBitrateAllocationUpdated(
|
void OnBitrateAllocationUpdated(
|
||||||
const VideoBitrateAllocation& allocation) override;
|
const VideoBitrateAllocation& allocation) override;
|
||||||
|
void OnVideoLayersAllocationUpdated(
|
||||||
|
VideoLayersAllocation allocation) override;
|
||||||
|
|
||||||
// Implements EncodedImageCallback. The implementation routes encoded frames
|
// Implements EncodedImageCallback. The implementation routes encoded frames
|
||||||
// to the |payload_router_| and |config.pre_encode_callback| if set.
|
// to the |payload_router_| and |config.pre_encode_callback| if set.
|
||||||
|
@ -198,6 +198,73 @@ VideoBitrateAllocation UpdateAllocationFromEncoderInfo(
|
|||||||
return new_allocation;
|
return new_allocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts a VideoBitrateAllocation that contains allocated bitrate per layer,
|
||||||
|
// and an EncoderInfo that contains information about the actual encoder
|
||||||
|
// structure used by a codec. Stream structures can be Ksvc, Full SVC, Simulcast
|
||||||
|
// etc.
|
||||||
|
VideoLayersAllocation CreateVideoLayersAllocation(
|
||||||
|
const VideoCodec& encoder_config,
|
||||||
|
const VideoEncoder::RateControlParameters& current_rate,
|
||||||
|
const VideoEncoder::EncoderInfo& encoder_info) {
|
||||||
|
const VideoBitrateAllocation& target_bitrate = current_rate.target_bitrate;
|
||||||
|
VideoLayersAllocation layers_allocation;
|
||||||
|
if (target_bitrate.get_sum_bps() == 0) {
|
||||||
|
return layers_allocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoder_config.numberOfSimulcastStreams > 0) {
|
||||||
|
layers_allocation.resolution_and_frame_rate_is_valid = true;
|
||||||
|
for (int si = 0; si < encoder_config.numberOfSimulcastStreams; ++si) {
|
||||||
|
if (!target_bitrate.IsSpatialLayerUsed(si) ||
|
||||||
|
target_bitrate.GetSpatialLayerSum(si) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
layers_allocation.active_spatial_layers.emplace_back();
|
||||||
|
VideoLayersAllocation::SpatialLayer& spatial_layer =
|
||||||
|
layers_allocation.active_spatial_layers.back();
|
||||||
|
spatial_layer.width = encoder_config.simulcastStream[si].width;
|
||||||
|
spatial_layer.height = encoder_config.simulcastStream[si].height;
|
||||||
|
spatial_layer.rtp_stream_index = si;
|
||||||
|
spatial_layer.spatial_id = 0;
|
||||||
|
auto frame_rate_fraction =
|
||||||
|
VideoEncoder::EncoderInfo::kMaxFramerateFraction;
|
||||||
|
if (encoder_info.fps_allocation[si].size() == 1) {
|
||||||
|
// One TL is signalled to be used by the encoder. Do not distribute
|
||||||
|
// bitrate allocation across TLs (use sum at tl:0).
|
||||||
|
spatial_layer.target_bitrate_per_temporal_layer.push_back(
|
||||||
|
DataRate::BitsPerSec(target_bitrate.GetSpatialLayerSum(si)));
|
||||||
|
frame_rate_fraction = encoder_info.fps_allocation[si][0];
|
||||||
|
} else { // Temporal layers are supported.
|
||||||
|
uint32_t temporal_layer_bitrate_bps = 0;
|
||||||
|
for (size_t ti = 0;
|
||||||
|
ti < encoder_config.simulcastStream[si].numberOfTemporalLayers;
|
||||||
|
++ti) {
|
||||||
|
if (!target_bitrate.HasBitrate(si, ti)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ti < encoder_info.fps_allocation[si].size()) {
|
||||||
|
// Use frame rate of the top used temporal layer.
|
||||||
|
frame_rate_fraction = encoder_info.fps_allocation[si][ti];
|
||||||
|
}
|
||||||
|
temporal_layer_bitrate_bps += target_bitrate.GetBitrate(si, ti);
|
||||||
|
spatial_layer.target_bitrate_per_temporal_layer.push_back(
|
||||||
|
DataRate::BitsPerSec(temporal_layer_bitrate_bps));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Encoder may drop frames internally if `maxFramerate` is set.
|
||||||
|
spatial_layer.frame_rate_fps = std::min(
|
||||||
|
static_cast<uint8_t>(encoder_config.simulcastStream[si].maxFramerate),
|
||||||
|
static_cast<uint8_t>(
|
||||||
|
(current_rate.framerate_fps * frame_rate_fraction) /
|
||||||
|
VideoEncoder::EncoderInfo::kMaxFramerateFraction));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO(bugs.webrtc.org/12000): Implement support for kSVC and full SVC.
|
||||||
|
}
|
||||||
|
|
||||||
|
return layers_allocation;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
VideoStreamEncoder::EncoderRateSettings::EncoderRateSettings()
|
VideoStreamEncoder::EncoderRateSettings::EncoderRateSettings()
|
||||||
@ -1124,6 +1191,12 @@ void VideoStreamEncoder::SetEncoderRates(
|
|||||||
rate_settings.rate_control.bitrate,
|
rate_settings.rate_control.bitrate,
|
||||||
static_cast<uint32_t>(rate_settings.rate_control.framerate_fps + 0.5));
|
static_cast<uint32_t>(rate_settings.rate_control.framerate_fps + 0.5));
|
||||||
stream_resource_manager_.SetEncoderRates(rate_settings.rate_control);
|
stream_resource_manager_.SetEncoderRates(rate_settings.rate_control);
|
||||||
|
if (settings_.allocation_cb_type ==
|
||||||
|
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
|
||||||
|
kVideoLayersAllocation) {
|
||||||
|
sink_->OnVideoLayersAllocationUpdated(CreateVideoLayersAllocation(
|
||||||
|
send_codec_, rate_settings.rate_control, encoder_->GetEncoderInfo()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((settings_.allocation_cb_type ==
|
if ((settings_.allocation_cb_type ==
|
||||||
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
|
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
|
||||||
|
@ -1254,6 +1254,16 @@ class VideoStreamEncoderTest : public ::testing::Test {
|
|||||||
return number_of_bitrate_allocations_;
|
return number_of_bitrate_allocations_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VideoLayersAllocation GetLastVideoLayersAllocation() {
|
||||||
|
MutexLock lock(&mutex_);
|
||||||
|
return last_layers_allocation_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int number_of_layers_allocations() const {
|
||||||
|
MutexLock lock(&mutex_);
|
||||||
|
return number_of_layers_allocations_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Result OnEncodedImage(
|
Result OnEncodedImage(
|
||||||
const EncodedImage& encoded_image,
|
const EncodedImage& encoded_image,
|
||||||
@ -1296,6 +1306,24 @@ class VideoStreamEncoderTest : public ::testing::Test {
|
|||||||
last_bitrate_allocation_ = allocation;
|
last_bitrate_allocation_ = allocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnVideoLayersAllocationUpdated(
|
||||||
|
VideoLayersAllocation allocation) override {
|
||||||
|
MutexLock lock(&mutex_);
|
||||||
|
++number_of_layers_allocations_;
|
||||||
|
last_layers_allocation_ = allocation;
|
||||||
|
rtc::StringBuilder log;
|
||||||
|
for (const auto& layer : allocation.active_spatial_layers) {
|
||||||
|
log << layer.width << "x" << layer.height << "@" << layer.frame_rate_fps
|
||||||
|
<< "[";
|
||||||
|
for (const auto target_bitrate :
|
||||||
|
layer.target_bitrate_per_temporal_layer) {
|
||||||
|
log << target_bitrate.kbps() << ",";
|
||||||
|
}
|
||||||
|
log << "]";
|
||||||
|
}
|
||||||
|
RTC_DLOG(INFO) << "OnVideoLayersAllocationUpdated " << log.str();
|
||||||
|
}
|
||||||
|
|
||||||
TimeController* const time_controller_;
|
TimeController* const time_controller_;
|
||||||
mutable Mutex mutex_;
|
mutable Mutex mutex_;
|
||||||
TestEncoder* test_encoder_;
|
TestEncoder* test_encoder_;
|
||||||
@ -1313,6 +1341,8 @@ class VideoStreamEncoderTest : public ::testing::Test {
|
|||||||
int min_transmit_bitrate_bps_ = 0;
|
int min_transmit_bitrate_bps_ = 0;
|
||||||
VideoBitrateAllocation last_bitrate_allocation_ RTC_GUARDED_BY(&mutex_);
|
VideoBitrateAllocation last_bitrate_allocation_ RTC_GUARDED_BY(&mutex_);
|
||||||
int number_of_bitrate_allocations_ RTC_GUARDED_BY(&mutex_) = 0;
|
int number_of_bitrate_allocations_ RTC_GUARDED_BY(&mutex_) = 0;
|
||||||
|
VideoLayersAllocation last_layers_allocation_ RTC_GUARDED_BY(&mutex_);
|
||||||
|
int number_of_layers_allocations_ RTC_GUARDED_BY(&mutex_) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VideoBitrateAllocatorProxyFactory
|
class VideoBitrateAllocatorProxyFactory
|
||||||
@ -4013,6 +4043,100 @@ TEST_F(VideoStreamEncoderTest, ReportsVideoBitrateAllocation) {
|
|||||||
video_stream_encoder_->Stop();
|
video_stream_encoder_->Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(VideoStreamEncoderTest, ReportsVideoLayersAllocationForV8Simulcast) {
|
||||||
|
ResetEncoder("VP8", /*num_streams*/ 2, 1, 1, /*screenshare*/ false,
|
||||||
|
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
|
||||||
|
kVideoLayersAllocation);
|
||||||
|
|
||||||
|
const int kDefaultFps = 30;
|
||||||
|
|
||||||
|
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
|
||||||
|
DataRate::BitsPerSec(kLowTargetBitrateBps),
|
||||||
|
DataRate::BitsPerSec(kLowTargetBitrateBps),
|
||||||
|
DataRate::BitsPerSec(kLowTargetBitrateBps), 0, 0, 0);
|
||||||
|
|
||||||
|
video_source_.IncomingCapturedFrame(
|
||||||
|
CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
|
||||||
|
WaitForEncodedFrame(CurrentTimeMs());
|
||||||
|
EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
|
||||||
|
VideoLayersAllocation last_layer_allocation =
|
||||||
|
sink_.GetLastVideoLayersAllocation();
|
||||||
|
// kLowTargetBitrateBps is only enough for one spatial layer.
|
||||||
|
ASSERT_EQ(last_layer_allocation.active_spatial_layers.size(), 1u);
|
||||||
|
|
||||||
|
VideoBitrateAllocation bitrate_allocation =
|
||||||
|
fake_encoder_.GetAndResetLastRateControlSettings()->bitrate;
|
||||||
|
// Check that encoder has been updated too, not just allocation observer.
|
||||||
|
EXPECT_EQ(bitrate_allocation.get_sum_bps(), kLowTargetBitrateBps);
|
||||||
|
AdvanceTime(TimeDelta::Seconds(1) / kDefaultFps);
|
||||||
|
|
||||||
|
// VideoLayersAllocation might be updated if frame rate change.
|
||||||
|
int number_of_layers_allocation = 1;
|
||||||
|
const int64_t start_time_ms = CurrentTimeMs();
|
||||||
|
while (CurrentTimeMs() - start_time_ms < 10 * kProcessIntervalMs) {
|
||||||
|
video_source_.IncomingCapturedFrame(
|
||||||
|
CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
|
||||||
|
WaitForEncodedFrame(CurrentTimeMs());
|
||||||
|
AdvanceTime(TimeDelta::Millis(1) / kDefaultFps);
|
||||||
|
if (number_of_layers_allocation != sink_.number_of_layers_allocations()) {
|
||||||
|
number_of_layers_allocation = sink_.number_of_layers_allocations();
|
||||||
|
VideoLayersAllocation new_allocation =
|
||||||
|
sink_.GetLastVideoLayersAllocation();
|
||||||
|
ASSERT_EQ(new_allocation.active_spatial_layers.size(), 1u);
|
||||||
|
EXPECT_NE(new_allocation.active_spatial_layers[0].frame_rate_fps,
|
||||||
|
last_layer_allocation.active_spatial_layers[0].frame_rate_fps);
|
||||||
|
EXPECT_EQ(new_allocation.active_spatial_layers[0]
|
||||||
|
.target_bitrate_per_temporal_layer,
|
||||||
|
last_layer_allocation.active_spatial_layers[0]
|
||||||
|
.target_bitrate_per_temporal_layer);
|
||||||
|
last_layer_allocation = new_allocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPECT_LE(sink_.number_of_layers_allocations(), 3);
|
||||||
|
video_stream_encoder_->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(VideoStreamEncoderTest,
|
||||||
|
ReportsUpdatedVideoLayersAllocationWhenBweChanges) {
|
||||||
|
ResetEncoder("VP8", /*num_streams*/ 2, 1, 1, /*screenshare*/ false,
|
||||||
|
VideoStreamEncoderSettings::BitrateAllocationCallbackType::
|
||||||
|
kVideoLayersAllocation);
|
||||||
|
|
||||||
|
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
|
||||||
|
DataRate::BitsPerSec(kLowTargetBitrateBps),
|
||||||
|
DataRate::BitsPerSec(kLowTargetBitrateBps),
|
||||||
|
DataRate::BitsPerSec(kLowTargetBitrateBps), 0, 0, 0);
|
||||||
|
|
||||||
|
video_source_.IncomingCapturedFrame(
|
||||||
|
CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
|
||||||
|
WaitForEncodedFrame(CurrentTimeMs());
|
||||||
|
EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
|
||||||
|
VideoLayersAllocation last_layer_allocation =
|
||||||
|
sink_.GetLastVideoLayersAllocation();
|
||||||
|
// kLowTargetBitrateBps is only enough for one spatial layer.
|
||||||
|
ASSERT_EQ(last_layer_allocation.active_spatial_layers.size(), 1u);
|
||||||
|
EXPECT_EQ(last_layer_allocation.active_spatial_layers[0]
|
||||||
|
.target_bitrate_per_temporal_layer[0],
|
||||||
|
DataRate::BitsPerSec(kLowTargetBitrateBps));
|
||||||
|
|
||||||
|
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
|
||||||
|
DataRate::BitsPerSec(kSimulcastTargetBitrateBps),
|
||||||
|
DataRate::BitsPerSec(kSimulcastTargetBitrateBps),
|
||||||
|
DataRate::BitsPerSec(kSimulcastTargetBitrateBps), 0, 0, 0);
|
||||||
|
video_source_.IncomingCapturedFrame(
|
||||||
|
CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
|
||||||
|
WaitForEncodedFrame(CurrentTimeMs());
|
||||||
|
|
||||||
|
EXPECT_EQ(sink_.number_of_layers_allocations(), 2);
|
||||||
|
last_layer_allocation = sink_.GetLastVideoLayersAllocation();
|
||||||
|
ASSERT_EQ(last_layer_allocation.active_spatial_layers.size(), 2u);
|
||||||
|
EXPECT_GT(last_layer_allocation.active_spatial_layers[1]
|
||||||
|
.target_bitrate_per_temporal_layer[0],
|
||||||
|
DataRate::Zero());
|
||||||
|
|
||||||
|
video_stream_encoder_->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(VideoStreamEncoderTest, TemporalLayersNotDisabledIfSupported) {
|
TEST_F(VideoStreamEncoderTest, TemporalLayersNotDisabledIfSupported) {
|
||||||
// 2 TLs configured, temporal layers supported by encoder.
|
// 2 TLs configured, temporal layers supported by encoder.
|
||||||
const int kNumTemporalLayers = 2;
|
const int kNumTemporalLayers = 2;
|
||||||
|
Reference in New Issue
Block a user