2017-01-26 06:12:26 -08:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
2018-03-28 19:32:37 +02:00
|
|
|
#include "modules/video_coding/include/video_codec_initializer.h"
|
2018-11-28 16:47:49 +01:00
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <stdint.h>
|
2019-07-05 19:08:33 +02:00
|
|
|
|
2018-11-28 16:47:49 +01:00
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
|
|
#include "absl/types/optional.h"
|
2019-01-25 20:26:48 +01:00
|
|
|
#include "api/scoped_refptr.h"
|
2019-07-02 11:20:09 +02:00
|
|
|
#include "api/test/mock_fec_controller_override.h"
|
2018-11-08 10:02:56 -08:00
|
|
|
#include "api/video/builtin_video_bitrate_allocator_factory.h"
|
2018-11-28 16:47:49 +01:00
|
|
|
#include "api/video/video_bitrate_allocation.h"
|
|
|
|
|
#include "api/video/video_bitrate_allocator.h"
|
|
|
|
|
#include "api/video/video_bitrate_allocator_factory.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "api/video_codecs/video_encoder.h"
|
2018-10-12 10:30:31 +02:00
|
|
|
#include "api/video_codecs/vp8_temporal_layers.h"
|
2019-03-20 11:56:20 +01:00
|
|
|
#include "api/video_codecs/vp8_temporal_layers_factory.h"
|
2018-03-28 19:32:37 +02:00
|
|
|
#include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
|
2018-11-08 10:02:56 -08:00
|
|
|
#include "rtc_base/checks.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "rtc_base/ref_counted_object.h"
|
2019-07-02 11:20:09 +02:00
|
|
|
#include "test/gmock.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "test/gtest.h"
|
2017-01-26 06:12:26 -08:00
|
|
|
|
|
|
|
|
namespace webrtc {
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
static const int kDefaultWidth = 1280;
|
|
|
|
|
static const int kDefaultHeight = 720;
|
|
|
|
|
static const int kDefaultFrameRate = 30;
|
|
|
|
|
static const uint32_t kDefaultMinBitrateBps = 60000;
|
|
|
|
|
static const uint32_t kDefaultTargetBitrateBps = 2000000;
|
|
|
|
|
static const uint32_t kDefaultMaxBitrateBps = 2000000;
|
|
|
|
|
static const uint32_t kDefaultMinTransmitBitrateBps = 400000;
|
|
|
|
|
static const int kDefaultMaxQp = 48;
|
2020-08-04 11:40:23 +02:00
|
|
|
static const uint32_t kScreenshareTl0BitrateBps = 120000;
|
|
|
|
|
static const uint32_t kScreenshareConferenceTl0BitrateBps = 200000;
|
2017-01-26 06:12:26 -08:00
|
|
|
static const uint32_t kScreenshareCodecTargetBitrateBps = 200000;
|
|
|
|
|
static const uint32_t kScreenshareDefaultFramerate = 5;
|
|
|
|
|
// Bitrates for the temporal layers of the higher screenshare simulcast stream.
|
|
|
|
|
static const uint32_t kHighScreenshareTl0Bps = 800000;
|
|
|
|
|
static const uint32_t kHighScreenshareTl1Bps = 1200000;
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
// TODO(sprang): Extend coverage to handle the rest of the codec initializer.
|
|
|
|
|
class VideoCodecInitializerTest : public ::testing::Test {
|
|
|
|
|
public:
|
2018-04-26 09:51:47 +02:00
|
|
|
VideoCodecInitializerTest() {}
|
2017-01-26 06:12:26 -08:00
|
|
|
virtual ~VideoCodecInitializerTest() {}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
void SetUpFor(VideoCodecType type,
|
|
|
|
|
int num_spatial_streams,
|
|
|
|
|
int num_temporal_streams,
|
|
|
|
|
bool screenshare) {
|
|
|
|
|
config_ = VideoEncoderConfig();
|
Reland "Reland "Move rtp-specific config out of EncoderSettings.""
This reverts commit 6c2c13af06b32778b86950681758a7970d1c5d9e.
Reason for revert: Intend to investigate and fix perf problems.
Original change's description:
> Revert "Reland "Move rtp-specific config out of EncoderSettings.""
>
> This reverts commit 04dd1768625eb2241d1fb97fd0137897e703e266.
>
> Reason for revert: Regression in ramp up perf tests.
>
> Original change's description:
> > Reland "Move rtp-specific config out of EncoderSettings."
> >
> > This is a reland of bc900cb1d1810fcf678fe41cf1e3966daa39c88c
> >
> > Original change's description:
> > > Move rtp-specific config out of EncoderSettings.
> > >
> > > In VideoSendStream::Config, move payload_name and payload_type from
> > > EncoderSettings to Rtp.
> > >
> > > EncoderSettings now contains configuration for VideoStreamEncoder only,
> > > and should perhaps be renamed in a follow up cl. It's no longer
> > > passed as an argument to VideoCodecInitializer::SetupCodec.
> > >
> > > The latter then needs a different way to know the codec type,
> > > which is provided by a new codec_type member in VideoEncoderConfig.
> > >
> > > Bug: webrtc:8830
> > > Change-Id: Ifcc691aef1ee6a95e43c0452c5e630d92a511cd6
> > > Reviewed-on: https://webrtc-review.googlesource.com/62062
> > > Commit-Queue: Niels Moller <nisse@webrtc.org>
> > > Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
> > > Reviewed-by: Stefan Holmer <stefan@webrtc.org>
> > > Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
> > > Cr-Commit-Position: refs/heads/master@{#22532}
> >
> > Bug: webrtc:8830
> > Change-Id: If88ef7d57cdaa4fae3c7b2a97ea5a6e1b833e019
> > Reviewed-on: https://webrtc-review.googlesource.com/63721
> > Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
> > Reviewed-by: Stefan Holmer <stefan@webrtc.org>
> > Commit-Queue: Niels Moller <nisse@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#22595}
>
> TBR=brandtr@webrtc.org,magjed@webrtc.org,nisse@webrtc.org,stefan@webrtc.org
>
> Bug: webrtc:8830,chromium:827080
> Change-Id: Iaaf146de91ec5c0d741b8efdf143f7e173084fef
> Reviewed-on: https://webrtc-review.googlesource.com/65520
> Commit-Queue: Niels Moller <nisse@webrtc.org>
> Reviewed-by: Niels Moller <nisse@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#22677}
TBR=brandtr@webrtc.org,magjed@webrtc.org,nisse@webrtc.org,stefan@webrtc.org
# Not skipping CQ checks because original CL landed > 1 day ago.
Bug: webrtc:8830, chromium:827080
Change-Id: I9b62987bf5daced90dfeb3ebb6739c80117c487f
Reviewed-on: https://webrtc-review.googlesource.com/66862
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22751}
2018-04-05 15:36:51 +02:00
|
|
|
config_.codec_type = type;
|
|
|
|
|
|
2017-01-26 06:12:26 -08:00
|
|
|
if (screenshare) {
|
|
|
|
|
config_.min_transmit_bitrate_bps = kDefaultMinTransmitBitrateBps;
|
|
|
|
|
config_.content_type = VideoEncoderConfig::ContentType::kScreen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type == VideoCodecType::kVideoCodecVP8) {
|
|
|
|
|
config_.number_of_streams = num_spatial_streams;
|
|
|
|
|
VideoCodecVP8 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
|
|
|
|
|
vp8_settings.numberOfTemporalLayers = num_temporal_streams;
|
2021-04-27 14:43:08 +02:00
|
|
|
config_.encoder_specific_settings = rtc::make_ref_counted<
|
2017-01-26 06:12:26 -08:00
|
|
|
webrtc::VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings);
|
2018-03-28 19:32:37 +02:00
|
|
|
} else if (type == VideoCodecType::kVideoCodecVP9) {
|
|
|
|
|
VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
|
|
|
|
|
vp9_settings.numberOfSpatialLayers = num_spatial_streams;
|
|
|
|
|
vp9_settings.numberOfTemporalLayers = num_temporal_streams;
|
2021-04-27 14:43:08 +02:00
|
|
|
config_.encoder_specific_settings = rtc::make_ref_counted<
|
2018-03-28 19:32:37 +02:00
|
|
|
webrtc::VideoEncoderConfig::Vp9EncoderSpecificSettings>(vp9_settings);
|
|
|
|
|
} else if (type != VideoCodecType::kVideoCodecMultiplex) {
|
2017-01-26 06:12:26 -08:00
|
|
|
ADD_FAILURE() << "Unexpected codec type: " << type;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool InitializeCodec() {
|
|
|
|
|
codec_out_ = VideoCodec();
|
2019-03-20 11:56:20 +01:00
|
|
|
frame_buffer_controller_.reset();
|
2018-11-08 10:02:56 -08:00
|
|
|
if (!VideoCodecInitializer::SetupCodec(config_, streams_, &codec_out_)) {
|
2017-01-26 06:12:26 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
2018-11-08 10:02:56 -08:00
|
|
|
bitrate_allocator_ = CreateBuiltinVideoBitrateAllocatorFactory()
|
|
|
|
|
->CreateVideoBitrateAllocator(codec_out_);
|
|
|
|
|
RTC_CHECK(bitrate_allocator_);
|
2018-01-25 13:01:09 -08:00
|
|
|
if (codec_out_.codecType == VideoCodecType::kVideoCodecMultiplex)
|
2017-12-11 12:21:02 +05:30
|
|
|
return true;
|
2018-03-21 09:57:23 +01:00
|
|
|
|
2017-01-26 06:12:26 -08:00
|
|
|
// Make sure temporal layers instances have been created.
|
|
|
|
|
if (codec_out_.codecType == VideoCodecType::kVideoCodecVP8) {
|
2019-03-20 11:56:20 +01:00
|
|
|
Vp8TemporalLayersFactory factory;
|
2019-06-07 23:10:00 +02:00
|
|
|
const VideoEncoder::Settings settings(VideoEncoder::Capabilities(false),
|
|
|
|
|
1, 1000);
|
2019-07-02 11:20:09 +02:00
|
|
|
frame_buffer_controller_ =
|
|
|
|
|
factory.Create(codec_out_, settings, &fec_controller_override_);
|
2017-01-26 06:12:26 -08:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VideoStream DefaultStream() {
|
|
|
|
|
VideoStream stream;
|
|
|
|
|
stream.width = kDefaultWidth;
|
|
|
|
|
stream.height = kDefaultHeight;
|
|
|
|
|
stream.max_framerate = kDefaultFrameRate;
|
|
|
|
|
stream.min_bitrate_bps = kDefaultMinBitrateBps;
|
|
|
|
|
stream.target_bitrate_bps = kDefaultTargetBitrateBps;
|
|
|
|
|
stream.max_bitrate_bps = kDefaultMaxBitrateBps;
|
|
|
|
|
stream.max_qp = kDefaultMaxQp;
|
2018-03-01 15:11:29 +01:00
|
|
|
stream.num_temporal_layers = 1;
|
2018-01-18 10:39:54 -08:00
|
|
|
stream.active = true;
|
2017-01-26 06:12:26 -08:00
|
|
|
return stream;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VideoStream DefaultScreenshareStream() {
|
|
|
|
|
VideoStream stream = DefaultStream();
|
|
|
|
|
stream.min_bitrate_bps = 30000;
|
2020-08-04 11:40:23 +02:00
|
|
|
stream.target_bitrate_bps = kScreenshareCodecTargetBitrateBps;
|
2017-01-26 06:12:26 -08:00
|
|
|
stream.max_bitrate_bps = 1000000;
|
|
|
|
|
stream.max_framerate = kScreenshareDefaultFramerate;
|
2018-03-01 15:11:29 +01:00
|
|
|
stream.num_temporal_layers = 2;
|
2018-01-18 10:39:54 -08:00
|
|
|
stream.active = true;
|
2017-01-26 06:12:26 -08:00
|
|
|
return stream;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-02 11:20:09 +02:00
|
|
|
MockFecControllerOverride fec_controller_override_;
|
|
|
|
|
|
2017-01-26 06:12:26 -08:00
|
|
|
// Input settings.
|
|
|
|
|
VideoEncoderConfig config_;
|
|
|
|
|
std::vector<VideoStream> streams_;
|
|
|
|
|
|
|
|
|
|
// Output.
|
|
|
|
|
VideoCodec codec_out_;
|
2018-11-08 10:02:56 -08:00
|
|
|
std::unique_ptr<VideoBitrateAllocator> bitrate_allocator_;
|
2019-03-20 11:56:20 +01:00
|
|
|
std::unique_ptr<Vp8FrameBufferController> frame_buffer_controller_;
|
2017-01-26 06:12:26 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TEST_F(VideoCodecInitializerTest, SingleStreamVp8Screenshare) {
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
|
|
|
|
|
streams_.push_back(DefaultStream());
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
|
2019-08-02 15:16:28 +02:00
|
|
|
VideoBitrateAllocation bitrate_allocation =
|
|
|
|
|
bitrate_allocator_->Allocate(VideoBitrateAllocationParameters(
|
|
|
|
|
kDefaultTargetBitrateBps, kDefaultFrameRate));
|
2017-01-26 06:12:26 -08:00
|
|
|
EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
|
|
|
|
|
EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
|
|
|
|
|
EXPECT_EQ(kDefaultTargetBitrateBps, bitrate_allocation.get_sum_bps());
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-18 10:39:54 -08:00
|
|
|
TEST_F(VideoCodecInitializerTest, SingleStreamVp8ScreenshareInactive) {
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 1, true);
|
|
|
|
|
VideoStream inactive_stream = DefaultStream();
|
|
|
|
|
inactive_stream.active = false;
|
|
|
|
|
streams_.push_back(inactive_stream);
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
|
2019-08-02 15:16:28 +02:00
|
|
|
VideoBitrateAllocation bitrate_allocation =
|
|
|
|
|
bitrate_allocator_->Allocate(VideoBitrateAllocationParameters(
|
|
|
|
|
kDefaultTargetBitrateBps, kDefaultFrameRate));
|
2018-01-18 10:39:54 -08:00
|
|
|
EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
|
|
|
|
|
EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
|
|
|
|
|
EXPECT_EQ(0U, bitrate_allocation.get_sum_bps());
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-04 11:40:23 +02:00
|
|
|
TEST_F(VideoCodecInitializerTest, TemporalLayeredVp8ScreenshareConference) {
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 2, true);
|
|
|
|
|
streams_.push_back(DefaultScreenshareStream());
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
bitrate_allocator_->SetLegacyConferenceMode(true);
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
|
|
|
|
|
EXPECT_EQ(2u, codec_out_.VP8()->numberOfTemporalLayers);
|
|
|
|
|
VideoBitrateAllocation bitrate_allocation =
|
|
|
|
|
bitrate_allocator_->Allocate(VideoBitrateAllocationParameters(
|
|
|
|
|
kScreenshareCodecTargetBitrateBps, kScreenshareDefaultFramerate));
|
|
|
|
|
EXPECT_EQ(kScreenshareCodecTargetBitrateBps,
|
|
|
|
|
bitrate_allocation.get_sum_bps());
|
|
|
|
|
EXPECT_EQ(kScreenshareConferenceTl0BitrateBps,
|
|
|
|
|
bitrate_allocation.GetBitrate(0, 0));
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-26 06:12:26 -08:00
|
|
|
TEST_F(VideoCodecInitializerTest, TemporalLayeredVp8Screenshare) {
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP8, 1, 2, true);
|
|
|
|
|
streams_.push_back(DefaultScreenshareStream());
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(1u, codec_out_.numberOfSimulcastStreams);
|
|
|
|
|
EXPECT_EQ(2u, codec_out_.VP8()->numberOfTemporalLayers);
|
2019-08-02 15:16:28 +02:00
|
|
|
VideoBitrateAllocation bitrate_allocation =
|
|
|
|
|
bitrate_allocator_->Allocate(VideoBitrateAllocationParameters(
|
|
|
|
|
kScreenshareCodecTargetBitrateBps, kScreenshareDefaultFramerate));
|
2017-01-26 06:12:26 -08:00
|
|
|
EXPECT_EQ(kScreenshareCodecTargetBitrateBps,
|
|
|
|
|
bitrate_allocation.get_sum_bps());
|
|
|
|
|
EXPECT_EQ(kScreenshareTl0BitrateBps, bitrate_allocation.GetBitrate(0, 0));
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-18 10:39:54 -08:00
|
|
|
TEST_F(VideoCodecInitializerTest, SimulcastVp8Screenshare) {
|
2017-01-26 06:12:26 -08:00
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
|
|
|
|
|
streams_.push_back(DefaultScreenshareStream());
|
|
|
|
|
VideoStream video_stream = DefaultStream();
|
|
|
|
|
video_stream.max_framerate = kScreenshareDefaultFramerate;
|
|
|
|
|
streams_.push_back(video_stream);
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
|
|
|
|
|
EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
|
|
|
|
|
const uint32_t max_bitrate_bps =
|
|
|
|
|
streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
|
2019-08-02 15:16:28 +02:00
|
|
|
VideoBitrateAllocation bitrate_allocation =
|
|
|
|
|
bitrate_allocator_->Allocate(VideoBitrateAllocationParameters(
|
|
|
|
|
max_bitrate_bps, kScreenshareDefaultFramerate));
|
2017-01-26 06:12:26 -08:00
|
|
|
EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
|
|
|
|
|
EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
|
|
|
|
|
bitrate_allocation.GetSpatialLayerSum(0));
|
|
|
|
|
EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
|
|
|
|
|
bitrate_allocation.GetSpatialLayerSum(1));
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-18 10:39:54 -08:00
|
|
|
// Tests that when a video stream is inactive, then the bitrate allocation will
|
|
|
|
|
// be 0 for that stream.
|
|
|
|
|
TEST_F(VideoCodecInitializerTest, SimulcastVp8ScreenshareInactive) {
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 1, true);
|
|
|
|
|
streams_.push_back(DefaultScreenshareStream());
|
|
|
|
|
VideoStream inactive_video_stream = DefaultStream();
|
|
|
|
|
inactive_video_stream.active = false;
|
|
|
|
|
inactive_video_stream.max_framerate = kScreenshareDefaultFramerate;
|
|
|
|
|
streams_.push_back(inactive_video_stream);
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
|
|
|
|
|
EXPECT_EQ(1u, codec_out_.VP8()->numberOfTemporalLayers);
|
|
|
|
|
const uint32_t target_bitrate =
|
|
|
|
|
streams_[0].target_bitrate_bps + streams_[1].target_bitrate_bps;
|
2019-08-02 15:16:28 +02:00
|
|
|
VideoBitrateAllocation bitrate_allocation =
|
|
|
|
|
bitrate_allocator_->Allocate(VideoBitrateAllocationParameters(
|
|
|
|
|
target_bitrate, kScreenshareDefaultFramerate));
|
2018-01-18 10:39:54 -08:00
|
|
|
EXPECT_EQ(static_cast<uint32_t>(streams_[0].max_bitrate_bps),
|
|
|
|
|
bitrate_allocation.get_sum_bps());
|
|
|
|
|
EXPECT_EQ(static_cast<uint32_t>(streams_[0].max_bitrate_bps),
|
|
|
|
|
bitrate_allocation.GetSpatialLayerSum(0));
|
|
|
|
|
EXPECT_EQ(0U, bitrate_allocation.GetSpatialLayerSum(1));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(VideoCodecInitializerTest, HighFpsSimulcastVp8Screenshare) {
|
2017-01-26 06:12:26 -08:00
|
|
|
// Two simulcast streams, the lower one using legacy settings (two temporal
|
|
|
|
|
// streams, 5fps), the higher one using 3 temporal streams and 30fps.
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP8, 2, 3, true);
|
|
|
|
|
streams_.push_back(DefaultScreenshareStream());
|
|
|
|
|
VideoStream video_stream = DefaultStream();
|
2018-03-01 15:11:29 +01:00
|
|
|
video_stream.num_temporal_layers = 3;
|
2017-01-26 06:12:26 -08:00
|
|
|
streams_.push_back(video_stream);
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(2u, codec_out_.numberOfSimulcastStreams);
|
|
|
|
|
EXPECT_EQ(3u, codec_out_.VP8()->numberOfTemporalLayers);
|
|
|
|
|
const uint32_t max_bitrate_bps =
|
|
|
|
|
streams_[0].target_bitrate_bps + streams_[1].max_bitrate_bps;
|
2019-08-02 15:16:28 +02:00
|
|
|
VideoBitrateAllocation bitrate_allocation = bitrate_allocator_->Allocate(
|
|
|
|
|
VideoBitrateAllocationParameters(max_bitrate_bps, kDefaultFrameRate));
|
2017-01-26 06:12:26 -08:00
|
|
|
EXPECT_EQ(max_bitrate_bps, bitrate_allocation.get_sum_bps());
|
|
|
|
|
EXPECT_EQ(static_cast<uint32_t>(streams_[0].target_bitrate_bps),
|
|
|
|
|
bitrate_allocation.GetSpatialLayerSum(0));
|
|
|
|
|
EXPECT_EQ(static_cast<uint32_t>(streams_[1].max_bitrate_bps),
|
|
|
|
|
bitrate_allocation.GetSpatialLayerSum(1));
|
|
|
|
|
EXPECT_EQ(kHighScreenshareTl0Bps, bitrate_allocation.GetBitrate(1, 0));
|
|
|
|
|
EXPECT_EQ(kHighScreenshareTl1Bps - kHighScreenshareTl0Bps,
|
|
|
|
|
bitrate_allocation.GetBitrate(1, 1));
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-25 13:01:09 -08:00
|
|
|
TEST_F(VideoCodecInitializerTest, SingleStreamMultiplexCodec) {
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecMultiplex, 1, 1, true);
|
2017-12-11 12:21:02 +05:30
|
|
|
streams_.push_back(DefaultStream());
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-28 19:32:37 +02:00
|
|
|
TEST_F(VideoCodecInitializerTest, Vp9SvcDefaultLayering) {
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP9, 3, 3, false);
|
|
|
|
|
VideoStream stream = DefaultStream();
|
|
|
|
|
stream.num_temporal_layers = 3;
|
|
|
|
|
streams_.push_back(stream);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 3u);
|
|
|
|
|
EXPECT_EQ(codec_out_.VP9()->numberOfTemporalLayers, 3u);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(VideoCodecInitializerTest, Vp9SvcAdjustedLayering) {
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP9, 3, 3, false);
|
|
|
|
|
VideoStream stream = DefaultStream();
|
|
|
|
|
stream.num_temporal_layers = 3;
|
|
|
|
|
// Set resolution which is only enough to produce 2 spatial layers.
|
2021-12-09 09:43:56 +01:00
|
|
|
stream.width = kMinVp9SpatialLayerLongSideLength * 2;
|
|
|
|
|
stream.height = kMinVp9SpatialLayerShortSideLength * 2;
|
2018-03-28 19:32:37 +02:00
|
|
|
|
|
|
|
|
streams_.push_back(stream);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 2u);
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-13 16:36:39 +02:00
|
|
|
TEST_F(VideoCodecInitializerTest,
|
|
|
|
|
Vp9SingleSpatialLayerMaxBitrateIsEqualToCodecMaxBitrate) {
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP9, 1, 3, false);
|
|
|
|
|
VideoStream stream = DefaultStream();
|
|
|
|
|
stream.num_temporal_layers = 3;
|
|
|
|
|
streams_.push_back(stream);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
EXPECT_EQ(codec_out_.spatialLayers[0].maxBitrate,
|
|
|
|
|
kDefaultMaxBitrateBps / 1000);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-05 10:08:35 +01:00
|
|
|
TEST_F(VideoCodecInitializerTest,
|
|
|
|
|
Vp9SingleSpatialLayerTargetBitrateIsEqualToCodecMaxBitrate) {
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP9, 1, 1, true);
|
|
|
|
|
VideoStream stream = DefaultStream();
|
|
|
|
|
stream.num_temporal_layers = 1;
|
|
|
|
|
streams_.push_back(stream);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
EXPECT_EQ(codec_out_.spatialLayers[0].targetBitrate,
|
|
|
|
|
kDefaultMaxBitrateBps / 1000);
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-28 13:32:13 +01:00
|
|
|
TEST_F(VideoCodecInitializerTest,
|
|
|
|
|
Vp9KeepBitrateLimitsIfNumberOfSpatialLayersIsReducedToOne) {
|
|
|
|
|
// Request 3 spatial layers for 320x180 input. Actual number of layers will be
|
|
|
|
|
// reduced to 1 due to low input resolution but SVC bitrate limits should be
|
|
|
|
|
// applied.
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP9, 3, 3, false);
|
|
|
|
|
VideoStream stream = DefaultStream();
|
|
|
|
|
stream.width = 320;
|
|
|
|
|
stream.height = 180;
|
|
|
|
|
stream.num_temporal_layers = 3;
|
|
|
|
|
streams_.push_back(stream);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
EXPECT_LT(codec_out_.spatialLayers[0].maxBitrate,
|
|
|
|
|
kDefaultMaxBitrateBps / 1000);
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-10 09:28:53 +01:00
|
|
|
TEST_F(VideoCodecInitializerTest, Vp9DeactivateLayers) {
|
|
|
|
|
SetUpFor(VideoCodecType::kVideoCodecVP9, 3, 1, false);
|
|
|
|
|
VideoStream stream = DefaultStream();
|
|
|
|
|
streams_.push_back(stream);
|
|
|
|
|
|
|
|
|
|
config_.simulcast_layers.resize(3);
|
|
|
|
|
|
|
|
|
|
// Activate all layers.
|
|
|
|
|
config_.simulcast_layers[0].active = true;
|
|
|
|
|
config_.simulcast_layers[1].active = true;
|
|
|
|
|
config_.simulcast_layers[2].active = true;
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
2020-09-22 15:55:23 +02:00
|
|
|
EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 3);
|
2018-12-10 09:28:53 +01:00
|
|
|
EXPECT_TRUE(codec_out_.spatialLayers[0].active);
|
|
|
|
|
EXPECT_TRUE(codec_out_.spatialLayers[1].active);
|
|
|
|
|
EXPECT_TRUE(codec_out_.spatialLayers[2].active);
|
|
|
|
|
|
|
|
|
|
// Deactivate top layer.
|
2020-09-22 15:55:23 +02:00
|
|
|
config_.simulcast_layers[0].active = true;
|
|
|
|
|
config_.simulcast_layers[1].active = true;
|
2020-02-05 17:31:00 +01:00
|
|
|
config_.simulcast_layers[2].active = false;
|
2018-12-10 09:28:53 +01:00
|
|
|
EXPECT_TRUE(InitializeCodec());
|
2020-09-22 15:55:23 +02:00
|
|
|
EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 3);
|
2018-12-10 09:28:53 +01:00
|
|
|
EXPECT_TRUE(codec_out_.spatialLayers[0].active);
|
|
|
|
|
EXPECT_TRUE(codec_out_.spatialLayers[1].active);
|
|
|
|
|
EXPECT_FALSE(codec_out_.spatialLayers[2].active);
|
|
|
|
|
|
|
|
|
|
// Deactivate middle layer.
|
2020-09-22 15:55:23 +02:00
|
|
|
config_.simulcast_layers[0].active = true;
|
2018-12-10 09:28:53 +01:00
|
|
|
config_.simulcast_layers[1].active = false;
|
2020-09-22 15:55:23 +02:00
|
|
|
config_.simulcast_layers[2].active = true;
|
2018-12-10 09:28:53 +01:00
|
|
|
EXPECT_TRUE(InitializeCodec());
|
2020-09-22 15:55:23 +02:00
|
|
|
EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 3);
|
2018-12-10 09:28:53 +01:00
|
|
|
EXPECT_TRUE(codec_out_.spatialLayers[0].active);
|
|
|
|
|
EXPECT_FALSE(codec_out_.spatialLayers[1].active);
|
|
|
|
|
EXPECT_TRUE(codec_out_.spatialLayers[2].active);
|
2020-09-22 15:55:23 +02:00
|
|
|
|
|
|
|
|
// Deactivate first layer.
|
|
|
|
|
config_.simulcast_layers[0].active = false;
|
|
|
|
|
config_.simulcast_layers[1].active = true;
|
|
|
|
|
config_.simulcast_layers[2].active = true;
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 2);
|
|
|
|
|
EXPECT_TRUE(codec_out_.spatialLayers[0].active);
|
|
|
|
|
EXPECT_TRUE(codec_out_.spatialLayers[1].active);
|
|
|
|
|
|
|
|
|
|
// HD singlecast.
|
|
|
|
|
config_.simulcast_layers[0].active = false;
|
|
|
|
|
config_.simulcast_layers[1].active = false;
|
|
|
|
|
config_.simulcast_layers[2].active = true;
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 1);
|
|
|
|
|
EXPECT_TRUE(codec_out_.spatialLayers[0].active);
|
|
|
|
|
|
|
|
|
|
// VGA singlecast.
|
|
|
|
|
config_.simulcast_layers[0].active = false;
|
|
|
|
|
config_.simulcast_layers[1].active = true;
|
|
|
|
|
config_.simulcast_layers[2].active = false;
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 2);
|
|
|
|
|
EXPECT_TRUE(codec_out_.spatialLayers[0].active);
|
|
|
|
|
EXPECT_FALSE(codec_out_.spatialLayers[1].active);
|
|
|
|
|
|
|
|
|
|
// QVGA singlecast.
|
|
|
|
|
config_.simulcast_layers[0].active = true;
|
|
|
|
|
config_.simulcast_layers[1].active = false;
|
|
|
|
|
config_.simulcast_layers[2].active = false;
|
|
|
|
|
EXPECT_TRUE(InitializeCodec());
|
|
|
|
|
EXPECT_EQ(codec_out_.VP9()->numberOfSpatialLayers, 3);
|
|
|
|
|
EXPECT_TRUE(codec_out_.spatialLayers[0].active);
|
|
|
|
|
EXPECT_FALSE(codec_out_.spatialLayers[1].active);
|
|
|
|
|
EXPECT_FALSE(codec_out_.spatialLayers[2].active);
|
2018-12-10 09:28:53 +01:00
|
|
|
}
|
|
|
|
|
|
2021-05-04 13:06:29 +02:00
|
|
|
TEST_F(VideoCodecInitializerTest, Av1SingleSpatialLayerBitratesAreConsistent) {
|
|
|
|
|
VideoEncoderConfig config;
|
|
|
|
|
config.codec_type = VideoCodecType::kVideoCodecAV1;
|
|
|
|
|
std::vector<VideoStream> streams = {DefaultStream()};
|
|
|
|
|
streams[0].scalability_mode = "L1T2";
|
|
|
|
|
|
|
|
|
|
VideoCodec codec;
|
|
|
|
|
EXPECT_TRUE(VideoCodecInitializer::SetupCodec(config, streams, &codec));
|
|
|
|
|
|
|
|
|
|
EXPECT_GE(codec.spatialLayers[0].targetBitrate,
|
|
|
|
|
codec.spatialLayers[0].minBitrate);
|
|
|
|
|
EXPECT_LE(codec.spatialLayers[0].targetBitrate,
|
|
|
|
|
codec.spatialLayers[0].maxBitrate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(VideoCodecInitializerTest, Av1TwoSpatialLayersBitratesAreConsistent) {
|
|
|
|
|
VideoEncoderConfig config;
|
|
|
|
|
config.codec_type = VideoCodecType::kVideoCodecAV1;
|
|
|
|
|
std::vector<VideoStream> streams = {DefaultStream()};
|
|
|
|
|
streams[0].scalability_mode = "L2T2";
|
|
|
|
|
|
|
|
|
|
VideoCodec codec;
|
|
|
|
|
EXPECT_TRUE(VideoCodecInitializer::SetupCodec(config, streams, &codec));
|
|
|
|
|
|
|
|
|
|
EXPECT_GE(codec.spatialLayers[0].targetBitrate,
|
|
|
|
|
codec.spatialLayers[0].minBitrate);
|
|
|
|
|
EXPECT_LE(codec.spatialLayers[0].targetBitrate,
|
|
|
|
|
codec.spatialLayers[0].maxBitrate);
|
|
|
|
|
|
|
|
|
|
EXPECT_GE(codec.spatialLayers[1].targetBitrate,
|
|
|
|
|
codec.spatialLayers[1].minBitrate);
|
|
|
|
|
EXPECT_LE(codec.spatialLayers[1].targetBitrate,
|
|
|
|
|
codec.spatialLayers[1].maxBitrate);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-01 16:52:24 +02:00
|
|
|
TEST_F(VideoCodecInitializerTest, Av1TwoSpatialLayersActiveByDefault) {
|
|
|
|
|
VideoEncoderConfig config;
|
|
|
|
|
config.codec_type = VideoCodecType::kVideoCodecAV1;
|
|
|
|
|
std::vector<VideoStream> streams = {DefaultStream()};
|
|
|
|
|
streams[0].scalability_mode = "L2T2";
|
|
|
|
|
config.spatial_layers = {};
|
|
|
|
|
|
|
|
|
|
VideoCodec codec;
|
|
|
|
|
EXPECT_TRUE(VideoCodecInitializer::SetupCodec(config, streams, &codec));
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(codec.spatialLayers[0].active);
|
|
|
|
|
EXPECT_TRUE(codec.spatialLayers[1].active);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(VideoCodecInitializerTest, Av1TwoSpatialLayersOneDeactivated) {
|
|
|
|
|
VideoEncoderConfig config;
|
|
|
|
|
config.codec_type = VideoCodecType::kVideoCodecAV1;
|
|
|
|
|
std::vector<VideoStream> streams = {DefaultStream()};
|
|
|
|
|
streams[0].scalability_mode = "L2T2";
|
|
|
|
|
config.spatial_layers.resize(2);
|
|
|
|
|
config.spatial_layers[0].active = true;
|
|
|
|
|
config.spatial_layers[1].active = false;
|
|
|
|
|
|
|
|
|
|
VideoCodec codec;
|
|
|
|
|
EXPECT_TRUE(VideoCodecInitializer::SetupCodec(config, streams, &codec));
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(codec.spatialLayers[0].active);
|
|
|
|
|
EXPECT_FALSE(codec.spatialLayers[1].active);
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-26 06:12:26 -08:00
|
|
|
} // namespace webrtc
|