Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
Jonas Olsson | a4d8737 | 2019-07-05 17:08:33 | [diff] [blame] | 11 | #include "api/video_codecs/video_encoder_software_fallback_wrapper.h" |
| 12 | |
Yves Gerey | 3e70781 | 2018-11-28 15:47:49 | [diff] [blame] | 13 | #include <stddef.h> |
| 14 | #include <stdint.h> |
Jonas Olsson | a4d8737 | 2019-07-05 17:08:33 | [diff] [blame] | 15 | |
Yves Gerey | 3e70781 | 2018-11-28 15:47:49 | [diff] [blame] | 16 | #include <memory> |
| 17 | #include <string> |
| 18 | #include <vector> |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 19 | |
Yves Gerey | 3e70781 | 2018-11-28 15:47:49 | [diff] [blame] | 20 | #include "absl/types/optional.h" |
Elad Alon | 8f01c4e | 2019-06-28 13:19:43 | [diff] [blame] | 21 | #include "api/fec_controller_override.h" |
Mirko Bonadei | d970807 | 2019-01-25 19:26:48 | [diff] [blame] | 22 | #include "api/scoped_refptr.h" |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 23 | #include "api/test/mock_video_encoder.h" |
Yves Gerey | 3e70781 | 2018-11-28 15:47:49 | [diff] [blame] | 24 | #include "api/video/encoded_image.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 04:47:31 | [diff] [blame] | 25 | #include "api/video/i420_buffer.h" |
Erik Språng | 7fd0a28 | 2018-05-22 13:37:23 | [diff] [blame] | 26 | #include "api/video/video_bitrate_allocation.h" |
Yves Gerey | 3e70781 | 2018-11-28 15:47:49 | [diff] [blame] | 27 | #include "api/video/video_frame.h" |
| 28 | #include "api/video/video_frame_buffer.h" |
| 29 | #include "api/video/video_rotation.h" |
| 30 | #include "api/video_codecs/video_codec.h" |
| 31 | #include "api/video_codecs/video_encoder.h" |
Yves Gerey | 3e70781 | 2018-11-28 15:47:49 | [diff] [blame] | 32 | #include "modules/include/module_common_types.h" |
Magnus Jedvert | ee92d62 | 2017-11-13 14:26:17 | [diff] [blame] | 33 | #include "modules/video_coding/codecs/vp8/include/vp8.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 04:47:31 | [diff] [blame] | 34 | #include "modules/video_coding/include/video_codec_interface.h" |
| 35 | #include "modules/video_coding/include/video_error_codes.h" |
Sergio Garcia Murillo | 43800f9 | 2018-06-21 14:16:38 | [diff] [blame] | 36 | #include "modules/video_coding/utility/simulcast_rate_allocator.h" |
Steve Anton | 10542f2 | 2019-01-11 17:11:00 | [diff] [blame] | 37 | #include "rtc_base/fake_clock.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 04:47:31 | [diff] [blame] | 38 | #include "test/field_trial.h" |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 39 | #include "test/gmock.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 04:47:31 | [diff] [blame] | 40 | #include "test/gtest.h" |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 41 | |
| 42 | namespace webrtc { |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 43 | using ::testing::Return; |
| 44 | |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 45 | namespace { |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 46 | const int kWidth = 320; |
| 47 | const int kHeight = 240; |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 48 | const int kNumCores = 2; |
| 49 | const uint32_t kFramerate = 30; |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 50 | const size_t kMaxPayloadSize = 800; |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 51 | const int kDefaultMinPixelsPerFrame = 320 * 180; |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 52 | const int kLowThreshold = 10; |
| 53 | const int kHighThreshold = 20; |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 54 | |
Elad Alon | 370f93a | 2019-06-11 12:57:57 | [diff] [blame] | 55 | const VideoEncoder::Capabilities kCapabilities(false); |
| 56 | const VideoEncoder::Settings kSettings(kCapabilities, |
| 57 | kNumCores, |
| 58 | kMaxPayloadSize); |
| 59 | |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 60 | VideoEncoder::EncoderInfo GetEncoderInfoWithTrustedRateController( |
| 61 | bool trusted_rate_controller) { |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 62 | VideoEncoder::EncoderInfo info; |
| 63 | info.has_trusted_rate_controller = trusted_rate_controller; |
| 64 | return info; |
| 65 | } |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 66 | |
| 67 | VideoEncoder::EncoderInfo GetEncoderInfoWithHardwareAccelerated( |
| 68 | bool hardware_accelerated) { |
| 69 | VideoEncoder::EncoderInfo info; |
| 70 | info.is_hardware_accelerated = hardware_accelerated; |
| 71 | return info; |
| 72 | } |
| 73 | |
| 74 | VideoEncoder::EncoderInfo GetEncoderInfoWithInternalSource( |
| 75 | bool internal_source) { |
| 76 | VideoEncoder::EncoderInfo info; |
| 77 | info.has_internal_source = internal_source; |
| 78 | return info; |
| 79 | } |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 80 | } // namespace |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 81 | |
| 82 | class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test { |
| 83 | protected: |
| 84 | VideoEncoderSoftwareFallbackWrapperTest() |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 85 | : VideoEncoderSoftwareFallbackWrapperTest("") {} |
| 86 | explicit VideoEncoderSoftwareFallbackWrapperTest( |
| 87 | const std::string& field_trials) |
| 88 | : override_field_trials_(field_trials), |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 89 | fake_encoder_(new CountingFakeEncoder()), |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 90 | fallback_wrapper_(CreateVideoEncoderSoftwareFallbackWrapper( |
| 91 | std::unique_ptr<VideoEncoder>(VP8Encoder::Create()), |
| 92 | std::unique_ptr<VideoEncoder>(fake_encoder_))) {} |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 93 | |
| 94 | class CountingFakeEncoder : public VideoEncoder { |
| 95 | public: |
Elad Alon | 8f01c4e | 2019-06-28 13:19:43 | [diff] [blame] | 96 | void SetFecControllerOverride( |
| 97 | FecControllerOverride* fec_controller_override) override { |
| 98 | // Ignored. |
| 99 | } |
| 100 | |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 101 | int32_t InitEncode(const VideoCodec* codec_settings, |
Elad Alon | 370f93a | 2019-06-11 12:57:57 | [diff] [blame] | 102 | const VideoEncoder::Settings& settings) override { |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 103 | ++init_encode_count_; |
| 104 | return init_encode_return_code_; |
| 105 | } |
Elad Alon | 370f93a | 2019-06-11 12:57:57 | [diff] [blame] | 106 | |
Miguel Casas-Sanchez | 4765070 | 2015-05-30 00:21:40 | [diff] [blame] | 107 | int32_t Encode(const VideoFrame& frame, |
Niels Möller | 87e2d78 | 2019-03-07 09:18:23 | [diff] [blame] | 108 | const std::vector<VideoFrameType>* frame_types) override { |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 109 | ++encode_count_; |
perkj | 275afc5 | 2016-09-01 07:21:16 | [diff] [blame] | 110 | if (encode_complete_callback_ && |
| 111 | encode_return_code_ == WEBRTC_VIDEO_CODEC_OK) { |
Erik Språng | e2fd86a7 | 2018-10-24 09:32:39 | [diff] [blame] | 112 | encode_complete_callback_->OnEncodedImage(EncodedImage(), nullptr, |
perkj | 275afc5 | 2016-09-01 07:21:16 | [diff] [blame] | 113 | nullptr); |
| 114 | } |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 115 | return encode_return_code_; |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 116 | } |
| 117 | |
| 118 | int32_t RegisterEncodeCompleteCallback( |
| 119 | EncodedImageCallback* callback) override { |
| 120 | encode_complete_callback_ = callback; |
| 121 | return WEBRTC_VIDEO_CODEC_OK; |
| 122 | } |
| 123 | |
| 124 | int32_t Release() override { |
| 125 | ++release_count_; |
| 126 | return WEBRTC_VIDEO_CODEC_OK; |
| 127 | } |
| 128 | |
Erik Språng | 16cb8f5 | 2019-04-12 11:59:09 | [diff] [blame] | 129 | void SetRates(const RateControlParameters& parameters) override { |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 130 | ++set_rates_count_; |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 131 | } |
| 132 | |
Erik Språng | e2fd86a7 | 2018-10-24 09:32:39 | [diff] [blame] | 133 | EncoderInfo GetEncoderInfo() const override { |
Peter Boström | eb66e80 | 2015-06-05 09:08:03 | [diff] [blame] | 134 | ++supports_native_handle_count_; |
Erik Språng | ff7020a | 2018-11-06 14:32:48 | [diff] [blame] | 135 | EncoderInfo info; |
| 136 | info.scaling_settings = ScalingSettings(kLowThreshold, kHighThreshold); |
| 137 | info.supports_native_handle = supports_native_handle_; |
| 138 | info.implementation_name = "fake-encoder"; |
| 139 | return info; |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 140 | } |
| 141 | |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 142 | int init_encode_count_ = 0; |
| 143 | int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK; |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 144 | int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK; |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 145 | int encode_count_ = 0; |
| 146 | EncodedImageCallback* encode_complete_callback_ = nullptr; |
| 147 | int release_count_ = 0; |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 148 | int set_rates_count_ = 0; |
Peter Boström | eb66e80 | 2015-06-05 09:08:03 | [diff] [blame] | 149 | mutable int supports_native_handle_count_ = 0; |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 150 | bool supports_native_handle_ = false; |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 151 | }; |
| 152 | |
| 153 | class FakeEncodedImageCallback : public EncodedImageCallback { |
| 154 | public: |
Sergey Ulanov | 525df3f | 2016-08-03 00:46:41 | [diff] [blame] | 155 | Result OnEncodedImage( |
| 156 | const EncodedImage& encoded_image, |
| 157 | const CodecSpecificInfo* codec_specific_info, |
| 158 | const RTPFragmentationHeader* fragmentation) override { |
| 159 | ++callback_count_; |
| 160 | return Result(Result::OK, callback_count_); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 161 | } |
| 162 | int callback_count_ = 0; |
| 163 | }; |
| 164 | |
| 165 | void UtilizeFallbackEncoder(); |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 166 | void FallbackFromEncodeRequest(); |
| 167 | void EncodeFrame(); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 168 | void EncodeFrame(int expected_ret); |
perkj | 275afc5 | 2016-09-01 07:21:16 | [diff] [blame] | 169 | void CheckLastEncoderName(const char* expected_name) { |
Erik Språng | e2fd86a7 | 2018-10-24 09:32:39 | [diff] [blame] | 170 | EXPECT_EQ(expected_name, |
| 171 | fallback_wrapper_->GetEncoderInfo().implementation_name); |
perkj | 275afc5 | 2016-09-01 07:21:16 | [diff] [blame] | 172 | } |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 173 | |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 174 | test::ScopedFieldTrials override_field_trials_; |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 175 | FakeEncodedImageCallback callback_; |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 176 | // |fake_encoder_| is owned and released by |fallback_wrapper_|. |
| 177 | CountingFakeEncoder* fake_encoder_; |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 178 | std::unique_ptr<VideoEncoder> fallback_wrapper_; |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 179 | VideoCodec codec_ = {}; |
nisse | 64ec8f8 | 2016-09-27 07:17:25 | [diff] [blame] | 180 | std::unique_ptr<VideoFrame> frame_; |
Erik Språng | 08127a9 | 2016-11-16 15:41:30 | [diff] [blame] | 181 | std::unique_ptr<SimulcastRateAllocator> rate_allocator_; |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 182 | }; |
| 183 | |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 184 | void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame() { |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 185 | EncodeFrame(WEBRTC_VIDEO_CODEC_OK); |
| 186 | } |
| 187 | |
| 188 | void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame(int expected_ret) { |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 189 | rtc::scoped_refptr<I420Buffer> buffer = |
| 190 | I420Buffer::Create(codec_.width, codec_.height); |
nisse | af91689 | 2017-01-10 15:44:26 | [diff] [blame] | 191 | I420Buffer::SetBlack(buffer); |
Niels Möller | 8f7ce22 | 2019-03-21 14:43:58 | [diff] [blame] | 192 | std::vector<VideoFrameType> types(1, VideoFrameType::kVideoFrameKey); |
nisse | 64ec8f8 | 2016-09-27 07:17:25 | [diff] [blame] | 193 | |
Artem Titov | 1ebfb6a | 2019-01-03 22:49:37 | [diff] [blame] | 194 | frame_ = |
Mirko Bonadei | 317a1f0 | 2019-09-17 15:06:18 | [diff] [blame^] | 195 | std::make_unique<VideoFrame>(VideoFrame::Builder() |
| 196 | .set_video_frame_buffer(buffer) |
| 197 | .set_rotation(webrtc::kVideoRotation_0) |
| 198 | .set_timestamp_us(0) |
| 199 | .build()); |
Niels Möller | c8d2e73 | 2019-03-06 11:00:33 | [diff] [blame] | 200 | EXPECT_EQ(expected_ret, fallback_wrapper_->Encode(*frame_, &types)); |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 201 | } |
| 202 | |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 203 | void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() { |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 204 | fallback_wrapper_->RegisterEncodeCompleteCallback(&callback_); |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 205 | EXPECT_EQ(&callback_, fake_encoder_->encode_complete_callback_); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 206 | |
| 207 | // Register with failing fake encoder. Should succeed with VP8 fallback. |
| 208 | codec_.codecType = kVideoCodecVP8; |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 209 | codec_.maxFramerate = kFramerate; |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 210 | codec_.width = kWidth; |
| 211 | codec_.height = kHeight; |
Erik Språng | 08127a9 | 2016-11-16 15:41:30 | [diff] [blame] | 212 | codec_.VP8()->numberOfTemporalLayers = 1; |
Erik Språng | 82fad3d | 2018-03-21 08:57:23 | [diff] [blame] | 213 | rate_allocator_.reset(new SimulcastRateAllocator(codec_)); |
Erik Språng | 08127a9 | 2016-11-16 15:41:30 | [diff] [blame] | 214 | |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 215 | fake_encoder_->init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR; |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 216 | EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
Elad Alon | 370f93a | 2019-06-11 12:57:57 | [diff] [blame] | 217 | fallback_wrapper_->InitEncode(&codec_, kSettings)); |
Erik Språng | 16cb8f5 | 2019-04-12 11:59:09 | [diff] [blame] | 218 | fallback_wrapper_->SetRates(VideoEncoder::RateControlParameters( |
Florent Castelli | 8bbdb5b | 2019-08-02 13:16:28 | [diff] [blame] | 219 | rate_allocator_->Allocate( |
| 220 | VideoBitrateAllocationParameters(300000, kFramerate)), |
| 221 | kFramerate)); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 222 | |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 223 | int callback_count = callback_.callback_count_; |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 224 | int encode_count = fake_encoder_->encode_count_; |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 225 | EncodeFrame(); |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 226 | EXPECT_EQ(encode_count, fake_encoder_->encode_count_); |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 227 | EXPECT_EQ(callback_count + 1, callback_.callback_count_); |
| 228 | } |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 229 | |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 230 | void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() { |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 231 | fallback_wrapper_->RegisterEncodeCompleteCallback(&callback_); |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 232 | codec_.codecType = kVideoCodecVP8; |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 233 | codec_.maxFramerate = kFramerate; |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 234 | codec_.width = kWidth; |
| 235 | codec_.height = kHeight; |
Erik Språng | 08127a9 | 2016-11-16 15:41:30 | [diff] [blame] | 236 | codec_.VP8()->numberOfTemporalLayers = 1; |
Erik Språng | 82fad3d | 2018-03-21 08:57:23 | [diff] [blame] | 237 | rate_allocator_.reset(new SimulcastRateAllocator(codec_)); |
Elad Alon | 370f93a | 2019-06-11 12:57:57 | [diff] [blame] | 238 | fallback_wrapper_->InitEncode(&codec_, kSettings); |
Erik Språng | 16cb8f5 | 2019-04-12 11:59:09 | [diff] [blame] | 239 | fallback_wrapper_->SetRates(VideoEncoder::RateControlParameters( |
Florent Castelli | 8bbdb5b | 2019-08-02 13:16:28 | [diff] [blame] | 240 | rate_allocator_->Allocate( |
| 241 | VideoBitrateAllocationParameters(300000, kFramerate)), |
| 242 | kFramerate)); |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 243 | EXPECT_EQ(1, fake_encoder_->init_encode_count_); |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 244 | |
| 245 | // Have the non-fallback encoder request a software fallback. |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 246 | fake_encoder_->encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 247 | int callback_count = callback_.callback_count_; |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 248 | int encode_count = fake_encoder_->encode_count_; |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 249 | EncodeFrame(); |
| 250 | // Single encode request, which returned failure. |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 251 | EXPECT_EQ(encode_count + 1, fake_encoder_->encode_count_); |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 252 | EXPECT_EQ(callback_count + 1, callback_.callback_count_); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 253 | } |
| 254 | |
| 255 | TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) { |
| 256 | VideoCodec codec = {}; |
Elad Alon | 370f93a | 2019-06-11 12:57:57 | [diff] [blame] | 257 | fallback_wrapper_->InitEncode(&codec, kSettings); |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 258 | EXPECT_EQ(1, fake_encoder_->init_encode_count_); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 259 | } |
| 260 | |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 261 | TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) { |
| 262 | FallbackFromEncodeRequest(); |
| 263 | // After fallback, further encodes shouldn't hit the fake encoder. |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 264 | int encode_count = fake_encoder_->encode_count_; |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 265 | EncodeFrame(); |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 266 | EXPECT_EQ(encode_count, fake_encoder_->encode_count_); |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 267 | } |
| 268 | |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 269 | TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) { |
| 270 | UtilizeFallbackEncoder(); |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 271 | EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 272 | } |
| 273 | |
| 274 | TEST_F(VideoEncoderSoftwareFallbackWrapperTest, |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 275 | InternalEncoderReleasedDuringFallback) { |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 276 | EXPECT_EQ(0, fake_encoder_->release_count_); |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 277 | UtilizeFallbackEncoder(); |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 278 | EXPECT_EQ(1, fake_encoder_->release_count_); |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 279 | EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 280 | // No extra release when the fallback is released. |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 281 | EXPECT_EQ(1, fake_encoder_->release_count_); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 282 | } |
| 283 | |
| 284 | TEST_F(VideoEncoderSoftwareFallbackWrapperTest, |
| 285 | InternalEncoderNotEncodingDuringFallback) { |
| 286 | UtilizeFallbackEncoder(); |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 287 | int encode_count = fake_encoder_->encode_count_; |
noahric | b1ce663 | 2015-10-22 06:54:51 | [diff] [blame] | 288 | EncodeFrame(); |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 289 | EXPECT_EQ(encode_count, fake_encoder_->encode_count_); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 290 | |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 291 | EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 292 | } |
| 293 | |
| 294 | TEST_F(VideoEncoderSoftwareFallbackWrapperTest, |
| 295 | CanRegisterCallbackWhileUsingFallbackEncoder) { |
| 296 | UtilizeFallbackEncoder(); |
| 297 | // Registering an encode-complete callback should still work when fallback |
| 298 | // encoder is being used. |
| 299 | FakeEncodedImageCallback callback2; |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 300 | fallback_wrapper_->RegisterEncodeCompleteCallback(&callback2); |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 301 | EXPECT_EQ(&callback2, fake_encoder_->encode_complete_callback_); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 302 | |
| 303 | // Encoding a frame using the fallback should arrive at the new callback. |
Niels Möller | 8f7ce22 | 2019-03-21 14:43:58 | [diff] [blame] | 304 | std::vector<VideoFrameType> types(1, VideoFrameType::kVideoFrameKey); |
nisse | 64ec8f8 | 2016-09-27 07:17:25 | [diff] [blame] | 305 | frame_->set_timestamp(frame_->timestamp() + 1000); |
Niels Möller | c8d2e73 | 2019-03-06 11:00:33 | [diff] [blame] | 306 | EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Encode(*frame_, &types)); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 307 | |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 308 | EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 309 | } |
| 310 | |
| 311 | TEST_F(VideoEncoderSoftwareFallbackWrapperTest, |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 312 | SetRatesForwardedDuringFallback) { |
| 313 | UtilizeFallbackEncoder(); |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 314 | EXPECT_EQ(1, fake_encoder_->set_rates_count_); |
Erik Språng | 16cb8f5 | 2019-04-12 11:59:09 | [diff] [blame] | 315 | fallback_wrapper_->SetRates( |
| 316 | VideoEncoder::RateControlParameters(VideoBitrateAllocation(), 1)); |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 317 | EXPECT_EQ(2, fake_encoder_->set_rates_count_); |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 318 | EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 319 | } |
| 320 | |
| 321 | TEST_F(VideoEncoderSoftwareFallbackWrapperTest, |
Peter Boström | eb66e80 | 2015-06-05 09:08:03 | [diff] [blame] | 322 | SupportsNativeHandleForwardedWithoutFallback) { |
Erik Språng | e2fd86a7 | 2018-10-24 09:32:39 | [diff] [blame] | 323 | fallback_wrapper_->GetEncoderInfo(); |
magjed | f52d34d | 2017-08-29 07:58:52 | [diff] [blame] | 324 | EXPECT_EQ(1, fake_encoder_->supports_native_handle_count_); |
Peter Boström | eb66e80 | 2015-06-05 09:08:03 | [diff] [blame] | 325 | } |
| 326 | |
| 327 | TEST_F(VideoEncoderSoftwareFallbackWrapperTest, |
| 328 | SupportsNativeHandleNotForwardedDuringFallback) { |
Erik Språng | e2fd86a7 | 2018-10-24 09:32:39 | [diff] [blame] | 329 | // Fake encoder signals support for native handle, default (libvpx) does not. |
| 330 | fake_encoder_->supports_native_handle_ = true; |
| 331 | EXPECT_TRUE(fallback_wrapper_->GetEncoderInfo().supports_native_handle); |
Peter Boström | eb66e80 | 2015-06-05 09:08:03 | [diff] [blame] | 332 | UtilizeFallbackEncoder(); |
Erik Språng | e2fd86a7 | 2018-10-24 09:32:39 | [diff] [blame] | 333 | EXPECT_FALSE(fallback_wrapper_->GetEncoderInfo().supports_native_handle); |
| 334 | // Both times, both encoders are queried. |
| 335 | EXPECT_EQ(2, fake_encoder_->supports_native_handle_count_); |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 336 | EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); |
Peter Boström | eb66e80 | 2015-06-05 09:08:03 | [diff] [blame] | 337 | } |
| 338 | |
perkj | 275afc5 | 2016-09-01 07:21:16 | [diff] [blame] | 339 | TEST_F(VideoEncoderSoftwareFallbackWrapperTest, ReportsImplementationName) { |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 340 | codec_.width = kWidth; |
| 341 | codec_.height = kHeight; |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 342 | fallback_wrapper_->RegisterEncodeCompleteCallback(&callback_); |
Elad Alon | 370f93a | 2019-06-11 12:57:57 | [diff] [blame] | 343 | fallback_wrapper_->InitEncode(&codec_, kSettings); |
perkj | 275afc5 | 2016-09-01 07:21:16 | [diff] [blame] | 344 | EncodeFrame(); |
| 345 | CheckLastEncoderName("fake-encoder"); |
| 346 | } |
| 347 | |
Peter Boström | b7d9a97 | 2015-12-18 15:01:11 | [diff] [blame] | 348 | TEST_F(VideoEncoderSoftwareFallbackWrapperTest, |
| 349 | ReportsFallbackImplementationName) { |
| 350 | UtilizeFallbackEncoder(); |
| 351 | // Hard coded expected value since libvpx is the software implementation name |
| 352 | // for VP8. Change accordingly if the underlying implementation does. |
perkj | 275afc5 | 2016-09-01 07:21:16 | [diff] [blame] | 353 | CheckLastEncoderName("libvpx"); |
Peter Boström | b7d9a97 | 2015-12-18 15:01:11 | [diff] [blame] | 354 | } |
| 355 | |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 356 | namespace { |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 357 | const int kBitrateKbps = 200; |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 358 | const int kMinPixelsPerFrame = 1; |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 359 | const char kFieldTrial[] = "WebRTC-VP8-Forced-Fallback-Encoder-v2"; |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 360 | } // namespace |
| 361 | |
| 362 | class ForcedFallbackTest : public VideoEncoderSoftwareFallbackWrapperTest { |
| 363 | public: |
Steve Anton | e78bcb9 | 2017-10-31 16:53:08 | [diff] [blame] | 364 | explicit ForcedFallbackTest(const std::string& field_trials) |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 365 | : VideoEncoderSoftwareFallbackWrapperTest(field_trials) {} |
| 366 | |
| 367 | ~ForcedFallbackTest() override {} |
| 368 | |
| 369 | protected: |
| 370 | void SetUp() override { |
Sebastian Jansson | 40889f3 | 2019-04-17 10:11:20 | [diff] [blame] | 371 | clock_.SetTime(Timestamp::us(1234)); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 372 | ConfigureVp8Codec(); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 373 | } |
| 374 | |
| 375 | void TearDown() override { |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 376 | EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_->Release()); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 377 | } |
| 378 | |
| 379 | void ConfigureVp8Codec() { |
Anders Carlsson | dd3e0ab | 2018-06-12 09:15:56 | [diff] [blame] | 380 | fallback_wrapper_->RegisterEncodeCompleteCallback(&callback_); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 381 | codec_.codecType = kVideoCodecVP8; |
| 382 | codec_.maxFramerate = kFramerate; |
| 383 | codec_.width = kWidth; |
| 384 | codec_.height = kHeight; |
| 385 | codec_.VP8()->numberOfTemporalLayers = 1; |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 386 | codec_.VP8()->automaticResizeOn = true; |
| 387 | codec_.VP8()->frameDroppingOn = true; |
Erik Språng | 82fad3d | 2018-03-21 08:57:23 | [diff] [blame] | 388 | rate_allocator_.reset(new SimulcastRateAllocator(codec_)); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 389 | } |
| 390 | |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 391 | void InitEncode(int width, int height) { |
| 392 | codec_.width = width; |
| 393 | codec_.height = height; |
Elad Alon | 370f93a | 2019-06-11 12:57:57 | [diff] [blame] | 394 | EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| 395 | fallback_wrapper_->InitEncode(&codec_, kSettings)); |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 396 | SetRateAllocation(kBitrateKbps); |
| 397 | } |
| 398 | |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 399 | void SetRateAllocation(uint32_t bitrate_kbps) { |
Erik Språng | 16cb8f5 | 2019-04-12 11:59:09 | [diff] [blame] | 400 | fallback_wrapper_->SetRates(VideoEncoder::RateControlParameters( |
Florent Castelli | 8bbdb5b | 2019-08-02 13:16:28 | [diff] [blame] | 401 | rate_allocator_->Allocate( |
| 402 | VideoBitrateAllocationParameters(bitrate_kbps * 1000, kFramerate)), |
Erik Språng | 16cb8f5 | 2019-04-12 11:59:09 | [diff] [blame] | 403 | kFramerate)); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 404 | } |
| 405 | |
| 406 | void EncodeFrameAndVerifyLastName(const char* expected_name) { |
| 407 | EncodeFrameAndVerifyLastName(expected_name, WEBRTC_VIDEO_CODEC_OK); |
| 408 | } |
| 409 | |
| 410 | void EncodeFrameAndVerifyLastName(const char* expected_name, |
| 411 | int expected_ret) { |
| 412 | EncodeFrame(expected_ret); |
| 413 | CheckLastEncoderName(expected_name); |
| 414 | } |
| 415 | |
| 416 | rtc::ScopedFakeClock clock_; |
| 417 | }; |
| 418 | |
| 419 | class ForcedFallbackTestEnabled : public ForcedFallbackTest { |
| 420 | public: |
| 421 | ForcedFallbackTestEnabled() |
Steve Anton | e78bcb9 | 2017-10-31 16:53:08 | [diff] [blame] | 422 | : ForcedFallbackTest(std::string(kFieldTrial) + "/Enabled-" + |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 423 | std::to_string(kMinPixelsPerFrame) + "," + |
| 424 | std::to_string(kWidth * kHeight) + ",30000/") {} |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 425 | }; |
| 426 | |
| 427 | class ForcedFallbackTestDisabled : public ForcedFallbackTest { |
| 428 | public: |
| 429 | ForcedFallbackTestDisabled() |
Steve Anton | e78bcb9 | 2017-10-31 16:53:08 | [diff] [blame] | 430 | : ForcedFallbackTest(std::string(kFieldTrial) + "/Disabled/") {} |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 431 | }; |
| 432 | |
| 433 | TEST_F(ForcedFallbackTestDisabled, NoFallbackWithoutFieldTrial) { |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 434 | // Resolution above max threshold. |
| 435 | InitEncode(kWidth + 1, kHeight); |
| 436 | EXPECT_EQ(1, fake_encoder_->init_encode_count_); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 437 | EncodeFrameAndVerifyLastName("fake-encoder"); |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 438 | |
| 439 | // Resolution at max threshold. |
| 440 | InitEncode(kWidth, kHeight); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 441 | EncodeFrameAndVerifyLastName("fake-encoder"); |
| 442 | } |
| 443 | |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 444 | TEST_F(ForcedFallbackTestEnabled, FallbackIfAtMaxResolutionLimit) { |
| 445 | // Resolution above max threshold. |
| 446 | InitEncode(kWidth + 1, kHeight); |
| 447 | EXPECT_EQ(1, fake_encoder_->init_encode_count_); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 448 | EncodeFrameAndVerifyLastName("fake-encoder"); |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 449 | |
| 450 | // Resolution at max threshold. |
| 451 | InitEncode(kWidth, kHeight); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 452 | EncodeFrameAndVerifyLastName("libvpx"); |
| 453 | } |
| 454 | |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 455 | TEST_F(ForcedFallbackTestEnabled, FallbackIsKeptWhenInitEncodeIsCalled) { |
| 456 | // Resolution above max threshold. |
| 457 | InitEncode(kWidth + 1, kHeight); |
| 458 | EXPECT_EQ(1, fake_encoder_->init_encode_count_); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 459 | EncodeFrameAndVerifyLastName("fake-encoder"); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 460 | |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 461 | // Resolution at max threshold. |
| 462 | InitEncode(kWidth, kHeight); |
| 463 | EncodeFrameAndVerifyLastName("libvpx"); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 464 | |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 465 | // Re-initialize encoder, still expect fallback. |
| 466 | InitEncode(kWidth / 2, kHeight / 2); |
| 467 | EXPECT_EQ(1, fake_encoder_->init_encode_count_); // No change. |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 468 | EncodeFrameAndVerifyLastName("libvpx"); |
| 469 | } |
| 470 | |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 471 | TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedWhenResolutionIsTooLarge) { |
| 472 | // Resolution above max threshold. |
| 473 | InitEncode(kWidth + 1, kHeight); |
| 474 | EXPECT_EQ(1, fake_encoder_->init_encode_count_); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 475 | EncodeFrameAndVerifyLastName("fake-encoder"); |
| 476 | |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 477 | // Resolution at max threshold. |
| 478 | InitEncode(kWidth, kHeight); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 479 | EncodeFrameAndVerifyLastName("libvpx"); |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 480 | |
| 481 | // Re-initialize encoder with a larger resolution, expect no fallback. |
| 482 | InitEncode(kWidth + 1, kHeight); |
| 483 | EXPECT_EQ(2, fake_encoder_->init_encode_count_); |
| 484 | EncodeFrameAndVerifyLastName("fake-encoder"); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 485 | } |
| 486 | |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 487 | TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedForNonValidSettings) { |
| 488 | // Resolution at max threshold. |
| 489 | InitEncode(kWidth, kHeight); |
| 490 | EncodeFrameAndVerifyLastName("libvpx"); |
| 491 | |
| 492 | // Re-initialize encoder with invalid setting, expect no fallback. |
| 493 | codec_.VP8()->numberOfTemporalLayers = 2; |
| 494 | InitEncode(kWidth, kHeight); |
| 495 | EXPECT_EQ(1, fake_encoder_->init_encode_count_); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 496 | EncodeFrameAndVerifyLastName("fake-encoder"); |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 497 | |
| 498 | // Re-initialize encoder with valid setting but fallback disabled from now on. |
| 499 | codec_.VP8()->numberOfTemporalLayers = 1; |
| 500 | InitEncode(kWidth, kHeight); |
| 501 | EXPECT_EQ(2, fake_encoder_->init_encode_count_); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 502 | EncodeFrameAndVerifyLastName("fake-encoder"); |
| 503 | } |
| 504 | |
| 505 | TEST_F(ForcedFallbackTestEnabled, MultipleStartEndFallback) { |
| 506 | const int kNumRuns = 5; |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 507 | for (int i = 1; i <= kNumRuns; ++i) { |
| 508 | // Resolution at max threshold. |
| 509 | InitEncode(kWidth, kHeight); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 510 | EncodeFrameAndVerifyLastName("libvpx"); |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 511 | // Resolution above max threshold. |
| 512 | InitEncode(kWidth + 1, kHeight); |
| 513 | EXPECT_EQ(i, fake_encoder_->init_encode_count_); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 514 | EncodeFrameAndVerifyLastName("fake-encoder"); |
| 515 | } |
| 516 | } |
| 517 | |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 518 | TEST_F(ForcedFallbackTestDisabled, GetScaleSettings) { |
| 519 | // Resolution above max threshold. |
| 520 | InitEncode(kWidth + 1, kHeight); |
| 521 | EXPECT_EQ(1, fake_encoder_->init_encode_count_); |
asapersson | 22c76c4 | 2017-08-16 07:53:59 | [diff] [blame] | 522 | EncodeFrameAndVerifyLastName("fake-encoder"); |
| 523 | |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 524 | // Default min pixels per frame should be used. |
Erik Språng | e2fd86a7 | 2018-10-24 09:32:39 | [diff] [blame] | 525 | const auto settings = fallback_wrapper_->GetEncoderInfo().scaling_settings; |
Niels Möller | 225c787c | 2018-02-22 14:03:53 | [diff] [blame] | 526 | EXPECT_TRUE(settings.thresholds.has_value()); |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 527 | EXPECT_EQ(kDefaultMinPixelsPerFrame, settings.min_pixels_per_frame); |
| 528 | } |
| 529 | |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 530 | TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithNoFallback) { |
| 531 | // Resolution above max threshold. |
| 532 | InitEncode(kWidth + 1, kHeight); |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 533 | EncodeFrameAndVerifyLastName("fake-encoder"); |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 534 | |
| 535 | // Configured min pixels per frame should be used. |
Erik Språng | e2fd86a7 | 2018-10-24 09:32:39 | [diff] [blame] | 536 | const auto settings = fallback_wrapper_->GetEncoderInfo().scaling_settings; |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 537 | EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame); |
| 538 | ASSERT_TRUE(settings.thresholds); |
| 539 | EXPECT_EQ(kLowThreshold, settings.thresholds->low); |
| 540 | EXPECT_EQ(kHighThreshold, settings.thresholds->high); |
| 541 | } |
| 542 | |
| 543 | TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithFallback) { |
| 544 | // Resolution at max threshold. |
| 545 | InitEncode(kWidth, kHeight); |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 546 | EncodeFrameAndVerifyLastName("libvpx"); |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 547 | |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 548 | // Configured min pixels per frame should be used. |
Erik Språng | e2fd86a7 | 2018-10-24 09:32:39 | [diff] [blame] | 549 | const auto settings = fallback_wrapper_->GetEncoderInfo().scaling_settings; |
Niels Möller | 225c787c | 2018-02-22 14:03:53 | [diff] [blame] | 550 | EXPECT_TRUE(settings.thresholds.has_value()); |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 551 | EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame); |
| 552 | } |
| 553 | |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 554 | TEST_F(ForcedFallbackTestEnabled, ScalingDisabledIfResizeOff) { |
| 555 | // Resolution at max threshold. |
| 556 | codec_.VP8()->automaticResizeOn = false; |
| 557 | InitEncode(kWidth, kHeight); |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 558 | EncodeFrameAndVerifyLastName("libvpx"); |
| 559 | |
Åsa Persson | 45bbc8a | 2017-11-13 09:16:47 | [diff] [blame] | 560 | // Should be disabled for automatic resize off. |
Erik Språng | e2fd86a7 | 2018-10-24 09:32:39 | [diff] [blame] | 561 | const auto settings = fallback_wrapper_->GetEncoderInfo().scaling_settings; |
Niels Möller | 225c787c | 2018-02-22 14:03:53 | [diff] [blame] | 562 | EXPECT_FALSE(settings.thresholds.has_value()); |
asapersson | 142fcc9 | 2017-08-17 15:58:54 | [diff] [blame] | 563 | } |
| 564 | |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 565 | TEST(SoftwareFallbackEncoderTest, BothRateControllersNotTrusted) { |
Mirko Bonadei | 6a489f2 | 2019-04-09 13:11:12 | [diff] [blame] | 566 | auto* sw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); |
| 567 | auto* hw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 568 | |
| 569 | EXPECT_CALL(*sw_encoder, GetEncoderInfo()) |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 570 | .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(false))); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 571 | EXPECT_CALL(*hw_encoder, GetEncoderInfo()) |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 572 | .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(false))); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 573 | |
| 574 | std::unique_ptr<VideoEncoder> wrapper = |
| 575 | CreateVideoEncoderSoftwareFallbackWrapper( |
| 576 | std::unique_ptr<VideoEncoder>(sw_encoder), |
| 577 | std::unique_ptr<VideoEncoder>(hw_encoder)); |
| 578 | EXPECT_FALSE(wrapper->GetEncoderInfo().has_trusted_rate_controller); |
| 579 | } |
| 580 | |
| 581 | TEST(SoftwareFallbackEncoderTest, SwRateControllerTrusted) { |
Mirko Bonadei | 6a489f2 | 2019-04-09 13:11:12 | [diff] [blame] | 582 | auto* sw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); |
| 583 | auto* hw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 584 | EXPECT_CALL(*sw_encoder, GetEncoderInfo()) |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 585 | .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(true))); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 586 | EXPECT_CALL(*hw_encoder, GetEncoderInfo()) |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 587 | .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(false))); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 588 | |
| 589 | std::unique_ptr<VideoEncoder> wrapper = |
| 590 | CreateVideoEncoderSoftwareFallbackWrapper( |
| 591 | std::unique_ptr<VideoEncoder>(sw_encoder), |
| 592 | std::unique_ptr<VideoEncoder>(hw_encoder)); |
| 593 | EXPECT_FALSE(wrapper->GetEncoderInfo().has_trusted_rate_controller); |
| 594 | } |
| 595 | |
| 596 | TEST(SoftwareFallbackEncoderTest, HwRateControllerTrusted) { |
Mirko Bonadei | 6a489f2 | 2019-04-09 13:11:12 | [diff] [blame] | 597 | auto* sw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); |
| 598 | auto* hw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 599 | EXPECT_CALL(*sw_encoder, GetEncoderInfo()) |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 600 | .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(false))); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 601 | EXPECT_CALL(*hw_encoder, GetEncoderInfo()) |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 602 | .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(true))); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 603 | |
| 604 | std::unique_ptr<VideoEncoder> wrapper = |
| 605 | CreateVideoEncoderSoftwareFallbackWrapper( |
| 606 | std::unique_ptr<VideoEncoder>(sw_encoder), |
| 607 | std::unique_ptr<VideoEncoder>(hw_encoder)); |
| 608 | EXPECT_TRUE(wrapper->GetEncoderInfo().has_trusted_rate_controller); |
| 609 | |
Elad Alon | 370f93a | 2019-06-11 12:57:57 | [diff] [blame] | 610 | VideoCodec codec_ = {}; |
| 611 | wrapper->InitEncode(&codec_, kSettings); |
| 612 | |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 613 | // Trigger fallback to software. |
| 614 | EXPECT_CALL(*hw_encoder, Encode) |
| 615 | .WillOnce(Return(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE)); |
Ilya Nikolaevskiy | 6aca0b7 | 2019-02-13 10:55:57 | [diff] [blame] | 616 | VideoFrame frame = VideoFrame::Builder() |
| 617 | .set_video_frame_buffer(I420Buffer::Create(100, 100)) |
| 618 | .build(); |
Niels Möller | c8d2e73 | 2019-03-06 11:00:33 | [diff] [blame] | 619 | wrapper->Encode(frame, nullptr); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 620 | |
| 621 | EXPECT_FALSE(wrapper->GetEncoderInfo().has_trusted_rate_controller); |
| 622 | } |
| 623 | |
| 624 | TEST(SoftwareFallbackEncoderTest, BothRateControllersTrusted) { |
Mirko Bonadei | 6a489f2 | 2019-04-09 13:11:12 | [diff] [blame] | 625 | auto* sw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); |
| 626 | auto* hw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 627 | EXPECT_CALL(*sw_encoder, GetEncoderInfo()) |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 628 | .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(true))); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 629 | EXPECT_CALL(*hw_encoder, GetEncoderInfo()) |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 630 | .WillRepeatedly(Return(GetEncoderInfoWithTrustedRateController(true))); |
Erik Språng | d3438aa | 2018-11-08 15:56:43 | [diff] [blame] | 631 | |
| 632 | std::unique_ptr<VideoEncoder> wrapper = |
| 633 | CreateVideoEncoderSoftwareFallbackWrapper( |
| 634 | std::unique_ptr<VideoEncoder>(sw_encoder), |
| 635 | std::unique_ptr<VideoEncoder>(hw_encoder)); |
| 636 | EXPECT_TRUE(wrapper->GetEncoderInfo().has_trusted_rate_controller); |
| 637 | } |
| 638 | |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 639 | TEST(SoftwareFallbackEncoderTest, ReportsHardwareAccelerated) { |
Mirko Bonadei | 6a489f2 | 2019-04-09 13:11:12 | [diff] [blame] | 640 | auto* sw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); |
| 641 | auto* hw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 642 | EXPECT_CALL(*sw_encoder, GetEncoderInfo()) |
| 643 | .WillRepeatedly(Return(GetEncoderInfoWithHardwareAccelerated(false))); |
| 644 | EXPECT_CALL(*hw_encoder, GetEncoderInfo()) |
| 645 | .WillRepeatedly(Return(GetEncoderInfoWithHardwareAccelerated(true))); |
| 646 | |
| 647 | std::unique_ptr<VideoEncoder> wrapper = |
| 648 | CreateVideoEncoderSoftwareFallbackWrapper( |
| 649 | std::unique_ptr<VideoEncoder>(sw_encoder), |
| 650 | std::unique_ptr<VideoEncoder>(hw_encoder)); |
| 651 | EXPECT_TRUE(wrapper->GetEncoderInfo().is_hardware_accelerated); |
| 652 | |
Elad Alon | 370f93a | 2019-06-11 12:57:57 | [diff] [blame] | 653 | VideoCodec codec_ = {}; |
| 654 | wrapper->InitEncode(&codec_, kSettings); |
| 655 | |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 656 | // Trigger fallback to software. |
| 657 | EXPECT_CALL(*hw_encoder, Encode) |
| 658 | .WillOnce(Return(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE)); |
Ilya Nikolaevskiy | 6aca0b7 | 2019-02-13 10:55:57 | [diff] [blame] | 659 | VideoFrame frame = VideoFrame::Builder() |
| 660 | .set_video_frame_buffer(I420Buffer::Create(100, 100)) |
| 661 | .build(); |
Niels Möller | c8d2e73 | 2019-03-06 11:00:33 | [diff] [blame] | 662 | wrapper->Encode(frame, nullptr); |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 663 | EXPECT_FALSE(wrapper->GetEncoderInfo().is_hardware_accelerated); |
| 664 | } |
| 665 | |
| 666 | TEST(SoftwareFallbackEncoderTest, ReportsInternalSource) { |
Mirko Bonadei | 6a489f2 | 2019-04-09 13:11:12 | [diff] [blame] | 667 | auto* sw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); |
| 668 | auto* hw_encoder = new ::testing::NiceMock<MockVideoEncoder>(); |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 669 | EXPECT_CALL(*sw_encoder, GetEncoderInfo()) |
| 670 | .WillRepeatedly(Return(GetEncoderInfoWithInternalSource(false))); |
| 671 | EXPECT_CALL(*hw_encoder, GetEncoderInfo()) |
| 672 | .WillRepeatedly(Return(GetEncoderInfoWithInternalSource(true))); |
| 673 | |
| 674 | std::unique_ptr<VideoEncoder> wrapper = |
| 675 | CreateVideoEncoderSoftwareFallbackWrapper( |
| 676 | std::unique_ptr<VideoEncoder>(sw_encoder), |
| 677 | std::unique_ptr<VideoEncoder>(hw_encoder)); |
| 678 | EXPECT_TRUE(wrapper->GetEncoderInfo().has_internal_source); |
| 679 | |
Elad Alon | 370f93a | 2019-06-11 12:57:57 | [diff] [blame] | 680 | VideoCodec codec_ = {}; |
| 681 | wrapper->InitEncode(&codec_, kSettings); |
| 682 | |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 683 | // Trigger fallback to software. |
| 684 | EXPECT_CALL(*hw_encoder, Encode) |
| 685 | .WillOnce(Return(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE)); |
Ilya Nikolaevskiy | 6aca0b7 | 2019-02-13 10:55:57 | [diff] [blame] | 686 | VideoFrame frame = VideoFrame::Builder() |
| 687 | .set_video_frame_buffer(I420Buffer::Create(100, 100)) |
| 688 | .build(); |
Niels Möller | c8d2e73 | 2019-03-06 11:00:33 | [diff] [blame] | 689 | wrapper->Encode(frame, nullptr); |
Mirta Dvornicic | 897a991 | 2018-11-30 12:12:21 | [diff] [blame] | 690 | EXPECT_FALSE(wrapper->GetEncoderInfo().has_internal_source); |
| 691 | } |
| 692 | |
Peter Boström | 4d71ede | 2015-05-19 21:09:35 | [diff] [blame] | 693 | } // namespace webrtc |