1*d9f75844SAndroid Build Coastguard Worker
2*d9f75844SAndroid Build Coastguard Worker /*
3*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
4*d9f75844SAndroid Build Coastguard Worker *
5*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
6*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
7*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
8*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
9*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
10*d9f75844SAndroid Build Coastguard Worker */
11*d9f75844SAndroid Build Coastguard Worker #include "video/video_stream_encoder.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker #include <limits>
15*d9f75844SAndroid Build Coastguard Worker #include <memory>
16*d9f75844SAndroid Build Coastguard Worker #include <tuple>
17*d9f75844SAndroid Build Coastguard Worker #include <utility>
18*d9f75844SAndroid Build Coastguard Worker
19*d9f75844SAndroid Build Coastguard Worker #include "absl/memory/memory.h"
20*d9f75844SAndroid Build Coastguard Worker #include "api/field_trials_view.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_parameters.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/default_task_queue_factory.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/task_queue_base.h"
24*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/task_queue_factory.h"
25*d9f75844SAndroid Build Coastguard Worker #include "api/test/mock_fec_controller_override.h"
26*d9f75844SAndroid Build Coastguard Worker #include "api/test/mock_video_encoder.h"
27*d9f75844SAndroid Build Coastguard Worker #include "api/test/mock_video_encoder_factory.h"
28*d9f75844SAndroid Build Coastguard Worker #include "api/units/data_rate.h"
29*d9f75844SAndroid Build Coastguard Worker #include "api/units/time_delta.h"
30*d9f75844SAndroid Build Coastguard Worker #include "api/video/builtin_video_bitrate_allocator_factory.h"
31*d9f75844SAndroid Build Coastguard Worker #include "api/video/i420_buffer.h"
32*d9f75844SAndroid Build Coastguard Worker #include "api/video/nv12_buffer.h"
33*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_adaptation_reason.h"
34*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_bitrate_allocation.h"
35*d9f75844SAndroid Build Coastguard Worker #include "api/video_codecs/sdp_video_format.h"
36*d9f75844SAndroid Build Coastguard Worker #include "api/video_codecs/video_codec.h"
37*d9f75844SAndroid Build Coastguard Worker #include "api/video_codecs/video_encoder.h"
38*d9f75844SAndroid Build Coastguard Worker #include "api/video_codecs/vp8_temporal_layers.h"
39*d9f75844SAndroid Build Coastguard Worker #include "api/video_codecs/vp8_temporal_layers_factory.h"
40*d9f75844SAndroid Build Coastguard Worker #include "call/adaptation/test/fake_adaptation_constraint.h"
41*d9f75844SAndroid Build Coastguard Worker #include "call/adaptation/test/fake_resource.h"
42*d9f75844SAndroid Build Coastguard Worker #include "common_video/h264/h264_common.h"
43*d9f75844SAndroid Build Coastguard Worker #include "common_video/include/video_frame_buffer.h"
44*d9f75844SAndroid Build Coastguard Worker #include "media/base/video_adapter.h"
45*d9f75844SAndroid Build Coastguard Worker #include "media/engine/webrtc_video_engine.h"
46*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/codecs/av1/libaom_av1_encoder.h"
47*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/codecs/h264/include/h264.h"
48*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/codecs/multiplex/include/multiplex_encoder_adapter.h"
49*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/codecs/vp8/include/vp8.h"
50*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/codecs/vp9/include/vp9.h"
51*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
52*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/codecs/vp9/svc_config.h"
53*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/utility/quality_scaler.h"
54*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/utility/simulcast_rate_allocator.h"
55*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/utility/vp8_constants.h"
56*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/event.h"
57*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/experiments/encoder_info_settings.h"
58*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
59*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
60*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ref_counted_object.h"
61*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/synchronization/mutex.h"
62*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/metrics.h"
63*d9f75844SAndroid Build Coastguard Worker #include "test/encoder_settings.h"
64*d9f75844SAndroid Build Coastguard Worker #include "test/fake_encoder.h"
65*d9f75844SAndroid Build Coastguard Worker #include "test/frame_forwarder.h"
66*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
67*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
68*d9f75844SAndroid Build Coastguard Worker #include "test/mappable_native_buffer.h"
69*d9f75844SAndroid Build Coastguard Worker #include "test/scoped_key_value_config.h"
70*d9f75844SAndroid Build Coastguard Worker #include "test/time_controller/simulated_time_controller.h"
71*d9f75844SAndroid Build Coastguard Worker #include "test/video_encoder_nullable_proxy_factory.h"
72*d9f75844SAndroid Build Coastguard Worker #include "test/video_encoder_proxy_factory.h"
73*d9f75844SAndroid Build Coastguard Worker #include "video/config/encoder_stream_factory.h"
74*d9f75844SAndroid Build Coastguard Worker #include "video/frame_cadence_adapter.h"
75*d9f75844SAndroid Build Coastguard Worker #include "video/send_statistics_proxy.h"
76*d9f75844SAndroid Build Coastguard Worker
77*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
78*d9f75844SAndroid Build Coastguard Worker
79*d9f75844SAndroid Build Coastguard Worker using ::testing::_;
80*d9f75844SAndroid Build Coastguard Worker using ::testing::AllOf;
81*d9f75844SAndroid Build Coastguard Worker using ::testing::Eq;
82*d9f75844SAndroid Build Coastguard Worker using ::testing::Field;
83*d9f75844SAndroid Build Coastguard Worker using ::testing::Ge;
84*d9f75844SAndroid Build Coastguard Worker using ::testing::Gt;
85*d9f75844SAndroid Build Coastguard Worker using ::testing::Invoke;
86*d9f75844SAndroid Build Coastguard Worker using ::testing::Le;
87*d9f75844SAndroid Build Coastguard Worker using ::testing::Lt;
88*d9f75844SAndroid Build Coastguard Worker using ::testing::Matcher;
89*d9f75844SAndroid Build Coastguard Worker using ::testing::Mock;
90*d9f75844SAndroid Build Coastguard Worker using ::testing::NiceMock;
91*d9f75844SAndroid Build Coastguard Worker using ::testing::Optional;
92*d9f75844SAndroid Build Coastguard Worker using ::testing::Return;
93*d9f75844SAndroid Build Coastguard Worker using ::testing::SizeIs;
94*d9f75844SAndroid Build Coastguard Worker using ::testing::StrictMock;
95*d9f75844SAndroid Build Coastguard Worker
96*d9f75844SAndroid Build Coastguard Worker namespace {
97*d9f75844SAndroid Build Coastguard Worker const int kMinPixelsPerFrame = 320 * 180;
98*d9f75844SAndroid Build Coastguard Worker const int kQpLow = 1;
99*d9f75844SAndroid Build Coastguard Worker const int kQpHigh = 2;
100*d9f75844SAndroid Build Coastguard Worker const int kMinFramerateFps = 2;
101*d9f75844SAndroid Build Coastguard Worker const int kMinBalancedFramerateFps = 7;
102*d9f75844SAndroid Build Coastguard Worker constexpr TimeDelta kFrameTimeout = TimeDelta::Millis(100);
103*d9f75844SAndroid Build Coastguard Worker const size_t kMaxPayloadLength = 1440;
104*d9f75844SAndroid Build Coastguard Worker const DataRate kTargetBitrate = DataRate::KilobitsPerSec(1000);
105*d9f75844SAndroid Build Coastguard Worker const DataRate kLowTargetBitrate = DataRate::KilobitsPerSec(100);
106*d9f75844SAndroid Build Coastguard Worker const DataRate kStartBitrate = DataRate::KilobitsPerSec(600);
107*d9f75844SAndroid Build Coastguard Worker const DataRate kSimulcastTargetBitrate = DataRate::KilobitsPerSec(3150);
108*d9f75844SAndroid Build Coastguard Worker const int kMaxInitialFramedrop = 4;
109*d9f75844SAndroid Build Coastguard Worker const int kDefaultFramerate = 30;
110*d9f75844SAndroid Build Coastguard Worker const int64_t kFrameIntervalMs = rtc::kNumMillisecsPerSec / kDefaultFramerate;
111*d9f75844SAndroid Build Coastguard Worker const int64_t kProcessIntervalMs = 1000;
112*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits
113*d9f75844SAndroid Build Coastguard Worker kEncoderBitrateLimits540p(960 * 540, 100 * 1000, 100 * 1000, 2000 * 1000);
114*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits
115*d9f75844SAndroid Build Coastguard Worker kEncoderBitrateLimits720p(1280 * 720, 200 * 1000, 200 * 1000, 4000 * 1000);
116*d9f75844SAndroid Build Coastguard Worker
117*d9f75844SAndroid Build Coastguard Worker uint8_t kOptimalSps[] = {0, 0, 0, 1, H264::NaluType::kSps,
118*d9f75844SAndroid Build Coastguard Worker 0x00, 0x00, 0x03, 0x03, 0xF4,
119*d9f75844SAndroid Build Coastguard Worker 0x05, 0x03, 0xC7, 0xE0, 0x1B,
120*d9f75844SAndroid Build Coastguard Worker 0x41, 0x10, 0x8D, 0x00};
121*d9f75844SAndroid Build Coastguard Worker
122*d9f75844SAndroid Build Coastguard Worker const uint8_t kCodedFrameVp8Qp25[] = {
123*d9f75844SAndroid Build Coastguard Worker 0x10, 0x02, 0x00, 0x9d, 0x01, 0x2a, 0x10, 0x00, 0x10, 0x00,
124*d9f75844SAndroid Build Coastguard Worker 0x02, 0x47, 0x08, 0x85, 0x85, 0x88, 0x85, 0x84, 0x88, 0x0c,
125*d9f75844SAndroid Build Coastguard Worker 0x82, 0x00, 0x0c, 0x0d, 0x60, 0x00, 0xfe, 0xfc, 0x5c, 0xd0};
126*d9f75844SAndroid Build Coastguard Worker
CreateSimpleNV12Frame()127*d9f75844SAndroid Build Coastguard Worker VideoFrame CreateSimpleNV12Frame() {
128*d9f75844SAndroid Build Coastguard Worker return VideoFrame::Builder()
129*d9f75844SAndroid Build Coastguard Worker .set_video_frame_buffer(rtc::make_ref_counted<NV12Buffer>(
130*d9f75844SAndroid Build Coastguard Worker /*width=*/16, /*height=*/16))
131*d9f75844SAndroid Build Coastguard Worker .build();
132*d9f75844SAndroid Build Coastguard Worker }
133*d9f75844SAndroid Build Coastguard Worker
PassAFrame(TaskQueueBase * encoder_queue,FrameCadenceAdapterInterface::Callback * video_stream_encoder_callback,int64_t ntp_time_ms)134*d9f75844SAndroid Build Coastguard Worker void PassAFrame(
135*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* encoder_queue,
136*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::Callback* video_stream_encoder_callback,
137*d9f75844SAndroid Build Coastguard Worker int64_t ntp_time_ms) {
138*d9f75844SAndroid Build Coastguard Worker encoder_queue->PostTask([video_stream_encoder_callback, ntp_time_ms] {
139*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_callback->OnFrame(Timestamp::Millis(ntp_time_ms), 1,
140*d9f75844SAndroid Build Coastguard Worker CreateSimpleNV12Frame());
141*d9f75844SAndroid Build Coastguard Worker });
142*d9f75844SAndroid Build Coastguard Worker }
143*d9f75844SAndroid Build Coastguard Worker
144*d9f75844SAndroid Build Coastguard Worker class TestBuffer : public webrtc::I420Buffer {
145*d9f75844SAndroid Build Coastguard Worker public:
TestBuffer(rtc::Event * event,int width,int height)146*d9f75844SAndroid Build Coastguard Worker TestBuffer(rtc::Event* event, int width, int height)
147*d9f75844SAndroid Build Coastguard Worker : I420Buffer(width, height), event_(event) {}
148*d9f75844SAndroid Build Coastguard Worker
149*d9f75844SAndroid Build Coastguard Worker private:
150*d9f75844SAndroid Build Coastguard Worker friend class rtc::RefCountedObject<TestBuffer>;
~TestBuffer()151*d9f75844SAndroid Build Coastguard Worker ~TestBuffer() override {
152*d9f75844SAndroid Build Coastguard Worker if (event_)
153*d9f75844SAndroid Build Coastguard Worker event_->Set();
154*d9f75844SAndroid Build Coastguard Worker }
155*d9f75844SAndroid Build Coastguard Worker rtc::Event* const event_;
156*d9f75844SAndroid Build Coastguard Worker };
157*d9f75844SAndroid Build Coastguard Worker
158*d9f75844SAndroid Build Coastguard Worker // A fake native buffer that can't be converted to I420. Upon scaling, it
159*d9f75844SAndroid Build Coastguard Worker // produces another FakeNativeBuffer.
160*d9f75844SAndroid Build Coastguard Worker class FakeNativeBuffer : public webrtc::VideoFrameBuffer {
161*d9f75844SAndroid Build Coastguard Worker public:
FakeNativeBuffer(rtc::Event * event,int width,int height)162*d9f75844SAndroid Build Coastguard Worker FakeNativeBuffer(rtc::Event* event, int width, int height)
163*d9f75844SAndroid Build Coastguard Worker : event_(event), width_(width), height_(height) {}
type() const164*d9f75844SAndroid Build Coastguard Worker webrtc::VideoFrameBuffer::Type type() const override { return Type::kNative; }
width() const165*d9f75844SAndroid Build Coastguard Worker int width() const override { return width_; }
height() const166*d9f75844SAndroid Build Coastguard Worker int height() const override { return height_; }
ToI420()167*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<webrtc::I420BufferInterface> ToI420() override {
168*d9f75844SAndroid Build Coastguard Worker return nullptr;
169*d9f75844SAndroid Build Coastguard Worker }
CropAndScale(int offset_x,int offset_y,int crop_width,int crop_height,int scaled_width,int scaled_height)170*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<VideoFrameBuffer> CropAndScale(
171*d9f75844SAndroid Build Coastguard Worker int offset_x,
172*d9f75844SAndroid Build Coastguard Worker int offset_y,
173*d9f75844SAndroid Build Coastguard Worker int crop_width,
174*d9f75844SAndroid Build Coastguard Worker int crop_height,
175*d9f75844SAndroid Build Coastguard Worker int scaled_width,
176*d9f75844SAndroid Build Coastguard Worker int scaled_height) override {
177*d9f75844SAndroid Build Coastguard Worker return rtc::make_ref_counted<FakeNativeBuffer>(nullptr, scaled_width,
178*d9f75844SAndroid Build Coastguard Worker scaled_height);
179*d9f75844SAndroid Build Coastguard Worker }
180*d9f75844SAndroid Build Coastguard Worker
181*d9f75844SAndroid Build Coastguard Worker private:
182*d9f75844SAndroid Build Coastguard Worker friend class rtc::RefCountedObject<FakeNativeBuffer>;
~FakeNativeBuffer()183*d9f75844SAndroid Build Coastguard Worker ~FakeNativeBuffer() override {
184*d9f75844SAndroid Build Coastguard Worker if (event_)
185*d9f75844SAndroid Build Coastguard Worker event_->Set();
186*d9f75844SAndroid Build Coastguard Worker }
187*d9f75844SAndroid Build Coastguard Worker rtc::Event* const event_;
188*d9f75844SAndroid Build Coastguard Worker const int width_;
189*d9f75844SAndroid Build Coastguard Worker const int height_;
190*d9f75844SAndroid Build Coastguard Worker };
191*d9f75844SAndroid Build Coastguard Worker
192*d9f75844SAndroid Build Coastguard Worker // A fake native buffer that is backed by an NV12 buffer.
193*d9f75844SAndroid Build Coastguard Worker class FakeNV12NativeBuffer : public webrtc::VideoFrameBuffer {
194*d9f75844SAndroid Build Coastguard Worker public:
FakeNV12NativeBuffer(rtc::Event * event,int width,int height)195*d9f75844SAndroid Build Coastguard Worker FakeNV12NativeBuffer(rtc::Event* event, int width, int height)
196*d9f75844SAndroid Build Coastguard Worker : nv12_buffer_(NV12Buffer::Create(width, height)), event_(event) {}
197*d9f75844SAndroid Build Coastguard Worker
type() const198*d9f75844SAndroid Build Coastguard Worker webrtc::VideoFrameBuffer::Type type() const override { return Type::kNative; }
width() const199*d9f75844SAndroid Build Coastguard Worker int width() const override { return nv12_buffer_->width(); }
height() const200*d9f75844SAndroid Build Coastguard Worker int height() const override { return nv12_buffer_->height(); }
ToI420()201*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<webrtc::I420BufferInterface> ToI420() override {
202*d9f75844SAndroid Build Coastguard Worker return nv12_buffer_->ToI420();
203*d9f75844SAndroid Build Coastguard Worker }
GetMappedFrameBuffer(rtc::ArrayView<VideoFrameBuffer::Type> types)204*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<VideoFrameBuffer> GetMappedFrameBuffer(
205*d9f75844SAndroid Build Coastguard Worker rtc::ArrayView<VideoFrameBuffer::Type> types) override {
206*d9f75844SAndroid Build Coastguard Worker if (absl::c_find(types, Type::kNV12) != types.end()) {
207*d9f75844SAndroid Build Coastguard Worker return nv12_buffer_;
208*d9f75844SAndroid Build Coastguard Worker }
209*d9f75844SAndroid Build Coastguard Worker return nullptr;
210*d9f75844SAndroid Build Coastguard Worker }
GetNV12() const211*d9f75844SAndroid Build Coastguard Worker const NV12BufferInterface* GetNV12() const { return nv12_buffer_.get(); }
212*d9f75844SAndroid Build Coastguard Worker
213*d9f75844SAndroid Build Coastguard Worker private:
214*d9f75844SAndroid Build Coastguard Worker friend class rtc::RefCountedObject<FakeNV12NativeBuffer>;
~FakeNV12NativeBuffer()215*d9f75844SAndroid Build Coastguard Worker ~FakeNV12NativeBuffer() override {
216*d9f75844SAndroid Build Coastguard Worker if (event_)
217*d9f75844SAndroid Build Coastguard Worker event_->Set();
218*d9f75844SAndroid Build Coastguard Worker }
219*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<NV12Buffer> nv12_buffer_;
220*d9f75844SAndroid Build Coastguard Worker rtc::Event* const event_;
221*d9f75844SAndroid Build Coastguard Worker };
222*d9f75844SAndroid Build Coastguard Worker
223*d9f75844SAndroid Build Coastguard Worker class CpuOveruseDetectorProxy : public OveruseFrameDetector {
224*d9f75844SAndroid Build Coastguard Worker public:
CpuOveruseDetectorProxy(CpuOveruseMetricsObserver * metrics_observer,const FieldTrialsView & field_trials)225*d9f75844SAndroid Build Coastguard Worker CpuOveruseDetectorProxy(CpuOveruseMetricsObserver* metrics_observer,
226*d9f75844SAndroid Build Coastguard Worker const FieldTrialsView& field_trials)
227*d9f75844SAndroid Build Coastguard Worker : OveruseFrameDetector(metrics_observer, field_trials),
228*d9f75844SAndroid Build Coastguard Worker last_target_framerate_fps_(-1),
229*d9f75844SAndroid Build Coastguard Worker framerate_updated_event_(true /* manual_reset */,
230*d9f75844SAndroid Build Coastguard Worker false /* initially_signaled */) {}
~CpuOveruseDetectorProxy()231*d9f75844SAndroid Build Coastguard Worker virtual ~CpuOveruseDetectorProxy() {}
232*d9f75844SAndroid Build Coastguard Worker
OnTargetFramerateUpdated(int framerate_fps)233*d9f75844SAndroid Build Coastguard Worker void OnTargetFramerateUpdated(int framerate_fps) override {
234*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&lock_);
235*d9f75844SAndroid Build Coastguard Worker last_target_framerate_fps_ = framerate_fps;
236*d9f75844SAndroid Build Coastguard Worker OveruseFrameDetector::OnTargetFramerateUpdated(framerate_fps);
237*d9f75844SAndroid Build Coastguard Worker framerate_updated_event_.Set();
238*d9f75844SAndroid Build Coastguard Worker }
239*d9f75844SAndroid Build Coastguard Worker
GetLastTargetFramerate()240*d9f75844SAndroid Build Coastguard Worker int GetLastTargetFramerate() {
241*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&lock_);
242*d9f75844SAndroid Build Coastguard Worker return last_target_framerate_fps_;
243*d9f75844SAndroid Build Coastguard Worker }
244*d9f75844SAndroid Build Coastguard Worker
GetOptions()245*d9f75844SAndroid Build Coastguard Worker CpuOveruseOptions GetOptions() { return options_; }
246*d9f75844SAndroid Build Coastguard Worker
framerate_updated_event()247*d9f75844SAndroid Build Coastguard Worker rtc::Event* framerate_updated_event() { return &framerate_updated_event_; }
248*d9f75844SAndroid Build Coastguard Worker
249*d9f75844SAndroid Build Coastguard Worker private:
250*d9f75844SAndroid Build Coastguard Worker Mutex lock_;
251*d9f75844SAndroid Build Coastguard Worker int last_target_framerate_fps_ RTC_GUARDED_BY(lock_);
252*d9f75844SAndroid Build Coastguard Worker rtc::Event framerate_updated_event_;
253*d9f75844SAndroid Build Coastguard Worker };
254*d9f75844SAndroid Build Coastguard Worker
255*d9f75844SAndroid Build Coastguard Worker class FakeVideoSourceRestrictionsListener
256*d9f75844SAndroid Build Coastguard Worker : public VideoSourceRestrictionsListener {
257*d9f75844SAndroid Build Coastguard Worker public:
FakeVideoSourceRestrictionsListener()258*d9f75844SAndroid Build Coastguard Worker FakeVideoSourceRestrictionsListener()
259*d9f75844SAndroid Build Coastguard Worker : was_restrictions_updated_(false), restrictions_updated_event_() {}
~FakeVideoSourceRestrictionsListener()260*d9f75844SAndroid Build Coastguard Worker ~FakeVideoSourceRestrictionsListener() override {
261*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(was_restrictions_updated_);
262*d9f75844SAndroid Build Coastguard Worker }
263*d9f75844SAndroid Build Coastguard Worker
restrictions_updated_event()264*d9f75844SAndroid Build Coastguard Worker rtc::Event* restrictions_updated_event() {
265*d9f75844SAndroid Build Coastguard Worker return &restrictions_updated_event_;
266*d9f75844SAndroid Build Coastguard Worker }
267*d9f75844SAndroid Build Coastguard Worker
268*d9f75844SAndroid Build Coastguard Worker // VideoSourceRestrictionsListener implementation.
OnVideoSourceRestrictionsUpdated(VideoSourceRestrictions restrictions,const VideoAdaptationCounters & adaptation_counters,rtc::scoped_refptr<Resource> reason,const VideoSourceRestrictions & unfiltered_restrictions)269*d9f75844SAndroid Build Coastguard Worker void OnVideoSourceRestrictionsUpdated(
270*d9f75844SAndroid Build Coastguard Worker VideoSourceRestrictions restrictions,
271*d9f75844SAndroid Build Coastguard Worker const VideoAdaptationCounters& adaptation_counters,
272*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<Resource> reason,
273*d9f75844SAndroid Build Coastguard Worker const VideoSourceRestrictions& unfiltered_restrictions) override {
274*d9f75844SAndroid Build Coastguard Worker was_restrictions_updated_ = true;
275*d9f75844SAndroid Build Coastguard Worker restrictions_updated_event_.Set();
276*d9f75844SAndroid Build Coastguard Worker }
277*d9f75844SAndroid Build Coastguard Worker
278*d9f75844SAndroid Build Coastguard Worker private:
279*d9f75844SAndroid Build Coastguard Worker bool was_restrictions_updated_;
280*d9f75844SAndroid Build Coastguard Worker rtc::Event restrictions_updated_event_;
281*d9f75844SAndroid Build Coastguard Worker };
282*d9f75844SAndroid Build Coastguard Worker
WantsFps(Matcher<int> fps_matcher)283*d9f75844SAndroid Build Coastguard Worker auto WantsFps(Matcher<int> fps_matcher) {
284*d9f75844SAndroid Build Coastguard Worker return Field("max_framerate_fps", &rtc::VideoSinkWants::max_framerate_fps,
285*d9f75844SAndroid Build Coastguard Worker fps_matcher);
286*d9f75844SAndroid Build Coastguard Worker }
287*d9f75844SAndroid Build Coastguard Worker
WantsMaxPixels(Matcher<int> max_pixel_matcher)288*d9f75844SAndroid Build Coastguard Worker auto WantsMaxPixels(Matcher<int> max_pixel_matcher) {
289*d9f75844SAndroid Build Coastguard Worker return Field("max_pixel_count", &rtc::VideoSinkWants::max_pixel_count,
290*d9f75844SAndroid Build Coastguard Worker AllOf(max_pixel_matcher, Gt(0)));
291*d9f75844SAndroid Build Coastguard Worker }
292*d9f75844SAndroid Build Coastguard Worker
ResolutionMax()293*d9f75844SAndroid Build Coastguard Worker auto ResolutionMax() {
294*d9f75844SAndroid Build Coastguard Worker return AllOf(
295*d9f75844SAndroid Build Coastguard Worker WantsMaxPixels(Eq(std::numeric_limits<int>::max())),
296*d9f75844SAndroid Build Coastguard Worker Field("target_pixel_count", &rtc::VideoSinkWants::target_pixel_count,
297*d9f75844SAndroid Build Coastguard Worker Eq(absl::nullopt)));
298*d9f75844SAndroid Build Coastguard Worker }
299*d9f75844SAndroid Build Coastguard Worker
FpsMax()300*d9f75844SAndroid Build Coastguard Worker auto FpsMax() {
301*d9f75844SAndroid Build Coastguard Worker return WantsFps(Eq(kDefaultFramerate));
302*d9f75844SAndroid Build Coastguard Worker }
303*d9f75844SAndroid Build Coastguard Worker
FpsUnlimited()304*d9f75844SAndroid Build Coastguard Worker auto FpsUnlimited() {
305*d9f75844SAndroid Build Coastguard Worker return WantsFps(Eq(std::numeric_limits<int>::max()));
306*d9f75844SAndroid Build Coastguard Worker }
307*d9f75844SAndroid Build Coastguard Worker
FpsMatchesResolutionMax(Matcher<int> fps_matcher)308*d9f75844SAndroid Build Coastguard Worker auto FpsMatchesResolutionMax(Matcher<int> fps_matcher) {
309*d9f75844SAndroid Build Coastguard Worker return AllOf(WantsFps(fps_matcher), ResolutionMax());
310*d9f75844SAndroid Build Coastguard Worker }
311*d9f75844SAndroid Build Coastguard Worker
FpsMaxResolutionMatches(Matcher<int> pixel_matcher)312*d9f75844SAndroid Build Coastguard Worker auto FpsMaxResolutionMatches(Matcher<int> pixel_matcher) {
313*d9f75844SAndroid Build Coastguard Worker return AllOf(FpsMax(), WantsMaxPixels(pixel_matcher));
314*d9f75844SAndroid Build Coastguard Worker }
315*d9f75844SAndroid Build Coastguard Worker
FpsMaxResolutionMax()316*d9f75844SAndroid Build Coastguard Worker auto FpsMaxResolutionMax() {
317*d9f75844SAndroid Build Coastguard Worker return AllOf(FpsMax(), ResolutionMax());
318*d9f75844SAndroid Build Coastguard Worker }
319*d9f75844SAndroid Build Coastguard Worker
UnlimitedSinkWants()320*d9f75844SAndroid Build Coastguard Worker auto UnlimitedSinkWants() {
321*d9f75844SAndroid Build Coastguard Worker return AllOf(FpsUnlimited(), ResolutionMax());
322*d9f75844SAndroid Build Coastguard Worker }
323*d9f75844SAndroid Build Coastguard Worker
FpsInRangeForPixelsInBalanced(int last_frame_pixels)324*d9f75844SAndroid Build Coastguard Worker auto FpsInRangeForPixelsInBalanced(int last_frame_pixels) {
325*d9f75844SAndroid Build Coastguard Worker Matcher<int> fps_range_matcher;
326*d9f75844SAndroid Build Coastguard Worker
327*d9f75844SAndroid Build Coastguard Worker if (last_frame_pixels <= 320 * 240) {
328*d9f75844SAndroid Build Coastguard Worker fps_range_matcher = AllOf(Ge(7), Le(10));
329*d9f75844SAndroid Build Coastguard Worker } else if (last_frame_pixels <= 480 * 360) {
330*d9f75844SAndroid Build Coastguard Worker fps_range_matcher = AllOf(Ge(10), Le(15));
331*d9f75844SAndroid Build Coastguard Worker } else if (last_frame_pixels <= 640 * 480) {
332*d9f75844SAndroid Build Coastguard Worker fps_range_matcher = Ge(15);
333*d9f75844SAndroid Build Coastguard Worker } else {
334*d9f75844SAndroid Build Coastguard Worker fps_range_matcher = Eq(kDefaultFramerate);
335*d9f75844SAndroid Build Coastguard Worker }
336*d9f75844SAndroid Build Coastguard Worker return Field("max_framerate_fps", &rtc::VideoSinkWants::max_framerate_fps,
337*d9f75844SAndroid Build Coastguard Worker fps_range_matcher);
338*d9f75844SAndroid Build Coastguard Worker }
339*d9f75844SAndroid Build Coastguard Worker
FpsEqResolutionEqTo(const rtc::VideoSinkWants & other_wants)340*d9f75844SAndroid Build Coastguard Worker auto FpsEqResolutionEqTo(const rtc::VideoSinkWants& other_wants) {
341*d9f75844SAndroid Build Coastguard Worker return AllOf(WantsFps(Eq(other_wants.max_framerate_fps)),
342*d9f75844SAndroid Build Coastguard Worker WantsMaxPixels(Eq(other_wants.max_pixel_count)));
343*d9f75844SAndroid Build Coastguard Worker }
344*d9f75844SAndroid Build Coastguard Worker
FpsMaxResolutionLt(const rtc::VideoSinkWants & other_wants)345*d9f75844SAndroid Build Coastguard Worker auto FpsMaxResolutionLt(const rtc::VideoSinkWants& other_wants) {
346*d9f75844SAndroid Build Coastguard Worker return AllOf(FpsMax(), WantsMaxPixels(Lt(other_wants.max_pixel_count)));
347*d9f75844SAndroid Build Coastguard Worker }
348*d9f75844SAndroid Build Coastguard Worker
FpsMaxResolutionGt(const rtc::VideoSinkWants & other_wants)349*d9f75844SAndroid Build Coastguard Worker auto FpsMaxResolutionGt(const rtc::VideoSinkWants& other_wants) {
350*d9f75844SAndroid Build Coastguard Worker return AllOf(FpsMax(), WantsMaxPixels(Gt(other_wants.max_pixel_count)));
351*d9f75844SAndroid Build Coastguard Worker }
352*d9f75844SAndroid Build Coastguard Worker
FpsLtResolutionEq(const rtc::VideoSinkWants & other_wants)353*d9f75844SAndroid Build Coastguard Worker auto FpsLtResolutionEq(const rtc::VideoSinkWants& other_wants) {
354*d9f75844SAndroid Build Coastguard Worker return AllOf(WantsFps(Lt(other_wants.max_framerate_fps)),
355*d9f75844SAndroid Build Coastguard Worker WantsMaxPixels(Eq(other_wants.max_pixel_count)));
356*d9f75844SAndroid Build Coastguard Worker }
357*d9f75844SAndroid Build Coastguard Worker
FpsGtResolutionEq(const rtc::VideoSinkWants & other_wants)358*d9f75844SAndroid Build Coastguard Worker auto FpsGtResolutionEq(const rtc::VideoSinkWants& other_wants) {
359*d9f75844SAndroid Build Coastguard Worker return AllOf(WantsFps(Gt(other_wants.max_framerate_fps)),
360*d9f75844SAndroid Build Coastguard Worker WantsMaxPixels(Eq(other_wants.max_pixel_count)));
361*d9f75844SAndroid Build Coastguard Worker }
362*d9f75844SAndroid Build Coastguard Worker
FpsEqResolutionLt(const rtc::VideoSinkWants & other_wants)363*d9f75844SAndroid Build Coastguard Worker auto FpsEqResolutionLt(const rtc::VideoSinkWants& other_wants) {
364*d9f75844SAndroid Build Coastguard Worker return AllOf(WantsFps(Eq(other_wants.max_framerate_fps)),
365*d9f75844SAndroid Build Coastguard Worker WantsMaxPixels(Lt(other_wants.max_pixel_count)));
366*d9f75844SAndroid Build Coastguard Worker }
367*d9f75844SAndroid Build Coastguard Worker
FpsEqResolutionGt(const rtc::VideoSinkWants & other_wants)368*d9f75844SAndroid Build Coastguard Worker auto FpsEqResolutionGt(const rtc::VideoSinkWants& other_wants) {
369*d9f75844SAndroid Build Coastguard Worker return AllOf(WantsFps(Eq(other_wants.max_framerate_fps)),
370*d9f75844SAndroid Build Coastguard Worker WantsMaxPixels(Gt(other_wants.max_pixel_count)));
371*d9f75844SAndroid Build Coastguard Worker }
372*d9f75844SAndroid Build Coastguard Worker
373*d9f75844SAndroid Build Coastguard Worker class VideoStreamEncoderUnderTest : public VideoStreamEncoder {
374*d9f75844SAndroid Build Coastguard Worker public:
VideoStreamEncoderUnderTest(TimeController * time_controller,std::unique_ptr<FrameCadenceAdapterInterface> cadence_adapter,std::unique_ptr<webrtc::TaskQueueBase,webrtc::TaskQueueDeleter> encoder_queue,SendStatisticsProxy * stats_proxy,const VideoStreamEncoderSettings & settings,VideoStreamEncoder::BitrateAllocationCallbackType allocation_callback_type,const FieldTrialsView & field_trials,int num_cores)375*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoderUnderTest(
376*d9f75844SAndroid Build Coastguard Worker TimeController* time_controller,
377*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<FrameCadenceAdapterInterface> cadence_adapter,
378*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
379*d9f75844SAndroid Build Coastguard Worker encoder_queue,
380*d9f75844SAndroid Build Coastguard Worker SendStatisticsProxy* stats_proxy,
381*d9f75844SAndroid Build Coastguard Worker const VideoStreamEncoderSettings& settings,
382*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType
383*d9f75844SAndroid Build Coastguard Worker allocation_callback_type,
384*d9f75844SAndroid Build Coastguard Worker const FieldTrialsView& field_trials,
385*d9f75844SAndroid Build Coastguard Worker int num_cores)
386*d9f75844SAndroid Build Coastguard Worker : VideoStreamEncoder(
387*d9f75844SAndroid Build Coastguard Worker time_controller->GetClock(),
388*d9f75844SAndroid Build Coastguard Worker num_cores,
389*d9f75844SAndroid Build Coastguard Worker stats_proxy,
390*d9f75844SAndroid Build Coastguard Worker settings,
391*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<OveruseFrameDetector>(
392*d9f75844SAndroid Build Coastguard Worker overuse_detector_proxy_ =
393*d9f75844SAndroid Build Coastguard Worker new CpuOveruseDetectorProxy(stats_proxy, field_trials)),
394*d9f75844SAndroid Build Coastguard Worker std::move(cadence_adapter),
395*d9f75844SAndroid Build Coastguard Worker std::move(encoder_queue),
396*d9f75844SAndroid Build Coastguard Worker allocation_callback_type,
397*d9f75844SAndroid Build Coastguard Worker field_trials),
398*d9f75844SAndroid Build Coastguard Worker time_controller_(time_controller),
399*d9f75844SAndroid Build Coastguard Worker fake_cpu_resource_(FakeResource::Create("FakeResource[CPU]")),
400*d9f75844SAndroid Build Coastguard Worker fake_quality_resource_(FakeResource::Create("FakeResource[QP]")),
401*d9f75844SAndroid Build Coastguard Worker fake_adaptation_constraint_("FakeAdaptationConstraint") {
402*d9f75844SAndroid Build Coastguard Worker InjectAdaptationResource(fake_quality_resource_,
403*d9f75844SAndroid Build Coastguard Worker VideoAdaptationReason::kQuality);
404*d9f75844SAndroid Build Coastguard Worker InjectAdaptationResource(fake_cpu_resource_, VideoAdaptationReason::kCpu);
405*d9f75844SAndroid Build Coastguard Worker InjectAdaptationConstraint(&fake_adaptation_constraint_);
406*d9f75844SAndroid Build Coastguard Worker }
407*d9f75844SAndroid Build Coastguard Worker
SetSourceAndWaitForRestrictionsUpdated(rtc::VideoSourceInterface<VideoFrame> * source,const DegradationPreference & degradation_preference)408*d9f75844SAndroid Build Coastguard Worker void SetSourceAndWaitForRestrictionsUpdated(
409*d9f75844SAndroid Build Coastguard Worker rtc::VideoSourceInterface<VideoFrame>* source,
410*d9f75844SAndroid Build Coastguard Worker const DegradationPreference& degradation_preference) {
411*d9f75844SAndroid Build Coastguard Worker FakeVideoSourceRestrictionsListener listener;
412*d9f75844SAndroid Build Coastguard Worker AddRestrictionsListenerForTesting(&listener);
413*d9f75844SAndroid Build Coastguard Worker SetSource(source, degradation_preference);
414*d9f75844SAndroid Build Coastguard Worker listener.restrictions_updated_event()->Wait(TimeDelta::Seconds(5));
415*d9f75844SAndroid Build Coastguard Worker RemoveRestrictionsListenerForTesting(&listener);
416*d9f75844SAndroid Build Coastguard Worker }
417*d9f75844SAndroid Build Coastguard Worker
SetSourceAndWaitForFramerateUpdated(rtc::VideoSourceInterface<VideoFrame> * source,const DegradationPreference & degradation_preference)418*d9f75844SAndroid Build Coastguard Worker void SetSourceAndWaitForFramerateUpdated(
419*d9f75844SAndroid Build Coastguard Worker rtc::VideoSourceInterface<VideoFrame>* source,
420*d9f75844SAndroid Build Coastguard Worker const DegradationPreference& degradation_preference) {
421*d9f75844SAndroid Build Coastguard Worker overuse_detector_proxy_->framerate_updated_event()->Reset();
422*d9f75844SAndroid Build Coastguard Worker SetSource(source, degradation_preference);
423*d9f75844SAndroid Build Coastguard Worker overuse_detector_proxy_->framerate_updated_event()->Wait(
424*d9f75844SAndroid Build Coastguard Worker TimeDelta::Seconds(5));
425*d9f75844SAndroid Build Coastguard Worker }
426*d9f75844SAndroid Build Coastguard Worker
OnBitrateUpdatedAndWaitForManagedResources(DataRate target_bitrate,DataRate stable_target_bitrate,DataRate link_allocation,uint8_t fraction_lost,int64_t round_trip_time_ms,double cwnd_reduce_ratio)427*d9f75844SAndroid Build Coastguard Worker void OnBitrateUpdatedAndWaitForManagedResources(
428*d9f75844SAndroid Build Coastguard Worker DataRate target_bitrate,
429*d9f75844SAndroid Build Coastguard Worker DataRate stable_target_bitrate,
430*d9f75844SAndroid Build Coastguard Worker DataRate link_allocation,
431*d9f75844SAndroid Build Coastguard Worker uint8_t fraction_lost,
432*d9f75844SAndroid Build Coastguard Worker int64_t round_trip_time_ms,
433*d9f75844SAndroid Build Coastguard Worker double cwnd_reduce_ratio) {
434*d9f75844SAndroid Build Coastguard Worker OnBitrateUpdated(target_bitrate, stable_target_bitrate, link_allocation,
435*d9f75844SAndroid Build Coastguard Worker fraction_lost, round_trip_time_ms, cwnd_reduce_ratio);
436*d9f75844SAndroid Build Coastguard Worker // Bitrate is updated on the encoder queue.
437*d9f75844SAndroid Build Coastguard Worker WaitUntilTaskQueueIsIdle();
438*d9f75844SAndroid Build Coastguard Worker }
439*d9f75844SAndroid Build Coastguard Worker
440*d9f75844SAndroid Build Coastguard Worker // This is used as a synchronisation mechanism, to make sure that the
441*d9f75844SAndroid Build Coastguard Worker // encoder queue is not blocked before we start sending it frames.
WaitUntilTaskQueueIsIdle()442*d9f75844SAndroid Build Coastguard Worker void WaitUntilTaskQueueIsIdle() {
443*d9f75844SAndroid Build Coastguard Worker time_controller_->AdvanceTime(TimeDelta::Zero());
444*d9f75844SAndroid Build Coastguard Worker }
445*d9f75844SAndroid Build Coastguard Worker
446*d9f75844SAndroid Build Coastguard Worker // Triggers resource usage measurements on the fake CPU resource.
TriggerCpuOveruse()447*d9f75844SAndroid Build Coastguard Worker void TriggerCpuOveruse() {
448*d9f75844SAndroid Build Coastguard Worker rtc::Event event;
449*d9f75844SAndroid Build Coastguard Worker encoder_queue()->PostTask([this, &event] {
450*d9f75844SAndroid Build Coastguard Worker fake_cpu_resource_->SetUsageState(ResourceUsageState::kOveruse);
451*d9f75844SAndroid Build Coastguard Worker event.Set();
452*d9f75844SAndroid Build Coastguard Worker });
453*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(event.Wait(TimeDelta::Seconds(5)));
454*d9f75844SAndroid Build Coastguard Worker time_controller_->AdvanceTime(TimeDelta::Zero());
455*d9f75844SAndroid Build Coastguard Worker }
456*d9f75844SAndroid Build Coastguard Worker
TriggerCpuUnderuse()457*d9f75844SAndroid Build Coastguard Worker void TriggerCpuUnderuse() {
458*d9f75844SAndroid Build Coastguard Worker rtc::Event event;
459*d9f75844SAndroid Build Coastguard Worker encoder_queue()->PostTask([this, &event] {
460*d9f75844SAndroid Build Coastguard Worker fake_cpu_resource_->SetUsageState(ResourceUsageState::kUnderuse);
461*d9f75844SAndroid Build Coastguard Worker event.Set();
462*d9f75844SAndroid Build Coastguard Worker });
463*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(event.Wait(TimeDelta::Seconds(5)));
464*d9f75844SAndroid Build Coastguard Worker time_controller_->AdvanceTime(TimeDelta::Zero());
465*d9f75844SAndroid Build Coastguard Worker }
466*d9f75844SAndroid Build Coastguard Worker
467*d9f75844SAndroid Build Coastguard Worker // Triggers resource usage measurements on the fake quality resource.
TriggerQualityLow()468*d9f75844SAndroid Build Coastguard Worker void TriggerQualityLow() {
469*d9f75844SAndroid Build Coastguard Worker rtc::Event event;
470*d9f75844SAndroid Build Coastguard Worker encoder_queue()->PostTask([this, &event] {
471*d9f75844SAndroid Build Coastguard Worker fake_quality_resource_->SetUsageState(ResourceUsageState::kOveruse);
472*d9f75844SAndroid Build Coastguard Worker event.Set();
473*d9f75844SAndroid Build Coastguard Worker });
474*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(event.Wait(TimeDelta::Seconds(5)));
475*d9f75844SAndroid Build Coastguard Worker time_controller_->AdvanceTime(TimeDelta::Zero());
476*d9f75844SAndroid Build Coastguard Worker }
TriggerQualityHigh()477*d9f75844SAndroid Build Coastguard Worker void TriggerQualityHigh() {
478*d9f75844SAndroid Build Coastguard Worker rtc::Event event;
479*d9f75844SAndroid Build Coastguard Worker encoder_queue()->PostTask([this, &event] {
480*d9f75844SAndroid Build Coastguard Worker fake_quality_resource_->SetUsageState(ResourceUsageState::kUnderuse);
481*d9f75844SAndroid Build Coastguard Worker event.Set();
482*d9f75844SAndroid Build Coastguard Worker });
483*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(event.Wait(TimeDelta::Seconds(5)));
484*d9f75844SAndroid Build Coastguard Worker time_controller_->AdvanceTime(TimeDelta::Zero());
485*d9f75844SAndroid Build Coastguard Worker }
486*d9f75844SAndroid Build Coastguard Worker
487*d9f75844SAndroid Build Coastguard Worker TimeController* const time_controller_;
488*d9f75844SAndroid Build Coastguard Worker CpuOveruseDetectorProxy* overuse_detector_proxy_;
489*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<FakeResource> fake_cpu_resource_;
490*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<FakeResource> fake_quality_resource_;
491*d9f75844SAndroid Build Coastguard Worker FakeAdaptationConstraint fake_adaptation_constraint_;
492*d9f75844SAndroid Build Coastguard Worker };
493*d9f75844SAndroid Build Coastguard Worker
494*d9f75844SAndroid Build Coastguard Worker // Simulates simulcast behavior and makes highest stream resolutions divisible
495*d9f75844SAndroid Build Coastguard Worker // by 4.
496*d9f75844SAndroid Build Coastguard Worker class CroppingVideoStreamFactory
497*d9f75844SAndroid Build Coastguard Worker : public VideoEncoderConfig::VideoStreamFactoryInterface {
498*d9f75844SAndroid Build Coastguard Worker public:
CroppingVideoStreamFactory()499*d9f75844SAndroid Build Coastguard Worker CroppingVideoStreamFactory() {}
500*d9f75844SAndroid Build Coastguard Worker
501*d9f75844SAndroid Build Coastguard Worker private:
CreateEncoderStreams(int frame_width,int frame_height,const VideoEncoderConfig & encoder_config)502*d9f75844SAndroid Build Coastguard Worker std::vector<VideoStream> CreateEncoderStreams(
503*d9f75844SAndroid Build Coastguard Worker int frame_width,
504*d9f75844SAndroid Build Coastguard Worker int frame_height,
505*d9f75844SAndroid Build Coastguard Worker const VideoEncoderConfig& encoder_config) override {
506*d9f75844SAndroid Build Coastguard Worker std::vector<VideoStream> streams = test::CreateVideoStreams(
507*d9f75844SAndroid Build Coastguard Worker frame_width - frame_width % 4, frame_height - frame_height % 4,
508*d9f75844SAndroid Build Coastguard Worker encoder_config);
509*d9f75844SAndroid Build Coastguard Worker return streams;
510*d9f75844SAndroid Build Coastguard Worker }
511*d9f75844SAndroid Build Coastguard Worker };
512*d9f75844SAndroid Build Coastguard Worker
513*d9f75844SAndroid Build Coastguard Worker class AdaptingFrameForwarder : public test::FrameForwarder {
514*d9f75844SAndroid Build Coastguard Worker public:
AdaptingFrameForwarder(TimeController * time_controller)515*d9f75844SAndroid Build Coastguard Worker explicit AdaptingFrameForwarder(TimeController* time_controller)
516*d9f75844SAndroid Build Coastguard Worker : time_controller_(time_controller), adaptation_enabled_(false) {}
~AdaptingFrameForwarder()517*d9f75844SAndroid Build Coastguard Worker ~AdaptingFrameForwarder() override {}
518*d9f75844SAndroid Build Coastguard Worker
set_adaptation_enabled(bool enabled)519*d9f75844SAndroid Build Coastguard Worker void set_adaptation_enabled(bool enabled) {
520*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
521*d9f75844SAndroid Build Coastguard Worker adaptation_enabled_ = enabled;
522*d9f75844SAndroid Build Coastguard Worker }
523*d9f75844SAndroid Build Coastguard Worker
adaption_enabled() const524*d9f75844SAndroid Build Coastguard Worker bool adaption_enabled() const {
525*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
526*d9f75844SAndroid Build Coastguard Worker return adaptation_enabled_;
527*d9f75844SAndroid Build Coastguard Worker }
528*d9f75844SAndroid Build Coastguard Worker
529*d9f75844SAndroid Build Coastguard Worker // The "last wants" is a snapshot of the previous rtc::VideoSinkWants where
530*d9f75844SAndroid Build Coastguard Worker // the resolution or frame rate was different than it is currently. If
531*d9f75844SAndroid Build Coastguard Worker // something else is modified, such as encoder resolutions, but the resolution
532*d9f75844SAndroid Build Coastguard Worker // and frame rate stays the same, last wants is not updated.
last_wants() const533*d9f75844SAndroid Build Coastguard Worker rtc::VideoSinkWants last_wants() const {
534*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
535*d9f75844SAndroid Build Coastguard Worker return last_wants_;
536*d9f75844SAndroid Build Coastguard Worker }
537*d9f75844SAndroid Build Coastguard Worker
last_sent_width() const538*d9f75844SAndroid Build Coastguard Worker absl::optional<int> last_sent_width() const { return last_width_; }
last_sent_height() const539*d9f75844SAndroid Build Coastguard Worker absl::optional<int> last_sent_height() const { return last_height_; }
540*d9f75844SAndroid Build Coastguard Worker
IncomingCapturedFrame(const VideoFrame & video_frame)541*d9f75844SAndroid Build Coastguard Worker void IncomingCapturedFrame(const VideoFrame& video_frame) override {
542*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(time_controller_->GetMainThread()->IsCurrent());
543*d9f75844SAndroid Build Coastguard Worker time_controller_->AdvanceTime(TimeDelta::Zero());
544*d9f75844SAndroid Build Coastguard Worker
545*d9f75844SAndroid Build Coastguard Worker int cropped_width = 0;
546*d9f75844SAndroid Build Coastguard Worker int cropped_height = 0;
547*d9f75844SAndroid Build Coastguard Worker int out_width = 0;
548*d9f75844SAndroid Build Coastguard Worker int out_height = 0;
549*d9f75844SAndroid Build Coastguard Worker if (adaption_enabled()) {
550*d9f75844SAndroid Build Coastguard Worker RTC_DLOG(LS_INFO) << "IncomingCapturedFrame: AdaptFrameResolution()"
551*d9f75844SAndroid Build Coastguard Worker << "w=" << video_frame.width()
552*d9f75844SAndroid Build Coastguard Worker << "h=" << video_frame.height();
553*d9f75844SAndroid Build Coastguard Worker if (adapter_.AdaptFrameResolution(
554*d9f75844SAndroid Build Coastguard Worker video_frame.width(), video_frame.height(),
555*d9f75844SAndroid Build Coastguard Worker video_frame.timestamp_us() * 1000, &cropped_width,
556*d9f75844SAndroid Build Coastguard Worker &cropped_height, &out_width, &out_height)) {
557*d9f75844SAndroid Build Coastguard Worker VideoFrame adapted_frame =
558*d9f75844SAndroid Build Coastguard Worker VideoFrame::Builder()
559*d9f75844SAndroid Build Coastguard Worker .set_video_frame_buffer(rtc::make_ref_counted<TestBuffer>(
560*d9f75844SAndroid Build Coastguard Worker nullptr, out_width, out_height))
561*d9f75844SAndroid Build Coastguard Worker .set_ntp_time_ms(video_frame.ntp_time_ms())
562*d9f75844SAndroid Build Coastguard Worker .set_timestamp_ms(99)
563*d9f75844SAndroid Build Coastguard Worker .set_rotation(kVideoRotation_0)
564*d9f75844SAndroid Build Coastguard Worker .build();
565*d9f75844SAndroid Build Coastguard Worker if (video_frame.has_update_rect()) {
566*d9f75844SAndroid Build Coastguard Worker adapted_frame.set_update_rect(
567*d9f75844SAndroid Build Coastguard Worker video_frame.update_rect().ScaleWithFrame(
568*d9f75844SAndroid Build Coastguard Worker video_frame.width(), video_frame.height(), 0, 0,
569*d9f75844SAndroid Build Coastguard Worker video_frame.width(), video_frame.height(), out_width,
570*d9f75844SAndroid Build Coastguard Worker out_height));
571*d9f75844SAndroid Build Coastguard Worker }
572*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder::IncomingCapturedFrame(adapted_frame);
573*d9f75844SAndroid Build Coastguard Worker last_width_.emplace(adapted_frame.width());
574*d9f75844SAndroid Build Coastguard Worker last_height_.emplace(adapted_frame.height());
575*d9f75844SAndroid Build Coastguard Worker } else {
576*d9f75844SAndroid Build Coastguard Worker last_width_ = absl::nullopt;
577*d9f75844SAndroid Build Coastguard Worker last_height_ = absl::nullopt;
578*d9f75844SAndroid Build Coastguard Worker }
579*d9f75844SAndroid Build Coastguard Worker } else {
580*d9f75844SAndroid Build Coastguard Worker RTC_DLOG(LS_INFO) << "IncomingCapturedFrame: adaptation not enabled";
581*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder::IncomingCapturedFrame(video_frame);
582*d9f75844SAndroid Build Coastguard Worker last_width_.emplace(video_frame.width());
583*d9f75844SAndroid Build Coastguard Worker last_height_.emplace(video_frame.height());
584*d9f75844SAndroid Build Coastguard Worker }
585*d9f75844SAndroid Build Coastguard Worker }
586*d9f75844SAndroid Build Coastguard Worker
OnOutputFormatRequest(int width,int height)587*d9f75844SAndroid Build Coastguard Worker void OnOutputFormatRequest(int width, int height) {
588*d9f75844SAndroid Build Coastguard Worker absl::optional<std::pair<int, int>> target_aspect_ratio =
589*d9f75844SAndroid Build Coastguard Worker std::make_pair(width, height);
590*d9f75844SAndroid Build Coastguard Worker absl::optional<int> max_pixel_count = width * height;
591*d9f75844SAndroid Build Coastguard Worker absl::optional<int> max_fps;
592*d9f75844SAndroid Build Coastguard Worker adapter_.OnOutputFormatRequest(target_aspect_ratio, max_pixel_count,
593*d9f75844SAndroid Build Coastguard Worker max_fps);
594*d9f75844SAndroid Build Coastguard Worker }
595*d9f75844SAndroid Build Coastguard Worker
AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame> * sink,const rtc::VideoSinkWants & wants)596*d9f75844SAndroid Build Coastguard Worker void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
597*d9f75844SAndroid Build Coastguard Worker const rtc::VideoSinkWants& wants) override {
598*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
599*d9f75844SAndroid Build Coastguard Worker rtc::VideoSinkWants prev_wants = sink_wants_locked();
600*d9f75844SAndroid Build Coastguard Worker bool did_adapt =
601*d9f75844SAndroid Build Coastguard Worker prev_wants.max_pixel_count != wants.max_pixel_count ||
602*d9f75844SAndroid Build Coastguard Worker prev_wants.target_pixel_count != wants.target_pixel_count ||
603*d9f75844SAndroid Build Coastguard Worker prev_wants.max_framerate_fps != wants.max_framerate_fps;
604*d9f75844SAndroid Build Coastguard Worker if (did_adapt) {
605*d9f75844SAndroid Build Coastguard Worker last_wants_ = prev_wants;
606*d9f75844SAndroid Build Coastguard Worker }
607*d9f75844SAndroid Build Coastguard Worker adapter_.OnSinkWants(wants);
608*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder::AddOrUpdateSinkLocked(sink, wants);
609*d9f75844SAndroid Build Coastguard Worker }
610*d9f75844SAndroid Build Coastguard Worker
RequestRefreshFrame()611*d9f75844SAndroid Build Coastguard Worker void RequestRefreshFrame() override { ++refresh_frames_requested_; }
612*d9f75844SAndroid Build Coastguard Worker
613*d9f75844SAndroid Build Coastguard Worker TimeController* const time_controller_;
614*d9f75844SAndroid Build Coastguard Worker cricket::VideoAdapter adapter_;
615*d9f75844SAndroid Build Coastguard Worker bool adaptation_enabled_ RTC_GUARDED_BY(mutex_);
616*d9f75844SAndroid Build Coastguard Worker rtc::VideoSinkWants last_wants_ RTC_GUARDED_BY(mutex_);
617*d9f75844SAndroid Build Coastguard Worker absl::optional<int> last_width_;
618*d9f75844SAndroid Build Coastguard Worker absl::optional<int> last_height_;
619*d9f75844SAndroid Build Coastguard Worker int refresh_frames_requested_{0};
620*d9f75844SAndroid Build Coastguard Worker };
621*d9f75844SAndroid Build Coastguard Worker
622*d9f75844SAndroid Build Coastguard Worker // TODO(nisse): Mock only VideoStreamEncoderObserver.
623*d9f75844SAndroid Build Coastguard Worker class MockableSendStatisticsProxy : public SendStatisticsProxy {
624*d9f75844SAndroid Build Coastguard Worker public:
MockableSendStatisticsProxy(Clock * clock,const VideoSendStream::Config & config,VideoEncoderConfig::ContentType content_type,const FieldTrialsView & field_trials)625*d9f75844SAndroid Build Coastguard Worker MockableSendStatisticsProxy(Clock* clock,
626*d9f75844SAndroid Build Coastguard Worker const VideoSendStream::Config& config,
627*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType content_type,
628*d9f75844SAndroid Build Coastguard Worker const FieldTrialsView& field_trials)
629*d9f75844SAndroid Build Coastguard Worker : SendStatisticsProxy(clock, config, content_type, field_trials) {}
630*d9f75844SAndroid Build Coastguard Worker
GetStats()631*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats GetStats() override {
632*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&lock_);
633*d9f75844SAndroid Build Coastguard Worker if (mock_stats_)
634*d9f75844SAndroid Build Coastguard Worker return *mock_stats_;
635*d9f75844SAndroid Build Coastguard Worker return SendStatisticsProxy::GetStats();
636*d9f75844SAndroid Build Coastguard Worker }
637*d9f75844SAndroid Build Coastguard Worker
GetInputFrameRate() const638*d9f75844SAndroid Build Coastguard Worker int GetInputFrameRate() const override {
639*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&lock_);
640*d9f75844SAndroid Build Coastguard Worker if (mock_stats_)
641*d9f75844SAndroid Build Coastguard Worker return mock_stats_->input_frame_rate;
642*d9f75844SAndroid Build Coastguard Worker return SendStatisticsProxy::GetInputFrameRate();
643*d9f75844SAndroid Build Coastguard Worker }
SetMockStats(const VideoSendStream::Stats & stats)644*d9f75844SAndroid Build Coastguard Worker void SetMockStats(const VideoSendStream::Stats& stats) {
645*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&lock_);
646*d9f75844SAndroid Build Coastguard Worker mock_stats_.emplace(stats);
647*d9f75844SAndroid Build Coastguard Worker }
648*d9f75844SAndroid Build Coastguard Worker
ResetMockStats()649*d9f75844SAndroid Build Coastguard Worker void ResetMockStats() {
650*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&lock_);
651*d9f75844SAndroid Build Coastguard Worker mock_stats_.reset();
652*d9f75844SAndroid Build Coastguard Worker }
653*d9f75844SAndroid Build Coastguard Worker
SetDroppedFrameCallback(std::function<void (DropReason)> callback)654*d9f75844SAndroid Build Coastguard Worker void SetDroppedFrameCallback(std::function<void(DropReason)> callback) {
655*d9f75844SAndroid Build Coastguard Worker on_frame_dropped_ = std::move(callback);
656*d9f75844SAndroid Build Coastguard Worker }
657*d9f75844SAndroid Build Coastguard Worker
658*d9f75844SAndroid Build Coastguard Worker private:
OnFrameDropped(DropReason reason)659*d9f75844SAndroid Build Coastguard Worker void OnFrameDropped(DropReason reason) override {
660*d9f75844SAndroid Build Coastguard Worker SendStatisticsProxy::OnFrameDropped(reason);
661*d9f75844SAndroid Build Coastguard Worker if (on_frame_dropped_)
662*d9f75844SAndroid Build Coastguard Worker on_frame_dropped_(reason);
663*d9f75844SAndroid Build Coastguard Worker }
664*d9f75844SAndroid Build Coastguard Worker
665*d9f75844SAndroid Build Coastguard Worker mutable Mutex lock_;
666*d9f75844SAndroid Build Coastguard Worker absl::optional<VideoSendStream::Stats> mock_stats_ RTC_GUARDED_BY(lock_);
667*d9f75844SAndroid Build Coastguard Worker std::function<void(DropReason)> on_frame_dropped_;
668*d9f75844SAndroid Build Coastguard Worker };
669*d9f75844SAndroid Build Coastguard Worker
670*d9f75844SAndroid Build Coastguard Worker class SimpleVideoStreamEncoderFactory {
671*d9f75844SAndroid Build Coastguard Worker public:
672*d9f75844SAndroid Build Coastguard Worker class AdaptedVideoStreamEncoder : public VideoStreamEncoder {
673*d9f75844SAndroid Build Coastguard Worker public:
674*d9f75844SAndroid Build Coastguard Worker using VideoStreamEncoder::VideoStreamEncoder;
~AdaptedVideoStreamEncoder()675*d9f75844SAndroid Build Coastguard Worker ~AdaptedVideoStreamEncoder() { Stop(); }
676*d9f75844SAndroid Build Coastguard Worker };
677*d9f75844SAndroid Build Coastguard Worker
678*d9f75844SAndroid Build Coastguard Worker class MockFakeEncoder : public test::FakeEncoder {
679*d9f75844SAndroid Build Coastguard Worker public:
680*d9f75844SAndroid Build Coastguard Worker using FakeEncoder::FakeEncoder;
681*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(CodecSpecificInfo,
682*d9f75844SAndroid Build Coastguard Worker EncodeHook,
683*d9f75844SAndroid Build Coastguard Worker (EncodedImage & encoded_image,
684*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<EncodedImageBuffer> buffer),
685*d9f75844SAndroid Build Coastguard Worker (override));
686*d9f75844SAndroid Build Coastguard Worker };
687*d9f75844SAndroid Build Coastguard Worker
SimpleVideoStreamEncoderFactory()688*d9f75844SAndroid Build Coastguard Worker SimpleVideoStreamEncoderFactory() {
689*d9f75844SAndroid Build Coastguard Worker encoder_settings_.encoder_factory = &encoder_factory_;
690*d9f75844SAndroid Build Coastguard Worker encoder_settings_.bitrate_allocator_factory =
691*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.get();
692*d9f75844SAndroid Build Coastguard Worker }
693*d9f75844SAndroid Build Coastguard Worker
CreateWithEncoderQueue(std::unique_ptr<FrameCadenceAdapterInterface> zero_hertz_adapter,std::unique_ptr<TaskQueueBase,TaskQueueDeleter> encoder_queue,const FieldTrialsView * field_trials=nullptr)694*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<AdaptedVideoStreamEncoder> CreateWithEncoderQueue(
695*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<FrameCadenceAdapterInterface> zero_hertz_adapter,
696*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<TaskQueueBase, TaskQueueDeleter> encoder_queue,
697*d9f75844SAndroid Build Coastguard Worker const FieldTrialsView* field_trials = nullptr) {
698*d9f75844SAndroid Build Coastguard Worker auto result = std::make_unique<AdaptedVideoStreamEncoder>(
699*d9f75844SAndroid Build Coastguard Worker time_controller_.GetClock(),
700*d9f75844SAndroid Build Coastguard Worker /*number_of_cores=*/1,
701*d9f75844SAndroid Build Coastguard Worker /*stats_proxy=*/stats_proxy_.get(), encoder_settings_,
702*d9f75844SAndroid Build Coastguard Worker std::make_unique<CpuOveruseDetectorProxy>(
703*d9f75844SAndroid Build Coastguard Worker /*stats_proxy=*/nullptr,
704*d9f75844SAndroid Build Coastguard Worker field_trials ? *field_trials : field_trials_),
705*d9f75844SAndroid Build Coastguard Worker std::move(zero_hertz_adapter), std::move(encoder_queue),
706*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
707*d9f75844SAndroid Build Coastguard Worker kVideoBitrateAllocation,
708*d9f75844SAndroid Build Coastguard Worker field_trials ? *field_trials : field_trials_);
709*d9f75844SAndroid Build Coastguard Worker result->SetSink(&sink_, /*rotation_applied=*/false);
710*d9f75844SAndroid Build Coastguard Worker return result;
711*d9f75844SAndroid Build Coastguard Worker }
712*d9f75844SAndroid Build Coastguard Worker
Create(std::unique_ptr<FrameCadenceAdapterInterface> zero_hertz_adapter,TaskQueueBase ** encoder_queue_ptr=nullptr)713*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<AdaptedVideoStreamEncoder> Create(
714*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<FrameCadenceAdapterInterface> zero_hertz_adapter,
715*d9f75844SAndroid Build Coastguard Worker TaskQueueBase** encoder_queue_ptr = nullptr) {
716*d9f75844SAndroid Build Coastguard Worker auto encoder_queue =
717*d9f75844SAndroid Build Coastguard Worker time_controller_.GetTaskQueueFactory()->CreateTaskQueue(
718*d9f75844SAndroid Build Coastguard Worker "EncoderQueue", TaskQueueFactory::Priority::NORMAL);
719*d9f75844SAndroid Build Coastguard Worker if (encoder_queue_ptr)
720*d9f75844SAndroid Build Coastguard Worker *encoder_queue_ptr = encoder_queue.get();
721*d9f75844SAndroid Build Coastguard Worker return CreateWithEncoderQueue(std::move(zero_hertz_adapter),
722*d9f75844SAndroid Build Coastguard Worker std::move(encoder_queue));
723*d9f75844SAndroid Build Coastguard Worker }
724*d9f75844SAndroid Build Coastguard Worker
DepleteTaskQueues()725*d9f75844SAndroid Build Coastguard Worker void DepleteTaskQueues() { time_controller_.AdvanceTime(TimeDelta::Zero()); }
GetMockFakeEncoder()726*d9f75844SAndroid Build Coastguard Worker MockFakeEncoder& GetMockFakeEncoder() { return mock_fake_encoder_; }
727*d9f75844SAndroid Build Coastguard Worker
GetTimeController()728*d9f75844SAndroid Build Coastguard Worker GlobalSimulatedTimeController* GetTimeController() {
729*d9f75844SAndroid Build Coastguard Worker return &time_controller_;
730*d9f75844SAndroid Build Coastguard Worker }
731*d9f75844SAndroid Build Coastguard Worker
732*d9f75844SAndroid Build Coastguard Worker private:
733*d9f75844SAndroid Build Coastguard Worker class NullEncoderSink : public VideoStreamEncoderInterface::EncoderSink {
734*d9f75844SAndroid Build Coastguard Worker public:
735*d9f75844SAndroid Build Coastguard Worker ~NullEncoderSink() override = default;
OnEncoderConfigurationChanged(std::vector<VideoStream> streams,bool is_svc,VideoEncoderConfig::ContentType content_type,int min_transmit_bitrate_bps)736*d9f75844SAndroid Build Coastguard Worker void OnEncoderConfigurationChanged(
737*d9f75844SAndroid Build Coastguard Worker std::vector<VideoStream> streams,
738*d9f75844SAndroid Build Coastguard Worker bool is_svc,
739*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType content_type,
740*d9f75844SAndroid Build Coastguard Worker int min_transmit_bitrate_bps) override {}
OnBitrateAllocationUpdated(const VideoBitrateAllocation & allocation)741*d9f75844SAndroid Build Coastguard Worker void OnBitrateAllocationUpdated(
742*d9f75844SAndroid Build Coastguard Worker const VideoBitrateAllocation& allocation) override {}
OnVideoLayersAllocationUpdated(VideoLayersAllocation allocation)743*d9f75844SAndroid Build Coastguard Worker void OnVideoLayersAllocationUpdated(
744*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation allocation) override {}
OnEncodedImage(const EncodedImage & encoded_image,const CodecSpecificInfo * codec_specific_info)745*d9f75844SAndroid Build Coastguard Worker Result OnEncodedImage(
746*d9f75844SAndroid Build Coastguard Worker const EncodedImage& encoded_image,
747*d9f75844SAndroid Build Coastguard Worker const CodecSpecificInfo* codec_specific_info) override {
748*d9f75844SAndroid Build Coastguard Worker return Result(EncodedImageCallback::Result::OK);
749*d9f75844SAndroid Build Coastguard Worker }
750*d9f75844SAndroid Build Coastguard Worker };
751*d9f75844SAndroid Build Coastguard Worker
752*d9f75844SAndroid Build Coastguard Worker test::ScopedKeyValueConfig field_trials_;
753*d9f75844SAndroid Build Coastguard Worker GlobalSimulatedTimeController time_controller_{Timestamp::Zero()};
754*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<TaskQueueFactory> task_queue_factory_{
755*d9f75844SAndroid Build Coastguard Worker time_controller_.CreateTaskQueueFactory()};
756*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<MockableSendStatisticsProxy> stats_proxy_ =
757*d9f75844SAndroid Build Coastguard Worker std::make_unique<MockableSendStatisticsProxy>(
758*d9f75844SAndroid Build Coastguard Worker time_controller_.GetClock(),
759*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Config(nullptr),
760*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo,
761*d9f75844SAndroid Build Coastguard Worker field_trials_);
762*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<VideoBitrateAllocatorFactory> bitrate_allocator_factory_ =
763*d9f75844SAndroid Build Coastguard Worker CreateBuiltinVideoBitrateAllocatorFactory();
764*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoderSettings encoder_settings_{
765*d9f75844SAndroid Build Coastguard Worker VideoEncoder::Capabilities(/*loss_notification=*/false)};
766*d9f75844SAndroid Build Coastguard Worker MockFakeEncoder mock_fake_encoder_{time_controller_.GetClock()};
767*d9f75844SAndroid Build Coastguard Worker test::VideoEncoderProxyFactory encoder_factory_{&mock_fake_encoder_};
768*d9f75844SAndroid Build Coastguard Worker NullEncoderSink sink_;
769*d9f75844SAndroid Build Coastguard Worker };
770*d9f75844SAndroid Build Coastguard Worker
771*d9f75844SAndroid Build Coastguard Worker class MockFrameCadenceAdapter : public FrameCadenceAdapterInterface {
772*d9f75844SAndroid Build Coastguard Worker public:
773*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void, Initialize, (Callback * callback), (override));
774*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void,
775*d9f75844SAndroid Build Coastguard Worker SetZeroHertzModeEnabled,
776*d9f75844SAndroid Build Coastguard Worker (absl::optional<ZeroHertzModeParams>),
777*d9f75844SAndroid Build Coastguard Worker (override));
778*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void, OnFrame, (const VideoFrame&), (override));
779*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(absl::optional<uint32_t>, GetInputFrameRateFps, (), (override));
780*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void, UpdateFrameRate, (), (override));
781*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void,
782*d9f75844SAndroid Build Coastguard Worker UpdateLayerQualityConvergence,
783*d9f75844SAndroid Build Coastguard Worker (size_t spatial_index, bool converged),
784*d9f75844SAndroid Build Coastguard Worker (override));
785*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void,
786*d9f75844SAndroid Build Coastguard Worker UpdateLayerStatus,
787*d9f75844SAndroid Build Coastguard Worker (size_t spatial_index, bool enabled),
788*d9f75844SAndroid Build Coastguard Worker (override));
789*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void, ProcessKeyFrameRequest, (), (override));
790*d9f75844SAndroid Build Coastguard Worker };
791*d9f75844SAndroid Build Coastguard Worker
792*d9f75844SAndroid Build Coastguard Worker class MockEncoderSelector
793*d9f75844SAndroid Build Coastguard Worker : public VideoEncoderFactory::EncoderSelectorInterface {
794*d9f75844SAndroid Build Coastguard Worker public:
795*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void,
796*d9f75844SAndroid Build Coastguard Worker OnCurrentEncoder,
797*d9f75844SAndroid Build Coastguard Worker (const SdpVideoFormat& format),
798*d9f75844SAndroid Build Coastguard Worker (override));
799*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(absl::optional<SdpVideoFormat>,
800*d9f75844SAndroid Build Coastguard Worker OnAvailableBitrate,
801*d9f75844SAndroid Build Coastguard Worker (const DataRate& rate),
802*d9f75844SAndroid Build Coastguard Worker (override));
803*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(absl::optional<SdpVideoFormat>,
804*d9f75844SAndroid Build Coastguard Worker OnResolutionChange,
805*d9f75844SAndroid Build Coastguard Worker (const RenderResolution& resolution),
806*d9f75844SAndroid Build Coastguard Worker (override));
807*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(absl::optional<SdpVideoFormat>, OnEncoderBroken, (), (override));
808*d9f75844SAndroid Build Coastguard Worker };
809*d9f75844SAndroid Build Coastguard Worker
810*d9f75844SAndroid Build Coastguard Worker class MockVideoSourceInterface : public rtc::VideoSourceInterface<VideoFrame> {
811*d9f75844SAndroid Build Coastguard Worker public:
812*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void,
813*d9f75844SAndroid Build Coastguard Worker AddOrUpdateSink,
814*d9f75844SAndroid Build Coastguard Worker (rtc::VideoSinkInterface<VideoFrame>*,
815*d9f75844SAndroid Build Coastguard Worker const rtc::VideoSinkWants&),
816*d9f75844SAndroid Build Coastguard Worker (override));
817*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void,
818*d9f75844SAndroid Build Coastguard Worker RemoveSink,
819*d9f75844SAndroid Build Coastguard Worker (rtc::VideoSinkInterface<VideoFrame>*),
820*d9f75844SAndroid Build Coastguard Worker (override));
821*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void, RequestRefreshFrame, (), (override));
822*d9f75844SAndroid Build Coastguard Worker };
823*d9f75844SAndroid Build Coastguard Worker
824*d9f75844SAndroid Build Coastguard Worker } // namespace
825*d9f75844SAndroid Build Coastguard Worker
826*d9f75844SAndroid Build Coastguard Worker class VideoStreamEncoderTest : public ::testing::Test {
827*d9f75844SAndroid Build Coastguard Worker public:
828*d9f75844SAndroid Build Coastguard Worker static constexpr TimeDelta kDefaultTimeout = TimeDelta::Seconds(1);
829*d9f75844SAndroid Build Coastguard Worker
VideoStreamEncoderTest()830*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoderTest()
831*d9f75844SAndroid Build Coastguard Worker : video_send_config_(VideoSendStream::Config(nullptr)),
832*d9f75844SAndroid Build Coastguard Worker codec_width_(320),
833*d9f75844SAndroid Build Coastguard Worker codec_height_(240),
834*d9f75844SAndroid Build Coastguard Worker max_framerate_(kDefaultFramerate),
835*d9f75844SAndroid Build Coastguard Worker fake_encoder_(&time_controller_),
836*d9f75844SAndroid Build Coastguard Worker encoder_factory_(&fake_encoder_),
837*d9f75844SAndroid Build Coastguard Worker stats_proxy_(new MockableSendStatisticsProxy(
838*d9f75844SAndroid Build Coastguard Worker time_controller_.GetClock(),
839*d9f75844SAndroid Build Coastguard Worker video_send_config_,
840*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo,
841*d9f75844SAndroid Build Coastguard Worker field_trials_)),
842*d9f75844SAndroid Build Coastguard Worker sink_(&time_controller_, &fake_encoder_) {}
843*d9f75844SAndroid Build Coastguard Worker
SetUp()844*d9f75844SAndroid Build Coastguard Worker void SetUp() override {
845*d9f75844SAndroid Build Coastguard Worker metrics::Reset();
846*d9f75844SAndroid Build Coastguard Worker video_send_config_ = VideoSendStream::Config(nullptr);
847*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_factory = &encoder_factory_;
848*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.bitrate_allocator_factory =
849*d9f75844SAndroid Build Coastguard Worker &bitrate_allocator_factory_;
850*d9f75844SAndroid Build Coastguard Worker video_send_config_.rtp.payload_name = "FAKE";
851*d9f75844SAndroid Build Coastguard Worker video_send_config_.rtp.payload_type = 125;
852*d9f75844SAndroid Build Coastguard Worker
853*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
854*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
855*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, video_encoder_config.simulcast_layers.size());
856*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].num_temporal_layers = 1;
857*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].max_framerate = max_framerate_;
858*d9f75844SAndroid Build Coastguard Worker video_encoder_config_ = video_encoder_config.Copy();
859*d9f75844SAndroid Build Coastguard Worker
860*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config));
861*d9f75844SAndroid Build Coastguard Worker }
862*d9f75844SAndroid Build Coastguard Worker
ConfigureEncoder(VideoEncoderConfig video_encoder_config,VideoStreamEncoder::BitrateAllocationCallbackType allocation_callback_type=VideoStreamEncoder::BitrateAllocationCallbackType::kVideoBitrateAllocationWhenScreenSharing,int num_cores=1)863*d9f75844SAndroid Build Coastguard Worker void ConfigureEncoder(
864*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config,
865*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType
866*d9f75844SAndroid Build Coastguard Worker allocation_callback_type =
867*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
868*d9f75844SAndroid Build Coastguard Worker kVideoBitrateAllocationWhenScreenSharing,
869*d9f75844SAndroid Build Coastguard Worker int num_cores = 1) {
870*d9f75844SAndroid Build Coastguard Worker if (video_stream_encoder_)
871*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
872*d9f75844SAndroid Build Coastguard Worker
873*d9f75844SAndroid Build Coastguard Worker auto encoder_queue = GetTaskQueueFactory()->CreateTaskQueue(
874*d9f75844SAndroid Build Coastguard Worker "EncoderQueue", TaskQueueFactory::Priority::NORMAL);
875*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* encoder_queue_ptr = encoder_queue.get();
876*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<FrameCadenceAdapterInterface> cadence_adapter =
877*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::Create(time_controller_.GetClock(),
878*d9f75844SAndroid Build Coastguard Worker encoder_queue_ptr, field_trials_);
879*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_ = std::make_unique<VideoStreamEncoderUnderTest>(
880*d9f75844SAndroid Build Coastguard Worker &time_controller_, std::move(cadence_adapter), std::move(encoder_queue),
881*d9f75844SAndroid Build Coastguard Worker stats_proxy_.get(), video_send_config_.encoder_settings,
882*d9f75844SAndroid Build Coastguard Worker allocation_callback_type, field_trials_, num_cores);
883*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSink(&sink_, /*rotation_applied=*/false);
884*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
885*d9f75844SAndroid Build Coastguard Worker &video_source_, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
886*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetStartBitrate(kTargetBitrate.bps());
887*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
888*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength, nullptr);
889*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
890*d9f75844SAndroid Build Coastguard Worker }
891*d9f75844SAndroid Build Coastguard Worker
ResetEncoder(const std::string & payload_name,size_t num_streams,size_t num_temporal_layers,unsigned char num_spatial_layers,bool screenshare,VideoStreamEncoder::BitrateAllocationCallbackType allocation_callback_type=VideoStreamEncoder::BitrateAllocationCallbackType::kVideoBitrateAllocationWhenScreenSharing,int num_cores=1)892*d9f75844SAndroid Build Coastguard Worker void ResetEncoder(const std::string& payload_name,
893*d9f75844SAndroid Build Coastguard Worker size_t num_streams,
894*d9f75844SAndroid Build Coastguard Worker size_t num_temporal_layers,
895*d9f75844SAndroid Build Coastguard Worker unsigned char num_spatial_layers,
896*d9f75844SAndroid Build Coastguard Worker bool screenshare,
897*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType
898*d9f75844SAndroid Build Coastguard Worker allocation_callback_type =
899*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
900*d9f75844SAndroid Build Coastguard Worker kVideoBitrateAllocationWhenScreenSharing,
901*d9f75844SAndroid Build Coastguard Worker int num_cores = 1) {
902*d9f75844SAndroid Build Coastguard Worker video_send_config_.rtp.payload_name = payload_name;
903*d9f75844SAndroid Build Coastguard Worker
904*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
905*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(PayloadStringToCodecType(payload_name),
906*d9f75844SAndroid Build Coastguard Worker num_streams, &video_encoder_config);
907*d9f75844SAndroid Build Coastguard Worker for (auto& layer : video_encoder_config.simulcast_layers) {
908*d9f75844SAndroid Build Coastguard Worker layer.num_temporal_layers = num_temporal_layers;
909*d9f75844SAndroid Build Coastguard Worker layer.max_framerate = kDefaultFramerate;
910*d9f75844SAndroid Build Coastguard Worker }
911*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps =
912*d9f75844SAndroid Build Coastguard Worker num_streams == 1 ? kTargetBitrate.bps() : kSimulcastTargetBitrate.bps();
913*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
914*d9f75844SAndroid Build Coastguard Worker screenshare ? VideoEncoderConfig::ContentType::kScreen
915*d9f75844SAndroid Build Coastguard Worker : VideoEncoderConfig::ContentType::kRealtimeVideo;
916*d9f75844SAndroid Build Coastguard Worker if (payload_name == "VP9") {
917*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
918*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = num_spatial_layers;
919*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = num_spatial_layers <= 1;
920*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
921*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
922*d9f75844SAndroid Build Coastguard Worker vp9_settings);
923*d9f75844SAndroid Build Coastguard Worker }
924*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config), allocation_callback_type,
925*d9f75844SAndroid Build Coastguard Worker num_cores);
926*d9f75844SAndroid Build Coastguard Worker }
927*d9f75844SAndroid Build Coastguard Worker
CreateFrame(int64_t ntp_time_ms,rtc::Event * destruction_event) const928*d9f75844SAndroid Build Coastguard Worker VideoFrame CreateFrame(int64_t ntp_time_ms,
929*d9f75844SAndroid Build Coastguard Worker rtc::Event* destruction_event) const {
930*d9f75844SAndroid Build Coastguard Worker return VideoFrame::Builder()
931*d9f75844SAndroid Build Coastguard Worker .set_video_frame_buffer(rtc::make_ref_counted<TestBuffer>(
932*d9f75844SAndroid Build Coastguard Worker destruction_event, codec_width_, codec_height_))
933*d9f75844SAndroid Build Coastguard Worker .set_ntp_time_ms(ntp_time_ms)
934*d9f75844SAndroid Build Coastguard Worker .set_timestamp_ms(99)
935*d9f75844SAndroid Build Coastguard Worker .set_rotation(kVideoRotation_0)
936*d9f75844SAndroid Build Coastguard Worker .build();
937*d9f75844SAndroid Build Coastguard Worker }
938*d9f75844SAndroid Build Coastguard Worker
CreateFrameWithUpdatedPixel(int64_t ntp_time_ms,rtc::Event * destruction_event,int offset_x) const939*d9f75844SAndroid Build Coastguard Worker VideoFrame CreateFrameWithUpdatedPixel(int64_t ntp_time_ms,
940*d9f75844SAndroid Build Coastguard Worker rtc::Event* destruction_event,
941*d9f75844SAndroid Build Coastguard Worker int offset_x) const {
942*d9f75844SAndroid Build Coastguard Worker return VideoFrame::Builder()
943*d9f75844SAndroid Build Coastguard Worker .set_video_frame_buffer(rtc::make_ref_counted<TestBuffer>(
944*d9f75844SAndroid Build Coastguard Worker destruction_event, codec_width_, codec_height_))
945*d9f75844SAndroid Build Coastguard Worker .set_ntp_time_ms(ntp_time_ms)
946*d9f75844SAndroid Build Coastguard Worker .set_timestamp_ms(99)
947*d9f75844SAndroid Build Coastguard Worker .set_rotation(kVideoRotation_0)
948*d9f75844SAndroid Build Coastguard Worker .set_update_rect(VideoFrame::UpdateRect{offset_x, 0, 1, 1})
949*d9f75844SAndroid Build Coastguard Worker .build();
950*d9f75844SAndroid Build Coastguard Worker }
951*d9f75844SAndroid Build Coastguard Worker
CreateFrame(int64_t ntp_time_ms,int width,int height) const952*d9f75844SAndroid Build Coastguard Worker VideoFrame CreateFrame(int64_t ntp_time_ms, int width, int height) const {
953*d9f75844SAndroid Build Coastguard Worker auto buffer = rtc::make_ref_counted<TestBuffer>(nullptr, width, height);
954*d9f75844SAndroid Build Coastguard Worker I420Buffer::SetBlack(buffer.get());
955*d9f75844SAndroid Build Coastguard Worker return VideoFrame::Builder()
956*d9f75844SAndroid Build Coastguard Worker .set_video_frame_buffer(std::move(buffer))
957*d9f75844SAndroid Build Coastguard Worker .set_ntp_time_ms(ntp_time_ms)
958*d9f75844SAndroid Build Coastguard Worker .set_timestamp_ms(ntp_time_ms)
959*d9f75844SAndroid Build Coastguard Worker .set_rotation(kVideoRotation_0)
960*d9f75844SAndroid Build Coastguard Worker .build();
961*d9f75844SAndroid Build Coastguard Worker }
962*d9f75844SAndroid Build Coastguard Worker
CreateNV12Frame(int64_t ntp_time_ms,int width,int height) const963*d9f75844SAndroid Build Coastguard Worker VideoFrame CreateNV12Frame(int64_t ntp_time_ms, int width, int height) const {
964*d9f75844SAndroid Build Coastguard Worker return VideoFrame::Builder()
965*d9f75844SAndroid Build Coastguard Worker .set_video_frame_buffer(NV12Buffer::Create(width, height))
966*d9f75844SAndroid Build Coastguard Worker .set_ntp_time_ms(ntp_time_ms)
967*d9f75844SAndroid Build Coastguard Worker .set_timestamp_ms(ntp_time_ms)
968*d9f75844SAndroid Build Coastguard Worker .set_rotation(kVideoRotation_0)
969*d9f75844SAndroid Build Coastguard Worker .build();
970*d9f75844SAndroid Build Coastguard Worker }
971*d9f75844SAndroid Build Coastguard Worker
CreateFakeNativeFrame(int64_t ntp_time_ms,rtc::Event * destruction_event,int width,int height) const972*d9f75844SAndroid Build Coastguard Worker VideoFrame CreateFakeNativeFrame(int64_t ntp_time_ms,
973*d9f75844SAndroid Build Coastguard Worker rtc::Event* destruction_event,
974*d9f75844SAndroid Build Coastguard Worker int width,
975*d9f75844SAndroid Build Coastguard Worker int height) const {
976*d9f75844SAndroid Build Coastguard Worker return VideoFrame::Builder()
977*d9f75844SAndroid Build Coastguard Worker .set_video_frame_buffer(rtc::make_ref_counted<FakeNativeBuffer>(
978*d9f75844SAndroid Build Coastguard Worker destruction_event, width, height))
979*d9f75844SAndroid Build Coastguard Worker .set_ntp_time_ms(ntp_time_ms)
980*d9f75844SAndroid Build Coastguard Worker .set_timestamp_ms(99)
981*d9f75844SAndroid Build Coastguard Worker .set_rotation(kVideoRotation_0)
982*d9f75844SAndroid Build Coastguard Worker .build();
983*d9f75844SAndroid Build Coastguard Worker }
984*d9f75844SAndroid Build Coastguard Worker
CreateFakeNV12NativeFrame(int64_t ntp_time_ms,rtc::Event * destruction_event,int width,int height) const985*d9f75844SAndroid Build Coastguard Worker VideoFrame CreateFakeNV12NativeFrame(int64_t ntp_time_ms,
986*d9f75844SAndroid Build Coastguard Worker rtc::Event* destruction_event,
987*d9f75844SAndroid Build Coastguard Worker int width,
988*d9f75844SAndroid Build Coastguard Worker int height) const {
989*d9f75844SAndroid Build Coastguard Worker return VideoFrame::Builder()
990*d9f75844SAndroid Build Coastguard Worker .set_video_frame_buffer(rtc::make_ref_counted<FakeNV12NativeBuffer>(
991*d9f75844SAndroid Build Coastguard Worker destruction_event, width, height))
992*d9f75844SAndroid Build Coastguard Worker .set_ntp_time_ms(ntp_time_ms)
993*d9f75844SAndroid Build Coastguard Worker .set_timestamp_ms(99)
994*d9f75844SAndroid Build Coastguard Worker .set_rotation(kVideoRotation_0)
995*d9f75844SAndroid Build Coastguard Worker .build();
996*d9f75844SAndroid Build Coastguard Worker }
997*d9f75844SAndroid Build Coastguard Worker
CreateFakeNativeFrame(int64_t ntp_time_ms,rtc::Event * destruction_event) const998*d9f75844SAndroid Build Coastguard Worker VideoFrame CreateFakeNativeFrame(int64_t ntp_time_ms,
999*d9f75844SAndroid Build Coastguard Worker rtc::Event* destruction_event) const {
1000*d9f75844SAndroid Build Coastguard Worker return CreateFakeNativeFrame(ntp_time_ms, destruction_event, codec_width_,
1001*d9f75844SAndroid Build Coastguard Worker codec_height_);
1002*d9f75844SAndroid Build Coastguard Worker }
1003*d9f75844SAndroid Build Coastguard Worker
VerifyAllocatedBitrate(const VideoBitrateAllocation & expected_bitrate)1004*d9f75844SAndroid Build Coastguard Worker void VerifyAllocatedBitrate(const VideoBitrateAllocation& expected_bitrate) {
1005*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1006*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1007*d9f75844SAndroid Build Coastguard Worker
1008*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
1009*d9f75844SAndroid Build Coastguard Worker CreateFrame(1, codec_width_, codec_height_));
1010*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1011*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(expected_bitrate, sink_.GetLastVideoBitrateAllocation());
1012*d9f75844SAndroid Build Coastguard Worker }
1013*d9f75844SAndroid Build Coastguard Worker
WaitForEncodedFrame(int64_t expected_ntp_time)1014*d9f75844SAndroid Build Coastguard Worker void WaitForEncodedFrame(int64_t expected_ntp_time) {
1015*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(expected_ntp_time);
1016*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Seconds(1) / max_framerate_);
1017*d9f75844SAndroid Build Coastguard Worker }
1018*d9f75844SAndroid Build Coastguard Worker
TimedWaitForEncodedFrame(int64_t expected_ntp_time,TimeDelta timeout)1019*d9f75844SAndroid Build Coastguard Worker bool TimedWaitForEncodedFrame(int64_t expected_ntp_time, TimeDelta timeout) {
1020*d9f75844SAndroid Build Coastguard Worker bool ok = sink_.TimedWaitForEncodedFrame(expected_ntp_time, timeout);
1021*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Seconds(1) / max_framerate_);
1022*d9f75844SAndroid Build Coastguard Worker return ok;
1023*d9f75844SAndroid Build Coastguard Worker }
1024*d9f75844SAndroid Build Coastguard Worker
WaitForEncodedFrame(uint32_t expected_width,uint32_t expected_height)1025*d9f75844SAndroid Build Coastguard Worker void WaitForEncodedFrame(uint32_t expected_width, uint32_t expected_height) {
1026*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(expected_width, expected_height);
1027*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Seconds(1) / max_framerate_);
1028*d9f75844SAndroid Build Coastguard Worker }
1029*d9f75844SAndroid Build Coastguard Worker
ExpectDroppedFrame()1030*d9f75844SAndroid Build Coastguard Worker void ExpectDroppedFrame() {
1031*d9f75844SAndroid Build Coastguard Worker sink_.ExpectDroppedFrame();
1032*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Seconds(1) / max_framerate_);
1033*d9f75844SAndroid Build Coastguard Worker }
1034*d9f75844SAndroid Build Coastguard Worker
WaitForFrame(TimeDelta timeout)1035*d9f75844SAndroid Build Coastguard Worker bool WaitForFrame(TimeDelta timeout) {
1036*d9f75844SAndroid Build Coastguard Worker bool ok = sink_.WaitForFrame(timeout);
1037*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Seconds(1) / max_framerate_);
1038*d9f75844SAndroid Build Coastguard Worker return ok;
1039*d9f75844SAndroid Build Coastguard Worker }
1040*d9f75844SAndroid Build Coastguard Worker
1041*d9f75844SAndroid Build Coastguard Worker class TestEncoder : public test::FakeEncoder {
1042*d9f75844SAndroid Build Coastguard Worker public:
TestEncoder(TimeController * time_controller)1043*d9f75844SAndroid Build Coastguard Worker explicit TestEncoder(TimeController* time_controller)
1044*d9f75844SAndroid Build Coastguard Worker : FakeEncoder(time_controller->GetClock()),
1045*d9f75844SAndroid Build Coastguard Worker time_controller_(time_controller) {
1046*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(time_controller_);
1047*d9f75844SAndroid Build Coastguard Worker }
1048*d9f75844SAndroid Build Coastguard Worker
GetEncoderInfo() const1049*d9f75844SAndroid Build Coastguard Worker VideoEncoder::EncoderInfo GetEncoderInfo() const override {
1050*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1051*d9f75844SAndroid Build Coastguard Worker EncoderInfo info = FakeEncoder::GetEncoderInfo();
1052*d9f75844SAndroid Build Coastguard Worker if (initialized_ == EncoderState::kInitialized) {
1053*d9f75844SAndroid Build Coastguard Worker if (quality_scaling_) {
1054*d9f75844SAndroid Build Coastguard Worker info.scaling_settings = VideoEncoder::ScalingSettings(
1055*d9f75844SAndroid Build Coastguard Worker kQpLow, kQpHigh, kMinPixelsPerFrame);
1056*d9f75844SAndroid Build Coastguard Worker }
1057*d9f75844SAndroid Build Coastguard Worker info.is_hardware_accelerated = is_hardware_accelerated_;
1058*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < kMaxSpatialLayers; ++i) {
1059*d9f75844SAndroid Build Coastguard Worker if (temporal_layers_supported_[i]) {
1060*d9f75844SAndroid Build Coastguard Worker info.fps_allocation[i].clear();
1061*d9f75844SAndroid Build Coastguard Worker int num_layers = temporal_layers_supported_[i].value() ? 2 : 1;
1062*d9f75844SAndroid Build Coastguard Worker for (int tid = 0; tid < num_layers; ++tid)
1063*d9f75844SAndroid Build Coastguard Worker info.fps_allocation[i].push_back(255 / (num_layers - tid));
1064*d9f75844SAndroid Build Coastguard Worker }
1065*d9f75844SAndroid Build Coastguard Worker }
1066*d9f75844SAndroid Build Coastguard Worker }
1067*d9f75844SAndroid Build Coastguard Worker
1068*d9f75844SAndroid Build Coastguard Worker info.resolution_bitrate_limits = resolution_bitrate_limits_;
1069*d9f75844SAndroid Build Coastguard Worker info.requested_resolution_alignment = requested_resolution_alignment_;
1070*d9f75844SAndroid Build Coastguard Worker info.apply_alignment_to_all_simulcast_layers =
1071*d9f75844SAndroid Build Coastguard Worker apply_alignment_to_all_simulcast_layers_;
1072*d9f75844SAndroid Build Coastguard Worker info.preferred_pixel_formats = preferred_pixel_formats_;
1073*d9f75844SAndroid Build Coastguard Worker if (is_qp_trusted_.has_value()) {
1074*d9f75844SAndroid Build Coastguard Worker info.is_qp_trusted = is_qp_trusted_;
1075*d9f75844SAndroid Build Coastguard Worker }
1076*d9f75844SAndroid Build Coastguard Worker return info;
1077*d9f75844SAndroid Build Coastguard Worker }
1078*d9f75844SAndroid Build Coastguard Worker
RegisterEncodeCompleteCallback(EncodedImageCallback * callback)1079*d9f75844SAndroid Build Coastguard Worker int32_t RegisterEncodeCompleteCallback(
1080*d9f75844SAndroid Build Coastguard Worker EncodedImageCallback* callback) override {
1081*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1082*d9f75844SAndroid Build Coastguard Worker encoded_image_callback_ = callback;
1083*d9f75844SAndroid Build Coastguard Worker return FakeEncoder::RegisterEncodeCompleteCallback(callback);
1084*d9f75844SAndroid Build Coastguard Worker }
1085*d9f75844SAndroid Build Coastguard Worker
ContinueEncode()1086*d9f75844SAndroid Build Coastguard Worker void ContinueEncode() { continue_encode_event_.Set(); }
1087*d9f75844SAndroid Build Coastguard Worker
CheckLastTimeStampsMatch(int64_t ntp_time_ms,uint32_t timestamp) const1088*d9f75844SAndroid Build Coastguard Worker void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
1089*d9f75844SAndroid Build Coastguard Worker uint32_t timestamp) const {
1090*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1091*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(timestamp_, timestamp);
1092*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
1093*d9f75844SAndroid Build Coastguard Worker }
1094*d9f75844SAndroid Build Coastguard Worker
SetQualityScaling(bool b)1095*d9f75844SAndroid Build Coastguard Worker void SetQualityScaling(bool b) {
1096*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1097*d9f75844SAndroid Build Coastguard Worker quality_scaling_ = b;
1098*d9f75844SAndroid Build Coastguard Worker }
1099*d9f75844SAndroid Build Coastguard Worker
SetRequestedResolutionAlignment(int requested_resolution_alignment)1100*d9f75844SAndroid Build Coastguard Worker void SetRequestedResolutionAlignment(int requested_resolution_alignment) {
1101*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1102*d9f75844SAndroid Build Coastguard Worker requested_resolution_alignment_ = requested_resolution_alignment;
1103*d9f75844SAndroid Build Coastguard Worker }
1104*d9f75844SAndroid Build Coastguard Worker
SetApplyAlignmentToAllSimulcastLayers(bool b)1105*d9f75844SAndroid Build Coastguard Worker void SetApplyAlignmentToAllSimulcastLayers(bool b) {
1106*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1107*d9f75844SAndroid Build Coastguard Worker apply_alignment_to_all_simulcast_layers_ = b;
1108*d9f75844SAndroid Build Coastguard Worker }
1109*d9f75844SAndroid Build Coastguard Worker
SetIsHardwareAccelerated(bool is_hardware_accelerated)1110*d9f75844SAndroid Build Coastguard Worker void SetIsHardwareAccelerated(bool is_hardware_accelerated) {
1111*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1112*d9f75844SAndroid Build Coastguard Worker is_hardware_accelerated_ = is_hardware_accelerated;
1113*d9f75844SAndroid Build Coastguard Worker }
1114*d9f75844SAndroid Build Coastguard Worker
SetTemporalLayersSupported(size_t spatial_idx,bool supported)1115*d9f75844SAndroid Build Coastguard Worker void SetTemporalLayersSupported(size_t spatial_idx, bool supported) {
1116*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LT(spatial_idx, kMaxSpatialLayers);
1117*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1118*d9f75844SAndroid Build Coastguard Worker temporal_layers_supported_[spatial_idx] = supported;
1119*d9f75844SAndroid Build Coastguard Worker }
1120*d9f75844SAndroid Build Coastguard Worker
SetResolutionBitrateLimits(std::vector<ResolutionBitrateLimits> thresholds)1121*d9f75844SAndroid Build Coastguard Worker void SetResolutionBitrateLimits(
1122*d9f75844SAndroid Build Coastguard Worker std::vector<ResolutionBitrateLimits> thresholds) {
1123*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1124*d9f75844SAndroid Build Coastguard Worker resolution_bitrate_limits_ = thresholds;
1125*d9f75844SAndroid Build Coastguard Worker }
1126*d9f75844SAndroid Build Coastguard Worker
ForceInitEncodeFailure(bool force_failure)1127*d9f75844SAndroid Build Coastguard Worker void ForceInitEncodeFailure(bool force_failure) {
1128*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1129*d9f75844SAndroid Build Coastguard Worker force_init_encode_failed_ = force_failure;
1130*d9f75844SAndroid Build Coastguard Worker }
1131*d9f75844SAndroid Build Coastguard Worker
SimulateOvershoot(double rate_factor)1132*d9f75844SAndroid Build Coastguard Worker void SimulateOvershoot(double rate_factor) {
1133*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1134*d9f75844SAndroid Build Coastguard Worker rate_factor_ = rate_factor;
1135*d9f75844SAndroid Build Coastguard Worker }
1136*d9f75844SAndroid Build Coastguard Worker
GetLastFramerate() const1137*d9f75844SAndroid Build Coastguard Worker uint32_t GetLastFramerate() const {
1138*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1139*d9f75844SAndroid Build Coastguard Worker return last_framerate_;
1140*d9f75844SAndroid Build Coastguard Worker }
1141*d9f75844SAndroid Build Coastguard Worker
GetLastUpdateRect() const1142*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect GetLastUpdateRect() const {
1143*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1144*d9f75844SAndroid Build Coastguard Worker return last_update_rect_;
1145*d9f75844SAndroid Build Coastguard Worker }
1146*d9f75844SAndroid Build Coastguard Worker
LastFrameTypes() const1147*d9f75844SAndroid Build Coastguard Worker const std::vector<VideoFrameType>& LastFrameTypes() const {
1148*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1149*d9f75844SAndroid Build Coastguard Worker return last_frame_types_;
1150*d9f75844SAndroid Build Coastguard Worker }
1151*d9f75844SAndroid Build Coastguard Worker
InjectFrame(const VideoFrame & input_image,bool keyframe)1152*d9f75844SAndroid Build Coastguard Worker void InjectFrame(const VideoFrame& input_image, bool keyframe) {
1153*d9f75844SAndroid Build Coastguard Worker const std::vector<VideoFrameType> frame_type = {
1154*d9f75844SAndroid Build Coastguard Worker keyframe ? VideoFrameType::kVideoFrameKey
1155*d9f75844SAndroid Build Coastguard Worker : VideoFrameType::kVideoFrameDelta};
1156*d9f75844SAndroid Build Coastguard Worker {
1157*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1158*d9f75844SAndroid Build Coastguard Worker last_frame_types_ = frame_type;
1159*d9f75844SAndroid Build Coastguard Worker }
1160*d9f75844SAndroid Build Coastguard Worker FakeEncoder::Encode(input_image, &frame_type);
1161*d9f75844SAndroid Build Coastguard Worker }
1162*d9f75844SAndroid Build Coastguard Worker
InjectEncodedImage(const EncodedImage & image,const CodecSpecificInfo * codec_specific_info)1163*d9f75844SAndroid Build Coastguard Worker void InjectEncodedImage(const EncodedImage& image,
1164*d9f75844SAndroid Build Coastguard Worker const CodecSpecificInfo* codec_specific_info) {
1165*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1166*d9f75844SAndroid Build Coastguard Worker encoded_image_callback_->OnEncodedImage(image, codec_specific_info);
1167*d9f75844SAndroid Build Coastguard Worker }
1168*d9f75844SAndroid Build Coastguard Worker
SetEncodedImageData(rtc::scoped_refptr<EncodedImageBufferInterface> encoded_image_data)1169*d9f75844SAndroid Build Coastguard Worker void SetEncodedImageData(
1170*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<EncodedImageBufferInterface> encoded_image_data) {
1171*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1172*d9f75844SAndroid Build Coastguard Worker encoded_image_data_ = encoded_image_data;
1173*d9f75844SAndroid Build Coastguard Worker }
1174*d9f75844SAndroid Build Coastguard Worker
ExpectNullFrame()1175*d9f75844SAndroid Build Coastguard Worker void ExpectNullFrame() {
1176*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1177*d9f75844SAndroid Build Coastguard Worker expect_null_frame_ = true;
1178*d9f75844SAndroid Build Coastguard Worker }
1179*d9f75844SAndroid Build Coastguard Worker
1180*d9f75844SAndroid Build Coastguard Worker absl::optional<VideoEncoder::RateControlParameters>
GetAndResetLastRateControlSettings()1181*d9f75844SAndroid Build Coastguard Worker GetAndResetLastRateControlSettings() {
1182*d9f75844SAndroid Build Coastguard Worker auto settings = last_rate_control_settings_;
1183*d9f75844SAndroid Build Coastguard Worker last_rate_control_settings_.reset();
1184*d9f75844SAndroid Build Coastguard Worker return settings;
1185*d9f75844SAndroid Build Coastguard Worker }
1186*d9f75844SAndroid Build Coastguard Worker
GetLastInputWidth() const1187*d9f75844SAndroid Build Coastguard Worker int GetLastInputWidth() const {
1188*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1189*d9f75844SAndroid Build Coastguard Worker return last_input_width_;
1190*d9f75844SAndroid Build Coastguard Worker }
1191*d9f75844SAndroid Build Coastguard Worker
GetLastInputHeight() const1192*d9f75844SAndroid Build Coastguard Worker int GetLastInputHeight() const {
1193*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1194*d9f75844SAndroid Build Coastguard Worker return last_input_height_;
1195*d9f75844SAndroid Build Coastguard Worker }
1196*d9f75844SAndroid Build Coastguard Worker
GetLastInputPixelFormat()1197*d9f75844SAndroid Build Coastguard Worker absl::optional<VideoFrameBuffer::Type> GetLastInputPixelFormat() {
1198*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1199*d9f75844SAndroid Build Coastguard Worker return last_input_pixel_format_;
1200*d9f75844SAndroid Build Coastguard Worker }
1201*d9f75844SAndroid Build Coastguard Worker
GetNumSetRates() const1202*d9f75844SAndroid Build Coastguard Worker int GetNumSetRates() const {
1203*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1204*d9f75844SAndroid Build Coastguard Worker return num_set_rates_;
1205*d9f75844SAndroid Build Coastguard Worker }
1206*d9f75844SAndroid Build Coastguard Worker
SetPreferredPixelFormats(absl::InlinedVector<VideoFrameBuffer::Type,kMaxPreferredPixelFormats> pixel_formats)1207*d9f75844SAndroid Build Coastguard Worker void SetPreferredPixelFormats(
1208*d9f75844SAndroid Build Coastguard Worker absl::InlinedVector<VideoFrameBuffer::Type, kMaxPreferredPixelFormats>
1209*d9f75844SAndroid Build Coastguard Worker pixel_formats) {
1210*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1211*d9f75844SAndroid Build Coastguard Worker preferred_pixel_formats_ = std::move(pixel_formats);
1212*d9f75844SAndroid Build Coastguard Worker }
1213*d9f75844SAndroid Build Coastguard Worker
SetIsQpTrusted(absl::optional<bool> trusted)1214*d9f75844SAndroid Build Coastguard Worker void SetIsQpTrusted(absl::optional<bool> trusted) {
1215*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1216*d9f75844SAndroid Build Coastguard Worker is_qp_trusted_ = trusted;
1217*d9f75844SAndroid Build Coastguard Worker }
1218*d9f75844SAndroid Build Coastguard Worker
LastEncoderComplexity()1219*d9f75844SAndroid Build Coastguard Worker VideoCodecComplexity LastEncoderComplexity() {
1220*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1221*d9f75844SAndroid Build Coastguard Worker return last_encoder_complexity_;
1222*d9f75844SAndroid Build Coastguard Worker }
1223*d9f75844SAndroid Build Coastguard Worker
1224*d9f75844SAndroid Build Coastguard Worker private:
Encode(const VideoFrame & input_image,const std::vector<VideoFrameType> * frame_types)1225*d9f75844SAndroid Build Coastguard Worker int32_t Encode(const VideoFrame& input_image,
1226*d9f75844SAndroid Build Coastguard Worker const std::vector<VideoFrameType>* frame_types) override {
1227*d9f75844SAndroid Build Coastguard Worker {
1228*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1229*d9f75844SAndroid Build Coastguard Worker if (expect_null_frame_) {
1230*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(input_image.timestamp(), 0u);
1231*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(input_image.width(), 1);
1232*d9f75844SAndroid Build Coastguard Worker last_frame_types_ = *frame_types;
1233*d9f75844SAndroid Build Coastguard Worker expect_null_frame_ = false;
1234*d9f75844SAndroid Build Coastguard Worker } else {
1235*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(input_image.timestamp(), timestamp_);
1236*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
1237*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
1238*d9f75844SAndroid Build Coastguard Worker }
1239*d9f75844SAndroid Build Coastguard Worker
1240*d9f75844SAndroid Build Coastguard Worker timestamp_ = input_image.timestamp();
1241*d9f75844SAndroid Build Coastguard Worker ntp_time_ms_ = input_image.ntp_time_ms();
1242*d9f75844SAndroid Build Coastguard Worker last_input_width_ = input_image.width();
1243*d9f75844SAndroid Build Coastguard Worker last_input_height_ = input_image.height();
1244*d9f75844SAndroid Build Coastguard Worker last_update_rect_ = input_image.update_rect();
1245*d9f75844SAndroid Build Coastguard Worker last_frame_types_ = *frame_types;
1246*d9f75844SAndroid Build Coastguard Worker last_input_pixel_format_ = input_image.video_frame_buffer()->type();
1247*d9f75844SAndroid Build Coastguard Worker }
1248*d9f75844SAndroid Build Coastguard Worker int32_t result = FakeEncoder::Encode(input_image, frame_types);
1249*d9f75844SAndroid Build Coastguard Worker return result;
1250*d9f75844SAndroid Build Coastguard Worker }
1251*d9f75844SAndroid Build Coastguard Worker
EncodeHook(EncodedImage & encoded_image,rtc::scoped_refptr<EncodedImageBuffer> buffer)1252*d9f75844SAndroid Build Coastguard Worker CodecSpecificInfo EncodeHook(
1253*d9f75844SAndroid Build Coastguard Worker EncodedImage& encoded_image,
1254*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<EncodedImageBuffer> buffer) override {
1255*d9f75844SAndroid Build Coastguard Worker CodecSpecificInfo codec_specific;
1256*d9f75844SAndroid Build Coastguard Worker {
1257*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1258*d9f75844SAndroid Build Coastguard Worker codec_specific.codecType = config_.codecType;
1259*d9f75844SAndroid Build Coastguard Worker }
1260*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1261*d9f75844SAndroid Build Coastguard Worker if (encoded_image_data_) {
1262*d9f75844SAndroid Build Coastguard Worker encoded_image.SetEncodedData(encoded_image_data_);
1263*d9f75844SAndroid Build Coastguard Worker }
1264*d9f75844SAndroid Build Coastguard Worker return codec_specific;
1265*d9f75844SAndroid Build Coastguard Worker }
1266*d9f75844SAndroid Build Coastguard Worker
InitEncode(const VideoCodec * config,const Settings & settings)1267*d9f75844SAndroid Build Coastguard Worker int32_t InitEncode(const VideoCodec* config,
1268*d9f75844SAndroid Build Coastguard Worker const Settings& settings) override {
1269*d9f75844SAndroid Build Coastguard Worker int res = FakeEncoder::InitEncode(config, settings);
1270*d9f75844SAndroid Build Coastguard Worker
1271*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1272*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(initialized_, EncoderState::kUninitialized);
1273*d9f75844SAndroid Build Coastguard Worker
1274*d9f75844SAndroid Build Coastguard Worker if (config->codecType == kVideoCodecVP8) {
1275*d9f75844SAndroid Build Coastguard Worker // Simulate setting up temporal layers, in order to validate the life
1276*d9f75844SAndroid Build Coastguard Worker // cycle of these objects.
1277*d9f75844SAndroid Build Coastguard Worker Vp8TemporalLayersFactory factory;
1278*d9f75844SAndroid Build Coastguard Worker frame_buffer_controller_ =
1279*d9f75844SAndroid Build Coastguard Worker factory.Create(*config, settings, &fec_controller_override_);
1280*d9f75844SAndroid Build Coastguard Worker }
1281*d9f75844SAndroid Build Coastguard Worker
1282*d9f75844SAndroid Build Coastguard Worker last_encoder_complexity_ = config->GetVideoEncoderComplexity();
1283*d9f75844SAndroid Build Coastguard Worker
1284*d9f75844SAndroid Build Coastguard Worker if (force_init_encode_failed_) {
1285*d9f75844SAndroid Build Coastguard Worker initialized_ = EncoderState::kInitializationFailed;
1286*d9f75844SAndroid Build Coastguard Worker return -1;
1287*d9f75844SAndroid Build Coastguard Worker }
1288*d9f75844SAndroid Build Coastguard Worker
1289*d9f75844SAndroid Build Coastguard Worker initialized_ = EncoderState::kInitialized;
1290*d9f75844SAndroid Build Coastguard Worker return res;
1291*d9f75844SAndroid Build Coastguard Worker }
1292*d9f75844SAndroid Build Coastguard Worker
Release()1293*d9f75844SAndroid Build Coastguard Worker int32_t Release() override {
1294*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1295*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(initialized_, EncoderState::kUninitialized);
1296*d9f75844SAndroid Build Coastguard Worker initialized_ = EncoderState::kUninitialized;
1297*d9f75844SAndroid Build Coastguard Worker return FakeEncoder::Release();
1298*d9f75844SAndroid Build Coastguard Worker }
1299*d9f75844SAndroid Build Coastguard Worker
SetRates(const RateControlParameters & parameters)1300*d9f75844SAndroid Build Coastguard Worker void SetRates(const RateControlParameters& parameters) {
1301*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&local_mutex_);
1302*d9f75844SAndroid Build Coastguard Worker num_set_rates_++;
1303*d9f75844SAndroid Build Coastguard Worker VideoBitrateAllocation adjusted_rate_allocation;
1304*d9f75844SAndroid Build Coastguard Worker for (size_t si = 0; si < kMaxSpatialLayers; ++si) {
1305*d9f75844SAndroid Build Coastguard Worker for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) {
1306*d9f75844SAndroid Build Coastguard Worker if (parameters.bitrate.HasBitrate(si, ti)) {
1307*d9f75844SAndroid Build Coastguard Worker adjusted_rate_allocation.SetBitrate(
1308*d9f75844SAndroid Build Coastguard Worker si, ti,
1309*d9f75844SAndroid Build Coastguard Worker static_cast<uint32_t>(parameters.bitrate.GetBitrate(si, ti) *
1310*d9f75844SAndroid Build Coastguard Worker rate_factor_));
1311*d9f75844SAndroid Build Coastguard Worker }
1312*d9f75844SAndroid Build Coastguard Worker }
1313*d9f75844SAndroid Build Coastguard Worker }
1314*d9f75844SAndroid Build Coastguard Worker last_framerate_ = static_cast<uint32_t>(parameters.framerate_fps + 0.5);
1315*d9f75844SAndroid Build Coastguard Worker last_rate_control_settings_ = parameters;
1316*d9f75844SAndroid Build Coastguard Worker RateControlParameters adjusted_paramters = parameters;
1317*d9f75844SAndroid Build Coastguard Worker adjusted_paramters.bitrate = adjusted_rate_allocation;
1318*d9f75844SAndroid Build Coastguard Worker FakeEncoder::SetRates(adjusted_paramters);
1319*d9f75844SAndroid Build Coastguard Worker }
1320*d9f75844SAndroid Build Coastguard Worker
1321*d9f75844SAndroid Build Coastguard Worker TimeController* const time_controller_;
1322*d9f75844SAndroid Build Coastguard Worker mutable Mutex local_mutex_;
1323*d9f75844SAndroid Build Coastguard Worker enum class EncoderState {
1324*d9f75844SAndroid Build Coastguard Worker kUninitialized,
1325*d9f75844SAndroid Build Coastguard Worker kInitializationFailed,
1326*d9f75844SAndroid Build Coastguard Worker kInitialized
1327*d9f75844SAndroid Build Coastguard Worker } initialized_ RTC_GUARDED_BY(local_mutex_) = EncoderState::kUninitialized;
1328*d9f75844SAndroid Build Coastguard Worker rtc::Event continue_encode_event_;
1329*d9f75844SAndroid Build Coastguard Worker uint32_t timestamp_ RTC_GUARDED_BY(local_mutex_) = 0;
1330*d9f75844SAndroid Build Coastguard Worker int64_t ntp_time_ms_ RTC_GUARDED_BY(local_mutex_) = 0;
1331*d9f75844SAndroid Build Coastguard Worker int last_input_width_ RTC_GUARDED_BY(local_mutex_) = 0;
1332*d9f75844SAndroid Build Coastguard Worker int last_input_height_ RTC_GUARDED_BY(local_mutex_) = 0;
1333*d9f75844SAndroid Build Coastguard Worker bool quality_scaling_ RTC_GUARDED_BY(local_mutex_) = true;
1334*d9f75844SAndroid Build Coastguard Worker int requested_resolution_alignment_ RTC_GUARDED_BY(local_mutex_) = 1;
1335*d9f75844SAndroid Build Coastguard Worker bool apply_alignment_to_all_simulcast_layers_ RTC_GUARDED_BY(local_mutex_) =
1336*d9f75844SAndroid Build Coastguard Worker false;
1337*d9f75844SAndroid Build Coastguard Worker bool is_hardware_accelerated_ RTC_GUARDED_BY(local_mutex_) = false;
1338*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<EncodedImageBufferInterface> encoded_image_data_
1339*d9f75844SAndroid Build Coastguard Worker RTC_GUARDED_BY(local_mutex_);
1340*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Vp8FrameBufferController> frame_buffer_controller_
1341*d9f75844SAndroid Build Coastguard Worker RTC_GUARDED_BY(local_mutex_);
1342*d9f75844SAndroid Build Coastguard Worker absl::optional<bool>
1343*d9f75844SAndroid Build Coastguard Worker temporal_layers_supported_[kMaxSpatialLayers] RTC_GUARDED_BY(
1344*d9f75844SAndroid Build Coastguard Worker local_mutex_);
1345*d9f75844SAndroid Build Coastguard Worker bool force_init_encode_failed_ RTC_GUARDED_BY(local_mutex_) = false;
1346*d9f75844SAndroid Build Coastguard Worker double rate_factor_ RTC_GUARDED_BY(local_mutex_) = 1.0;
1347*d9f75844SAndroid Build Coastguard Worker uint32_t last_framerate_ RTC_GUARDED_BY(local_mutex_) = 0;
1348*d9f75844SAndroid Build Coastguard Worker absl::optional<VideoEncoder::RateControlParameters>
1349*d9f75844SAndroid Build Coastguard Worker last_rate_control_settings_;
1350*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect last_update_rect_ RTC_GUARDED_BY(local_mutex_) = {
1351*d9f75844SAndroid Build Coastguard Worker 0, 0, 0, 0};
1352*d9f75844SAndroid Build Coastguard Worker std::vector<VideoFrameType> last_frame_types_;
1353*d9f75844SAndroid Build Coastguard Worker bool expect_null_frame_ = false;
1354*d9f75844SAndroid Build Coastguard Worker EncodedImageCallback* encoded_image_callback_ RTC_GUARDED_BY(local_mutex_) =
1355*d9f75844SAndroid Build Coastguard Worker nullptr;
1356*d9f75844SAndroid Build Coastguard Worker NiceMock<MockFecControllerOverride> fec_controller_override_;
1357*d9f75844SAndroid Build Coastguard Worker std::vector<ResolutionBitrateLimits> resolution_bitrate_limits_
1358*d9f75844SAndroid Build Coastguard Worker RTC_GUARDED_BY(local_mutex_);
1359*d9f75844SAndroid Build Coastguard Worker int num_set_rates_ RTC_GUARDED_BY(local_mutex_) = 0;
1360*d9f75844SAndroid Build Coastguard Worker absl::optional<VideoFrameBuffer::Type> last_input_pixel_format_
1361*d9f75844SAndroid Build Coastguard Worker RTC_GUARDED_BY(local_mutex_);
1362*d9f75844SAndroid Build Coastguard Worker absl::InlinedVector<VideoFrameBuffer::Type, kMaxPreferredPixelFormats>
1363*d9f75844SAndroid Build Coastguard Worker preferred_pixel_formats_ RTC_GUARDED_BY(local_mutex_);
1364*d9f75844SAndroid Build Coastguard Worker absl::optional<bool> is_qp_trusted_ RTC_GUARDED_BY(local_mutex_);
RTC_GUARDED_BY(local_mutex_)1365*d9f75844SAndroid Build Coastguard Worker VideoCodecComplexity last_encoder_complexity_ RTC_GUARDED_BY(local_mutex_){
1366*d9f75844SAndroid Build Coastguard Worker VideoCodecComplexity::kComplexityNormal};
1367*d9f75844SAndroid Build Coastguard Worker };
1368*d9f75844SAndroid Build Coastguard Worker
1369*d9f75844SAndroid Build Coastguard Worker class TestSink : public VideoStreamEncoder::EncoderSink {
1370*d9f75844SAndroid Build Coastguard Worker public:
TestSink(TimeController * time_controller,TestEncoder * test_encoder)1371*d9f75844SAndroid Build Coastguard Worker TestSink(TimeController* time_controller, TestEncoder* test_encoder)
1372*d9f75844SAndroid Build Coastguard Worker : time_controller_(time_controller), test_encoder_(test_encoder) {
1373*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(time_controller_);
1374*d9f75844SAndroid Build Coastguard Worker }
1375*d9f75844SAndroid Build Coastguard Worker
WaitForEncodedFrame(int64_t expected_ntp_time)1376*d9f75844SAndroid Build Coastguard Worker void WaitForEncodedFrame(int64_t expected_ntp_time) {
1377*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(TimedWaitForEncodedFrame(expected_ntp_time, kDefaultTimeout));
1378*d9f75844SAndroid Build Coastguard Worker }
1379*d9f75844SAndroid Build Coastguard Worker
TimedWaitForEncodedFrame(int64_t expected_ntp_time,TimeDelta timeout)1380*d9f75844SAndroid Build Coastguard Worker bool TimedWaitForEncodedFrame(int64_t expected_ntp_time,
1381*d9f75844SAndroid Build Coastguard Worker TimeDelta timeout) {
1382*d9f75844SAndroid Build Coastguard Worker uint32_t timestamp = 0;
1383*d9f75844SAndroid Build Coastguard Worker if (!WaitForFrame(timeout))
1384*d9f75844SAndroid Build Coastguard Worker return false;
1385*d9f75844SAndroid Build Coastguard Worker {
1386*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1387*d9f75844SAndroid Build Coastguard Worker timestamp = last_timestamp_;
1388*d9f75844SAndroid Build Coastguard Worker }
1389*d9f75844SAndroid Build Coastguard Worker test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
1390*d9f75844SAndroid Build Coastguard Worker return true;
1391*d9f75844SAndroid Build Coastguard Worker }
1392*d9f75844SAndroid Build Coastguard Worker
WaitForEncodedFrame(uint32_t expected_width,uint32_t expected_height)1393*d9f75844SAndroid Build Coastguard Worker void WaitForEncodedFrame(uint32_t expected_width,
1394*d9f75844SAndroid Build Coastguard Worker uint32_t expected_height) {
1395*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(WaitForFrame(kDefaultTimeout));
1396*d9f75844SAndroid Build Coastguard Worker CheckLastFrameSizeMatches(expected_width, expected_height);
1397*d9f75844SAndroid Build Coastguard Worker }
1398*d9f75844SAndroid Build Coastguard Worker
CheckLastFrameSizeMatches(uint32_t expected_width,uint32_t expected_height)1399*d9f75844SAndroid Build Coastguard Worker void CheckLastFrameSizeMatches(uint32_t expected_width,
1400*d9f75844SAndroid Build Coastguard Worker uint32_t expected_height) {
1401*d9f75844SAndroid Build Coastguard Worker uint32_t width = 0;
1402*d9f75844SAndroid Build Coastguard Worker uint32_t height = 0;
1403*d9f75844SAndroid Build Coastguard Worker {
1404*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1405*d9f75844SAndroid Build Coastguard Worker width = last_width_;
1406*d9f75844SAndroid Build Coastguard Worker height = last_height_;
1407*d9f75844SAndroid Build Coastguard Worker }
1408*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(expected_height, height);
1409*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(expected_width, width);
1410*d9f75844SAndroid Build Coastguard Worker }
1411*d9f75844SAndroid Build Coastguard Worker
CheckLastFrameRotationMatches(VideoRotation expected_rotation)1412*d9f75844SAndroid Build Coastguard Worker void CheckLastFrameRotationMatches(VideoRotation expected_rotation) {
1413*d9f75844SAndroid Build Coastguard Worker VideoRotation rotation;
1414*d9f75844SAndroid Build Coastguard Worker {
1415*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1416*d9f75844SAndroid Build Coastguard Worker rotation = last_rotation_;
1417*d9f75844SAndroid Build Coastguard Worker }
1418*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(expected_rotation, rotation);
1419*d9f75844SAndroid Build Coastguard Worker }
1420*d9f75844SAndroid Build Coastguard Worker
ExpectDroppedFrame()1421*d9f75844SAndroid Build Coastguard Worker void ExpectDroppedFrame() {
1422*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(WaitForFrame(TimeDelta::Millis(100)));
1423*d9f75844SAndroid Build Coastguard Worker }
1424*d9f75844SAndroid Build Coastguard Worker
WaitForFrame(TimeDelta timeout)1425*d9f75844SAndroid Build Coastguard Worker bool WaitForFrame(TimeDelta timeout) {
1426*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(time_controller_->GetMainThread()->IsCurrent());
1427*d9f75844SAndroid Build Coastguard Worker time_controller_->AdvanceTime(TimeDelta::Zero());
1428*d9f75844SAndroid Build Coastguard Worker bool ret = encoded_frame_event_.Wait(timeout);
1429*d9f75844SAndroid Build Coastguard Worker time_controller_->AdvanceTime(TimeDelta::Zero());
1430*d9f75844SAndroid Build Coastguard Worker return ret;
1431*d9f75844SAndroid Build Coastguard Worker }
1432*d9f75844SAndroid Build Coastguard Worker
SetExpectNoFrames()1433*d9f75844SAndroid Build Coastguard Worker void SetExpectNoFrames() {
1434*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1435*d9f75844SAndroid Build Coastguard Worker expect_frames_ = false;
1436*d9f75844SAndroid Build Coastguard Worker }
1437*d9f75844SAndroid Build Coastguard Worker
number_of_reconfigurations() const1438*d9f75844SAndroid Build Coastguard Worker int number_of_reconfigurations() const {
1439*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1440*d9f75844SAndroid Build Coastguard Worker return number_of_reconfigurations_;
1441*d9f75844SAndroid Build Coastguard Worker }
1442*d9f75844SAndroid Build Coastguard Worker
last_min_transmit_bitrate() const1443*d9f75844SAndroid Build Coastguard Worker int last_min_transmit_bitrate() const {
1444*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1445*d9f75844SAndroid Build Coastguard Worker return min_transmit_bitrate_bps_;
1446*d9f75844SAndroid Build Coastguard Worker }
1447*d9f75844SAndroid Build Coastguard Worker
SetNumExpectedLayers(size_t num_layers)1448*d9f75844SAndroid Build Coastguard Worker void SetNumExpectedLayers(size_t num_layers) {
1449*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1450*d9f75844SAndroid Build Coastguard Worker num_expected_layers_ = num_layers;
1451*d9f75844SAndroid Build Coastguard Worker }
1452*d9f75844SAndroid Build Coastguard Worker
GetLastCaptureTimeMs() const1453*d9f75844SAndroid Build Coastguard Worker int64_t GetLastCaptureTimeMs() const {
1454*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1455*d9f75844SAndroid Build Coastguard Worker return last_capture_time_ms_;
1456*d9f75844SAndroid Build Coastguard Worker }
1457*d9f75844SAndroid Build Coastguard Worker
GetLastEncodedImage()1458*d9f75844SAndroid Build Coastguard Worker const EncodedImage& GetLastEncodedImage() {
1459*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1460*d9f75844SAndroid Build Coastguard Worker return last_encoded_image_;
1461*d9f75844SAndroid Build Coastguard Worker }
1462*d9f75844SAndroid Build Coastguard Worker
GetLastEncodedImageData()1463*d9f75844SAndroid Build Coastguard Worker std::vector<uint8_t> GetLastEncodedImageData() {
1464*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1465*d9f75844SAndroid Build Coastguard Worker return std::move(last_encoded_image_data_);
1466*d9f75844SAndroid Build Coastguard Worker }
1467*d9f75844SAndroid Build Coastguard Worker
GetLastVideoBitrateAllocation()1468*d9f75844SAndroid Build Coastguard Worker VideoBitrateAllocation GetLastVideoBitrateAllocation() {
1469*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1470*d9f75844SAndroid Build Coastguard Worker return last_bitrate_allocation_;
1471*d9f75844SAndroid Build Coastguard Worker }
1472*d9f75844SAndroid Build Coastguard Worker
number_of_bitrate_allocations() const1473*d9f75844SAndroid Build Coastguard Worker int number_of_bitrate_allocations() const {
1474*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1475*d9f75844SAndroid Build Coastguard Worker return number_of_bitrate_allocations_;
1476*d9f75844SAndroid Build Coastguard Worker }
1477*d9f75844SAndroid Build Coastguard Worker
GetLastVideoLayersAllocation()1478*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation GetLastVideoLayersAllocation() {
1479*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1480*d9f75844SAndroid Build Coastguard Worker return last_layers_allocation_;
1481*d9f75844SAndroid Build Coastguard Worker }
1482*d9f75844SAndroid Build Coastguard Worker
number_of_layers_allocations() const1483*d9f75844SAndroid Build Coastguard Worker int number_of_layers_allocations() const {
1484*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1485*d9f75844SAndroid Build Coastguard Worker return number_of_layers_allocations_;
1486*d9f75844SAndroid Build Coastguard Worker }
1487*d9f75844SAndroid Build Coastguard Worker
1488*d9f75844SAndroid Build Coastguard Worker private:
OnEncodedImage(const EncodedImage & encoded_image,const CodecSpecificInfo * codec_specific_info)1489*d9f75844SAndroid Build Coastguard Worker Result OnEncodedImage(
1490*d9f75844SAndroid Build Coastguard Worker const EncodedImage& encoded_image,
1491*d9f75844SAndroid Build Coastguard Worker const CodecSpecificInfo* codec_specific_info) override {
1492*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1493*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(expect_frames_);
1494*d9f75844SAndroid Build Coastguard Worker last_encoded_image_ = EncodedImage(encoded_image);
1495*d9f75844SAndroid Build Coastguard Worker last_encoded_image_data_ = std::vector<uint8_t>(
1496*d9f75844SAndroid Build Coastguard Worker encoded_image.data(), encoded_image.data() + encoded_image.size());
1497*d9f75844SAndroid Build Coastguard Worker uint32_t timestamp = encoded_image.Timestamp();
1498*d9f75844SAndroid Build Coastguard Worker if (last_timestamp_ != timestamp) {
1499*d9f75844SAndroid Build Coastguard Worker num_received_layers_ = 1;
1500*d9f75844SAndroid Build Coastguard Worker last_width_ = encoded_image._encodedWidth;
1501*d9f75844SAndroid Build Coastguard Worker last_height_ = encoded_image._encodedHeight;
1502*d9f75844SAndroid Build Coastguard Worker } else {
1503*d9f75844SAndroid Build Coastguard Worker ++num_received_layers_;
1504*d9f75844SAndroid Build Coastguard Worker last_width_ = std::max(encoded_image._encodedWidth, last_width_);
1505*d9f75844SAndroid Build Coastguard Worker last_height_ = std::max(encoded_image._encodedHeight, last_height_);
1506*d9f75844SAndroid Build Coastguard Worker }
1507*d9f75844SAndroid Build Coastguard Worker last_timestamp_ = timestamp;
1508*d9f75844SAndroid Build Coastguard Worker last_capture_time_ms_ = encoded_image.capture_time_ms_;
1509*d9f75844SAndroid Build Coastguard Worker last_rotation_ = encoded_image.rotation_;
1510*d9f75844SAndroid Build Coastguard Worker if (num_received_layers_ == num_expected_layers_) {
1511*d9f75844SAndroid Build Coastguard Worker encoded_frame_event_.Set();
1512*d9f75844SAndroid Build Coastguard Worker }
1513*d9f75844SAndroid Build Coastguard Worker return Result(Result::OK, last_timestamp_);
1514*d9f75844SAndroid Build Coastguard Worker }
1515*d9f75844SAndroid Build Coastguard Worker
OnEncoderConfigurationChanged(std::vector<VideoStream> streams,bool is_svc,VideoEncoderConfig::ContentType content_type,int min_transmit_bitrate_bps)1516*d9f75844SAndroid Build Coastguard Worker void OnEncoderConfigurationChanged(
1517*d9f75844SAndroid Build Coastguard Worker std::vector<VideoStream> streams,
1518*d9f75844SAndroid Build Coastguard Worker bool is_svc,
1519*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType content_type,
1520*d9f75844SAndroid Build Coastguard Worker int min_transmit_bitrate_bps) override {
1521*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1522*d9f75844SAndroid Build Coastguard Worker ++number_of_reconfigurations_;
1523*d9f75844SAndroid Build Coastguard Worker min_transmit_bitrate_bps_ = min_transmit_bitrate_bps;
1524*d9f75844SAndroid Build Coastguard Worker }
1525*d9f75844SAndroid Build Coastguard Worker
OnBitrateAllocationUpdated(const VideoBitrateAllocation & allocation)1526*d9f75844SAndroid Build Coastguard Worker void OnBitrateAllocationUpdated(
1527*d9f75844SAndroid Build Coastguard Worker const VideoBitrateAllocation& allocation) override {
1528*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1529*d9f75844SAndroid Build Coastguard Worker ++number_of_bitrate_allocations_;
1530*d9f75844SAndroid Build Coastguard Worker last_bitrate_allocation_ = allocation;
1531*d9f75844SAndroid Build Coastguard Worker }
1532*d9f75844SAndroid Build Coastguard Worker
OnVideoLayersAllocationUpdated(VideoLayersAllocation allocation)1533*d9f75844SAndroid Build Coastguard Worker void OnVideoLayersAllocationUpdated(
1534*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation allocation) override {
1535*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1536*d9f75844SAndroid Build Coastguard Worker ++number_of_layers_allocations_;
1537*d9f75844SAndroid Build Coastguard Worker last_layers_allocation_ = allocation;
1538*d9f75844SAndroid Build Coastguard Worker rtc::StringBuilder log;
1539*d9f75844SAndroid Build Coastguard Worker for (const auto& layer : allocation.active_spatial_layers) {
1540*d9f75844SAndroid Build Coastguard Worker log << layer.width << "x" << layer.height << "@" << layer.frame_rate_fps
1541*d9f75844SAndroid Build Coastguard Worker << "[";
1542*d9f75844SAndroid Build Coastguard Worker for (const auto target_bitrate :
1543*d9f75844SAndroid Build Coastguard Worker layer.target_bitrate_per_temporal_layer) {
1544*d9f75844SAndroid Build Coastguard Worker log << target_bitrate.kbps() << ",";
1545*d9f75844SAndroid Build Coastguard Worker }
1546*d9f75844SAndroid Build Coastguard Worker log << "]";
1547*d9f75844SAndroid Build Coastguard Worker }
1548*d9f75844SAndroid Build Coastguard Worker RTC_DLOG(LS_INFO) << "OnVideoLayersAllocationUpdated " << log.str();
1549*d9f75844SAndroid Build Coastguard Worker }
1550*d9f75844SAndroid Build Coastguard Worker
1551*d9f75844SAndroid Build Coastguard Worker TimeController* const time_controller_;
1552*d9f75844SAndroid Build Coastguard Worker mutable Mutex mutex_;
1553*d9f75844SAndroid Build Coastguard Worker TestEncoder* test_encoder_;
1554*d9f75844SAndroid Build Coastguard Worker rtc::Event encoded_frame_event_;
1555*d9f75844SAndroid Build Coastguard Worker EncodedImage last_encoded_image_;
1556*d9f75844SAndroid Build Coastguard Worker std::vector<uint8_t> last_encoded_image_data_;
1557*d9f75844SAndroid Build Coastguard Worker uint32_t last_timestamp_ = 0;
1558*d9f75844SAndroid Build Coastguard Worker int64_t last_capture_time_ms_ = 0;
1559*d9f75844SAndroid Build Coastguard Worker uint32_t last_height_ = 0;
1560*d9f75844SAndroid Build Coastguard Worker uint32_t last_width_ = 0;
1561*d9f75844SAndroid Build Coastguard Worker VideoRotation last_rotation_ = kVideoRotation_0;
1562*d9f75844SAndroid Build Coastguard Worker size_t num_expected_layers_ = 1;
1563*d9f75844SAndroid Build Coastguard Worker size_t num_received_layers_ = 0;
1564*d9f75844SAndroid Build Coastguard Worker bool expect_frames_ = true;
1565*d9f75844SAndroid Build Coastguard Worker int number_of_reconfigurations_ = 0;
1566*d9f75844SAndroid Build Coastguard Worker int min_transmit_bitrate_bps_ = 0;
1567*d9f75844SAndroid Build Coastguard Worker VideoBitrateAllocation last_bitrate_allocation_ RTC_GUARDED_BY(&mutex_);
1568*d9f75844SAndroid Build Coastguard Worker int number_of_bitrate_allocations_ RTC_GUARDED_BY(&mutex_) = 0;
1569*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation last_layers_allocation_ RTC_GUARDED_BY(&mutex_);
1570*d9f75844SAndroid Build Coastguard Worker int number_of_layers_allocations_ RTC_GUARDED_BY(&mutex_) = 0;
1571*d9f75844SAndroid Build Coastguard Worker };
1572*d9f75844SAndroid Build Coastguard Worker
1573*d9f75844SAndroid Build Coastguard Worker class VideoBitrateAllocatorProxyFactory
1574*d9f75844SAndroid Build Coastguard Worker : public VideoBitrateAllocatorFactory {
1575*d9f75844SAndroid Build Coastguard Worker public:
VideoBitrateAllocatorProxyFactory()1576*d9f75844SAndroid Build Coastguard Worker VideoBitrateAllocatorProxyFactory()
1577*d9f75844SAndroid Build Coastguard Worker : bitrate_allocator_factory_(
1578*d9f75844SAndroid Build Coastguard Worker CreateBuiltinVideoBitrateAllocatorFactory()) {}
1579*d9f75844SAndroid Build Coastguard Worker
CreateVideoBitrateAllocator(const VideoCodec & codec)1580*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<VideoBitrateAllocator> CreateVideoBitrateAllocator(
1581*d9f75844SAndroid Build Coastguard Worker const VideoCodec& codec) override {
1582*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1583*d9f75844SAndroid Build Coastguard Worker codec_config_ = codec;
1584*d9f75844SAndroid Build Coastguard Worker return bitrate_allocator_factory_->CreateVideoBitrateAllocator(codec);
1585*d9f75844SAndroid Build Coastguard Worker }
1586*d9f75844SAndroid Build Coastguard Worker
codec_config() const1587*d9f75844SAndroid Build Coastguard Worker VideoCodec codec_config() const {
1588*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&mutex_);
1589*d9f75844SAndroid Build Coastguard Worker return codec_config_;
1590*d9f75844SAndroid Build Coastguard Worker }
1591*d9f75844SAndroid Build Coastguard Worker
1592*d9f75844SAndroid Build Coastguard Worker private:
1593*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<VideoBitrateAllocatorFactory> bitrate_allocator_factory_;
1594*d9f75844SAndroid Build Coastguard Worker
1595*d9f75844SAndroid Build Coastguard Worker mutable Mutex mutex_;
1596*d9f75844SAndroid Build Coastguard Worker VideoCodec codec_config_ RTC_GUARDED_BY(mutex_);
1597*d9f75844SAndroid Build Coastguard Worker };
1598*d9f75844SAndroid Build Coastguard Worker
clock()1599*d9f75844SAndroid Build Coastguard Worker Clock* clock() { return time_controller_.GetClock(); }
AdvanceTime(TimeDelta duration)1600*d9f75844SAndroid Build Coastguard Worker void AdvanceTime(TimeDelta duration) {
1601*d9f75844SAndroid Build Coastguard Worker time_controller_.AdvanceTime(duration);
1602*d9f75844SAndroid Build Coastguard Worker }
1603*d9f75844SAndroid Build Coastguard Worker
CurrentTimeMs()1604*d9f75844SAndroid Build Coastguard Worker int64_t CurrentTimeMs() { return clock()->CurrentTime().ms(); }
1605*d9f75844SAndroid Build Coastguard Worker
1606*d9f75844SAndroid Build Coastguard Worker protected:
GetTaskQueueFactory()1607*d9f75844SAndroid Build Coastguard Worker virtual TaskQueueFactory* GetTaskQueueFactory() {
1608*d9f75844SAndroid Build Coastguard Worker return time_controller_.GetTaskQueueFactory();
1609*d9f75844SAndroid Build Coastguard Worker }
1610*d9f75844SAndroid Build Coastguard Worker
1611*d9f75844SAndroid Build Coastguard Worker test::ScopedKeyValueConfig field_trials_;
1612*d9f75844SAndroid Build Coastguard Worker GlobalSimulatedTimeController time_controller_{Timestamp::Micros(1234)};
1613*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Config video_send_config_;
1614*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config_;
1615*d9f75844SAndroid Build Coastguard Worker int codec_width_;
1616*d9f75844SAndroid Build Coastguard Worker int codec_height_;
1617*d9f75844SAndroid Build Coastguard Worker int max_framerate_;
1618*d9f75844SAndroid Build Coastguard Worker TestEncoder fake_encoder_;
1619*d9f75844SAndroid Build Coastguard Worker test::VideoEncoderProxyFactory encoder_factory_;
1620*d9f75844SAndroid Build Coastguard Worker VideoBitrateAllocatorProxyFactory bitrate_allocator_factory_;
1621*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<MockableSendStatisticsProxy> stats_proxy_;
1622*d9f75844SAndroid Build Coastguard Worker TestSink sink_;
1623*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder video_source_{&time_controller_};
1624*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<VideoStreamEncoderUnderTest> video_stream_encoder_;
1625*d9f75844SAndroid Build Coastguard Worker };
1626*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncodeOneFrame)1627*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, EncodeOneFrame) {
1628*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1629*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1630*d9f75844SAndroid Build Coastguard Worker rtc::Event frame_destroyed_event;
1631*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
1632*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1633*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeout));
1634*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1635*d9f75844SAndroid Build Coastguard Worker }
1636*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DropsFramesBeforeFirstOnBitrateUpdated)1637*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
1638*d9f75844SAndroid Build Coastguard Worker // Dropped since no target bitrate has been set.
1639*d9f75844SAndroid Build Coastguard Worker rtc::Event frame_destroyed_event;
1640*d9f75844SAndroid Build Coastguard Worker // The encoder will cache up to one frame for a short duration. Adding two
1641*d9f75844SAndroid Build Coastguard Worker // frames means that the first frame will be dropped and the second frame will
1642*d9f75844SAndroid Build Coastguard Worker // be sent when the encoder is enabled.
1643*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
1644*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Millis(10));
1645*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
1646*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Zero());
1647*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeout));
1648*d9f75844SAndroid Build Coastguard Worker
1649*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1650*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1651*d9f75844SAndroid Build Coastguard Worker
1652*d9f75844SAndroid Build Coastguard Worker // The pending frame should be received.
1653*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
1654*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
1655*d9f75844SAndroid Build Coastguard Worker
1656*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
1657*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1658*d9f75844SAndroid Build Coastguard Worker }
1659*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DropsFramesWhenRateSetToZero)1660*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DropsFramesWhenRateSetToZero) {
1661*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1662*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1663*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
1664*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1665*d9f75844SAndroid Build Coastguard Worker
1666*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1667*d9f75844SAndroid Build Coastguard Worker DataRate::Zero(), DataRate::Zero(), DataRate::Zero(), 0, 0, 0);
1668*d9f75844SAndroid Build Coastguard Worker
1669*d9f75844SAndroid Build Coastguard Worker // The encoder will cache up to one frame for a short duration. Adding two
1670*d9f75844SAndroid Build Coastguard Worker // frames means that the first frame will be dropped and the second frame will
1671*d9f75844SAndroid Build Coastguard Worker // be sent when the encoder is resumed.
1672*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
1673*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
1674*d9f75844SAndroid Build Coastguard Worker
1675*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1676*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1677*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
1678*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(4, nullptr));
1679*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(4);
1680*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1681*d9f75844SAndroid Build Coastguard Worker }
1682*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DropsFramesWithSameOrOldNtpTimestamp)1683*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
1684*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1685*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1686*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
1687*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1688*d9f75844SAndroid Build Coastguard Worker
1689*d9f75844SAndroid Build Coastguard Worker // This frame will be dropped since it has the same ntp timestamp.
1690*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
1691*d9f75844SAndroid Build Coastguard Worker
1692*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
1693*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
1694*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1695*d9f75844SAndroid Build Coastguard Worker }
1696*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DropsFrameAfterStop)1697*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DropsFrameAfterStop) {
1698*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1699*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1700*d9f75844SAndroid Build Coastguard Worker
1701*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
1702*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1703*d9f75844SAndroid Build Coastguard Worker
1704*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1705*d9f75844SAndroid Build Coastguard Worker sink_.SetExpectNoFrames();
1706*d9f75844SAndroid Build Coastguard Worker rtc::Event frame_destroyed_event;
1707*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
1708*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeout));
1709*d9f75844SAndroid Build Coastguard Worker }
1710*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DropsPendingFramesOnSlowEncode)1711*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DropsPendingFramesOnSlowEncode) {
1712*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
1713*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
1714*d9f75844SAndroid Build Coastguard Worker DegradationPreference::MAINTAIN_FRAMERATE);
1715*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1716*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1717*d9f75844SAndroid Build Coastguard Worker
1718*d9f75844SAndroid Build Coastguard Worker int dropped_count = 0;
1719*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetDroppedFrameCallback(
1720*d9f75844SAndroid Build Coastguard Worker [&dropped_count](VideoStreamEncoderObserver::DropReason) {
1721*d9f75844SAndroid Build Coastguard Worker ++dropped_count;
1722*d9f75844SAndroid Build Coastguard Worker });
1723*d9f75844SAndroid Build Coastguard Worker
1724*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, nullptr));
1725*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(2, nullptr));
1726*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
1727*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1728*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, dropped_count);
1729*d9f75844SAndroid Build Coastguard Worker }
1730*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NativeFrameWithoutI420SupportGetsDelivered)1731*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, NativeFrameWithoutI420SupportGetsDelivered) {
1732*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1733*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1734*d9f75844SAndroid Build Coastguard Worker
1735*d9f75844SAndroid Build Coastguard Worker rtc::Event frame_destroyed_event;
1736*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
1737*d9f75844SAndroid Build Coastguard Worker CreateFakeNativeFrame(1, &frame_destroyed_event));
1738*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1739*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(VideoFrameBuffer::Type::kNative,
1740*d9f75844SAndroid Build Coastguard Worker fake_encoder_.GetLastInputPixelFormat());
1741*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().width, fake_encoder_.GetLastInputWidth());
1742*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().height, fake_encoder_.GetLastInputHeight());
1743*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1744*d9f75844SAndroid Build Coastguard Worker }
1745*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NativeFrameWithoutI420SupportGetsCroppedIfNecessary)1746*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
1747*d9f75844SAndroid Build Coastguard Worker NativeFrameWithoutI420SupportGetsCroppedIfNecessary) {
1748*d9f75844SAndroid Build Coastguard Worker // Use the cropping factory.
1749*d9f75844SAndroid Build Coastguard Worker video_encoder_config_.video_stream_factory =
1750*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<CroppingVideoStreamFactory>();
1751*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config_),
1752*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
1753*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
1754*d9f75844SAndroid Build Coastguard Worker
1755*d9f75844SAndroid Build Coastguard Worker // Capture a frame at codec_width_/codec_height_.
1756*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1757*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1758*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
1759*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1760*d9f75844SAndroid Build Coastguard Worker // The encoder will have been configured once.
1761*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, sink_.number_of_reconfigurations());
1762*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(codec_width_, fake_encoder_.config().width);
1763*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(codec_height_, fake_encoder_.config().height);
1764*d9f75844SAndroid Build Coastguard Worker
1765*d9f75844SAndroid Build Coastguard Worker // Now send in a fake frame that needs to be cropped as the width/height
1766*d9f75844SAndroid Build Coastguard Worker // aren't divisible by 4 (see CreateEncoderStreams above).
1767*d9f75844SAndroid Build Coastguard Worker rtc::Event frame_destroyed_event;
1768*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFakeNativeFrame(
1769*d9f75844SAndroid Build Coastguard Worker 2, &frame_destroyed_event, codec_width_ + 1, codec_height_ + 1));
1770*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
1771*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(VideoFrameBuffer::Type::kNative,
1772*d9f75844SAndroid Build Coastguard Worker fake_encoder_.GetLastInputPixelFormat());
1773*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().width, fake_encoder_.GetLastInputWidth());
1774*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().height, fake_encoder_.GetLastInputHeight());
1775*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1776*d9f75844SAndroid Build Coastguard Worker }
1777*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NonI420FramesShouldNotBeConvertedToI420)1778*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, NonI420FramesShouldNotBeConvertedToI420) {
1779*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1780*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1781*d9f75844SAndroid Build Coastguard Worker
1782*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
1783*d9f75844SAndroid Build Coastguard Worker CreateNV12Frame(1, codec_width_, codec_height_));
1784*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1785*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(VideoFrameBuffer::Type::kNV12,
1786*d9f75844SAndroid Build Coastguard Worker fake_encoder_.GetLastInputPixelFormat());
1787*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1788*d9f75844SAndroid Build Coastguard Worker }
1789*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NativeFrameGetsDelivered_NoFrameTypePreference)1790*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, NativeFrameGetsDelivered_NoFrameTypePreference) {
1791*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1792*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1793*d9f75844SAndroid Build Coastguard Worker
1794*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetPreferredPixelFormats({});
1795*d9f75844SAndroid Build Coastguard Worker
1796*d9f75844SAndroid Build Coastguard Worker rtc::Event frame_destroyed_event;
1797*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFakeNV12NativeFrame(
1798*d9f75844SAndroid Build Coastguard Worker 1, &frame_destroyed_event, codec_width_, codec_height_));
1799*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1800*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(VideoFrameBuffer::Type::kNative,
1801*d9f75844SAndroid Build Coastguard Worker fake_encoder_.GetLastInputPixelFormat());
1802*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1803*d9f75844SAndroid Build Coastguard Worker }
1804*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NativeFrameGetsDelivered_PixelFormatPreferenceMatches)1805*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
1806*d9f75844SAndroid Build Coastguard Worker NativeFrameGetsDelivered_PixelFormatPreferenceMatches) {
1807*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1808*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1809*d9f75844SAndroid Build Coastguard Worker
1810*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetPreferredPixelFormats({VideoFrameBuffer::Type::kNV12});
1811*d9f75844SAndroid Build Coastguard Worker
1812*d9f75844SAndroid Build Coastguard Worker rtc::Event frame_destroyed_event;
1813*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFakeNV12NativeFrame(
1814*d9f75844SAndroid Build Coastguard Worker 1, &frame_destroyed_event, codec_width_, codec_height_));
1815*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1816*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(VideoFrameBuffer::Type::kNative,
1817*d9f75844SAndroid Build Coastguard Worker fake_encoder_.GetLastInputPixelFormat());
1818*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1819*d9f75844SAndroid Build Coastguard Worker }
1820*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NativeFrameGetsDelivered_MappingIsNotFeasible)1821*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, NativeFrameGetsDelivered_MappingIsNotFeasible) {
1822*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1823*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1824*d9f75844SAndroid Build Coastguard Worker
1825*d9f75844SAndroid Build Coastguard Worker // Fake NV12 native frame does not allow mapping to I444.
1826*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetPreferredPixelFormats({VideoFrameBuffer::Type::kI444});
1827*d9f75844SAndroid Build Coastguard Worker
1828*d9f75844SAndroid Build Coastguard Worker rtc::Event frame_destroyed_event;
1829*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFakeNV12NativeFrame(
1830*d9f75844SAndroid Build Coastguard Worker 1, &frame_destroyed_event, codec_width_, codec_height_));
1831*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1832*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(VideoFrameBuffer::Type::kNative,
1833*d9f75844SAndroid Build Coastguard Worker fake_encoder_.GetLastInputPixelFormat());
1834*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1835*d9f75844SAndroid Build Coastguard Worker }
1836*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NativeFrameGetsDelivered_BackedByNV12)1837*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, NativeFrameGetsDelivered_BackedByNV12) {
1838*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1839*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1840*d9f75844SAndroid Build Coastguard Worker
1841*d9f75844SAndroid Build Coastguard Worker rtc::Event frame_destroyed_event;
1842*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFakeNV12NativeFrame(
1843*d9f75844SAndroid Build Coastguard Worker 1, &frame_destroyed_event, codec_width_, codec_height_));
1844*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1845*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(VideoFrameBuffer::Type::kNative,
1846*d9f75844SAndroid Build Coastguard Worker fake_encoder_.GetLastInputPixelFormat());
1847*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1848*d9f75844SAndroid Build Coastguard Worker }
1849*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DropsFramesWhenCongestionWindowPushbackSet)1850*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DropsFramesWhenCongestionWindowPushbackSet) {
1851*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1852*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1853*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
1854*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1855*d9f75844SAndroid Build Coastguard Worker
1856*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1857*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0.5);
1858*d9f75844SAndroid Build Coastguard Worker // The congestion window pushback is set to 0.5, which will drop 1/2 of
1859*d9f75844SAndroid Build Coastguard Worker // frames. Adding two frames means that the first frame will be dropped and
1860*d9f75844SAndroid Build Coastguard Worker // the second frame will be sent to the encoder.
1861*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
1862*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
1863*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
1864*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(4, nullptr));
1865*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(5, nullptr));
1866*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(5);
1867*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2u, stats_proxy_->GetStats().frames_dropped_by_congestion_window);
1868*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1869*d9f75844SAndroid Build Coastguard Worker }
1870*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ConfigureEncoderTriggersOnEncoderConfigurationChanged)1871*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
1872*d9f75844SAndroid Build Coastguard Worker ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
1873*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1874*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1875*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, sink_.number_of_reconfigurations());
1876*d9f75844SAndroid Build Coastguard Worker
1877*d9f75844SAndroid Build Coastguard Worker // Capture a frame and wait for it to synchronize with the encoder thread.
1878*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
1879*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1880*d9f75844SAndroid Build Coastguard Worker // The encoder will have been configured once when the first frame is
1881*d9f75844SAndroid Build Coastguard Worker // received.
1882*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, sink_.number_of_reconfigurations());
1883*d9f75844SAndroid Build Coastguard Worker
1884*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
1885*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
1886*d9f75844SAndroid Build Coastguard Worker video_encoder_config.min_transmit_bitrate_bps = 9999;
1887*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
1888*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
1889*d9f75844SAndroid Build Coastguard Worker
1890*d9f75844SAndroid Build Coastguard Worker // Capture a frame and wait for it to synchronize with the encoder thread.
1891*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
1892*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
1893*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, sink_.number_of_reconfigurations());
1894*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
1895*d9f75844SAndroid Build Coastguard Worker
1896*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1897*d9f75844SAndroid Build Coastguard Worker }
1898*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,FrameResolutionChangeReconfigureEncoder)1899*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, FrameResolutionChangeReconfigureEncoder) {
1900*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1901*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1902*d9f75844SAndroid Build Coastguard Worker
1903*d9f75844SAndroid Build Coastguard Worker // Capture a frame and wait for it to synchronize with the encoder thread.
1904*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
1905*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1906*d9f75844SAndroid Build Coastguard Worker // The encoder will have been configured once.
1907*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, sink_.number_of_reconfigurations());
1908*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(codec_width_, fake_encoder_.config().width);
1909*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(codec_height_, fake_encoder_.config().height);
1910*d9f75844SAndroid Build Coastguard Worker
1911*d9f75844SAndroid Build Coastguard Worker codec_width_ *= 2;
1912*d9f75844SAndroid Build Coastguard Worker codec_height_ *= 2;
1913*d9f75844SAndroid Build Coastguard Worker // Capture a frame with a higher resolution and wait for it to synchronize
1914*d9f75844SAndroid Build Coastguard Worker // with the encoder thread.
1915*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
1916*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
1917*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(codec_width_, fake_encoder_.config().width);
1918*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(codec_height_, fake_encoder_.config().height);
1919*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, sink_.number_of_reconfigurations());
1920*d9f75844SAndroid Build Coastguard Worker
1921*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1922*d9f75844SAndroid Build Coastguard Worker }
1923*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderInstanceDestroyedBeforeAnotherInstanceCreated)1924*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
1925*d9f75844SAndroid Build Coastguard Worker EncoderInstanceDestroyedBeforeAnotherInstanceCreated) {
1926*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1927*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1928*d9f75844SAndroid Build Coastguard Worker
1929*d9f75844SAndroid Build Coastguard Worker // Capture a frame and wait for it to synchronize with the encoder thread.
1930*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
1931*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1932*d9f75844SAndroid Build Coastguard Worker
1933*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
1934*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
1935*d9f75844SAndroid Build Coastguard Worker // Changing the max payload data length recreates encoder.
1936*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
1937*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength / 2);
1938*d9f75844SAndroid Build Coastguard Worker
1939*d9f75844SAndroid Build Coastguard Worker // Capture a frame and wait for it to synchronize with the encoder thread.
1940*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
1941*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
1942*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, encoder_factory_.GetMaxNumberOfSimultaneousEncoderInstances());
1943*d9f75844SAndroid Build Coastguard Worker
1944*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1945*d9f75844SAndroid Build Coastguard Worker }
1946*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,BitrateLimitsChangeReconfigureRateAllocator)1947*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, BitrateLimitsChangeReconfigureRateAllocator) {
1948*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1949*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1950*d9f75844SAndroid Build Coastguard Worker
1951*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
1952*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
1953*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kTargetBitrate.bps();
1954*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetStartBitrate(kStartBitrate.bps());
1955*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
1956*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
1957*d9f75844SAndroid Build Coastguard Worker
1958*d9f75844SAndroid Build Coastguard Worker // Capture a frame and wait for it to synchronize with the encoder thread.
1959*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
1960*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
1961*d9f75844SAndroid Build Coastguard Worker // The encoder will have been configured once when the first frame is
1962*d9f75844SAndroid Build Coastguard Worker // received.
1963*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, sink_.number_of_reconfigurations());
1964*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kTargetBitrate.bps(),
1965*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
1966*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kStartBitrate.bps(),
1967*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().startBitrate * 1000);
1968*d9f75844SAndroid Build Coastguard Worker
1969*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1,
1970*d9f75844SAndroid Build Coastguard Worker &video_encoder_config); //???
1971*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kTargetBitrate.bps() * 2;
1972*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetStartBitrate(kStartBitrate.bps() * 2);
1973*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
1974*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
1975*d9f75844SAndroid Build Coastguard Worker
1976*d9f75844SAndroid Build Coastguard Worker // Capture a frame and wait for it to synchronize with the encoder thread.
1977*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
1978*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
1979*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, sink_.number_of_reconfigurations());
1980*d9f75844SAndroid Build Coastguard Worker // Bitrate limits have changed - rate allocator should be reconfigured,
1981*d9f75844SAndroid Build Coastguard Worker // encoder should not be reconfigured.
1982*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kTargetBitrate.bps() * 2,
1983*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
1984*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kStartBitrate.bps() * 2,
1985*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().startBitrate * 1000);
1986*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, fake_encoder_.GetNumInitializations());
1987*d9f75844SAndroid Build Coastguard Worker
1988*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
1989*d9f75844SAndroid Build Coastguard Worker }
1990*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,IntersectionOfEncoderAndAppBitrateLimitsUsedWhenBothProvided)1991*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
1992*d9f75844SAndroid Build Coastguard Worker IntersectionOfEncoderAndAppBitrateLimitsUsedWhenBothProvided) {
1993*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
1994*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
1995*d9f75844SAndroid Build Coastguard Worker
1996*d9f75844SAndroid Build Coastguard Worker const uint32_t kMinEncBitrateKbps = 100;
1997*d9f75844SAndroid Build Coastguard Worker const uint32_t kMaxEncBitrateKbps = 1000;
1998*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits encoder_bitrate_limits(
1999*d9f75844SAndroid Build Coastguard Worker /*frame_size_pixels=*/codec_width_ * codec_height_,
2000*d9f75844SAndroid Build Coastguard Worker /*min_start_bitrate_bps=*/0,
2001*d9f75844SAndroid Build Coastguard Worker /*min_bitrate_bps=*/kMinEncBitrateKbps * 1000,
2002*d9f75844SAndroid Build Coastguard Worker /*max_bitrate_bps=*/kMaxEncBitrateKbps * 1000);
2003*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits({encoder_bitrate_limits});
2004*d9f75844SAndroid Build Coastguard Worker
2005*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
2006*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
2007*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = (kMaxEncBitrateKbps + 1) * 1000;
2008*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].min_bitrate_bps =
2009*d9f75844SAndroid Build Coastguard Worker (kMinEncBitrateKbps + 1) * 1000;
2010*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
2011*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
2012*d9f75844SAndroid Build Coastguard Worker
2013*d9f75844SAndroid Build Coastguard Worker // When both encoder and app provide bitrate limits, the intersection of
2014*d9f75844SAndroid Build Coastguard Worker // provided sets should be used.
2015*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
2016*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
2017*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kMaxEncBitrateKbps,
2018*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().maxBitrate);
2019*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kMinEncBitrateKbps + 1,
2020*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().minBitrate);
2021*d9f75844SAndroid Build Coastguard Worker
2022*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = (kMaxEncBitrateKbps - 1) * 1000;
2023*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].min_bitrate_bps =
2024*d9f75844SAndroid Build Coastguard Worker (kMinEncBitrateKbps - 1) * 1000;
2025*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
2026*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
2027*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
2028*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
2029*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kMaxEncBitrateKbps - 1,
2030*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().maxBitrate);
2031*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kMinEncBitrateKbps,
2032*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().minBitrate);
2033*d9f75844SAndroid Build Coastguard Worker
2034*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2035*d9f75844SAndroid Build Coastguard Worker }
2036*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderAndAppLimitsDontIntersectEncoderLimitsIgnored)2037*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
2038*d9f75844SAndroid Build Coastguard Worker EncoderAndAppLimitsDontIntersectEncoderLimitsIgnored) {
2039*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
2040*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
2041*d9f75844SAndroid Build Coastguard Worker
2042*d9f75844SAndroid Build Coastguard Worker const uint32_t kMinAppBitrateKbps = 100;
2043*d9f75844SAndroid Build Coastguard Worker const uint32_t kMaxAppBitrateKbps = 200;
2044*d9f75844SAndroid Build Coastguard Worker const uint32_t kMinEncBitrateKbps = kMaxAppBitrateKbps + 1;
2045*d9f75844SAndroid Build Coastguard Worker const uint32_t kMaxEncBitrateKbps = kMaxAppBitrateKbps * 2;
2046*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits encoder_bitrate_limits(
2047*d9f75844SAndroid Build Coastguard Worker /*frame_size_pixels=*/codec_width_ * codec_height_,
2048*d9f75844SAndroid Build Coastguard Worker /*min_start_bitrate_bps=*/0,
2049*d9f75844SAndroid Build Coastguard Worker /*min_bitrate_bps=*/kMinEncBitrateKbps * 1000,
2050*d9f75844SAndroid Build Coastguard Worker /*max_bitrate_bps=*/kMaxEncBitrateKbps * 1000);
2051*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits({encoder_bitrate_limits});
2052*d9f75844SAndroid Build Coastguard Worker
2053*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
2054*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
2055*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kMaxAppBitrateKbps * 1000;
2056*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].min_bitrate_bps =
2057*d9f75844SAndroid Build Coastguard Worker kMinAppBitrateKbps * 1000;
2058*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
2059*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
2060*d9f75844SAndroid Build Coastguard Worker
2061*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
2062*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
2063*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kMaxAppBitrateKbps,
2064*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().maxBitrate);
2065*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kMinAppBitrateKbps,
2066*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().minBitrate);
2067*d9f75844SAndroid Build Coastguard Worker
2068*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2069*d9f75844SAndroid Build Coastguard Worker }
2070*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderRecommendedMaxAndMinBitratesUsedForGivenResolution)2071*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
2072*d9f75844SAndroid Build Coastguard Worker EncoderRecommendedMaxAndMinBitratesUsedForGivenResolution) {
2073*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
2074*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
2075*d9f75844SAndroid Build Coastguard Worker
2076*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits encoder_bitrate_limits_270p(
2077*d9f75844SAndroid Build Coastguard Worker 480 * 270, 34 * 1000, 12 * 1000, 1234 * 1000);
2078*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits encoder_bitrate_limits_360p(
2079*d9f75844SAndroid Build Coastguard Worker 640 * 360, 43 * 1000, 21 * 1000, 2345 * 1000);
2080*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits(
2081*d9f75844SAndroid Build Coastguard Worker {encoder_bitrate_limits_270p, encoder_bitrate_limits_360p});
2082*d9f75844SAndroid Build Coastguard Worker
2083*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
2084*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
2085*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = 0;
2086*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
2087*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
2088*d9f75844SAndroid Build Coastguard Worker
2089*d9f75844SAndroid Build Coastguard Worker // 270p. The bitrate limits recommended by encoder for 270p should be used.
2090*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 480, 270));
2091*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
2092*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_270p.min_bitrate_bps),
2093*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().minBitrate * 1000);
2094*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_270p.max_bitrate_bps),
2095*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
2096*d9f75844SAndroid Build Coastguard Worker
2097*d9f75844SAndroid Build Coastguard Worker // 360p. The bitrate limits recommended by encoder for 360p should be used.
2098*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
2099*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
2100*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_360p.min_bitrate_bps),
2101*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().minBitrate * 1000);
2102*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_360p.max_bitrate_bps),
2103*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
2104*d9f75844SAndroid Build Coastguard Worker
2105*d9f75844SAndroid Build Coastguard Worker // Resolution between 270p and 360p. The bitrate limits recommended by
2106*d9f75844SAndroid Build Coastguard Worker // encoder for 360p should be used.
2107*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2108*d9f75844SAndroid Build Coastguard Worker CreateFrame(3, (640 + 480) / 2, (360 + 270) / 2));
2109*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
2110*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_360p.min_bitrate_bps),
2111*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().minBitrate * 1000);
2112*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_360p.max_bitrate_bps),
2113*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
2114*d9f75844SAndroid Build Coastguard Worker
2115*d9f75844SAndroid Build Coastguard Worker // Resolution higher than 360p. The caps recommended by encoder should be
2116*d9f75844SAndroid Build Coastguard Worker // ignored.
2117*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(4, 960, 540));
2118*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(4);
2119*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(encoder_bitrate_limits_270p.min_bitrate_bps),
2120*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().minBitrate * 1000);
2121*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(encoder_bitrate_limits_270p.max_bitrate_bps),
2122*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
2123*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(encoder_bitrate_limits_360p.min_bitrate_bps),
2124*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().minBitrate * 1000);
2125*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(encoder_bitrate_limits_360p.max_bitrate_bps),
2126*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
2127*d9f75844SAndroid Build Coastguard Worker
2128*d9f75844SAndroid Build Coastguard Worker // Resolution lower than 270p. The max bitrate limit recommended by encoder
2129*d9f75844SAndroid Build Coastguard Worker // for 270p should be used.
2130*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(5, 320, 180));
2131*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(5);
2132*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_270p.min_bitrate_bps),
2133*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().minBitrate * 1000);
2134*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(encoder_bitrate_limits_270p.max_bitrate_bps),
2135*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config().maxBitrate * 1000);
2136*d9f75844SAndroid Build Coastguard Worker
2137*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2138*d9f75844SAndroid Build Coastguard Worker }
2139*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderRecommendedMaxBitrateCapsTargetBitrate)2140*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, EncoderRecommendedMaxBitrateCapsTargetBitrate) {
2141*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
2142*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
2143*d9f75844SAndroid Build Coastguard Worker
2144*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
2145*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
2146*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = 0;
2147*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
2148*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
2149*d9f75844SAndroid Build Coastguard Worker
2150*d9f75844SAndroid Build Coastguard Worker // Encode 720p frame to get the default encoder target bitrate.
2151*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
2152*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
2153*d9f75844SAndroid Build Coastguard Worker const uint32_t kDefaultTargetBitrateFor720pKbps =
2154*d9f75844SAndroid Build Coastguard Worker bitrate_allocator_factory_.codec_config()
2155*d9f75844SAndroid Build Coastguard Worker .simulcastStream[0]
2156*d9f75844SAndroid Build Coastguard Worker .targetBitrate;
2157*d9f75844SAndroid Build Coastguard Worker
2158*d9f75844SAndroid Build Coastguard Worker // Set the max recommended encoder bitrate to something lower than the default
2159*d9f75844SAndroid Build Coastguard Worker // target bitrate.
2160*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits encoder_bitrate_limits(
2161*d9f75844SAndroid Build Coastguard Worker 1280 * 720, 10 * 1000, 10 * 1000,
2162*d9f75844SAndroid Build Coastguard Worker kDefaultTargetBitrateFor720pKbps / 2 * 1000);
2163*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits({encoder_bitrate_limits});
2164*d9f75844SAndroid Build Coastguard Worker
2165*d9f75844SAndroid Build Coastguard Worker // Change resolution to trigger encoder reinitialization.
2166*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
2167*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
2168*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, 1280, 720));
2169*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
2170*d9f75844SAndroid Build Coastguard Worker
2171*d9f75844SAndroid Build Coastguard Worker // Ensure the target bitrate is capped by the max bitrate.
2172*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(bitrate_allocator_factory_.codec_config().maxBitrate * 1000,
2173*d9f75844SAndroid Build Coastguard Worker static_cast<uint32_t>(encoder_bitrate_limits.max_bitrate_bps));
2174*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(bitrate_allocator_factory_.codec_config()
2175*d9f75844SAndroid Build Coastguard Worker .simulcastStream[0]
2176*d9f75844SAndroid Build Coastguard Worker .targetBitrate *
2177*d9f75844SAndroid Build Coastguard Worker 1000,
2178*d9f75844SAndroid Build Coastguard Worker static_cast<uint32_t>(encoder_bitrate_limits.max_bitrate_bps));
2179*d9f75844SAndroid Build Coastguard Worker
2180*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2181*d9f75844SAndroid Build Coastguard Worker }
2182*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderMaxAndMinBitratesUsedForTwoStreamsHighestActive)2183*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
2184*d9f75844SAndroid Build Coastguard Worker EncoderMaxAndMinBitratesUsedForTwoStreamsHighestActive) {
2185*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits270p(
2186*d9f75844SAndroid Build Coastguard Worker 480 * 270, 34 * 1000, 12 * 1000, 1234 * 1000);
2187*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits360p(
2188*d9f75844SAndroid Build Coastguard Worker 640 * 360, 43 * 1000, 21 * 1000, 2345 * 1000);
2189*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits(
2190*d9f75844SAndroid Build Coastguard Worker {kEncoderLimits270p, kEncoderLimits360p});
2191*d9f75844SAndroid Build Coastguard Worker
2192*d9f75844SAndroid Build Coastguard Worker // Two streams, highest stream active.
2193*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
2194*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoder::EncoderInfo encoder_info;
2195*d9f75844SAndroid Build Coastguard Worker const int kNumStreams = 2;
2196*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, kNumStreams, &config);
2197*d9f75844SAndroid Build Coastguard Worker config.max_bitrate_bps = 0;
2198*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[0].active = false;
2199*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[1].active = true;
2200*d9f75844SAndroid Build Coastguard Worker config.video_stream_factory =
2201*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<cricket::EncoderStreamFactory>(
2202*d9f75844SAndroid Build Coastguard Worker "VP8", /*max qp*/ 56, /*screencast*/ false,
2203*d9f75844SAndroid Build Coastguard Worker /*screenshare enabled*/ false, encoder_info);
2204*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
2205*d9f75844SAndroid Build Coastguard Worker
2206*d9f75844SAndroid Build Coastguard Worker // The encoder bitrate limits for 270p should be used.
2207*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 480, 270));
2208*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2209*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().numberOfSimulcastStreams, kNumStreams);
2210*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits270p.min_bitrate_bps),
2211*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2212*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits270p.max_bitrate_bps),
2213*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2214*d9f75844SAndroid Build Coastguard Worker
2215*d9f75844SAndroid Build Coastguard Worker // The encoder bitrate limits for 360p should be used.
2216*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
2217*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2218*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits360p.min_bitrate_bps),
2219*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2220*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits360p.max_bitrate_bps),
2221*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2222*d9f75844SAndroid Build Coastguard Worker
2223*d9f75844SAndroid Build Coastguard Worker // Resolution b/w 270p and 360p. The encoder limits for 360p should be used.
2224*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2225*d9f75844SAndroid Build Coastguard Worker CreateFrame(3, (640 + 480) / 2, (360 + 270) / 2));
2226*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2227*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits360p.min_bitrate_bps),
2228*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2229*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits360p.max_bitrate_bps),
2230*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2231*d9f75844SAndroid Build Coastguard Worker
2232*d9f75844SAndroid Build Coastguard Worker // Resolution higher than 360p. Encoder limits should be ignored.
2233*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(4, 960, 540));
2234*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2235*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(kEncoderLimits270p.min_bitrate_bps),
2236*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2237*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(kEncoderLimits270p.max_bitrate_bps),
2238*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2239*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(kEncoderLimits360p.min_bitrate_bps),
2240*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2241*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(kEncoderLimits360p.max_bitrate_bps),
2242*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2243*d9f75844SAndroid Build Coastguard Worker
2244*d9f75844SAndroid Build Coastguard Worker // Resolution lower than 270p. The encoder limits for 270p should be used.
2245*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(5, 320, 180));
2246*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2247*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits270p.min_bitrate_bps),
2248*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2249*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits270p.max_bitrate_bps),
2250*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2251*d9f75844SAndroid Build Coastguard Worker
2252*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2253*d9f75844SAndroid Build Coastguard Worker }
2254*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DefaultEncoderMaxAndMinBitratesUsedForTwoStreamsHighestActive)2255*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
2256*d9f75844SAndroid Build Coastguard Worker DefaultEncoderMaxAndMinBitratesUsedForTwoStreamsHighestActive) {
2257*d9f75844SAndroid Build Coastguard Worker // Two streams, highest stream active.
2258*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
2259*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoder::EncoderInfo encoder_info;
2260*d9f75844SAndroid Build Coastguard Worker const int kNumStreams = 2;
2261*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, kNumStreams, &config);
2262*d9f75844SAndroid Build Coastguard Worker config.max_bitrate_bps = 0;
2263*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[0].active = false;
2264*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[1].active = true;
2265*d9f75844SAndroid Build Coastguard Worker config.video_stream_factory =
2266*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<cricket::EncoderStreamFactory>(
2267*d9f75844SAndroid Build Coastguard Worker "VP8", /*max qp*/ 56, /*screencast*/ false,
2268*d9f75844SAndroid Build Coastguard Worker /*screenshare enabled*/ false, encoder_info);
2269*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
2270*d9f75844SAndroid Build Coastguard Worker
2271*d9f75844SAndroid Build Coastguard Worker // Default bitrate limits for 270p should be used.
2272*d9f75844SAndroid Build Coastguard Worker const absl::optional<VideoEncoder::ResolutionBitrateLimits>
2273*d9f75844SAndroid Build Coastguard Worker kDefaultLimits270p =
2274*d9f75844SAndroid Build Coastguard Worker EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(
2275*d9f75844SAndroid Build Coastguard Worker kVideoCodecVP8, 480 * 270);
2276*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 480, 270));
2277*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2278*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().numberOfSimulcastStreams, kNumStreams);
2279*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits270p->min_bitrate_bps),
2280*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2281*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits270p->max_bitrate_bps),
2282*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2283*d9f75844SAndroid Build Coastguard Worker
2284*d9f75844SAndroid Build Coastguard Worker // Default bitrate limits for 360p should be used.
2285*d9f75844SAndroid Build Coastguard Worker const absl::optional<VideoEncoder::ResolutionBitrateLimits>
2286*d9f75844SAndroid Build Coastguard Worker kDefaultLimits360p =
2287*d9f75844SAndroid Build Coastguard Worker EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(
2288*d9f75844SAndroid Build Coastguard Worker kVideoCodecVP8, 640 * 360);
2289*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
2290*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2291*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits360p->min_bitrate_bps),
2292*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2293*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits360p->max_bitrate_bps),
2294*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2295*d9f75844SAndroid Build Coastguard Worker
2296*d9f75844SAndroid Build Coastguard Worker // Resolution b/w 270p and 360p. The default limits for 360p should be used.
2297*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2298*d9f75844SAndroid Build Coastguard Worker CreateFrame(3, (640 + 480) / 2, (360 + 270) / 2));
2299*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2300*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits360p->min_bitrate_bps),
2301*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2302*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits360p->max_bitrate_bps),
2303*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2304*d9f75844SAndroid Build Coastguard Worker
2305*d9f75844SAndroid Build Coastguard Worker // Default bitrate limits for 540p should be used.
2306*d9f75844SAndroid Build Coastguard Worker const absl::optional<VideoEncoder::ResolutionBitrateLimits>
2307*d9f75844SAndroid Build Coastguard Worker kDefaultLimits540p =
2308*d9f75844SAndroid Build Coastguard Worker EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(
2309*d9f75844SAndroid Build Coastguard Worker kVideoCodecVP8, 960 * 540);
2310*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(4, 960, 540));
2311*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2312*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits540p->min_bitrate_bps),
2313*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2314*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits540p->max_bitrate_bps),
2315*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2316*d9f75844SAndroid Build Coastguard Worker
2317*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2318*d9f75844SAndroid Build Coastguard Worker }
2319*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderMaxAndMinBitratesUsedForThreeStreamsMiddleActive)2320*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
2321*d9f75844SAndroid Build Coastguard Worker EncoderMaxAndMinBitratesUsedForThreeStreamsMiddleActive) {
2322*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits270p(
2323*d9f75844SAndroid Build Coastguard Worker 480 * 270, 34 * 1000, 12 * 1000, 1234 * 1000);
2324*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits360p(
2325*d9f75844SAndroid Build Coastguard Worker 640 * 360, 43 * 1000, 21 * 1000, 2345 * 1000);
2326*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits720p(
2327*d9f75844SAndroid Build Coastguard Worker 1280 * 720, 54 * 1000, 31 * 1000, 3456 * 1000);
2328*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits(
2329*d9f75844SAndroid Build Coastguard Worker {kEncoderLimits270p, kEncoderLimits360p, kEncoderLimits720p});
2330*d9f75844SAndroid Build Coastguard Worker
2331*d9f75844SAndroid Build Coastguard Worker // Three streams, middle stream active.
2332*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
2333*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoder::EncoderInfo encoder_info;
2334*d9f75844SAndroid Build Coastguard Worker const int kNumStreams = 3;
2335*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, kNumStreams, &config);
2336*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[0].active = false;
2337*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[1].active = true;
2338*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[2].active = false;
2339*d9f75844SAndroid Build Coastguard Worker config.video_stream_factory =
2340*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<cricket::EncoderStreamFactory>(
2341*d9f75844SAndroid Build Coastguard Worker "VP8", /*max qp*/ 56, /*screencast*/ false,
2342*d9f75844SAndroid Build Coastguard Worker /*screenshare enabled*/ false, encoder_info);
2343*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
2344*d9f75844SAndroid Build Coastguard Worker
2345*d9f75844SAndroid Build Coastguard Worker // The encoder bitrate limits for 360p should be used.
2346*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
2347*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2348*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().numberOfSimulcastStreams, kNumStreams);
2349*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits360p.min_bitrate_bps),
2350*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2351*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits360p.max_bitrate_bps),
2352*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2353*d9f75844SAndroid Build Coastguard Worker
2354*d9f75844SAndroid Build Coastguard Worker // The encoder bitrate limits for 270p should be used.
2355*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, 960, 540));
2356*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2357*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits270p.min_bitrate_bps),
2358*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2359*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits270p.max_bitrate_bps),
2360*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2361*d9f75844SAndroid Build Coastguard Worker
2362*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2363*d9f75844SAndroid Build Coastguard Worker }
2364*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderMaxAndMinBitratesNotUsedForThreeStreamsLowestActive)2365*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
2366*d9f75844SAndroid Build Coastguard Worker EncoderMaxAndMinBitratesNotUsedForThreeStreamsLowestActive) {
2367*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits270p(
2368*d9f75844SAndroid Build Coastguard Worker 480 * 270, 34 * 1000, 12 * 1000, 1234 * 1000);
2369*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits360p(
2370*d9f75844SAndroid Build Coastguard Worker 640 * 360, 43 * 1000, 21 * 1000, 2345 * 1000);
2371*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits720p(
2372*d9f75844SAndroid Build Coastguard Worker 1280 * 720, 54 * 1000, 31 * 1000, 3456 * 1000);
2373*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits(
2374*d9f75844SAndroid Build Coastguard Worker {kEncoderLimits270p, kEncoderLimits360p, kEncoderLimits720p});
2375*d9f75844SAndroid Build Coastguard Worker
2376*d9f75844SAndroid Build Coastguard Worker // Three streams, lowest stream active.
2377*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
2378*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoder::EncoderInfo encoder_info;
2379*d9f75844SAndroid Build Coastguard Worker const int kNumStreams = 3;
2380*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, kNumStreams, &config);
2381*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[0].active = true;
2382*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[1].active = false;
2383*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[2].active = false;
2384*d9f75844SAndroid Build Coastguard Worker config.video_stream_factory =
2385*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<cricket::EncoderStreamFactory>(
2386*d9f75844SAndroid Build Coastguard Worker "VP8", /*max qp*/ 56, /*screencast*/ false,
2387*d9f75844SAndroid Build Coastguard Worker /*screenshare enabled*/ false, encoder_info);
2388*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
2389*d9f75844SAndroid Build Coastguard Worker
2390*d9f75844SAndroid Build Coastguard Worker // Resolution on lowest stream lower than 270p. The encoder limits not applied
2391*d9f75844SAndroid Build Coastguard Worker // on lowest stream, limits for 270p should not be used
2392*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
2393*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2394*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().numberOfSimulcastStreams, kNumStreams);
2395*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(kEncoderLimits270p.min_bitrate_bps),
2396*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2397*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(kEncoderLimits270p.max_bitrate_bps),
2398*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2399*d9f75844SAndroid Build Coastguard Worker
2400*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2401*d9f75844SAndroid Build Coastguard Worker }
2402*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderMaxBitrateCappedByConfigForTwoStreamsHighestActive)2403*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
2404*d9f75844SAndroid Build Coastguard Worker EncoderMaxBitrateCappedByConfigForTwoStreamsHighestActive) {
2405*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits270p(
2406*d9f75844SAndroid Build Coastguard Worker 480 * 270, 34 * 1000, 12 * 1000, 1234 * 1000);
2407*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits360p(
2408*d9f75844SAndroid Build Coastguard Worker 640 * 360, 43 * 1000, 21 * 1000, 2345 * 1000);
2409*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits(
2410*d9f75844SAndroid Build Coastguard Worker {kEncoderLimits270p, kEncoderLimits360p});
2411*d9f75844SAndroid Build Coastguard Worker const int kMaxBitrateBps = kEncoderLimits360p.max_bitrate_bps - 100 * 1000;
2412*d9f75844SAndroid Build Coastguard Worker
2413*d9f75844SAndroid Build Coastguard Worker // Two streams, highest stream active.
2414*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
2415*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoder::EncoderInfo encoder_info;
2416*d9f75844SAndroid Build Coastguard Worker const int kNumStreams = 2;
2417*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, kNumStreams, &config);
2418*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[0].active = false;
2419*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[1].active = true;
2420*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[1].max_bitrate_bps = kMaxBitrateBps;
2421*d9f75844SAndroid Build Coastguard Worker config.video_stream_factory =
2422*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<cricket::EncoderStreamFactory>(
2423*d9f75844SAndroid Build Coastguard Worker "VP8", /*max qp*/ 56, /*screencast*/ false,
2424*d9f75844SAndroid Build Coastguard Worker /*screenshare enabled*/ false, encoder_info);
2425*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
2426*d9f75844SAndroid Build Coastguard Worker
2427*d9f75844SAndroid Build Coastguard Worker // The encoder bitrate limits for 270p should be used.
2428*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 480, 270));
2429*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2430*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().numberOfSimulcastStreams, kNumStreams);
2431*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits270p.min_bitrate_bps),
2432*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2433*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits270p.max_bitrate_bps),
2434*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2435*d9f75844SAndroid Build Coastguard Worker
2436*d9f75844SAndroid Build Coastguard Worker // The max configured bitrate is less than the encoder limit for 360p.
2437*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
2438*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
2439*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits360p.min_bitrate_bps),
2440*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].minBitrate * 1000);
2441*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kMaxBitrateBps),
2442*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().simulcastStream[1].maxBitrate * 1000);
2443*d9f75844SAndroid Build Coastguard Worker
2444*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2445*d9f75844SAndroid Build Coastguard Worker }
2446*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SwitchSourceDeregisterEncoderAsSink)2447*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, SwitchSourceDeregisterEncoderAsSink) {
2448*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(video_source_.has_sinks());
2449*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder new_video_source;
2450*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
2451*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
2452*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(video_source_.has_sinks());
2453*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(new_video_source.has_sinks());
2454*d9f75844SAndroid Build Coastguard Worker
2455*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2456*d9f75844SAndroid Build Coastguard Worker }
2457*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SinkWantsRotationApplied)2458*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, SinkWantsRotationApplied) {
2459*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(video_source_.sink_wants().rotation_applied);
2460*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSink(&sink_, true /*rotation_applied*/);
2461*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(video_source_.sink_wants().rotation_applied);
2462*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2463*d9f75844SAndroid Build Coastguard Worker }
2464*d9f75844SAndroid Build Coastguard Worker
2465*d9f75844SAndroid Build Coastguard Worker class ResolutionAlignmentTest
2466*d9f75844SAndroid Build Coastguard Worker : public VideoStreamEncoderTest,
2467*d9f75844SAndroid Build Coastguard Worker public ::testing::WithParamInterface<
2468*d9f75844SAndroid Build Coastguard Worker ::testing::tuple<int, std::vector<double>>> {
2469*d9f75844SAndroid Build Coastguard Worker public:
ResolutionAlignmentTest()2470*d9f75844SAndroid Build Coastguard Worker ResolutionAlignmentTest()
2471*d9f75844SAndroid Build Coastguard Worker : requested_alignment_(::testing::get<0>(GetParam())),
2472*d9f75844SAndroid Build Coastguard Worker scale_factors_(::testing::get<1>(GetParam())) {}
2473*d9f75844SAndroid Build Coastguard Worker
2474*d9f75844SAndroid Build Coastguard Worker protected:
2475*d9f75844SAndroid Build Coastguard Worker const int requested_alignment_;
2476*d9f75844SAndroid Build Coastguard Worker const std::vector<double> scale_factors_;
2477*d9f75844SAndroid Build Coastguard Worker };
2478*d9f75844SAndroid Build Coastguard Worker
2479*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
2480*d9f75844SAndroid Build Coastguard Worker AlignmentAndScaleFactors,
2481*d9f75844SAndroid Build Coastguard Worker ResolutionAlignmentTest,
2482*d9f75844SAndroid Build Coastguard Worker ::testing::Combine(
2483*d9f75844SAndroid Build Coastguard Worker ::testing::Values(1, 2, 3, 4, 5, 6, 16, 22), // requested_alignment_
2484*d9f75844SAndroid Build Coastguard Worker ::testing::Values(std::vector<double>{-1.0}, // scale_factors_
2485*d9f75844SAndroid Build Coastguard Worker std::vector<double>{-1.0, -1.0},
2486*d9f75844SAndroid Build Coastguard Worker std::vector<double>{-1.0, -1.0, -1.0},
2487*d9f75844SAndroid Build Coastguard Worker std::vector<double>{4.0, 2.0, 1.0},
2488*d9f75844SAndroid Build Coastguard Worker std::vector<double>{9999.0, -1.0, 1.0},
2489*d9f75844SAndroid Build Coastguard Worker std::vector<double>{3.99, 2.01, 1.0},
2490*d9f75844SAndroid Build Coastguard Worker std::vector<double>{4.9, 1.7, 1.25},
2491*d9f75844SAndroid Build Coastguard Worker std::vector<double>{10.0, 4.0, 3.0},
2492*d9f75844SAndroid Build Coastguard Worker std::vector<double>{1.75, 3.5},
2493*d9f75844SAndroid Build Coastguard Worker std::vector<double>{1.5, 2.5},
2494*d9f75844SAndroid Build Coastguard Worker std::vector<double>{1.3, 1.0})));
2495*d9f75844SAndroid Build Coastguard Worker
TEST_P(ResolutionAlignmentTest,SinkWantsAlignmentApplied)2496*d9f75844SAndroid Build Coastguard Worker TEST_P(ResolutionAlignmentTest, SinkWantsAlignmentApplied) {
2497*d9f75844SAndroid Build Coastguard Worker // Set requested resolution alignment.
2498*d9f75844SAndroid Build Coastguard Worker video_source_.set_adaptation_enabled(true);
2499*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetRequestedResolutionAlignment(requested_alignment_);
2500*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetApplyAlignmentToAllSimulcastLayers(true);
2501*d9f75844SAndroid Build Coastguard Worker
2502*d9f75844SAndroid Build Coastguard Worker // Fill config with the scaling factor by which to reduce encoding size.
2503*d9f75844SAndroid Build Coastguard Worker const int num_streams = scale_factors_.size();
2504*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
2505*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoder::EncoderInfo encoder_info;
2506*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, num_streams, &config);
2507*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < num_streams; ++i) {
2508*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[i].scale_resolution_down_by = scale_factors_[i];
2509*d9f75844SAndroid Build Coastguard Worker }
2510*d9f75844SAndroid Build Coastguard Worker config.video_stream_factory =
2511*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<cricket::EncoderStreamFactory>(
2512*d9f75844SAndroid Build Coastguard Worker "VP8", /*max qp*/ 56, /*screencast*/ false,
2513*d9f75844SAndroid Build Coastguard Worker /*screenshare enabled*/ false, encoder_info);
2514*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(config), kMaxPayloadLength);
2515*d9f75844SAndroid Build Coastguard Worker
2516*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
2517*d9f75844SAndroid Build Coastguard Worker kSimulcastTargetBitrate, kSimulcastTargetBitrate, kSimulcastTargetBitrate,
2518*d9f75844SAndroid Build Coastguard Worker 0, 0, 0);
2519*d9f75844SAndroid Build Coastguard Worker // Wait for all layers before triggering event.
2520*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(num_streams);
2521*d9f75844SAndroid Build Coastguard Worker
2522*d9f75844SAndroid Build Coastguard Worker // On the 1st frame, we should have initialized the encoder and
2523*d9f75844SAndroid Build Coastguard Worker // asked for its resolution requirements.
2524*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
2525*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(timestamp_ms, 1280, 720));
2526*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
2527*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, fake_encoder_.GetNumInitializations());
2528*d9f75844SAndroid Build Coastguard Worker
2529*d9f75844SAndroid Build Coastguard Worker // On the 2nd frame, we should be receiving a correctly aligned resolution.
2530*d9f75844SAndroid Build Coastguard Worker // (It's up the to the encoder to potentially drop the previous frame,
2531*d9f75844SAndroid Build Coastguard Worker // to avoid coding back-to-back keyframes.)
2532*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
2533*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(timestamp_ms, 1280, 720));
2534*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
2535*d9f75844SAndroid Build Coastguard Worker EXPECT_GE(fake_encoder_.GetNumInitializations(), 1);
2536*d9f75844SAndroid Build Coastguard Worker
2537*d9f75844SAndroid Build Coastguard Worker VideoCodec codec = fake_encoder_.config();
2538*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(codec.numberOfSimulcastStreams, num_streams);
2539*d9f75844SAndroid Build Coastguard Worker // Frame size should be a multiple of the requested alignment.
2540*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < codec.numberOfSimulcastStreams; ++i) {
2541*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(codec.simulcastStream[i].width % requested_alignment_, 0);
2542*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(codec.simulcastStream[i].height % requested_alignment_, 0);
2543*d9f75844SAndroid Build Coastguard Worker // Aspect ratio should match.
2544*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(codec.width * codec.simulcastStream[i].height,
2545*d9f75844SAndroid Build Coastguard Worker codec.height * codec.simulcastStream[i].width);
2546*d9f75844SAndroid Build Coastguard Worker }
2547*d9f75844SAndroid Build Coastguard Worker
2548*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2549*d9f75844SAndroid Build Coastguard Worker }
2550*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,TestCpuDowngrades_BalancedMode)2551*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, TestCpuDowngrades_BalancedMode) {
2552*d9f75844SAndroid Build Coastguard Worker const int kFramerateFps = 30;
2553*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
2554*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
2555*d9f75844SAndroid Build Coastguard Worker
2556*d9f75844SAndroid Build Coastguard Worker // We rely on the automatic resolution adaptation, but we handle framerate
2557*d9f75844SAndroid Build Coastguard Worker // adaptation manually by mocking the stats proxy.
2558*d9f75844SAndroid Build Coastguard Worker video_source_.set_adaptation_enabled(true);
2559*d9f75844SAndroid Build Coastguard Worker
2560*d9f75844SAndroid Build Coastguard Worker // Enable BALANCED preference, no initial limitation.
2561*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
2562*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
2563*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&video_source_,
2564*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
2565*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(), UnlimitedSinkWants());
2566*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2567*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
2568*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2569*d9f75844SAndroid Build Coastguard Worker
2570*d9f75844SAndroid Build Coastguard Worker // Adapt down as far as possible.
2571*d9f75844SAndroid Build Coastguard Worker rtc::VideoSinkWants last_wants;
2572*d9f75844SAndroid Build Coastguard Worker int64_t t = 1;
2573*d9f75844SAndroid Build Coastguard Worker int loop_count = 0;
2574*d9f75844SAndroid Build Coastguard Worker do {
2575*d9f75844SAndroid Build Coastguard Worker ++loop_count;
2576*d9f75844SAndroid Build Coastguard Worker last_wants = video_source_.sink_wants();
2577*d9f75844SAndroid Build Coastguard Worker
2578*d9f75844SAndroid Build Coastguard Worker // Simulate the framerate we've been asked to adapt to.
2579*d9f75844SAndroid Build Coastguard Worker const int fps = std::min(kFramerateFps, last_wants.max_framerate_fps);
2580*d9f75844SAndroid Build Coastguard Worker const int frame_interval_ms = rtc::kNumMillisecsPerSec / fps;
2581*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats mock_stats = stats_proxy_->GetStats();
2582*d9f75844SAndroid Build Coastguard Worker mock_stats.input_frame_rate = fps;
2583*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(mock_stats);
2584*d9f75844SAndroid Build Coastguard Worker
2585*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(t, kWidth, kHeight));
2586*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(t);
2587*d9f75844SAndroid Build Coastguard Worker t += frame_interval_ms;
2588*d9f75844SAndroid Build Coastguard Worker
2589*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
2590*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(
2591*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants(),
2592*d9f75844SAndroid Build Coastguard Worker FpsInRangeForPixelsInBalanced(*video_source_.last_sent_width() *
2593*d9f75844SAndroid Build Coastguard Worker *video_source_.last_sent_height()));
2594*d9f75844SAndroid Build Coastguard Worker } while (video_source_.sink_wants().max_pixel_count <
2595*d9f75844SAndroid Build Coastguard Worker last_wants.max_pixel_count ||
2596*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants().max_framerate_fps <
2597*d9f75844SAndroid Build Coastguard Worker last_wants.max_framerate_fps);
2598*d9f75844SAndroid Build Coastguard Worker
2599*d9f75844SAndroid Build Coastguard Worker // Verify that we've adapted all the way down.
2600*d9f75844SAndroid Build Coastguard Worker stats_proxy_->ResetMockStats();
2601*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
2602*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_framerate);
2603*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(loop_count - 1,
2604*d9f75844SAndroid Build Coastguard Worker stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2605*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kMinPixelsPerFrame, *video_source_.last_sent_width() *
2606*d9f75844SAndroid Build Coastguard Worker *video_source_.last_sent_height());
2607*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kMinBalancedFramerateFps,
2608*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants().max_framerate_fps);
2609*d9f75844SAndroid Build Coastguard Worker
2610*d9f75844SAndroid Build Coastguard Worker // Adapt back up the same number of times we adapted down.
2611*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < loop_count - 1; ++i) {
2612*d9f75844SAndroid Build Coastguard Worker last_wants = video_source_.sink_wants();
2613*d9f75844SAndroid Build Coastguard Worker
2614*d9f75844SAndroid Build Coastguard Worker // Simulate the framerate we've been asked to adapt to.
2615*d9f75844SAndroid Build Coastguard Worker const int fps = std::min(kFramerateFps, last_wants.max_framerate_fps);
2616*d9f75844SAndroid Build Coastguard Worker const int frame_interval_ms = rtc::kNumMillisecsPerSec / fps;
2617*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats mock_stats = stats_proxy_->GetStats();
2618*d9f75844SAndroid Build Coastguard Worker mock_stats.input_frame_rate = fps;
2619*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(mock_stats);
2620*d9f75844SAndroid Build Coastguard Worker
2621*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(t, kWidth, kHeight));
2622*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(t);
2623*d9f75844SAndroid Build Coastguard Worker t += frame_interval_ms;
2624*d9f75844SAndroid Build Coastguard Worker
2625*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
2626*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(
2627*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants(),
2628*d9f75844SAndroid Build Coastguard Worker FpsInRangeForPixelsInBalanced(*video_source_.last_sent_width() *
2629*d9f75844SAndroid Build Coastguard Worker *video_source_.last_sent_height()));
2630*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(video_source_.sink_wants().max_pixel_count >
2631*d9f75844SAndroid Build Coastguard Worker last_wants.max_pixel_count ||
2632*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants().max_framerate_fps >
2633*d9f75844SAndroid Build Coastguard Worker last_wants.max_framerate_fps);
2634*d9f75844SAndroid Build Coastguard Worker }
2635*d9f75844SAndroid Build Coastguard Worker
2636*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(), FpsMaxResolutionMax());
2637*d9f75844SAndroid Build Coastguard Worker stats_proxy_->ResetMockStats();
2638*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2639*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
2640*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ((loop_count - 1) * 2,
2641*d9f75844SAndroid Build Coastguard Worker stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2642*d9f75844SAndroid Build Coastguard Worker
2643*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2644*d9f75844SAndroid Build Coastguard Worker }
2645*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SinkWantsNotChangedByResourceLimitedBeforeDegradationPreferenceChange)2646*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
2647*d9f75844SAndroid Build Coastguard Worker SinkWantsNotChangedByResourceLimitedBeforeDegradationPreferenceChange) {
2648*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdated(kTargetBitrate, kTargetBitrate,
2649*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, 0, 0, 0);
2650*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(), UnlimitedSinkWants());
2651*d9f75844SAndroid Build Coastguard Worker
2652*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
2653*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
2654*d9f75844SAndroid Build Coastguard Worker
2655*d9f75844SAndroid Build Coastguard Worker int64_t ntp_time = kFrameIntervalMs;
2656*d9f75844SAndroid Build Coastguard Worker
2657*d9f75844SAndroid Build Coastguard Worker // Force an input frame rate to be available, or the adaptation call won't
2658*d9f75844SAndroid Build Coastguard Worker // know what framerate to adapt form.
2659*d9f75844SAndroid Build Coastguard Worker const int kInputFps = 30;
2660*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
2661*d9f75844SAndroid Build Coastguard Worker stats.input_frame_rate = kInputFps;
2662*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(stats);
2663*d9f75844SAndroid Build Coastguard Worker
2664*d9f75844SAndroid Build Coastguard Worker video_source_.set_adaptation_enabled(true);
2665*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
2666*d9f75844SAndroid Build Coastguard Worker &video_source_, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
2667*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(), UnlimitedSinkWants());
2668*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2669*d9f75844SAndroid Build Coastguard Worker CreateFrame(ntp_time, kFrameWidth, kFrameHeight));
2670*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(ntp_time);
2671*d9f75844SAndroid Build Coastguard Worker ntp_time += kFrameIntervalMs;
2672*d9f75844SAndroid Build Coastguard Worker
2673*d9f75844SAndroid Build Coastguard Worker // Trigger CPU overuse.
2674*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
2675*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2676*d9f75844SAndroid Build Coastguard Worker CreateFrame(ntp_time, kFrameWidth, kFrameHeight));
2677*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(ntp_time);
2678*d9f75844SAndroid Build Coastguard Worker ntp_time += kFrameIntervalMs;
2679*d9f75844SAndroid Build Coastguard Worker
2680*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
2681*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(std::numeric_limits<int>::max(),
2682*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants().max_pixel_count);
2683*d9f75844SAndroid Build Coastguard Worker // Some framerate constraint should be set.
2684*d9f75844SAndroid Build Coastguard Worker int restricted_fps = video_source_.sink_wants().max_framerate_fps;
2685*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(restricted_fps, kInputFps);
2686*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2687*d9f75844SAndroid Build Coastguard Worker CreateFrame(ntp_time, kFrameWidth, kFrameHeight));
2688*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(ntp_time);
2689*d9f75844SAndroid Build Coastguard Worker ntp_time += 100;
2690*d9f75844SAndroid Build Coastguard Worker
2691*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSourceAndWaitForRestrictionsUpdated(
2692*d9f75844SAndroid Build Coastguard Worker &video_source_, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
2693*d9f75844SAndroid Build Coastguard Worker // Give the encoder queue time to process the change in degradation preference
2694*d9f75844SAndroid Build Coastguard Worker // by waiting for an encoded frame.
2695*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2696*d9f75844SAndroid Build Coastguard Worker CreateFrame(ntp_time, kFrameWidth, kFrameHeight));
2697*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(ntp_time);
2698*d9f75844SAndroid Build Coastguard Worker ntp_time += kFrameIntervalMs;
2699*d9f75844SAndroid Build Coastguard Worker
2700*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
2701*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2702*d9f75844SAndroid Build Coastguard Worker CreateFrame(ntp_time, kFrameWidth, kFrameHeight));
2703*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(ntp_time);
2704*d9f75844SAndroid Build Coastguard Worker ntp_time += kFrameIntervalMs;
2705*d9f75844SAndroid Build Coastguard Worker
2706*d9f75844SAndroid Build Coastguard Worker // Some resolution constraint should be set.
2707*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
2708*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(video_source_.sink_wants().max_pixel_count,
2709*d9f75844SAndroid Build Coastguard Worker kFrameWidth * kFrameHeight);
2710*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_source_.sink_wants().max_framerate_fps, kInputFps);
2711*d9f75844SAndroid Build Coastguard Worker
2712*d9f75844SAndroid Build Coastguard Worker int pixel_count = video_source_.sink_wants().max_pixel_count;
2713*d9f75844SAndroid Build Coastguard Worker // Triggering a CPU underuse should not change the sink wants since it has
2714*d9f75844SAndroid Build Coastguard Worker // not been overused for resolution since we changed degradation preference.
2715*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
2716*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2717*d9f75844SAndroid Build Coastguard Worker CreateFrame(ntp_time, kFrameWidth, kFrameHeight));
2718*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(ntp_time);
2719*d9f75844SAndroid Build Coastguard Worker ntp_time += kFrameIntervalMs;
2720*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_source_.sink_wants().max_pixel_count, pixel_count);
2721*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_source_.sink_wants().max_framerate_fps, kInputFps);
2722*d9f75844SAndroid Build Coastguard Worker
2723*d9f75844SAndroid Build Coastguard Worker // Change the degradation preference back. CPU underuse should not adapt since
2724*d9f75844SAndroid Build Coastguard Worker // QP is most limited.
2725*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSourceAndWaitForRestrictionsUpdated(
2726*d9f75844SAndroid Build Coastguard Worker &video_source_, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
2727*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2728*d9f75844SAndroid Build Coastguard Worker CreateFrame(ntp_time, kFrameWidth, kFrameHeight));
2729*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(ntp_time);
2730*d9f75844SAndroid Build Coastguard Worker ntp_time += 100;
2731*d9f75844SAndroid Build Coastguard Worker // Resolution adaptations is gone after changing degradation preference.
2732*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
2733*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(std::numeric_limits<int>::max(),
2734*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants().max_pixel_count);
2735*d9f75844SAndroid Build Coastguard Worker // The fps adaptation from above is now back.
2736*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_source_.sink_wants().max_framerate_fps, restricted_fps);
2737*d9f75844SAndroid Build Coastguard Worker
2738*d9f75844SAndroid Build Coastguard Worker // Trigger CPU underuse.
2739*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
2740*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2741*d9f75844SAndroid Build Coastguard Worker CreateFrame(ntp_time, kFrameWidth, kFrameHeight));
2742*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(ntp_time);
2743*d9f75844SAndroid Build Coastguard Worker ntp_time += kFrameIntervalMs;
2744*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_source_.sink_wants().max_framerate_fps, restricted_fps);
2745*d9f75844SAndroid Build Coastguard Worker
2746*d9f75844SAndroid Build Coastguard Worker // Trigger QP underuse, fps should return to normal.
2747*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
2748*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2749*d9f75844SAndroid Build Coastguard Worker CreateFrame(ntp_time, kFrameWidth, kFrameHeight));
2750*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(ntp_time);
2751*d9f75844SAndroid Build Coastguard Worker ntp_time += kFrameIntervalMs;
2752*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(), FpsMax());
2753*d9f75844SAndroid Build Coastguard Worker
2754*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2755*d9f75844SAndroid Build Coastguard Worker }
2756*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SinkWantsStoredByDegradationPreference)2757*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, SinkWantsStoredByDegradationPreference) {
2758*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
2759*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
2760*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(), UnlimitedSinkWants());
2761*d9f75844SAndroid Build Coastguard Worker
2762*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
2763*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
2764*d9f75844SAndroid Build Coastguard Worker
2765*d9f75844SAndroid Build Coastguard Worker int64_t frame_timestamp = 1;
2766*d9f75844SAndroid Build Coastguard Worker
2767*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2768*d9f75844SAndroid Build Coastguard Worker CreateFrame(frame_timestamp, kFrameWidth, kFrameHeight));
2769*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(frame_timestamp);
2770*d9f75844SAndroid Build Coastguard Worker frame_timestamp += kFrameIntervalMs;
2771*d9f75844SAndroid Build Coastguard Worker
2772*d9f75844SAndroid Build Coastguard Worker // Trigger CPU overuse.
2773*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
2774*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
2775*d9f75844SAndroid Build Coastguard Worker CreateFrame(frame_timestamp, kFrameWidth, kFrameHeight));
2776*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(frame_timestamp);
2777*d9f75844SAndroid Build Coastguard Worker frame_timestamp += kFrameIntervalMs;
2778*d9f75844SAndroid Build Coastguard Worker
2779*d9f75844SAndroid Build Coastguard Worker // Default degradation preference is maintain-framerate, so will lower max
2780*d9f75844SAndroid Build Coastguard Worker // wanted resolution.
2781*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
2782*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(video_source_.sink_wants().max_pixel_count,
2783*d9f75844SAndroid Build Coastguard Worker kFrameWidth * kFrameHeight);
2784*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kDefaultFramerate, video_source_.sink_wants().max_framerate_fps);
2785*d9f75844SAndroid Build Coastguard Worker
2786*d9f75844SAndroid Build Coastguard Worker // Set new source, switch to maintain-resolution.
2787*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder new_video_source;
2788*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSourceAndWaitForRestrictionsUpdated(
2789*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
2790*d9f75844SAndroid Build Coastguard Worker // Give the encoder queue time to process the change in degradation preference
2791*d9f75844SAndroid Build Coastguard Worker // by waiting for an encoded frame.
2792*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(
2793*d9f75844SAndroid Build Coastguard Worker CreateFrame(frame_timestamp, kFrameWidth, kFrameWidth));
2794*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(frame_timestamp);
2795*d9f75844SAndroid Build Coastguard Worker frame_timestamp += kFrameIntervalMs;
2796*d9f75844SAndroid Build Coastguard Worker // Initially no degradation registered.
2797*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(new_video_source.sink_wants(), FpsMaxResolutionMax());
2798*d9f75844SAndroid Build Coastguard Worker
2799*d9f75844SAndroid Build Coastguard Worker // Force an input frame rate to be available, or the adaptation call won't
2800*d9f75844SAndroid Build Coastguard Worker // know what framerate to adapt form.
2801*d9f75844SAndroid Build Coastguard Worker const int kInputFps = 30;
2802*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
2803*d9f75844SAndroid Build Coastguard Worker stats.input_frame_rate = kInputFps;
2804*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(stats);
2805*d9f75844SAndroid Build Coastguard Worker
2806*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
2807*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(
2808*d9f75844SAndroid Build Coastguard Worker CreateFrame(frame_timestamp, kFrameWidth, kFrameHeight));
2809*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(frame_timestamp);
2810*d9f75844SAndroid Build Coastguard Worker frame_timestamp += kFrameIntervalMs;
2811*d9f75844SAndroid Build Coastguard Worker
2812*d9f75844SAndroid Build Coastguard Worker // Some framerate constraint should be set.
2813*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
2814*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(std::numeric_limits<int>::max(),
2815*d9f75844SAndroid Build Coastguard Worker new_video_source.sink_wants().max_pixel_count);
2816*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(new_video_source.sink_wants().max_framerate_fps, kInputFps);
2817*d9f75844SAndroid Build Coastguard Worker
2818*d9f75844SAndroid Build Coastguard Worker // Turn off degradation completely.
2819*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSourceAndWaitForRestrictionsUpdated(
2820*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::DISABLED);
2821*d9f75844SAndroid Build Coastguard Worker // Give the encoder queue time to process the change in degradation preference
2822*d9f75844SAndroid Build Coastguard Worker // by waiting for an encoded frame.
2823*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(
2824*d9f75844SAndroid Build Coastguard Worker CreateFrame(frame_timestamp, kFrameWidth, kFrameWidth));
2825*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(frame_timestamp);
2826*d9f75844SAndroid Build Coastguard Worker frame_timestamp += kFrameIntervalMs;
2827*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(new_video_source.sink_wants(), FpsMaxResolutionMax());
2828*d9f75844SAndroid Build Coastguard Worker
2829*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
2830*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(
2831*d9f75844SAndroid Build Coastguard Worker CreateFrame(frame_timestamp, kFrameWidth, kFrameHeight));
2832*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(frame_timestamp);
2833*d9f75844SAndroid Build Coastguard Worker frame_timestamp += kFrameIntervalMs;
2834*d9f75844SAndroid Build Coastguard Worker
2835*d9f75844SAndroid Build Coastguard Worker // Still no degradation.
2836*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(new_video_source.sink_wants(), FpsMaxResolutionMax());
2837*d9f75844SAndroid Build Coastguard Worker
2838*d9f75844SAndroid Build Coastguard Worker // Calling SetSource with resolution scaling enabled apply the old SinkWants.
2839*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSourceAndWaitForRestrictionsUpdated(
2840*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
2841*d9f75844SAndroid Build Coastguard Worker // Give the encoder queue time to process the change in degradation preference
2842*d9f75844SAndroid Build Coastguard Worker // by waiting for an encoded frame.
2843*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(
2844*d9f75844SAndroid Build Coastguard Worker CreateFrame(frame_timestamp, kFrameWidth, kFrameWidth));
2845*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(frame_timestamp);
2846*d9f75844SAndroid Build Coastguard Worker frame_timestamp += kFrameIntervalMs;
2847*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(new_video_source.sink_wants().max_pixel_count,
2848*d9f75844SAndroid Build Coastguard Worker kFrameWidth * kFrameHeight);
2849*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
2850*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kDefaultFramerate, new_video_source.sink_wants().max_framerate_fps);
2851*d9f75844SAndroid Build Coastguard Worker
2852*d9f75844SAndroid Build Coastguard Worker // Calling SetSource with framerate scaling enabled apply the old SinkWants.
2853*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSourceAndWaitForRestrictionsUpdated(
2854*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
2855*d9f75844SAndroid Build Coastguard Worker // Give the encoder queue time to process the change in degradation preference
2856*d9f75844SAndroid Build Coastguard Worker // by waiting for an encoded frame.
2857*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(
2858*d9f75844SAndroid Build Coastguard Worker CreateFrame(frame_timestamp, kFrameWidth, kFrameWidth));
2859*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(frame_timestamp);
2860*d9f75844SAndroid Build Coastguard Worker frame_timestamp += kFrameIntervalMs;
2861*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
2862*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(std::numeric_limits<int>::max(),
2863*d9f75844SAndroid Build Coastguard Worker new_video_source.sink_wants().max_pixel_count);
2864*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(new_video_source.sink_wants().max_framerate_fps, kInputFps);
2865*d9f75844SAndroid Build Coastguard Worker
2866*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2867*d9f75844SAndroid Build Coastguard Worker }
2868*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,StatsTracksQualityAdaptationStats)2869*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, StatsTracksQualityAdaptationStats) {
2870*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
2871*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
2872*d9f75844SAndroid Build Coastguard Worker
2873*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
2874*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
2875*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
2876*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
2877*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
2878*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_resolution);
2879*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
2880*d9f75844SAndroid Build Coastguard Worker
2881*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down.
2882*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
2883*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
2884*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
2885*d9f75844SAndroid Build Coastguard Worker
2886*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
2887*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats.bw_limited_resolution);
2888*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_quality_adapt_changes);
2889*d9f75844SAndroid Build Coastguard Worker
2890*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up.
2891*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
2892*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
2893*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
2894*d9f75844SAndroid Build Coastguard Worker
2895*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
2896*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_resolution);
2897*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats.number_of_quality_adapt_changes);
2898*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
2899*d9f75844SAndroid Build Coastguard Worker
2900*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2901*d9f75844SAndroid Build Coastguard Worker }
2902*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,StatsTracksCpuAdaptationStats)2903*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, StatsTracksCpuAdaptationStats) {
2904*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
2905*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
2906*d9f75844SAndroid Build Coastguard Worker
2907*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
2908*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
2909*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
2910*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
2911*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
2912*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
2913*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
2914*d9f75844SAndroid Build Coastguard Worker
2915*d9f75844SAndroid Build Coastguard Worker // Trigger CPU overuse.
2916*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
2917*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
2918*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
2919*d9f75844SAndroid Build Coastguard Worker
2920*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
2921*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats.cpu_limited_resolution);
2922*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
2923*d9f75844SAndroid Build Coastguard Worker
2924*d9f75844SAndroid Build Coastguard Worker // Trigger CPU normal use.
2925*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
2926*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
2927*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
2928*d9f75844SAndroid Build Coastguard Worker
2929*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
2930*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
2931*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
2932*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
2933*d9f75844SAndroid Build Coastguard Worker
2934*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
2935*d9f75844SAndroid Build Coastguard Worker }
2936*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SwitchingSourceKeepsCpuAdaptation)2937*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
2938*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
2939*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
2940*d9f75844SAndroid Build Coastguard Worker
2941*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
2942*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
2943*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
2944*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
2945*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
2946*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_resolution);
2947*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
2948*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
2949*d9f75844SAndroid Build Coastguard Worker
2950*d9f75844SAndroid Build Coastguard Worker // Trigger CPU overuse.
2951*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
2952*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
2953*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
2954*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
2955*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_resolution);
2956*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats.cpu_limited_resolution);
2957*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
2958*d9f75844SAndroid Build Coastguard Worker
2959*d9f75844SAndroid Build Coastguard Worker // Set new source with adaptation still enabled.
2960*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder new_video_source;
2961*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
2962*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
2963*d9f75844SAndroid Build Coastguard Worker
2964*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
2965*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
2966*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
2967*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_resolution);
2968*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats.cpu_limited_resolution);
2969*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
2970*d9f75844SAndroid Build Coastguard Worker
2971*d9f75844SAndroid Build Coastguard Worker // Set adaptation disabled.
2972*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&new_video_source,
2973*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::DISABLED);
2974*d9f75844SAndroid Build Coastguard Worker
2975*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
2976*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(4);
2977*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
2978*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_resolution);
2979*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
2980*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
2981*d9f75844SAndroid Build Coastguard Worker
2982*d9f75844SAndroid Build Coastguard Worker // Set adaptation back to enabled.
2983*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
2984*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
2985*d9f75844SAndroid Build Coastguard Worker
2986*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight));
2987*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(5);
2988*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
2989*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_resolution);
2990*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats.cpu_limited_resolution);
2991*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
2992*d9f75844SAndroid Build Coastguard Worker
2993*d9f75844SAndroid Build Coastguard Worker // Trigger CPU normal use.
2994*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
2995*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(CreateFrame(6, kWidth, kHeight));
2996*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(6);
2997*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
2998*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_resolution);
2999*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
3000*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
3001*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
3002*d9f75844SAndroid Build Coastguard Worker
3003*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3004*d9f75844SAndroid Build Coastguard Worker }
3005*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SwitchingSourceKeepsQualityAdaptation)3006*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, SwitchingSourceKeepsQualityAdaptation) {
3007*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3008*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3009*d9f75844SAndroid Build Coastguard Worker
3010*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3011*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3012*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
3013*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
3014*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
3015*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_resolution);
3016*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_framerate);
3017*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
3018*d9f75844SAndroid Build Coastguard Worker
3019*d9f75844SAndroid Build Coastguard Worker // Set new source with adaptation still enabled.
3020*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder new_video_source;
3021*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&new_video_source,
3022*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
3023*d9f75844SAndroid Build Coastguard Worker
3024*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
3025*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
3026*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3027*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_resolution);
3028*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_framerate);
3029*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
3030*d9f75844SAndroid Build Coastguard Worker
3031*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down.
3032*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3033*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
3034*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
3035*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3036*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats.bw_limited_resolution);
3037*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_framerate);
3038*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_quality_adapt_changes);
3039*d9f75844SAndroid Build Coastguard Worker
3040*d9f75844SAndroid Build Coastguard Worker // Set new source with adaptation still enabled.
3041*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&new_video_source,
3042*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
3043*d9f75844SAndroid Build Coastguard Worker
3044*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
3045*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(4);
3046*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3047*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats.bw_limited_resolution);
3048*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_framerate);
3049*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_quality_adapt_changes);
3050*d9f75844SAndroid Build Coastguard Worker
3051*d9f75844SAndroid Build Coastguard Worker // Disable resolution scaling.
3052*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
3053*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
3054*d9f75844SAndroid Build Coastguard Worker
3055*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight));
3056*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(5);
3057*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3058*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_resolution);
3059*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.bw_limited_framerate);
3060*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_quality_adapt_changes);
3061*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
3062*d9f75844SAndroid Build Coastguard Worker
3063*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3064*d9f75844SAndroid Build Coastguard Worker }
3065*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QualityAdaptationStatsAreResetWhenScalerIsDisabled)3066*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3067*d9f75844SAndroid Build Coastguard Worker QualityAdaptationStatsAreResetWhenScalerIsDisabled) {
3068*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3069*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3070*d9f75844SAndroid Build Coastguard Worker
3071*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3072*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3073*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
3074*d9f75844SAndroid Build Coastguard Worker video_source_.set_adaptation_enabled(true);
3075*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
3076*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kWidth, kHeight));
3077*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3078*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
3079*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3080*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3081*d9f75844SAndroid Build Coastguard Worker
3082*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down.
3083*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3084*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3085*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
3086*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kWidth, kHeight));
3087*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3088*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
3089*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3090*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3091*d9f75844SAndroid Build Coastguard Worker
3092*d9f75844SAndroid Build Coastguard Worker // Trigger overuse.
3093*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
3094*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3095*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
3096*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kWidth, kHeight));
3097*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3098*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
3099*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3100*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3101*d9f75844SAndroid Build Coastguard Worker
3102*d9f75844SAndroid Build Coastguard Worker // Leave source unchanged, but disable quality scaler.
3103*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
3104*d9f75844SAndroid Build Coastguard Worker
3105*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
3106*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
3107*d9f75844SAndroid Build Coastguard Worker // Make format different, to force recreation of encoder.
3108*d9f75844SAndroid Build Coastguard Worker video_encoder_config.video_format.parameters["foo"] = "foo";
3109*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
3110*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
3111*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3112*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
3113*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kWidth, kHeight));
3114*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3115*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
3116*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3117*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3118*d9f75844SAndroid Build Coastguard Worker
3119*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3120*d9f75844SAndroid Build Coastguard Worker }
3121*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,StatsTracksCpuAdaptationStatsWhenSwitchingSource_Balanced)3122*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3123*d9f75844SAndroid Build Coastguard Worker StatsTracksCpuAdaptationStatsWhenSwitchingSource_Balanced) {
3124*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3125*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3126*d9f75844SAndroid Build Coastguard Worker
3127*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3128*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3129*d9f75844SAndroid Build Coastguard Worker int sequence = 1;
3130*d9f75844SAndroid Build Coastguard Worker
3131*d9f75844SAndroid Build Coastguard Worker // Enable BALANCED preference, no initial limitation.
3132*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
3133*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
3134*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
3135*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
3136*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3137*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
3138*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
3139*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_framerate);
3140*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
3141*d9f75844SAndroid Build Coastguard Worker
3142*d9f75844SAndroid Build Coastguard Worker // Trigger CPU overuse, should now adapt down.
3143*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
3144*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
3145*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3146*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3147*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
3148*d9f75844SAndroid Build Coastguard Worker
3149*d9f75844SAndroid Build Coastguard Worker // Set new degradation preference should clear restrictions since we changed
3150*d9f75844SAndroid Build Coastguard Worker // from BALANCED.
3151*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSourceAndWaitForRestrictionsUpdated(
3152*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
3153*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
3154*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3155*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3156*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
3157*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_framerate);
3158*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
3159*d9f75844SAndroid Build Coastguard Worker
3160*d9f75844SAndroid Build Coastguard Worker // Force an input frame rate to be available, or the adaptation call won't
3161*d9f75844SAndroid Build Coastguard Worker // know what framerate to adapt from.
3162*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats mock_stats = stats_proxy_->GetStats();
3163*d9f75844SAndroid Build Coastguard Worker mock_stats.input_frame_rate = 30;
3164*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(mock_stats);
3165*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
3166*d9f75844SAndroid Build Coastguard Worker stats_proxy_->ResetMockStats();
3167*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
3168*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3169*d9f75844SAndroid Build Coastguard Worker
3170*d9f75844SAndroid Build Coastguard Worker // We have now adapted once.
3171*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3172*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
3173*d9f75844SAndroid Build Coastguard Worker
3174*d9f75844SAndroid Build Coastguard Worker // Back to BALANCED, should clear the restrictions again.
3175*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSourceAndWaitForRestrictionsUpdated(
3176*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::BALANCED);
3177*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
3178*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3179*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3180*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
3181*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_framerate);
3182*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
3183*d9f75844SAndroid Build Coastguard Worker
3184*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3185*d9f75844SAndroid Build Coastguard Worker }
3186*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,StatsTracksCpuAdaptationStatsWhenSwitchingSource)3187*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3188*d9f75844SAndroid Build Coastguard Worker StatsTracksCpuAdaptationStatsWhenSwitchingSource) {
3189*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3190*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3191*d9f75844SAndroid Build Coastguard Worker
3192*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3193*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3194*d9f75844SAndroid Build Coastguard Worker int sequence = 1;
3195*d9f75844SAndroid Build Coastguard Worker
3196*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
3197*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3198*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
3199*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
3200*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_framerate);
3201*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
3202*d9f75844SAndroid Build Coastguard Worker
3203*d9f75844SAndroid Build Coastguard Worker // Trigger CPU overuse, should now adapt down.
3204*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
3205*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
3206*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3207*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3208*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats.cpu_limited_resolution);
3209*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_framerate);
3210*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
3211*d9f75844SAndroid Build Coastguard Worker
3212*d9f75844SAndroid Build Coastguard Worker // Set new source with adaptation still enabled.
3213*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder new_video_source;
3214*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
3215*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
3216*d9f75844SAndroid Build Coastguard Worker
3217*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(
3218*d9f75844SAndroid Build Coastguard Worker CreateFrame(sequence, kWidth, kHeight));
3219*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3220*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3221*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats.cpu_limited_resolution);
3222*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_framerate);
3223*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
3224*d9f75844SAndroid Build Coastguard Worker
3225*d9f75844SAndroid Build Coastguard Worker // Set cpu adaptation by frame dropping.
3226*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
3227*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
3228*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(
3229*d9f75844SAndroid Build Coastguard Worker CreateFrame(sequence, kWidth, kHeight));
3230*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3231*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3232*d9f75844SAndroid Build Coastguard Worker // Not adapted at first.
3233*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
3234*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_framerate);
3235*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
3236*d9f75844SAndroid Build Coastguard Worker
3237*d9f75844SAndroid Build Coastguard Worker // Force an input frame rate to be available, or the adaptation call won't
3238*d9f75844SAndroid Build Coastguard Worker // know what framerate to adapt from.
3239*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats mock_stats = stats_proxy_->GetStats();
3240*d9f75844SAndroid Build Coastguard Worker mock_stats.input_frame_rate = 30;
3241*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(mock_stats);
3242*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
3243*d9f75844SAndroid Build Coastguard Worker stats_proxy_->ResetMockStats();
3244*d9f75844SAndroid Build Coastguard Worker
3245*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(
3246*d9f75844SAndroid Build Coastguard Worker CreateFrame(sequence, kWidth, kHeight));
3247*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3248*d9f75844SAndroid Build Coastguard Worker
3249*d9f75844SAndroid Build Coastguard Worker // Framerate now adapted.
3250*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3251*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
3252*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats.cpu_limited_framerate);
3253*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
3254*d9f75844SAndroid Build Coastguard Worker
3255*d9f75844SAndroid Build Coastguard Worker // Disable CPU adaptation.
3256*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&new_video_source,
3257*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::DISABLED);
3258*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(
3259*d9f75844SAndroid Build Coastguard Worker CreateFrame(sequence, kWidth, kHeight));
3260*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3261*d9f75844SAndroid Build Coastguard Worker
3262*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3263*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
3264*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_framerate);
3265*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
3266*d9f75844SAndroid Build Coastguard Worker
3267*d9f75844SAndroid Build Coastguard Worker // Try to trigger overuse. Should not succeed.
3268*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(mock_stats);
3269*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
3270*d9f75844SAndroid Build Coastguard Worker stats_proxy_->ResetMockStats();
3271*d9f75844SAndroid Build Coastguard Worker
3272*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3273*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
3274*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_framerate);
3275*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
3276*d9f75844SAndroid Build Coastguard Worker
3277*d9f75844SAndroid Build Coastguard Worker // Switch back the source with resolution adaptation enabled.
3278*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
3279*d9f75844SAndroid Build Coastguard Worker &video_source_, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
3280*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
3281*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3282*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3283*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats.cpu_limited_resolution);
3284*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_framerate);
3285*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
3286*d9f75844SAndroid Build Coastguard Worker
3287*d9f75844SAndroid Build Coastguard Worker // Trigger CPU normal usage.
3288*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
3289*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
3290*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3291*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3292*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
3293*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_framerate);
3294*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats.number_of_cpu_adapt_changes);
3295*d9f75844SAndroid Build Coastguard Worker
3296*d9f75844SAndroid Build Coastguard Worker // Back to the source with adaptation off, set it back to maintain-resolution.
3297*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
3298*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
3299*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(
3300*d9f75844SAndroid Build Coastguard Worker CreateFrame(sequence, kWidth, kHeight));
3301*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3302*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3303*d9f75844SAndroid Build Coastguard Worker // Disabled, since we previously switched the source to disabled.
3304*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
3305*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats.cpu_limited_framerate);
3306*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats.number_of_cpu_adapt_changes);
3307*d9f75844SAndroid Build Coastguard Worker
3308*d9f75844SAndroid Build Coastguard Worker // Trigger CPU normal usage.
3309*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
3310*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(
3311*d9f75844SAndroid Build Coastguard Worker CreateFrame(sequence, kWidth, kHeight));
3312*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(sequence++);
3313*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
3314*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_resolution);
3315*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats.cpu_limited_framerate);
3316*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats.number_of_cpu_adapt_changes);
3317*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
3318*d9f75844SAndroid Build Coastguard Worker
3319*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3320*d9f75844SAndroid Build Coastguard Worker }
3321*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ScalingUpAndDownDoesNothingWithMaintainResolution)3322*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3323*d9f75844SAndroid Build Coastguard Worker ScalingUpAndDownDoesNothingWithMaintainResolution) {
3324*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3325*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3326*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3327*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3328*d9f75844SAndroid Build Coastguard Worker
3329*d9f75844SAndroid Build Coastguard Worker // Expect no scaling to begin with.
3330*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(), UnlimitedSinkWants());
3331*d9f75844SAndroid Build Coastguard Worker
3332*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
3333*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
3334*d9f75844SAndroid Build Coastguard Worker
3335*d9f75844SAndroid Build Coastguard Worker // Trigger scale down.
3336*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3337*d9f75844SAndroid Build Coastguard Worker
3338*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
3339*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
3340*d9f75844SAndroid Build Coastguard Worker
3341*d9f75844SAndroid Build Coastguard Worker // Expect a scale down.
3342*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
3343*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(video_source_.sink_wants().max_pixel_count, kWidth * kHeight);
3344*d9f75844SAndroid Build Coastguard Worker
3345*d9f75844SAndroid Build Coastguard Worker // Set resolution scaling disabled.
3346*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder new_video_source;
3347*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
3348*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
3349*d9f75844SAndroid Build Coastguard Worker
3350*d9f75844SAndroid Build Coastguard Worker // Trigger scale down.
3351*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3352*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
3353*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
3354*d9f75844SAndroid Build Coastguard Worker
3355*d9f75844SAndroid Build Coastguard Worker // Expect no scaling.
3356*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(std::numeric_limits<int>::max(),
3357*d9f75844SAndroid Build Coastguard Worker new_video_source.sink_wants().max_pixel_count);
3358*d9f75844SAndroid Build Coastguard Worker
3359*d9f75844SAndroid Build Coastguard Worker // Trigger scale up.
3360*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
3361*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
3362*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(4);
3363*d9f75844SAndroid Build Coastguard Worker
3364*d9f75844SAndroid Build Coastguard Worker // Expect nothing to change, still no scaling.
3365*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(std::numeric_limits<int>::max(),
3366*d9f75844SAndroid Build Coastguard Worker new_video_source.sink_wants().max_pixel_count);
3367*d9f75844SAndroid Build Coastguard Worker
3368*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3369*d9f75844SAndroid Build Coastguard Worker }
3370*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SkipsSameAdaptDownRequest_MaintainFramerateMode)3371*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3372*d9f75844SAndroid Build Coastguard Worker SkipsSameAdaptDownRequest_MaintainFramerateMode) {
3373*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3374*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3375*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3376*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3377*d9f75844SAndroid Build Coastguard Worker
3378*d9f75844SAndroid Build Coastguard Worker // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
3379*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
3380*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
3381*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
3382*d9f75844SAndroid Build Coastguard Worker
3383*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
3384*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
3385*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3386*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
3387*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3388*d9f75844SAndroid Build Coastguard Worker
3389*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution.
3390*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
3391*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(),
3392*d9f75844SAndroid Build Coastguard Worker FpsMaxResolutionMatches(Lt(kWidth * kHeight)));
3393*d9f75844SAndroid Build Coastguard Worker const int kLastMaxPixelCount = source.sink_wants().max_pixel_count;
3394*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
3395*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3396*d9f75844SAndroid Build Coastguard Worker
3397*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down for same input resolution, expect no change.
3398*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
3399*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kLastMaxPixelCount, source.sink_wants().max_pixel_count);
3400*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
3401*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3402*d9f75844SAndroid Build Coastguard Worker
3403*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3404*d9f75844SAndroid Build Coastguard Worker }
3405*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SkipsSameOrLargerAdaptDownRequest_BalancedMode)3406*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, SkipsSameOrLargerAdaptDownRequest_BalancedMode) {
3407*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3408*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3409*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3410*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3411*d9f75844SAndroid Build Coastguard Worker
3412*d9f75844SAndroid Build Coastguard Worker // Enable BALANCED preference, no initial limitation.
3413*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
3414*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
3415*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
3416*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
3417*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(1);
3418*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3419*d9f75844SAndroid Build Coastguard Worker
3420*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution.
3421*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3422*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(),
3423*d9f75844SAndroid Build Coastguard Worker FpsMaxResolutionMatches(Lt(kWidth * kHeight)));
3424*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3425*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3426*d9f75844SAndroid Build Coastguard Worker const int kLastMaxPixelCount = source.sink_wants().max_pixel_count;
3427*d9f75844SAndroid Build Coastguard Worker
3428*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down for same input resolution, expect no change.
3429*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
3430*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(2);
3431*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3432*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kLastMaxPixelCount, source.sink_wants().max_pixel_count);
3433*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3434*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3435*d9f75844SAndroid Build Coastguard Worker
3436*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down for larger input resolution, expect no change.
3437*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(3, kWidth + 1, kHeight + 1));
3438*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(3);
3439*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3440*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kLastMaxPixelCount, source.sink_wants().max_pixel_count);
3441*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3442*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3443*d9f75844SAndroid Build Coastguard Worker
3444*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3445*d9f75844SAndroid Build Coastguard Worker }
3446*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,FpsCountReturnsToZeroForFewerAdaptationsUpThanDown)3447*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3448*d9f75844SAndroid Build Coastguard Worker FpsCountReturnsToZeroForFewerAdaptationsUpThanDown) {
3449*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
3450*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
3451*d9f75844SAndroid Build Coastguard Worker const int64_t kFrameIntervalMs = 150;
3452*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3453*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3454*d9f75844SAndroid Build Coastguard Worker
3455*d9f75844SAndroid Build Coastguard Worker // Enable BALANCED preference, no initial limitation.
3456*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
3457*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
3458*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
3459*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
3460*d9f75844SAndroid Build Coastguard Worker
3461*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
3462*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3463*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(kWidth, kHeight);
3464*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3465*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3466*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
3467*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3468*d9f75844SAndroid Build Coastguard Worker
3469*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect reduced fps (640x360@15fps).
3470*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3471*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3472*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3473*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(timestamp_ms);
3474*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(),
3475*d9f75844SAndroid Build Coastguard Worker FpsMatchesResolutionMax(Lt(kDefaultFramerate)));
3476*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3477*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
3478*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3479*d9f75844SAndroid Build Coastguard Worker
3480*d9f75844SAndroid Build Coastguard Worker // Source requests 270p, expect reduced resolution (480x270@15fps).
3481*d9f75844SAndroid Build Coastguard Worker source.OnOutputFormatRequest(480, 270);
3482*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3483*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3484*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(480, 270);
3485*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3486*d9f75844SAndroid Build Coastguard Worker
3487*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect reduced fps (480x270@10fps).
3488*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3489*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3490*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3491*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(timestamp_ms);
3492*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsLtResolutionEq(source.last_wants()));
3493*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3494*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
3495*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3496*d9f75844SAndroid Build Coastguard Worker
3497*d9f75844SAndroid Build Coastguard Worker // Source requests QVGA, expect reduced resolution (320x180@10fps).
3498*d9f75844SAndroid Build Coastguard Worker source.OnOutputFormatRequest(320, 180);
3499*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3500*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3501*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(320, 180);
3502*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3503*d9f75844SAndroid Build Coastguard Worker
3504*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect reduced fps (320x180@7fps).
3505*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3506*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3507*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3508*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(timestamp_ms);
3509*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsLtResolutionEq(source.last_wants()));
3510*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3511*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
3512*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3513*d9f75844SAndroid Build Coastguard Worker
3514*d9f75844SAndroid Build Coastguard Worker // Source requests VGA, expect increased resolution (640x360@7fps).
3515*d9f75844SAndroid Build Coastguard Worker source.OnOutputFormatRequest(640, 360);
3516*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3517*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3518*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3519*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3520*d9f75844SAndroid Build Coastguard Worker
3521*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect increased fps (640x360@(max-2)fps).
3522*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
3523*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3524*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3525*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3526*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsGtResolutionEq(source.last_wants()));
3527*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3528*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
3529*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3530*d9f75844SAndroid Build Coastguard Worker
3531*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect increased fps (640x360@(max-1)fps).
3532*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
3533*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3534*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3535*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3536*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsGtResolutionEq(source.last_wants()));
3537*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3538*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
3539*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(5, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3540*d9f75844SAndroid Build Coastguard Worker
3541*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect increased fps (640x360@maxfps).
3542*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
3543*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3544*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3545*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3546*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsGtResolutionEq(source.last_wants()));
3547*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3548*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
3549*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(6, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3550*d9f75844SAndroid Build Coastguard Worker
3551*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3552*d9f75844SAndroid Build Coastguard Worker }
3553*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,FpsCountReturnsToZeroForFewerAdaptationsUpThanDownWithTwoResources)3554*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3555*d9f75844SAndroid Build Coastguard Worker FpsCountReturnsToZeroForFewerAdaptationsUpThanDownWithTwoResources) {
3556*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3557*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3558*d9f75844SAndroid Build Coastguard Worker const int64_t kFrameIntervalMs = 150;
3559*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3560*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3561*d9f75844SAndroid Build Coastguard Worker
3562*d9f75844SAndroid Build Coastguard Worker // Enable BALANCED preference, no initial limitation.
3563*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
3564*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
3565*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
3566*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
3567*d9f75844SAndroid Build Coastguard Worker
3568*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
3569*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3570*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(kWidth, kHeight);
3571*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3572*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3573*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
3574*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3575*d9f75844SAndroid Build Coastguard Worker
3576*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution (960x540@maxfps).
3577*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3578*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3579*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3580*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(timestamp_ms);
3581*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(),
3582*d9f75844SAndroid Build Coastguard Worker FpsMaxResolutionMatches(Lt(kWidth * kHeight)));
3583*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3584*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
3585*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3586*d9f75844SAndroid Build Coastguard Worker
3587*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution (640x360@maxfps).
3588*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3589*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3590*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3591*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(timestamp_ms);
3592*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionLt(source.last_wants()));
3593*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3594*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
3595*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3596*d9f75844SAndroid Build Coastguard Worker
3597*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect reduced fps (640x360@15fps).
3598*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3599*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3600*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3601*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3602*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsLtResolutionEq(source.last_wants()));
3603*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3604*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
3605*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3606*d9f75844SAndroid Build Coastguard Worker
3607*d9f75844SAndroid Build Coastguard Worker // Source requests QVGA, expect reduced resolution (320x180@15fps).
3608*d9f75844SAndroid Build Coastguard Worker source.OnOutputFormatRequest(320, 180);
3609*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3610*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3611*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(320, 180);
3612*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3613*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3614*d9f75844SAndroid Build Coastguard Worker
3615*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect reduced fps (320x180@7fps).
3616*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
3617*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3618*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3619*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3620*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsLtResolutionEq(source.last_wants()));
3621*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3622*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
3623*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
3624*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_framerate);
3625*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3626*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3627*d9f75844SAndroid Build Coastguard Worker
3628*d9f75844SAndroid Build Coastguard Worker // Source requests HD, expect increased resolution (640x360@7fps).
3629*d9f75844SAndroid Build Coastguard Worker source.OnOutputFormatRequest(1280, 720);
3630*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3631*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3632*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3633*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3634*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3635*d9f75844SAndroid Build Coastguard Worker
3636*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect increased fps (640x360@(max-1)fps).
3637*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
3638*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3639*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3640*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3641*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsGtResolutionEq(source.last_wants()));
3642*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3643*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
3644*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
3645*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_framerate);
3646*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3647*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3648*d9f75844SAndroid Build Coastguard Worker
3649*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect increased fps (640x360@maxfps).
3650*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
3651*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
3652*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3653*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3654*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3655*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsGtResolutionEq(source.last_wants()));
3656*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3657*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
3658*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
3659*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
3660*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3661*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3662*d9f75844SAndroid Build Coastguard Worker
3663*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect increased resolution (960x570@maxfps).
3664*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
3665*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
3666*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3667*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3668*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3669*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsEqResolutionGt(source.last_wants()));
3670*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3671*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
3672*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
3673*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
3674*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(5, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3675*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3676*d9f75844SAndroid Build Coastguard Worker
3677*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect increased resolution (1280x720@maxfps).
3678*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
3679*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
3680*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3681*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3682*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3683*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsEqResolutionGt(source.last_wants()));
3684*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3685*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
3686*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
3687*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
3688*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(6, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3689*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(5, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3690*d9f75844SAndroid Build Coastguard Worker
3691*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3692*d9f75844SAndroid Build Coastguard Worker }
3693*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NoChangeForInitialNormalUsage_MaintainFramerateMode)3694*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3695*d9f75844SAndroid Build Coastguard Worker NoChangeForInitialNormalUsage_MaintainFramerateMode) {
3696*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3697*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3698*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3699*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3700*d9f75844SAndroid Build Coastguard Worker
3701*d9f75844SAndroid Build Coastguard Worker // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
3702*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
3703*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
3704*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
3705*d9f75844SAndroid Build Coastguard Worker
3706*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
3707*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kWidth, kHeight);
3708*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3709*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
3710*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3711*d9f75844SAndroid Build Coastguard Worker
3712*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no change.
3713*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
3714*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3715*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
3716*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3717*d9f75844SAndroid Build Coastguard Worker
3718*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3719*d9f75844SAndroid Build Coastguard Worker }
3720*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NoChangeForInitialNormalUsage_MaintainResolutionMode)3721*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3722*d9f75844SAndroid Build Coastguard Worker NoChangeForInitialNormalUsage_MaintainResolutionMode) {
3723*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3724*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3725*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3726*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3727*d9f75844SAndroid Build Coastguard Worker
3728*d9f75844SAndroid Build Coastguard Worker // Enable MAINTAIN_RESOLUTION preference, no initial limitation.
3729*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
3730*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
3731*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
3732*d9f75844SAndroid Build Coastguard Worker
3733*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
3734*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kWidth, kHeight);
3735*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3736*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
3737*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3738*d9f75844SAndroid Build Coastguard Worker
3739*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no change.
3740*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
3741*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3742*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
3743*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3744*d9f75844SAndroid Build Coastguard Worker
3745*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3746*d9f75844SAndroid Build Coastguard Worker }
3747*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NoChangeForInitialNormalUsage_BalancedMode)3748*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, NoChangeForInitialNormalUsage_BalancedMode) {
3749*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3750*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3751*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3752*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3753*d9f75844SAndroid Build Coastguard Worker
3754*d9f75844SAndroid Build Coastguard Worker // Enable BALANCED preference, no initial limitation.
3755*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
3756*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
3757*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
3758*d9f75844SAndroid Build Coastguard Worker
3759*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
3760*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(kWidth, kHeight);
3761*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3762*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3763*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
3764*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3765*d9f75844SAndroid Build Coastguard Worker
3766*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no change.
3767*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
3768*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3769*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3770*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
3771*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3772*d9f75844SAndroid Build Coastguard Worker
3773*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3774*d9f75844SAndroid Build Coastguard Worker }
3775*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NoChangeForInitialNormalUsage_DisabledMode)3776*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, NoChangeForInitialNormalUsage_DisabledMode) {
3777*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3778*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3779*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3780*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3781*d9f75844SAndroid Build Coastguard Worker
3782*d9f75844SAndroid Build Coastguard Worker // Enable DISABLED preference, no initial limitation.
3783*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
3784*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
3785*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::DISABLED);
3786*d9f75844SAndroid Build Coastguard Worker
3787*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
3788*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(kWidth, kHeight);
3789*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3790*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3791*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
3792*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3793*d9f75844SAndroid Build Coastguard Worker
3794*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no change.
3795*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
3796*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3797*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3798*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
3799*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3800*d9f75844SAndroid Build Coastguard Worker
3801*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3802*d9f75844SAndroid Build Coastguard Worker }
3803*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AdaptsResolutionForLowQuality_MaintainFramerateMode)3804*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3805*d9f75844SAndroid Build Coastguard Worker AdaptsResolutionForLowQuality_MaintainFramerateMode) {
3806*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3807*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3808*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3809*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3810*d9f75844SAndroid Build Coastguard Worker
3811*d9f75844SAndroid Build Coastguard Worker // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
3812*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
3813*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
3814*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
3815*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
3816*d9f75844SAndroid Build Coastguard Worker
3817*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
3818*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
3819*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3820*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3821*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3822*d9f75844SAndroid Build Coastguard Worker
3823*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution.
3824*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3825*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
3826*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
3827*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(),
3828*d9f75844SAndroid Build Coastguard Worker FpsMaxResolutionMatches(Lt(kWidth * kHeight)));
3829*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3830*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3831*d9f75844SAndroid Build Coastguard Worker
3832*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no restriction.
3833*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
3834*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3835*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3836*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3837*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3838*d9f75844SAndroid Build Coastguard Worker
3839*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3840*d9f75844SAndroid Build Coastguard Worker }
3841*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AdaptsFramerateForLowQuality_MaintainResolutionMode)3842*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3843*d9f75844SAndroid Build Coastguard Worker AdaptsFramerateForLowQuality_MaintainResolutionMode) {
3844*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3845*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3846*d9f75844SAndroid Build Coastguard Worker const int kInputFps = 30;
3847*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3848*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3849*d9f75844SAndroid Build Coastguard Worker
3850*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
3851*d9f75844SAndroid Build Coastguard Worker stats.input_frame_rate = kInputFps;
3852*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(stats);
3853*d9f75844SAndroid Build Coastguard Worker
3854*d9f75844SAndroid Build Coastguard Worker // Expect no scaling to begin with (preference: MAINTAIN_FRAMERATE).
3855*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
3856*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(1);
3857*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(), FpsMaxResolutionMax());
3858*d9f75844SAndroid Build Coastguard Worker
3859*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution.
3860*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3861*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
3862*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(2);
3863*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(),
3864*d9f75844SAndroid Build Coastguard Worker FpsMaxResolutionMatches(Lt(kWidth * kHeight)));
3865*d9f75844SAndroid Build Coastguard Worker
3866*d9f75844SAndroid Build Coastguard Worker // Enable MAINTAIN_RESOLUTION preference.
3867*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder new_video_source;
3868*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSourceAndWaitForRestrictionsUpdated(
3869*d9f75844SAndroid Build Coastguard Worker &new_video_source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
3870*d9f75844SAndroid Build Coastguard Worker // Give the encoder queue time to process the change in degradation preference
3871*d9f75844SAndroid Build Coastguard Worker // by waiting for an encoded frame.
3872*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
3873*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(3);
3874*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(new_video_source.sink_wants(), FpsMaxResolutionMax());
3875*d9f75844SAndroid Build Coastguard Worker
3876*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect reduced framerate.
3877*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3878*d9f75844SAndroid Build Coastguard Worker new_video_source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
3879*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(4);
3880*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(new_video_source.sink_wants(),
3881*d9f75844SAndroid Build Coastguard Worker FpsMatchesResolutionMax(Lt(kInputFps)));
3882*d9f75844SAndroid Build Coastguard Worker
3883*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no restriction.
3884*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
3885*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(new_video_source.sink_wants(), FpsMaxResolutionMax());
3886*d9f75844SAndroid Build Coastguard Worker
3887*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3888*d9f75844SAndroid Build Coastguard Worker }
3889*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DoesNotScaleBelowSetResolutionLimit)3890*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DoesNotScaleBelowSetResolutionLimit) {
3891*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3892*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3893*d9f75844SAndroid Build Coastguard Worker const size_t kNumFrames = 10;
3894*d9f75844SAndroid Build Coastguard Worker
3895*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3896*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3897*d9f75844SAndroid Build Coastguard Worker
3898*d9f75844SAndroid Build Coastguard Worker // Enable adapter, expected input resolutions when downscaling:
3899*d9f75844SAndroid Build Coastguard Worker // 1280x720 -> 960x540 -> 640x360 -> 480x270 -> 320x180 (kMinPixelsPerFrame)
3900*d9f75844SAndroid Build Coastguard Worker video_source_.set_adaptation_enabled(true);
3901*d9f75844SAndroid Build Coastguard Worker
3902*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
3903*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
3904*d9f75844SAndroid Build Coastguard Worker
3905*d9f75844SAndroid Build Coastguard Worker int downscales = 0;
3906*d9f75844SAndroid Build Coastguard Worker for (size_t i = 1; i <= kNumFrames; i++) {
3907*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
3908*d9f75844SAndroid Build Coastguard Worker CreateFrame(i * kFrameIntervalMs, kWidth, kHeight));
3909*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(i * kFrameIntervalMs);
3910*d9f75844SAndroid Build Coastguard Worker
3911*d9f75844SAndroid Build Coastguard Worker // Trigger scale down.
3912*d9f75844SAndroid Build Coastguard Worker rtc::VideoSinkWants last_wants = video_source_.sink_wants();
3913*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
3914*d9f75844SAndroid Build Coastguard Worker EXPECT_GE(video_source_.sink_wants().max_pixel_count, kMinPixelsPerFrame);
3915*d9f75844SAndroid Build Coastguard Worker
3916*d9f75844SAndroid Build Coastguard Worker if (video_source_.sink_wants().max_pixel_count < last_wants.max_pixel_count)
3917*d9f75844SAndroid Build Coastguard Worker ++downscales;
3918*d9f75844SAndroid Build Coastguard Worker
3919*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
3920*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(downscales,
3921*d9f75844SAndroid Build Coastguard Worker stats_proxy_->GetStats().number_of_quality_adapt_changes);
3922*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(downscales, 0);
3923*d9f75844SAndroid Build Coastguard Worker }
3924*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3925*d9f75844SAndroid Build Coastguard Worker }
3926*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AdaptsResolutionUpAndDownTwiceOnOveruse_MaintainFramerateMode)3927*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3928*d9f75844SAndroid Build Coastguard Worker AdaptsResolutionUpAndDownTwiceOnOveruse_MaintainFramerateMode) {
3929*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3930*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3931*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3932*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3933*d9f75844SAndroid Build Coastguard Worker
3934*d9f75844SAndroid Build Coastguard Worker // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
3935*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
3936*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
3937*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
3938*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
3939*d9f75844SAndroid Build Coastguard Worker
3940*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
3941*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3942*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kWidth, kHeight);
3943*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3944*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
3945*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3946*d9f75844SAndroid Build Coastguard Worker
3947*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution.
3948*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
3949*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3950*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3951*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3952*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(),
3953*d9f75844SAndroid Build Coastguard Worker FpsMaxResolutionMatches(Lt(kWidth * kHeight)));
3954*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
3955*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3956*d9f75844SAndroid Build Coastguard Worker
3957*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no restriction.
3958*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
3959*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3960*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3961*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kWidth, kHeight);
3962*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3963*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
3964*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3965*d9f75844SAndroid Build Coastguard Worker
3966*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution.
3967*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
3968*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3969*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3970*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
3971*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(),
3972*d9f75844SAndroid Build Coastguard Worker FpsMaxResolutionMatches(Lt(kWidth * kHeight)));
3973*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
3974*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3975*d9f75844SAndroid Build Coastguard Worker
3976*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no restriction.
3977*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
3978*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
3979*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
3980*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(kWidth, kHeight);
3981*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
3982*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
3983*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
3984*d9f75844SAndroid Build Coastguard Worker
3985*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
3986*d9f75844SAndroid Build Coastguard Worker }
3987*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AdaptsResolutionUpAndDownTwiceForLowQuality_BalancedMode_NoFpsLimit)3988*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
3989*d9f75844SAndroid Build Coastguard Worker AdaptsResolutionUpAndDownTwiceForLowQuality_BalancedMode_NoFpsLimit) {
3990*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
3991*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
3992*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
3993*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
3994*d9f75844SAndroid Build Coastguard Worker
3995*d9f75844SAndroid Build Coastguard Worker // Enable BALANCED preference, no initial limitation.
3996*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
3997*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
3998*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
3999*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
4000*d9f75844SAndroid Build Coastguard Worker
4001*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
4002*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4003*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(kWidth, kHeight);
4004*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
4005*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
4006*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4007*d9f75844SAndroid Build Coastguard Worker
4008*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution.
4009*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4010*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4011*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4012*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(timestamp_ms);
4013*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(),
4014*d9f75844SAndroid Build Coastguard Worker FpsMaxResolutionMatches(Lt(kWidth * kHeight)));
4015*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
4016*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4017*d9f75844SAndroid Build Coastguard Worker
4018*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no restriction.
4019*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4020*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4021*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4022*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(kWidth, kHeight);
4023*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
4024*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
4025*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4026*d9f75844SAndroid Build Coastguard Worker
4027*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution.
4028*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4029*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4030*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4031*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(timestamp_ms);
4032*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(),
4033*d9f75844SAndroid Build Coastguard Worker FpsMaxResolutionMatches(Lt(kWidth * kHeight)));
4034*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
4035*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4036*d9f75844SAndroid Build Coastguard Worker
4037*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no restriction.
4038*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4039*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4040*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4041*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(kWidth, kHeight);
4042*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
4043*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
4044*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4045*d9f75844SAndroid Build Coastguard Worker
4046*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4047*d9f75844SAndroid Build Coastguard Worker }
4048*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AdaptUpIfBwEstimateIsHigherThanMinBitrate)4049*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, AdaptUpIfBwEstimateIsHigherThanMinBitrate) {
4050*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits(
4051*d9f75844SAndroid Build Coastguard Worker {kEncoderBitrateLimits540p, kEncoderBitrateLimits720p});
4052*d9f75844SAndroid Build Coastguard Worker
4053*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4054*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kEncoderBitrateLimits720p.min_start_bitrate_bps),
4055*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kEncoderBitrateLimits720p.min_start_bitrate_bps),
4056*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kEncoderBitrateLimits720p.min_start_bitrate_bps), 0,
4057*d9f75844SAndroid Build Coastguard Worker 0, 0);
4058*d9f75844SAndroid Build Coastguard Worker
4059*d9f75844SAndroid Build Coastguard Worker // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
4060*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
4061*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
4062*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
4063*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
4064*d9f75844SAndroid Build Coastguard Worker
4065*d9f75844SAndroid Build Coastguard Worker // Insert 720p frame.
4066*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
4067*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, 1280, 720));
4068*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1280, 720);
4069*d9f75844SAndroid Build Coastguard Worker
4070*d9f75844SAndroid Build Coastguard Worker // Reduce bitrate and trigger adapt down.
4071*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4072*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kEncoderBitrateLimits540p.min_start_bitrate_bps),
4073*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kEncoderBitrateLimits540p.min_start_bitrate_bps),
4074*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kEncoderBitrateLimits540p.min_start_bitrate_bps), 0,
4075*d9f75844SAndroid Build Coastguard Worker 0, 0);
4076*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4077*d9f75844SAndroid Build Coastguard Worker
4078*d9f75844SAndroid Build Coastguard Worker // Insert 720p frame. It should be downscaled and encoded.
4079*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4080*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, 1280, 720));
4081*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(960, 540);
4082*d9f75844SAndroid Build Coastguard Worker
4083*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up. Higher resolution should not be requested duo to lack
4084*d9f75844SAndroid Build Coastguard Worker // of bitrate.
4085*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4086*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMatches(Lt(1280 * 720)));
4087*d9f75844SAndroid Build Coastguard Worker
4088*d9f75844SAndroid Build Coastguard Worker // Increase bitrate.
4089*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4090*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kEncoderBitrateLimits720p.min_start_bitrate_bps),
4091*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kEncoderBitrateLimits720p.min_start_bitrate_bps),
4092*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kEncoderBitrateLimits720p.min_start_bitrate_bps), 0,
4093*d9f75844SAndroid Build Coastguard Worker 0, 0);
4094*d9f75844SAndroid Build Coastguard Worker
4095*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up. Higher resolution should be requested.
4096*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4097*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
4098*d9f75844SAndroid Build Coastguard Worker
4099*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4100*d9f75844SAndroid Build Coastguard Worker }
4101*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DropFirstFramesIfBwEstimateIsTooLow)4102*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DropFirstFramesIfBwEstimateIsTooLow) {
4103*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits(
4104*d9f75844SAndroid Build Coastguard Worker {kEncoderBitrateLimits540p, kEncoderBitrateLimits720p});
4105*d9f75844SAndroid Build Coastguard Worker
4106*d9f75844SAndroid Build Coastguard Worker // Set bitrate equal to min bitrate of 540p.
4107*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4108*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kEncoderBitrateLimits540p.min_start_bitrate_bps),
4109*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kEncoderBitrateLimits540p.min_start_bitrate_bps),
4110*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kEncoderBitrateLimits540p.min_start_bitrate_bps), 0,
4111*d9f75844SAndroid Build Coastguard Worker 0, 0);
4112*d9f75844SAndroid Build Coastguard Worker
4113*d9f75844SAndroid Build Coastguard Worker // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
4114*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
4115*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
4116*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
4117*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
4118*d9f75844SAndroid Build Coastguard Worker
4119*d9f75844SAndroid Build Coastguard Worker // Insert 720p frame. It should be dropped and lower resolution should be
4120*d9f75844SAndroid Build Coastguard Worker // requested.
4121*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
4122*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, 1280, 720));
4123*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
4124*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(source.sink_wants().max_pixel_count < 1280 * 720, 5000);
4125*d9f75844SAndroid Build Coastguard Worker
4126*d9f75844SAndroid Build Coastguard Worker // Insert 720p frame. It should be downscaled and encoded.
4127*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4128*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, 1280, 720));
4129*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(960, 540);
4130*d9f75844SAndroid Build Coastguard Worker
4131*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4132*d9f75844SAndroid Build Coastguard Worker }
4133*d9f75844SAndroid Build Coastguard Worker
4134*d9f75844SAndroid Build Coastguard Worker class BalancedDegradationTest : public VideoStreamEncoderTest {
4135*d9f75844SAndroid Build Coastguard Worker protected:
SetupTest()4136*d9f75844SAndroid Build Coastguard Worker void SetupTest() {
4137*d9f75844SAndroid Build Coastguard Worker // Reset encoder for field trials to take effect.
4138*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config_.Copy());
4139*d9f75844SAndroid Build Coastguard Worker OnBitrateUpdated(kTargetBitrate);
4140*d9f75844SAndroid Build Coastguard Worker
4141*d9f75844SAndroid Build Coastguard Worker // Enable BALANCED preference.
4142*d9f75844SAndroid Build Coastguard Worker source_.set_adaptation_enabled(true);
4143*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source_, DegradationPreference::BALANCED);
4144*d9f75844SAndroid Build Coastguard Worker }
4145*d9f75844SAndroid Build Coastguard Worker
OnBitrateUpdated(DataRate bitrate)4146*d9f75844SAndroid Build Coastguard Worker void OnBitrateUpdated(DataRate bitrate) {
4147*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4148*d9f75844SAndroid Build Coastguard Worker bitrate, bitrate, bitrate, 0, 0, 0);
4149*d9f75844SAndroid Build Coastguard Worker }
4150*d9f75844SAndroid Build Coastguard Worker
InsertFrame()4151*d9f75844SAndroid Build Coastguard Worker void InsertFrame() {
4152*d9f75844SAndroid Build Coastguard Worker timestamp_ms_ += kFrameIntervalMs;
4153*d9f75844SAndroid Build Coastguard Worker source_.IncomingCapturedFrame(CreateFrame(timestamp_ms_, kWidth, kHeight));
4154*d9f75844SAndroid Build Coastguard Worker }
4155*d9f75844SAndroid Build Coastguard Worker
InsertFrameAndWaitForEncoded()4156*d9f75844SAndroid Build Coastguard Worker void InsertFrameAndWaitForEncoded() {
4157*d9f75844SAndroid Build Coastguard Worker InsertFrame();
4158*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(timestamp_ms_);
4159*d9f75844SAndroid Build Coastguard Worker }
4160*d9f75844SAndroid Build Coastguard Worker
4161*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640; // pixels:640x360=230400
4162*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
4163*d9f75844SAndroid Build Coastguard Worker const int64_t kFrameIntervalMs = 150; // Use low fps to not drop any frame.
4164*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms_ = 0;
4165*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source_{&time_controller_};
4166*d9f75844SAndroid Build Coastguard Worker };
4167*d9f75844SAndroid Build Coastguard Worker
TEST_F(BalancedDegradationTest,AdaptDownTwiceIfMinFpsDiffLtThreshold)4168*d9f75844SAndroid Build Coastguard Worker TEST_F(BalancedDegradationTest, AdaptDownTwiceIfMinFpsDiffLtThreshold) {
4169*d9f75844SAndroid Build Coastguard Worker test::ScopedKeyValueConfig field_trials(
4170*d9f75844SAndroid Build Coastguard Worker field_trials_,
4171*d9f75844SAndroid Build Coastguard Worker "WebRTC-Video-BalancedDegradationSettings/"
4172*d9f75844SAndroid Build Coastguard Worker "pixels:57600|129600|230400,fps:7|10|24,fps_diff:1|1|1/");
4173*d9f75844SAndroid Build Coastguard Worker SetupTest();
4174*d9f75844SAndroid Build Coastguard Worker
4175*d9f75844SAndroid Build Coastguard Worker // Force input frame rate.
4176*d9f75844SAndroid Build Coastguard Worker const int kInputFps = 24;
4177*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
4178*d9f75844SAndroid Build Coastguard Worker stats.input_frame_rate = kInputFps;
4179*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(stats);
4180*d9f75844SAndroid Build Coastguard Worker
4181*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4182*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsMaxResolutionMax());
4183*d9f75844SAndroid Build Coastguard Worker
4184*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down framerate and resolution,
4185*d9f75844SAndroid Build Coastguard Worker // since Fps diff (input-requested:0) < threshold.
4186*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4187*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(),
4188*d9f75844SAndroid Build Coastguard Worker AllOf(WantsFps(Eq(24)), WantsMaxPixels(Le(230400))));
4189*d9f75844SAndroid Build Coastguard Worker
4190*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4191*d9f75844SAndroid Build Coastguard Worker }
4192*d9f75844SAndroid Build Coastguard Worker
TEST_F(BalancedDegradationTest,AdaptDownOnceIfFpsDiffGeThreshold)4193*d9f75844SAndroid Build Coastguard Worker TEST_F(BalancedDegradationTest, AdaptDownOnceIfFpsDiffGeThreshold) {
4194*d9f75844SAndroid Build Coastguard Worker test::ScopedKeyValueConfig field_trials(
4195*d9f75844SAndroid Build Coastguard Worker field_trials_,
4196*d9f75844SAndroid Build Coastguard Worker "WebRTC-Video-BalancedDegradationSettings/"
4197*d9f75844SAndroid Build Coastguard Worker "pixels:57600|129600|230400,fps:7|10|24,fps_diff:1|1|1/");
4198*d9f75844SAndroid Build Coastguard Worker SetupTest();
4199*d9f75844SAndroid Build Coastguard Worker
4200*d9f75844SAndroid Build Coastguard Worker // Force input frame rate.
4201*d9f75844SAndroid Build Coastguard Worker const int kInputFps = 25;
4202*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
4203*d9f75844SAndroid Build Coastguard Worker stats.input_frame_rate = kInputFps;
4204*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(stats);
4205*d9f75844SAndroid Build Coastguard Worker
4206*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4207*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsMaxResolutionMax());
4208*d9f75844SAndroid Build Coastguard Worker
4209*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down framerate only (640x360@24fps).
4210*d9f75844SAndroid Build Coastguard Worker // Fps diff (input-requested:1) == threshold.
4211*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4212*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsMatchesResolutionMax(Eq(24)));
4213*d9f75844SAndroid Build Coastguard Worker
4214*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4215*d9f75844SAndroid Build Coastguard Worker }
4216*d9f75844SAndroid Build Coastguard Worker
TEST_F(BalancedDegradationTest,AdaptDownUsesCodecSpecificFps)4217*d9f75844SAndroid Build Coastguard Worker TEST_F(BalancedDegradationTest, AdaptDownUsesCodecSpecificFps) {
4218*d9f75844SAndroid Build Coastguard Worker test::ScopedKeyValueConfig field_trials(
4219*d9f75844SAndroid Build Coastguard Worker field_trials_,
4220*d9f75844SAndroid Build Coastguard Worker "WebRTC-Video-BalancedDegradationSettings/"
4221*d9f75844SAndroid Build Coastguard Worker "pixels:57600|129600|230400,fps:7|10|24,vp8_fps:8|11|22/");
4222*d9f75844SAndroid Build Coastguard Worker SetupTest();
4223*d9f75844SAndroid Build Coastguard Worker
4224*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kVideoCodecVP8, video_encoder_config_.codec_type);
4225*d9f75844SAndroid Build Coastguard Worker
4226*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4227*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsMaxResolutionMax());
4228*d9f75844SAndroid Build Coastguard Worker
4229*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down framerate (640x360@22fps).
4230*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4231*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsMatchesResolutionMax(Eq(22)));
4232*d9f75844SAndroid Build Coastguard Worker
4233*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4234*d9f75844SAndroid Build Coastguard Worker }
4235*d9f75844SAndroid Build Coastguard Worker
TEST_F(BalancedDegradationTest,NoAdaptUpIfBwEstimateIsLessThanMinBitrate)4236*d9f75844SAndroid Build Coastguard Worker TEST_F(BalancedDegradationTest, NoAdaptUpIfBwEstimateIsLessThanMinBitrate) {
4237*d9f75844SAndroid Build Coastguard Worker test::ScopedKeyValueConfig field_trials(
4238*d9f75844SAndroid Build Coastguard Worker field_trials_,
4239*d9f75844SAndroid Build Coastguard Worker "WebRTC-Video-BalancedDegradationSettings/"
4240*d9f75844SAndroid Build Coastguard Worker "pixels:57600|129600|230400,fps:7|10|14,kbps:0|0|425/");
4241*d9f75844SAndroid Build Coastguard Worker SetupTest();
4242*d9f75844SAndroid Build Coastguard Worker
4243*d9f75844SAndroid Build Coastguard Worker const DataRate kMinBitrate = DataRate::KilobitsPerSec(425);
4244*d9f75844SAndroid Build Coastguard Worker const DataRate kTooLowMinBitrate = DataRate::KilobitsPerSec(424);
4245*d9f75844SAndroid Build Coastguard Worker OnBitrateUpdated(kTooLowMinBitrate);
4246*d9f75844SAndroid Build Coastguard Worker
4247*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4248*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsMaxResolutionMax());
4249*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4250*d9f75844SAndroid Build Coastguard Worker
4251*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down framerate (640x360@14fps).
4252*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4253*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4254*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsMatchesResolutionMax(Eq(14)));
4255*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4256*d9f75844SAndroid Build Coastguard Worker
4257*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution (480x270@14fps).
4258*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4259*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4260*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsEqResolutionLt(source_.last_wants()));
4261*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4262*d9f75844SAndroid Build Coastguard Worker
4263*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down framerate (480x270@10fps).
4264*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4265*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4266*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsLtResolutionEq(source_.last_wants()));
4267*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(source_.sink_wants().max_framerate_fps, 10);
4268*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4269*d9f75844SAndroid Build Coastguard Worker
4270*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no upscale in fps (target bitrate < min bitrate).
4271*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4272*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4273*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4274*d9f75844SAndroid Build Coastguard Worker
4275*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect upscaled fps (target bitrate == min bitrate).
4276*d9f75844SAndroid Build Coastguard Worker OnBitrateUpdated(kMinBitrate);
4277*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4278*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4279*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(source_.sink_wants().max_framerate_fps, 14);
4280*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4281*d9f75844SAndroid Build Coastguard Worker
4282*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4283*d9f75844SAndroid Build Coastguard Worker }
4284*d9f75844SAndroid Build Coastguard Worker
TEST_F(BalancedDegradationTest,InitialFrameDropAdaptsFpsAndResolutionInOneStep)4285*d9f75844SAndroid Build Coastguard Worker TEST_F(BalancedDegradationTest,
4286*d9f75844SAndroid Build Coastguard Worker InitialFrameDropAdaptsFpsAndResolutionInOneStep) {
4287*d9f75844SAndroid Build Coastguard Worker test::ScopedKeyValueConfig field_trials(
4288*d9f75844SAndroid Build Coastguard Worker field_trials_,
4289*d9f75844SAndroid Build Coastguard Worker "WebRTC-Video-BalancedDegradationSettings/"
4290*d9f75844SAndroid Build Coastguard Worker "pixels:57600|129600|230400,fps:7|24|24/");
4291*d9f75844SAndroid Build Coastguard Worker SetupTest();
4292*d9f75844SAndroid Build Coastguard Worker OnBitrateUpdated(kLowTargetBitrate);
4293*d9f75844SAndroid Build Coastguard Worker
4294*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), UnlimitedSinkWants());
4295*d9f75844SAndroid Build Coastguard Worker
4296*d9f75844SAndroid Build Coastguard Worker // Insert frame, expect scaled down:
4297*d9f75844SAndroid Build Coastguard Worker // framerate (640x360@24fps) -> resolution (480x270@24fps).
4298*d9f75844SAndroid Build Coastguard Worker InsertFrame();
4299*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(WaitForFrame(TimeDelta::Seconds(1)));
4300*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(source_.sink_wants().max_pixel_count, kWidth * kHeight);
4301*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(source_.sink_wants().max_framerate_fps, 24);
4302*d9f75844SAndroid Build Coastguard Worker
4303*d9f75844SAndroid Build Coastguard Worker // Insert frame, expect scaled down:
4304*d9f75844SAndroid Build Coastguard Worker // resolution (320x180@24fps).
4305*d9f75844SAndroid Build Coastguard Worker InsertFrame();
4306*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(WaitForFrame(TimeDelta::Seconds(1)));
4307*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(source_.sink_wants().max_pixel_count,
4308*d9f75844SAndroid Build Coastguard Worker source_.last_wants().max_pixel_count);
4309*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(source_.sink_wants().max_framerate_fps, 24);
4310*d9f75844SAndroid Build Coastguard Worker
4311*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped (min pixels per frame reached).
4312*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4313*d9f75844SAndroid Build Coastguard Worker
4314*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4315*d9f75844SAndroid Build Coastguard Worker }
4316*d9f75844SAndroid Build Coastguard Worker
TEST_F(BalancedDegradationTest,NoAdaptUpInResolutionIfBwEstimateIsLessThanMinBitrate)4317*d9f75844SAndroid Build Coastguard Worker TEST_F(BalancedDegradationTest,
4318*d9f75844SAndroid Build Coastguard Worker NoAdaptUpInResolutionIfBwEstimateIsLessThanMinBitrate) {
4319*d9f75844SAndroid Build Coastguard Worker test::ScopedKeyValueConfig field_trials(
4320*d9f75844SAndroid Build Coastguard Worker field_trials_,
4321*d9f75844SAndroid Build Coastguard Worker "WebRTC-Video-BalancedDegradationSettings/"
4322*d9f75844SAndroid Build Coastguard Worker "pixels:57600|129600|230400,fps:7|10|14,kbps_res:0|0|435/");
4323*d9f75844SAndroid Build Coastguard Worker SetupTest();
4324*d9f75844SAndroid Build Coastguard Worker
4325*d9f75844SAndroid Build Coastguard Worker const DataRate kResolutionMinBitrate = DataRate::KilobitsPerSec(435);
4326*d9f75844SAndroid Build Coastguard Worker const DataRate kTooLowMinResolutionBitrate = DataRate::KilobitsPerSec(434);
4327*d9f75844SAndroid Build Coastguard Worker OnBitrateUpdated(kTooLowMinResolutionBitrate);
4328*d9f75844SAndroid Build Coastguard Worker
4329*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4330*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsMaxResolutionMax());
4331*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4332*d9f75844SAndroid Build Coastguard Worker
4333*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down framerate (640x360@14fps).
4334*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4335*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4336*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsMatchesResolutionMax(Eq(14)));
4337*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4338*d9f75844SAndroid Build Coastguard Worker
4339*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution (480x270@14fps).
4340*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4341*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4342*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsEqResolutionLt(source_.last_wants()));
4343*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4344*d9f75844SAndroid Build Coastguard Worker
4345*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down framerate (480x270@10fps).
4346*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4347*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4348*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsLtResolutionEq(source_.last_wants()));
4349*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4350*d9f75844SAndroid Build Coastguard Worker
4351*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect upscaled fps (no bitrate limit) (480x270@14fps).
4352*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4353*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4354*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsGtResolutionEq(source_.last_wants()));
4355*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4356*d9f75844SAndroid Build Coastguard Worker
4357*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no upscale in res (target bitrate < min bitrate).
4358*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4359*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4360*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4361*d9f75844SAndroid Build Coastguard Worker
4362*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect upscaled res (target bitrate == min bitrate).
4363*d9f75844SAndroid Build Coastguard Worker OnBitrateUpdated(kResolutionMinBitrate);
4364*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4365*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4366*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsEqResolutionGt(source_.last_wants()));
4367*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(5, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4368*d9f75844SAndroid Build Coastguard Worker
4369*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4370*d9f75844SAndroid Build Coastguard Worker }
4371*d9f75844SAndroid Build Coastguard Worker
TEST_F(BalancedDegradationTest,NoAdaptUpInFpsAndResolutionIfBwEstimateIsLessThanMinBitrate)4372*d9f75844SAndroid Build Coastguard Worker TEST_F(BalancedDegradationTest,
4373*d9f75844SAndroid Build Coastguard Worker NoAdaptUpInFpsAndResolutionIfBwEstimateIsLessThanMinBitrate) {
4374*d9f75844SAndroid Build Coastguard Worker test::ScopedKeyValueConfig field_trials(
4375*d9f75844SAndroid Build Coastguard Worker field_trials_,
4376*d9f75844SAndroid Build Coastguard Worker "WebRTC-Video-BalancedDegradationSettings/"
4377*d9f75844SAndroid Build Coastguard Worker "pixels:57600|129600|230400,fps:7|10|14,kbps:0|0|425,kbps_res:0|0|435/");
4378*d9f75844SAndroid Build Coastguard Worker SetupTest();
4379*d9f75844SAndroid Build Coastguard Worker
4380*d9f75844SAndroid Build Coastguard Worker const DataRate kMinBitrate = DataRate::KilobitsPerSec(425);
4381*d9f75844SAndroid Build Coastguard Worker const DataRate kTooLowMinBitrate = DataRate::KilobitsPerSec(424);
4382*d9f75844SAndroid Build Coastguard Worker const DataRate kResolutionMinBitrate = DataRate::KilobitsPerSec(435);
4383*d9f75844SAndroid Build Coastguard Worker const DataRate kTooLowMinResolutionBitrate = DataRate::KilobitsPerSec(434);
4384*d9f75844SAndroid Build Coastguard Worker OnBitrateUpdated(kTooLowMinBitrate);
4385*d9f75844SAndroid Build Coastguard Worker
4386*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4387*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsMaxResolutionMax());
4388*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4389*d9f75844SAndroid Build Coastguard Worker
4390*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down framerate (640x360@14fps).
4391*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4392*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4393*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsMatchesResolutionMax(Eq(14)));
4394*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4395*d9f75844SAndroid Build Coastguard Worker
4396*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution (480x270@14fps).
4397*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4398*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4399*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsEqResolutionLt(source_.last_wants()));
4400*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4401*d9f75844SAndroid Build Coastguard Worker
4402*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down framerate (480x270@10fps).
4403*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4404*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4405*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsLtResolutionEq(source_.last_wants()));
4406*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4407*d9f75844SAndroid Build Coastguard Worker
4408*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no upscale (target bitrate < min bitrate).
4409*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4410*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4411*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4412*d9f75844SAndroid Build Coastguard Worker
4413*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect upscaled fps (target bitrate == min bitrate).
4414*d9f75844SAndroid Build Coastguard Worker OnBitrateUpdated(kMinBitrate);
4415*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4416*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4417*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsGtResolutionEq(source_.last_wants()));
4418*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4419*d9f75844SAndroid Build Coastguard Worker
4420*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no upscale in res (target bitrate < min bitrate).
4421*d9f75844SAndroid Build Coastguard Worker OnBitrateUpdated(kTooLowMinResolutionBitrate);
4422*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4423*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4424*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4425*d9f75844SAndroid Build Coastguard Worker
4426*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect upscaled res (target bitrate == min bitrate).
4427*d9f75844SAndroid Build Coastguard Worker OnBitrateUpdated(kResolutionMinBitrate);
4428*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4429*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
4430*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source_.sink_wants(), FpsEqResolutionGt(source_.last_wants()));
4431*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(5, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4432*d9f75844SAndroid Build Coastguard Worker
4433*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4434*d9f75844SAndroid Build Coastguard Worker }
4435*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AdaptsResolutionOnOveruseAndLowQuality_MaintainFramerateMode)4436*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
4437*d9f75844SAndroid Build Coastguard Worker AdaptsResolutionOnOveruseAndLowQuality_MaintainFramerateMode) {
4438*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
4439*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
4440*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4441*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
4442*d9f75844SAndroid Build Coastguard Worker
4443*d9f75844SAndroid Build Coastguard Worker // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
4444*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
4445*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
4446*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
4447*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
4448*d9f75844SAndroid Build Coastguard Worker
4449*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
4450*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4451*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kWidth, kHeight);
4452*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
4453*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
4454*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
4455*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
4456*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4457*d9f75844SAndroid Build Coastguard Worker
4458*d9f75844SAndroid Build Coastguard Worker // Trigger cpu adapt down, expect scaled down resolution (960x540).
4459*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
4460*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4461*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4462*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
4463*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(),
4464*d9f75844SAndroid Build Coastguard Worker FpsMaxResolutionMatches(Lt(kWidth * kHeight)));
4465*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
4466*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
4467*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
4468*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4469*d9f75844SAndroid Build Coastguard Worker
4470*d9f75844SAndroid Build Coastguard Worker // Trigger cpu adapt down, expect scaled down resolution (640x360).
4471*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
4472*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4473*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4474*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
4475*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionLt(source.last_wants()));
4476*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
4477*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
4478*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
4479*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4480*d9f75844SAndroid Build Coastguard Worker
4481*d9f75844SAndroid Build Coastguard Worker // Trigger cpu adapt down, expect scaled down resolution (480x270).
4482*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
4483*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4484*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4485*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
4486*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionLt(source.last_wants()));
4487*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
4488*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
4489*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
4490*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4491*d9f75844SAndroid Build Coastguard Worker
4492*d9f75844SAndroid Build Coastguard Worker // Trigger quality adapt down, expect scaled down resolution (320x180).
4493*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4494*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4495*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4496*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
4497*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionLt(source.last_wants()));
4498*d9f75844SAndroid Build Coastguard Worker rtc::VideoSinkWants last_wants = source.sink_wants();
4499*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
4500*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
4501*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
4502*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4503*d9f75844SAndroid Build Coastguard Worker
4504*d9f75844SAndroid Build Coastguard Worker // Trigger quality adapt down, expect no change (min resolution reached).
4505*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
4506*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4507*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4508*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
4509*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMax());
4510*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(source.sink_wants().max_pixel_count, last_wants.max_pixel_count);
4511*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
4512*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
4513*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
4514*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4515*d9f75844SAndroid Build Coastguard Worker
4516*d9f75844SAndroid Build Coastguard Worker // Trigger quality adapt up, expect upscaled resolution (480x270).
4517*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4518*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4519*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4520*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
4521*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionGt(source.last_wants()));
4522*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
4523*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
4524*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
4525*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4526*d9f75844SAndroid Build Coastguard Worker
4527*d9f75844SAndroid Build Coastguard Worker // Trigger quality and cpu adapt up since both are most limited, expect
4528*d9f75844SAndroid Build Coastguard Worker // upscaled resolution (640x360).
4529*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
4530*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4531*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4532*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4533*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
4534*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionGt(source.last_wants()));
4535*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
4536*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
4537*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
4538*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4539*d9f75844SAndroid Build Coastguard Worker
4540*d9f75844SAndroid Build Coastguard Worker // Trigger quality and cpu adapt up since both are most limited, expect
4541*d9f75844SAndroid Build Coastguard Worker // upscaled resolution (960x540).
4542*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
4543*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4544*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4545*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4546*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
4547*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionGt(source.last_wants()));
4548*d9f75844SAndroid Build Coastguard Worker last_wants = source.sink_wants();
4549*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
4550*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
4551*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(5, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
4552*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4553*d9f75844SAndroid Build Coastguard Worker
4554*d9f75844SAndroid Build Coastguard Worker // Trigger cpu adapt up, expect no change since not most limited (960x540).
4555*d9f75844SAndroid Build Coastguard Worker // However the stats will change since the CPU resource is no longer limited.
4556*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
4557*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4558*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4559*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
4560*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsEqResolutionEqTo(last_wants));
4561*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
4562*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
4563*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(6, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
4564*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4565*d9f75844SAndroid Build Coastguard Worker
4566*d9f75844SAndroid Build Coastguard Worker // Trigger quality adapt up, expect no restriction (1280x720).
4567*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
4568*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
4569*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
4570*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kWidth, kHeight);
4571*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionGt(source.last_wants()));
4572*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
4573*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
4574*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
4575*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(6, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
4576*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(5, stats_proxy_->GetStats().number_of_quality_adapt_changes);
4577*d9f75844SAndroid Build Coastguard Worker
4578*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4579*d9f75844SAndroid Build Coastguard Worker }
4580*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,CpuLimitedHistogramIsReported)4581*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, CpuLimitedHistogramIsReported) {
4582*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
4583*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
4584*d9f75844SAndroid Build Coastguard Worker
4585*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4586*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
4587*d9f75844SAndroid Build Coastguard Worker
4588*d9f75844SAndroid Build Coastguard Worker for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
4589*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(i, kWidth, kHeight));
4590*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(i);
4591*d9f75844SAndroid Build Coastguard Worker }
4592*d9f75844SAndroid Build Coastguard Worker
4593*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
4594*d9f75844SAndroid Build Coastguard Worker for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
4595*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(
4596*d9f75844SAndroid Build Coastguard Worker SendStatisticsProxy::kMinRequiredMetricsSamples + i, kWidth, kHeight));
4597*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(SendStatisticsProxy::kMinRequiredMetricsSamples + i);
4598*d9f75844SAndroid Build Coastguard Worker }
4599*d9f75844SAndroid Build Coastguard Worker
4600*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4601*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_.reset();
4602*d9f75844SAndroid Build Coastguard Worker stats_proxy_.reset();
4603*d9f75844SAndroid Build Coastguard Worker
4604*d9f75844SAndroid Build Coastguard Worker EXPECT_METRIC_EQ(
4605*d9f75844SAndroid Build Coastguard Worker 1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
4606*d9f75844SAndroid Build Coastguard Worker EXPECT_METRIC_EQ(
4607*d9f75844SAndroid Build Coastguard Worker 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
4608*d9f75844SAndroid Build Coastguard Worker }
4609*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,CpuLimitedHistogramIsNotReportedForDisabledDegradation)4610*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
4611*d9f75844SAndroid Build Coastguard Worker CpuLimitedHistogramIsNotReportedForDisabledDegradation) {
4612*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4613*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
4614*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
4615*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
4616*d9f75844SAndroid Build Coastguard Worker
4617*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&video_source_,
4618*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::DISABLED);
4619*d9f75844SAndroid Build Coastguard Worker
4620*d9f75844SAndroid Build Coastguard Worker for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
4621*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(i, kWidth, kHeight));
4622*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(i);
4623*d9f75844SAndroid Build Coastguard Worker }
4624*d9f75844SAndroid Build Coastguard Worker
4625*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4626*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_.reset();
4627*d9f75844SAndroid Build Coastguard Worker stats_proxy_.reset();
4628*d9f75844SAndroid Build Coastguard Worker
4629*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0,
4630*d9f75844SAndroid Build Coastguard Worker metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
4631*d9f75844SAndroid Build Coastguard Worker }
4632*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsVideoBitrateAllocation)4633*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, ReportsVideoBitrateAllocation) {
4634*d9f75844SAndroid Build Coastguard Worker ResetEncoder("FAKE", 1, 1, 1, /*screenshare*/ false,
4635*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
4636*d9f75844SAndroid Build Coastguard Worker kVideoBitrateAllocation);
4637*d9f75844SAndroid Build Coastguard Worker
4638*d9f75844SAndroid Build Coastguard Worker const int kDefaultFps = 30;
4639*d9f75844SAndroid Build Coastguard Worker const VideoBitrateAllocation expected_bitrate =
4640*d9f75844SAndroid Build Coastguard Worker SimulcastRateAllocator(fake_encoder_.config())
4641*d9f75844SAndroid Build Coastguard Worker .Allocate(VideoBitrateAllocationParameters(kLowTargetBitrate.bps(),
4642*d9f75844SAndroid Build Coastguard Worker kDefaultFps));
4643*d9f75844SAndroid Build Coastguard Worker
4644*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4645*d9f75844SAndroid Build Coastguard Worker kLowTargetBitrate, kLowTargetBitrate, kLowTargetBitrate, 0, 0, 0);
4646*d9f75844SAndroid Build Coastguard Worker
4647*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
4648*d9f75844SAndroid Build Coastguard Worker CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
4649*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
4650*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.GetLastVideoBitrateAllocation(), expected_bitrate);
4651*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_bitrate_allocations(), 1);
4652*d9f75844SAndroid Build Coastguard Worker
4653*d9f75844SAndroid Build Coastguard Worker // Check that encoder has been updated too, not just allocation observer.
4654*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(fake_encoder_.GetAndResetLastRateControlSettings().has_value());
4655*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Seconds(1) / kDefaultFps);
4656*d9f75844SAndroid Build Coastguard Worker
4657*d9f75844SAndroid Build Coastguard Worker // VideoBitrateAllocation not updated on second frame.
4658*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
4659*d9f75844SAndroid Build Coastguard Worker CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
4660*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
4661*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_bitrate_allocations(), 1);
4662*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Millis(1) / kDefaultFps);
4663*d9f75844SAndroid Build Coastguard Worker
4664*d9f75844SAndroid Build Coastguard Worker // VideoBitrateAllocation updated after a process interval.
4665*d9f75844SAndroid Build Coastguard Worker const int64_t start_time_ms = CurrentTimeMs();
4666*d9f75844SAndroid Build Coastguard Worker while (CurrentTimeMs() - start_time_ms < 5 * kProcessIntervalMs) {
4667*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
4668*d9f75844SAndroid Build Coastguard Worker CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
4669*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
4670*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Millis(1) / kDefaultFps);
4671*d9f75844SAndroid Build Coastguard Worker }
4672*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(sink_.number_of_bitrate_allocations(), 3);
4673*d9f75844SAndroid Build Coastguard Worker
4674*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4675*d9f75844SAndroid Build Coastguard Worker }
4676*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsVideoLayersAllocationForVP8Simulcast)4677*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, ReportsVideoLayersAllocationForVP8Simulcast) {
4678*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", /*num_streams*/ 2, 1, 1, /*screenshare*/ false,
4679*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
4680*d9f75844SAndroid Build Coastguard Worker kVideoLayersAllocation);
4681*d9f75844SAndroid Build Coastguard Worker
4682*d9f75844SAndroid Build Coastguard Worker const int kDefaultFps = 30;
4683*d9f75844SAndroid Build Coastguard Worker
4684*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4685*d9f75844SAndroid Build Coastguard Worker kLowTargetBitrate, kLowTargetBitrate, kLowTargetBitrate, 0, 0, 0);
4686*d9f75844SAndroid Build Coastguard Worker
4687*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
4688*d9f75844SAndroid Build Coastguard Worker CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
4689*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
4690*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
4691*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation last_layer_allocation =
4692*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation();
4693*d9f75844SAndroid Build Coastguard Worker // kLowTargetBitrate is only enough for one spatial layer.
4694*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(last_layer_allocation.active_spatial_layers.size(), 1u);
4695*d9f75844SAndroid Build Coastguard Worker
4696*d9f75844SAndroid Build Coastguard Worker VideoBitrateAllocation bitrate_allocation =
4697*d9f75844SAndroid Build Coastguard Worker fake_encoder_.GetAndResetLastRateControlSettings()->target_bitrate;
4698*d9f75844SAndroid Build Coastguard Worker // Check that encoder has been updated too, not just allocation observer.
4699*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(bitrate_allocation.get_sum_bps(), kLowTargetBitrate.bps());
4700*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Seconds(1) / kDefaultFps);
4701*d9f75844SAndroid Build Coastguard Worker
4702*d9f75844SAndroid Build Coastguard Worker // VideoLayersAllocation might be updated if frame rate changes.
4703*d9f75844SAndroid Build Coastguard Worker int number_of_layers_allocation = 1;
4704*d9f75844SAndroid Build Coastguard Worker const int64_t start_time_ms = CurrentTimeMs();
4705*d9f75844SAndroid Build Coastguard Worker while (CurrentTimeMs() - start_time_ms < 10 * kProcessIntervalMs) {
4706*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
4707*d9f75844SAndroid Build Coastguard Worker CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
4708*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
4709*d9f75844SAndroid Build Coastguard Worker if (number_of_layers_allocation != sink_.number_of_layers_allocations()) {
4710*d9f75844SAndroid Build Coastguard Worker number_of_layers_allocation = sink_.number_of_layers_allocations();
4711*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation new_allocation =
4712*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation();
4713*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(new_allocation.active_spatial_layers.size(), 1u);
4714*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(new_allocation.active_spatial_layers[0].frame_rate_fps,
4715*d9f75844SAndroid Build Coastguard Worker last_layer_allocation.active_spatial_layers[0].frame_rate_fps);
4716*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(new_allocation.active_spatial_layers[0]
4717*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
4718*d9f75844SAndroid Build Coastguard Worker last_layer_allocation.active_spatial_layers[0]
4719*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer);
4720*d9f75844SAndroid Build Coastguard Worker last_layer_allocation = new_allocation;
4721*d9f75844SAndroid Build Coastguard Worker }
4722*d9f75844SAndroid Build Coastguard Worker }
4723*d9f75844SAndroid Build Coastguard Worker EXPECT_LE(sink_.number_of_layers_allocations(), 3);
4724*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4725*d9f75844SAndroid Build Coastguard Worker }
4726*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsVideoLayersAllocationForVP8WithMiddleLayerDisabled)4727*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
4728*d9f75844SAndroid Build Coastguard Worker ReportsVideoLayersAllocationForVP8WithMiddleLayerDisabled) {
4729*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
4730*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
4731*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 2, true);
4732*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
4733*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP8,
4734*d9f75844SAndroid Build Coastguard Worker /* num_streams*/ 3, &video_encoder_config);
4735*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = 2 * kTargetBitrate.bps();
4736*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
4737*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
4738*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
4739*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp8EncoderSpecificSettings>(
4740*d9f75844SAndroid Build Coastguard Worker VideoEncoder::GetDefaultVp8Settings());
4741*d9f75844SAndroid Build Coastguard Worker for (auto& layer : video_encoder_config.simulcast_layers) {
4742*d9f75844SAndroid Build Coastguard Worker layer.num_temporal_layers = 2;
4743*d9f75844SAndroid Build Coastguard Worker }
4744*d9f75844SAndroid Build Coastguard Worker // Simulcast layers are used for enabling/disabling streams.
4745*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].active = true;
4746*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[1].active = false;
4747*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = true;
4748*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config),
4749*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
4750*d9f75844SAndroid Build Coastguard Worker kVideoLayersAllocation);
4751*d9f75844SAndroid Build Coastguard Worker
4752*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4753*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
4754*d9f75844SAndroid Build Coastguard Worker
4755*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
4756*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
4757*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
4758*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation last_layer_allocation =
4759*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation();
4760*d9f75844SAndroid Build Coastguard Worker
4761*d9f75844SAndroid Build Coastguard Worker ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(2));
4762*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
4763*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
4764*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
4765*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(last_layer_allocation.active_spatial_layers[0].width, 1280);
4766*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].width, 1280);
4767*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4768*d9f75844SAndroid Build Coastguard Worker }
4769*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsVideoLayersAllocationForVP8WithMiddleAndHighestLayerDisabled)4770*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
4771*d9f75844SAndroid Build Coastguard Worker ReportsVideoLayersAllocationForVP8WithMiddleAndHighestLayerDisabled) {
4772*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
4773*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
4774*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 2, true);
4775*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
4776*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP8,
4777*d9f75844SAndroid Build Coastguard Worker /* num_streams*/ 3, &video_encoder_config);
4778*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = 2 * kTargetBitrate.bps();
4779*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
4780*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
4781*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
4782*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp8EncoderSpecificSettings>(
4783*d9f75844SAndroid Build Coastguard Worker VideoEncoder::GetDefaultVp8Settings());
4784*d9f75844SAndroid Build Coastguard Worker for (auto& layer : video_encoder_config.simulcast_layers) {
4785*d9f75844SAndroid Build Coastguard Worker layer.num_temporal_layers = 2;
4786*d9f75844SAndroid Build Coastguard Worker }
4787*d9f75844SAndroid Build Coastguard Worker // Simulcast layers are used for enabling/disabling streams.
4788*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].active = true;
4789*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[1].active = false;
4790*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = false;
4791*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config),
4792*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
4793*d9f75844SAndroid Build Coastguard Worker kVideoLayersAllocation);
4794*d9f75844SAndroid Build Coastguard Worker
4795*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4796*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
4797*d9f75844SAndroid Build Coastguard Worker
4798*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
4799*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
4800*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
4801*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation last_layer_allocation =
4802*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation();
4803*d9f75844SAndroid Build Coastguard Worker
4804*d9f75844SAndroid Build Coastguard Worker ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(1));
4805*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
4806*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
4807*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
4808*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(last_layer_allocation.active_spatial_layers[0].width, 1280);
4809*d9f75844SAndroid Build Coastguard Worker
4810*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4811*d9f75844SAndroid Build Coastguard Worker }
4812*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsVideoLayersAllocationForV9SvcWithTemporalLayerSupport)4813*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
4814*d9f75844SAndroid Build Coastguard Worker ReportsVideoLayersAllocationForV9SvcWithTemporalLayerSupport) {
4815*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
4816*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
4817*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
4818*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
4819*d9f75844SAndroid Build Coastguard Worker /* num_streams*/ 1, &video_encoder_config);
4820*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = 2 * kTargetBitrate.bps();
4821*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
4822*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
4823*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
4824*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = 2;
4825*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfTemporalLayers = 2;
4826*d9f75844SAndroid Build Coastguard Worker vp9_settings.interLayerPred = InterLayerPredMode::kOn;
4827*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = false;
4828*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
4829*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
4830*d9f75844SAndroid Build Coastguard Worker vp9_settings);
4831*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config),
4832*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
4833*d9f75844SAndroid Build Coastguard Worker kVideoLayersAllocation);
4834*d9f75844SAndroid Build Coastguard Worker
4835*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4836*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
4837*d9f75844SAndroid Build Coastguard Worker
4838*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
4839*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
4840*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
4841*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation last_layer_allocation =
4842*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation();
4843*d9f75844SAndroid Build Coastguard Worker
4844*d9f75844SAndroid Build Coastguard Worker ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(2));
4845*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
4846*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
4847*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
4848*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].width, 640);
4849*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].height, 360);
4850*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].frame_rate_fps, 30);
4851*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[1]
4852*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
4853*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
4854*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].width, 1280);
4855*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].height, 720);
4856*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].frame_rate_fps, 30);
4857*d9f75844SAndroid Build Coastguard Worker
4858*d9f75844SAndroid Build Coastguard Worker // Since full SVC is used, expect the top layer to utilize the full target
4859*d9f75844SAndroid Build Coastguard Worker // rate.
4860*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[1]
4861*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer[1],
4862*d9f75844SAndroid Build Coastguard Worker kTargetBitrate);
4863*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4864*d9f75844SAndroid Build Coastguard Worker }
4865*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsVideoLayersAllocationForV9SvcWithoutTemporalLayerSupport)4866*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
4867*d9f75844SAndroid Build Coastguard Worker ReportsVideoLayersAllocationForV9SvcWithoutTemporalLayerSupport) {
4868*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, false);
4869*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, false);
4870*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
4871*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
4872*d9f75844SAndroid Build Coastguard Worker /* num_streams*/ 1, &video_encoder_config);
4873*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = 2 * kTargetBitrate.bps();
4874*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
4875*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
4876*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
4877*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = 2;
4878*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfTemporalLayers = 2;
4879*d9f75844SAndroid Build Coastguard Worker vp9_settings.interLayerPred = InterLayerPredMode::kOn;
4880*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = false;
4881*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
4882*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
4883*d9f75844SAndroid Build Coastguard Worker vp9_settings);
4884*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config),
4885*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
4886*d9f75844SAndroid Build Coastguard Worker kVideoLayersAllocation);
4887*d9f75844SAndroid Build Coastguard Worker
4888*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4889*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
4890*d9f75844SAndroid Build Coastguard Worker
4891*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
4892*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
4893*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
4894*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation last_layer_allocation =
4895*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation();
4896*d9f75844SAndroid Build Coastguard Worker
4897*d9f75844SAndroid Build Coastguard Worker ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(2));
4898*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
4899*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
4900*d9f75844SAndroid Build Coastguard Worker SizeIs(1));
4901*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[1]
4902*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
4903*d9f75844SAndroid Build Coastguard Worker SizeIs(1));
4904*d9f75844SAndroid Build Coastguard Worker // Since full SVC is used, expect the top layer to utilize the full target
4905*d9f75844SAndroid Build Coastguard Worker // rate.
4906*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[1]
4907*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer[0],
4908*d9f75844SAndroid Build Coastguard Worker kTargetBitrate);
4909*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4910*d9f75844SAndroid Build Coastguard Worker }
4911*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsVideoLayersAllocationForVP9KSvcWithTemporalLayerSupport)4912*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
4913*d9f75844SAndroid Build Coastguard Worker ReportsVideoLayersAllocationForVP9KSvcWithTemporalLayerSupport) {
4914*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
4915*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
4916*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
4917*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
4918*d9f75844SAndroid Build Coastguard Worker /* num_streams*/ 1, &video_encoder_config);
4919*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = 2 * kTargetBitrate.bps();
4920*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
4921*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
4922*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
4923*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = 2;
4924*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfTemporalLayers = 2;
4925*d9f75844SAndroid Build Coastguard Worker vp9_settings.interLayerPred = InterLayerPredMode::kOnKeyPic;
4926*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = false;
4927*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
4928*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
4929*d9f75844SAndroid Build Coastguard Worker vp9_settings);
4930*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config),
4931*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
4932*d9f75844SAndroid Build Coastguard Worker kVideoLayersAllocation);
4933*d9f75844SAndroid Build Coastguard Worker
4934*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4935*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
4936*d9f75844SAndroid Build Coastguard Worker
4937*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
4938*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
4939*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
4940*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation last_layer_allocation =
4941*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation();
4942*d9f75844SAndroid Build Coastguard Worker
4943*d9f75844SAndroid Build Coastguard Worker ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(2));
4944*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
4945*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
4946*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
4947*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[1]
4948*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
4949*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
4950*d9f75844SAndroid Build Coastguard Worker // Since KSVC is, spatial layers are independend except on key frames.
4951*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(last_layer_allocation.active_spatial_layers[1]
4952*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer[1],
4953*d9f75844SAndroid Build Coastguard Worker kTargetBitrate);
4954*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
4955*d9f75844SAndroid Build Coastguard Worker }
4956*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsVideoLayersAllocationForV9SvcWithLowestLayerDisabled)4957*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
4958*d9f75844SAndroid Build Coastguard Worker ReportsVideoLayersAllocationForV9SvcWithLowestLayerDisabled) {
4959*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
4960*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
4961*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 2, true);
4962*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
4963*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
4964*d9f75844SAndroid Build Coastguard Worker /* num_streams*/ 1, &video_encoder_config);
4965*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = 2 * kTargetBitrate.bps();
4966*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
4967*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
4968*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
4969*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = 3;
4970*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfTemporalLayers = 2;
4971*d9f75844SAndroid Build Coastguard Worker vp9_settings.interLayerPred = InterLayerPredMode::kOn;
4972*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = false;
4973*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
4974*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
4975*d9f75844SAndroid Build Coastguard Worker vp9_settings);
4976*d9f75844SAndroid Build Coastguard Worker // Simulcast layers are used for enabling/disabling streams.
4977*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers.resize(3);
4978*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].active = false;
4979*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[1].active = true;
4980*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = true;
4981*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config),
4982*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
4983*d9f75844SAndroid Build Coastguard Worker kVideoLayersAllocation);
4984*d9f75844SAndroid Build Coastguard Worker
4985*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
4986*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
4987*d9f75844SAndroid Build Coastguard Worker
4988*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
4989*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
4990*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
4991*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation last_layer_allocation =
4992*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation();
4993*d9f75844SAndroid Build Coastguard Worker
4994*d9f75844SAndroid Build Coastguard Worker ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(2));
4995*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
4996*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
4997*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
4998*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].width, 640);
4999*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].spatial_id, 0);
5000*d9f75844SAndroid Build Coastguard Worker
5001*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].width, 1280);
5002*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].spatial_id, 1);
5003*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[1]
5004*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
5005*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
5006*d9f75844SAndroid Build Coastguard Worker // Since full SVC is used, expect the top layer to utilize the full target
5007*d9f75844SAndroid Build Coastguard Worker // rate.
5008*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[1]
5009*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer[1],
5010*d9f75844SAndroid Build Coastguard Worker kTargetBitrate);
5011*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5012*d9f75844SAndroid Build Coastguard Worker }
5013*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsVideoLayersAllocationForV9SvcWithHighestLayerDisabled)5014*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
5015*d9f75844SAndroid Build Coastguard Worker ReportsVideoLayersAllocationForV9SvcWithHighestLayerDisabled) {
5016*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
5017*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
5018*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 2, true);
5019*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
5020*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
5021*d9f75844SAndroid Build Coastguard Worker /* num_streams*/ 1, &video_encoder_config);
5022*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = 2 * kTargetBitrate.bps();
5023*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
5024*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
5025*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
5026*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = 3;
5027*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfTemporalLayers = 2;
5028*d9f75844SAndroid Build Coastguard Worker vp9_settings.interLayerPred = InterLayerPredMode::kOn;
5029*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = false;
5030*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
5031*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
5032*d9f75844SAndroid Build Coastguard Worker vp9_settings);
5033*d9f75844SAndroid Build Coastguard Worker // Simulcast layers are used for enabling/disabling streams.
5034*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers.resize(3);
5035*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = false;
5036*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config),
5037*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
5038*d9f75844SAndroid Build Coastguard Worker kVideoLayersAllocation);
5039*d9f75844SAndroid Build Coastguard Worker
5040*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5041*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
5042*d9f75844SAndroid Build Coastguard Worker
5043*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
5044*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
5045*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
5046*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation last_layer_allocation =
5047*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation();
5048*d9f75844SAndroid Build Coastguard Worker
5049*d9f75844SAndroid Build Coastguard Worker ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(2));
5050*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
5051*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
5052*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
5053*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].width, 320);
5054*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].spatial_id, 0);
5055*d9f75844SAndroid Build Coastguard Worker
5056*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].width, 640);
5057*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[1].spatial_id, 1);
5058*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[1]
5059*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
5060*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
5061*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5062*d9f75844SAndroid Build Coastguard Worker }
5063*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsVideoLayersAllocationForV9SvcWithAllButHighestLayerDisabled)5064*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
5065*d9f75844SAndroid Build Coastguard Worker ReportsVideoLayersAllocationForV9SvcWithAllButHighestLayerDisabled) {
5066*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx=*/0, true);
5067*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 1, true);
5068*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(/*spatial_idx*/ 2, true);
5069*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
5070*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(VideoCodecType::kVideoCodecVP9,
5071*d9f75844SAndroid Build Coastguard Worker /* num_streams*/ 1, &video_encoder_config);
5072*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = 2 * kTargetBitrate.bps();
5073*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
5074*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
5075*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
5076*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = 3;
5077*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfTemporalLayers = 2;
5078*d9f75844SAndroid Build Coastguard Worker vp9_settings.interLayerPred = InterLayerPredMode::kOn;
5079*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = false;
5080*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
5081*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
5082*d9f75844SAndroid Build Coastguard Worker vp9_settings);
5083*d9f75844SAndroid Build Coastguard Worker // Simulcast layers are used for enabling/disabling streams.
5084*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers.resize(3);
5085*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].active = false;
5086*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[1].active = false;
5087*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = true;
5088*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config),
5089*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
5090*d9f75844SAndroid Build Coastguard Worker kVideoLayersAllocation);
5091*d9f75844SAndroid Build Coastguard Worker
5092*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5093*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
5094*d9f75844SAndroid Build Coastguard Worker
5095*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
5096*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
5097*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
5098*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation last_layer_allocation =
5099*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation();
5100*d9f75844SAndroid Build Coastguard Worker
5101*d9f75844SAndroid Build Coastguard Worker ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(1));
5102*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(last_layer_allocation.active_spatial_layers[0]
5103*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
5104*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
5105*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].width, 1280);
5106*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].spatial_id, 0);
5107*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0]
5108*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer[1],
5109*d9f75844SAndroid Build Coastguard Worker kTargetBitrate);
5110*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5111*d9f75844SAndroid Build Coastguard Worker }
5112*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsVideoLayersAllocationForH264)5113*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, ReportsVideoLayersAllocationForH264) {
5114*d9f75844SAndroid Build Coastguard Worker ResetEncoder("H264", 1, 1, 1, false,
5115*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
5116*d9f75844SAndroid Build Coastguard Worker kVideoLayersAllocation);
5117*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5118*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
5119*d9f75844SAndroid Build Coastguard Worker
5120*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(CurrentTimeMs(), 1280, 720));
5121*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
5122*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
5123*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation last_layer_allocation =
5124*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation();
5125*d9f75844SAndroid Build Coastguard Worker
5126*d9f75844SAndroid Build Coastguard Worker ASSERT_THAT(last_layer_allocation.active_spatial_layers, SizeIs(1));
5127*d9f75844SAndroid Build Coastguard Worker ASSERT_THAT(last_layer_allocation.active_spatial_layers[0]
5128*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer,
5129*d9f75844SAndroid Build Coastguard Worker SizeIs(1));
5130*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0]
5131*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer[0],
5132*d9f75844SAndroid Build Coastguard Worker kTargetBitrate);
5133*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].width, 1280);
5134*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].height, 720);
5135*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0].frame_rate_fps, 30);
5136*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5137*d9f75844SAndroid Build Coastguard Worker }
5138*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsUpdatedVideoLayersAllocationWhenBweChanges)5139*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
5140*d9f75844SAndroid Build Coastguard Worker ReportsUpdatedVideoLayersAllocationWhenBweChanges) {
5141*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", /*num_streams*/ 2, 1, 1, /*screenshare*/ false,
5142*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
5143*d9f75844SAndroid Build Coastguard Worker kVideoLayersAllocation);
5144*d9f75844SAndroid Build Coastguard Worker
5145*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5146*d9f75844SAndroid Build Coastguard Worker kLowTargetBitrate, kLowTargetBitrate, kLowTargetBitrate, 0, 0, 0);
5147*d9f75844SAndroid Build Coastguard Worker
5148*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
5149*d9f75844SAndroid Build Coastguard Worker CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
5150*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
5151*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
5152*d9f75844SAndroid Build Coastguard Worker VideoLayersAllocation last_layer_allocation =
5153*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation();
5154*d9f75844SAndroid Build Coastguard Worker // kLowTargetBitrate is only enough for one spatial layer.
5155*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(last_layer_allocation.active_spatial_layers.size(), 1u);
5156*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(last_layer_allocation.active_spatial_layers[0]
5157*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer[0],
5158*d9f75844SAndroid Build Coastguard Worker kLowTargetBitrate);
5159*d9f75844SAndroid Build Coastguard Worker
5160*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5161*d9f75844SAndroid Build Coastguard Worker kSimulcastTargetBitrate, kSimulcastTargetBitrate, kSimulcastTargetBitrate,
5162*d9f75844SAndroid Build Coastguard Worker 0, 0, 0);
5163*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
5164*d9f75844SAndroid Build Coastguard Worker CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
5165*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
5166*d9f75844SAndroid Build Coastguard Worker
5167*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 2);
5168*d9f75844SAndroid Build Coastguard Worker last_layer_allocation = sink_.GetLastVideoLayersAllocation();
5169*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(last_layer_allocation.active_spatial_layers.size(), 2u);
5170*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(last_layer_allocation.active_spatial_layers[1]
5171*d9f75844SAndroid Build Coastguard Worker .target_bitrate_per_temporal_layer[0],
5172*d9f75844SAndroid Build Coastguard Worker DataRate::Zero());
5173*d9f75844SAndroid Build Coastguard Worker
5174*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5175*d9f75844SAndroid Build Coastguard Worker }
5176*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ReportsUpdatedVideoLayersAllocationWhenResolutionChanges)5177*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
5178*d9f75844SAndroid Build Coastguard Worker ReportsUpdatedVideoLayersAllocationWhenResolutionChanges) {
5179*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", /*num_streams*/ 2, 1, 1, /*screenshare*/ false,
5180*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
5181*d9f75844SAndroid Build Coastguard Worker kVideoLayersAllocation);
5182*d9f75844SAndroid Build Coastguard Worker
5183*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5184*d9f75844SAndroid Build Coastguard Worker kSimulcastTargetBitrate, kSimulcastTargetBitrate, kSimulcastTargetBitrate,
5185*d9f75844SAndroid Build Coastguard Worker 0, 0, 0);
5186*d9f75844SAndroid Build Coastguard Worker
5187*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
5188*d9f75844SAndroid Build Coastguard Worker CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
5189*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
5190*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 1);
5191*d9f75844SAndroid Build Coastguard Worker ASSERT_THAT(sink_.GetLastVideoLayersAllocation().active_spatial_layers,
5192*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
5193*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.GetLastVideoLayersAllocation().active_spatial_layers[1].width,
5194*d9f75844SAndroid Build Coastguard Worker codec_width_);
5195*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
5196*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation().active_spatial_layers[1].height,
5197*d9f75844SAndroid Build Coastguard Worker codec_height_);
5198*d9f75844SAndroid Build Coastguard Worker
5199*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
5200*d9f75844SAndroid Build Coastguard Worker CreateFrame(CurrentTimeMs(), codec_width_ / 2, codec_height_ / 2));
5201*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(CurrentTimeMs());
5202*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_layers_allocations(), 2);
5203*d9f75844SAndroid Build Coastguard Worker ASSERT_THAT(sink_.GetLastVideoLayersAllocation().active_spatial_layers,
5204*d9f75844SAndroid Build Coastguard Worker SizeIs(2));
5205*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.GetLastVideoLayersAllocation().active_spatial_layers[1].width,
5206*d9f75844SAndroid Build Coastguard Worker codec_width_ / 2);
5207*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
5208*d9f75844SAndroid Build Coastguard Worker sink_.GetLastVideoLayersAllocation().active_spatial_layers[1].height,
5209*d9f75844SAndroid Build Coastguard Worker codec_height_ / 2);
5210*d9f75844SAndroid Build Coastguard Worker
5211*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5212*d9f75844SAndroid Build Coastguard Worker }
5213*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,TemporalLayersNotDisabledIfSupported)5214*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, TemporalLayersNotDisabledIfSupported) {
5215*d9f75844SAndroid Build Coastguard Worker // 2 TLs configured, temporal layers supported by encoder.
5216*d9f75844SAndroid Build Coastguard Worker const int kNumTemporalLayers = 2;
5217*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", 1, kNumTemporalLayers, 1, /*screenshare*/ false,
5218*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
5219*d9f75844SAndroid Build Coastguard Worker kVideoBitrateAllocation);
5220*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(0, true);
5221*d9f75844SAndroid Build Coastguard Worker
5222*d9f75844SAndroid Build Coastguard Worker // Bitrate allocated across temporal layers.
5223*d9f75844SAndroid Build Coastguard Worker const int kTl0Bps = kTargetBitrate.bps() *
5224*d9f75844SAndroid Build Coastguard Worker webrtc::SimulcastRateAllocator::GetTemporalRateAllocation(
5225*d9f75844SAndroid Build Coastguard Worker kNumTemporalLayers, /*temporal_id*/ 0,
5226*d9f75844SAndroid Build Coastguard Worker /*base_heavy_tl3_alloc*/ false);
5227*d9f75844SAndroid Build Coastguard Worker const int kTl1Bps = kTargetBitrate.bps() *
5228*d9f75844SAndroid Build Coastguard Worker webrtc::SimulcastRateAllocator::GetTemporalRateAllocation(
5229*d9f75844SAndroid Build Coastguard Worker kNumTemporalLayers, /*temporal_id*/ 1,
5230*d9f75844SAndroid Build Coastguard Worker /*base_heavy_tl3_alloc*/ false);
5231*d9f75844SAndroid Build Coastguard Worker VideoBitrateAllocation expected_bitrate;
5232*d9f75844SAndroid Build Coastguard Worker expected_bitrate.SetBitrate(/*si*/ 0, /*ti*/ 0, kTl0Bps);
5233*d9f75844SAndroid Build Coastguard Worker expected_bitrate.SetBitrate(/*si*/ 0, /*ti*/ 1, kTl1Bps - kTl0Bps);
5234*d9f75844SAndroid Build Coastguard Worker
5235*d9f75844SAndroid Build Coastguard Worker VerifyAllocatedBitrate(expected_bitrate);
5236*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5237*d9f75844SAndroid Build Coastguard Worker }
5238*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,TemporalLayersDisabledIfNotSupported)5239*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, TemporalLayersDisabledIfNotSupported) {
5240*d9f75844SAndroid Build Coastguard Worker // 2 TLs configured, temporal layers not supported by encoder.
5241*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", 1, /*num_temporal_layers*/ 2, 1, /*screenshare*/ false,
5242*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
5243*d9f75844SAndroid Build Coastguard Worker kVideoBitrateAllocation);
5244*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(0, false);
5245*d9f75844SAndroid Build Coastguard Worker
5246*d9f75844SAndroid Build Coastguard Worker // Temporal layers not supported by the encoder.
5247*d9f75844SAndroid Build Coastguard Worker // Total bitrate should be at ti:0.
5248*d9f75844SAndroid Build Coastguard Worker VideoBitrateAllocation expected_bitrate;
5249*d9f75844SAndroid Build Coastguard Worker expected_bitrate.SetBitrate(/*si*/ 0, /*ti*/ 0, kTargetBitrate.bps());
5250*d9f75844SAndroid Build Coastguard Worker
5251*d9f75844SAndroid Build Coastguard Worker VerifyAllocatedBitrate(expected_bitrate);
5252*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5253*d9f75844SAndroid Build Coastguard Worker }
5254*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,VerifyBitrateAllocationForTwoStreams)5255*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, VerifyBitrateAllocationForTwoStreams) {
5256*d9f75844SAndroid Build Coastguard Worker webrtc::test::ScopedKeyValueConfig field_trials(
5257*d9f75844SAndroid Build Coastguard Worker field_trials_,
5258*d9f75844SAndroid Build Coastguard Worker "WebRTC-Video-QualityScalerSettings/"
5259*d9f75844SAndroid Build Coastguard Worker "initial_bitrate_interval_ms:1000,initial_bitrate_factor:0.2/");
5260*d9f75844SAndroid Build Coastguard Worker // Reset encoder for field trials to take effect.
5261*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config_.Copy());
5262*d9f75844SAndroid Build Coastguard Worker
5263*d9f75844SAndroid Build Coastguard Worker // 2 TLs configured, temporal layers only supported for first stream.
5264*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", 2, /*num_temporal_layers*/ 2, 1, /*screenshare*/ false,
5265*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
5266*d9f75844SAndroid Build Coastguard Worker kVideoBitrateAllocation);
5267*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(0, true);
5268*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetTemporalLayersSupported(1, false);
5269*d9f75844SAndroid Build Coastguard Worker
5270*d9f75844SAndroid Build Coastguard Worker const int kS0Bps = 150000;
5271*d9f75844SAndroid Build Coastguard Worker const int kS0Tl0Bps =
5272*d9f75844SAndroid Build Coastguard Worker kS0Bps *
5273*d9f75844SAndroid Build Coastguard Worker webrtc::SimulcastRateAllocator::GetTemporalRateAllocation(
5274*d9f75844SAndroid Build Coastguard Worker /*num_layers*/ 2, /*temporal_id*/ 0, /*base_heavy_tl3_alloc*/ false);
5275*d9f75844SAndroid Build Coastguard Worker const int kS0Tl1Bps =
5276*d9f75844SAndroid Build Coastguard Worker kS0Bps *
5277*d9f75844SAndroid Build Coastguard Worker webrtc::SimulcastRateAllocator::GetTemporalRateAllocation(
5278*d9f75844SAndroid Build Coastguard Worker /*num_layers*/ 2, /*temporal_id*/ 1, /*base_heavy_tl3_alloc*/ false);
5279*d9f75844SAndroid Build Coastguard Worker const int kS1Bps = kTargetBitrate.bps() - kS0Tl1Bps;
5280*d9f75844SAndroid Build Coastguard Worker // Temporal layers not supported by si:1.
5281*d9f75844SAndroid Build Coastguard Worker VideoBitrateAllocation expected_bitrate;
5282*d9f75844SAndroid Build Coastguard Worker expected_bitrate.SetBitrate(/*si*/ 0, /*ti*/ 0, kS0Tl0Bps);
5283*d9f75844SAndroid Build Coastguard Worker expected_bitrate.SetBitrate(/*si*/ 0, /*ti*/ 1, kS0Tl1Bps - kS0Tl0Bps);
5284*d9f75844SAndroid Build Coastguard Worker expected_bitrate.SetBitrate(/*si*/ 1, /*ti*/ 0, kS1Bps);
5285*d9f75844SAndroid Build Coastguard Worker
5286*d9f75844SAndroid Build Coastguard Worker VerifyAllocatedBitrate(expected_bitrate);
5287*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5288*d9f75844SAndroid Build Coastguard Worker }
5289*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,OveruseDetectorUpdatedOnReconfigureAndAdaption)5290*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, OveruseDetectorUpdatedOnReconfigureAndAdaption) {
5291*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
5292*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
5293*d9f75844SAndroid Build Coastguard Worker const int kFramerate = 24;
5294*d9f75844SAndroid Build Coastguard Worker
5295*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5296*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
5297*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
5298*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
5299*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
5300*d9f75844SAndroid Build Coastguard Worker
5301*d9f75844SAndroid Build Coastguard Worker // Insert a single frame, triggering initial configuration.
5302*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kFrameWidth, kFrameHeight));
5303*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5304*d9f75844SAndroid Build Coastguard Worker
5305*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
5306*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
5307*d9f75844SAndroid Build Coastguard Worker kDefaultFramerate);
5308*d9f75844SAndroid Build Coastguard Worker
5309*d9f75844SAndroid Build Coastguard Worker // Trigger reconfigure encoder (without resetting the entire instance).
5310*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
5311*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
5312*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].max_framerate = kFramerate;
5313*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kTargetBitrate.bps();
5314*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
5315*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5316*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5317*d9f75844SAndroid Build Coastguard Worker
5318*d9f75844SAndroid Build Coastguard Worker // Detector should be updated with fps limit from codec config.
5319*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
5320*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
5321*d9f75844SAndroid Build Coastguard Worker kFramerate);
5322*d9f75844SAndroid Build Coastguard Worker
5323*d9f75844SAndroid Build Coastguard Worker // Trigger overuse, max framerate should be reduced.
5324*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
5325*d9f75844SAndroid Build Coastguard Worker stats.input_frame_rate = kFramerate;
5326*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(stats);
5327*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
5328*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5329*d9f75844SAndroid Build Coastguard Worker int adapted_framerate =
5330*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->overuse_detector_proxy_->GetLastTargetFramerate();
5331*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(adapted_framerate, kFramerate);
5332*d9f75844SAndroid Build Coastguard Worker
5333*d9f75844SAndroid Build Coastguard Worker // Trigger underuse, max framerate should go back to codec configured fps.
5334*d9f75844SAndroid Build Coastguard Worker // Set extra low fps, to make sure it's actually reset, not just incremented.
5335*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
5336*d9f75844SAndroid Build Coastguard Worker stats.input_frame_rate = adapted_framerate / 2;
5337*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(stats);
5338*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
5339*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5340*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
5341*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
5342*d9f75844SAndroid Build Coastguard Worker kFramerate);
5343*d9f75844SAndroid Build Coastguard Worker
5344*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5345*d9f75844SAndroid Build Coastguard Worker }
5346*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,OveruseDetectorUpdatedRespectsFramerateAfterUnderuse)5347*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
5348*d9f75844SAndroid Build Coastguard Worker OveruseDetectorUpdatedRespectsFramerateAfterUnderuse) {
5349*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
5350*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
5351*d9f75844SAndroid Build Coastguard Worker const int kLowFramerate = 15;
5352*d9f75844SAndroid Build Coastguard Worker const int kHighFramerate = 25;
5353*d9f75844SAndroid Build Coastguard Worker
5354*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5355*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
5356*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
5357*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
5358*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
5359*d9f75844SAndroid Build Coastguard Worker
5360*d9f75844SAndroid Build Coastguard Worker // Trigger initial configuration.
5361*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
5362*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
5363*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].max_framerate = kLowFramerate;
5364*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kTargetBitrate.bps();
5365*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kFrameWidth, kFrameHeight));
5366*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
5367*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5368*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5369*d9f75844SAndroid Build Coastguard Worker
5370*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
5371*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
5372*d9f75844SAndroid Build Coastguard Worker kLowFramerate);
5373*d9f75844SAndroid Build Coastguard Worker
5374*d9f75844SAndroid Build Coastguard Worker // Trigger overuse, max framerate should be reduced.
5375*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
5376*d9f75844SAndroid Build Coastguard Worker stats.input_frame_rate = kLowFramerate;
5377*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(stats);
5378*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
5379*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5380*d9f75844SAndroid Build Coastguard Worker int adapted_framerate =
5381*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->overuse_detector_proxy_->GetLastTargetFramerate();
5382*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(adapted_framerate, kLowFramerate);
5383*d9f75844SAndroid Build Coastguard Worker
5384*d9f75844SAndroid Build Coastguard Worker // Reconfigure the encoder with a new (higher max framerate), max fps should
5385*d9f75844SAndroid Build Coastguard Worker // still respect the adaptation.
5386*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].max_framerate = kHighFramerate;
5387*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kFrameWidth, kFrameHeight));
5388*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
5389*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5390*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5391*d9f75844SAndroid Build Coastguard Worker
5392*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
5393*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
5394*d9f75844SAndroid Build Coastguard Worker adapted_framerate);
5395*d9f75844SAndroid Build Coastguard Worker
5396*d9f75844SAndroid Build Coastguard Worker // Trigger underuse, max framerate should go back to codec configured fps.
5397*d9f75844SAndroid Build Coastguard Worker stats = stats_proxy_->GetStats();
5398*d9f75844SAndroid Build Coastguard Worker stats.input_frame_rate = adapted_framerate;
5399*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(stats);
5400*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
5401*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5402*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
5403*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
5404*d9f75844SAndroid Build Coastguard Worker kHighFramerate);
5405*d9f75844SAndroid Build Coastguard Worker
5406*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5407*d9f75844SAndroid Build Coastguard Worker }
5408*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,OveruseDetectorUpdatedOnDegradationPreferenceChange)5409*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
5410*d9f75844SAndroid Build Coastguard Worker OveruseDetectorUpdatedOnDegradationPreferenceChange) {
5411*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
5412*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
5413*d9f75844SAndroid Build Coastguard Worker const int kFramerate = 24;
5414*d9f75844SAndroid Build Coastguard Worker
5415*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5416*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
5417*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
5418*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
5419*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
5420*d9f75844SAndroid Build Coastguard Worker
5421*d9f75844SAndroid Build Coastguard Worker // Trigger initial configuration.
5422*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
5423*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
5424*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].max_framerate = kFramerate;
5425*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kTargetBitrate.bps();
5426*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kFrameWidth, kFrameHeight));
5427*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
5428*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5429*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5430*d9f75844SAndroid Build Coastguard Worker
5431*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
5432*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
5433*d9f75844SAndroid Build Coastguard Worker kFramerate);
5434*d9f75844SAndroid Build Coastguard Worker
5435*d9f75844SAndroid Build Coastguard Worker // Trigger overuse, max framerate should be reduced.
5436*d9f75844SAndroid Build Coastguard Worker VideoSendStream::Stats stats = stats_proxy_->GetStats();
5437*d9f75844SAndroid Build Coastguard Worker stats.input_frame_rate = kFramerate;
5438*d9f75844SAndroid Build Coastguard Worker stats_proxy_->SetMockStats(stats);
5439*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
5440*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5441*d9f75844SAndroid Build Coastguard Worker int adapted_framerate =
5442*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->overuse_detector_proxy_->GetLastTargetFramerate();
5443*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(adapted_framerate, kFramerate);
5444*d9f75844SAndroid Build Coastguard Worker
5445*d9f75844SAndroid Build Coastguard Worker // Change degradation preference to not enable framerate scaling. Target
5446*d9f75844SAndroid Build Coastguard Worker // framerate should be changed to codec defined limit.
5447*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSourceAndWaitForFramerateUpdated(
5448*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
5449*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
5450*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
5451*d9f75844SAndroid Build Coastguard Worker kFramerate);
5452*d9f75844SAndroid Build Coastguard Worker
5453*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5454*d9f75844SAndroid Build Coastguard Worker }
5455*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DropsFramesAndScalesWhenBitrateIsTooLow)5456*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DropsFramesAndScalesWhenBitrateIsTooLow) {
5457*d9f75844SAndroid Build Coastguard Worker const int kTooLowBitrateForFrameSizeBps = 10000;
5458*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5459*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kTooLowBitrateForFrameSizeBps),
5460*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kTooLowBitrateForFrameSizeBps),
5461*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kTooLowBitrateForFrameSizeBps), 0, 0, 0);
5462*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
5463*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
5464*d9f75844SAndroid Build Coastguard Worker
5465*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
5466*d9f75844SAndroid Build Coastguard Worker
5467*d9f75844SAndroid Build Coastguard Worker // Expect to drop this frame, the wait should time out.
5468*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
5469*d9f75844SAndroid Build Coastguard Worker
5470*d9f75844SAndroid Build Coastguard Worker // Expect the sink_wants to specify a scaled frame.
5471*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(
5472*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants().max_pixel_count < kWidth * kHeight, 5000);
5473*d9f75844SAndroid Build Coastguard Worker
5474*d9f75844SAndroid Build Coastguard Worker int last_pixel_count = video_source_.sink_wants().max_pixel_count;
5475*d9f75844SAndroid Build Coastguard Worker
5476*d9f75844SAndroid Build Coastguard Worker // Next frame is scaled.
5477*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
5478*d9f75844SAndroid Build Coastguard Worker CreateFrame(2, kWidth * 3 / 4, kHeight * 3 / 4));
5479*d9f75844SAndroid Build Coastguard Worker
5480*d9f75844SAndroid Build Coastguard Worker // Expect to drop this frame, the wait should time out.
5481*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
5482*d9f75844SAndroid Build Coastguard Worker
5483*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(
5484*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants().max_pixel_count < last_pixel_count, 5000);
5485*d9f75844SAndroid Build Coastguard Worker
5486*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5487*d9f75844SAndroid Build Coastguard Worker }
5488*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NumberOfDroppedFramesLimitedWhenBitrateIsTooLow)5489*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
5490*d9f75844SAndroid Build Coastguard Worker NumberOfDroppedFramesLimitedWhenBitrateIsTooLow) {
5491*d9f75844SAndroid Build Coastguard Worker const int kTooLowBitrateForFrameSizeBps = 10000;
5492*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5493*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kTooLowBitrateForFrameSizeBps),
5494*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kTooLowBitrateForFrameSizeBps),
5495*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kTooLowBitrateForFrameSizeBps), 0, 0, 0);
5496*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
5497*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
5498*d9f75844SAndroid Build Coastguard Worker
5499*d9f75844SAndroid Build Coastguard Worker // We expect the n initial frames to get dropped.
5500*d9f75844SAndroid Build Coastguard Worker int i;
5501*d9f75844SAndroid Build Coastguard Worker for (i = 1; i <= kMaxInitialFramedrop; ++i) {
5502*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(i, kWidth, kHeight));
5503*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
5504*d9f75844SAndroid Build Coastguard Worker }
5505*d9f75844SAndroid Build Coastguard Worker // The n+1th frame should not be dropped, even though it's size is too large.
5506*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(i, kWidth, kHeight));
5507*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(i);
5508*d9f75844SAndroid Build Coastguard Worker
5509*d9f75844SAndroid Build Coastguard Worker // Expect the sink_wants to specify a scaled frame.
5510*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(video_source_.sink_wants().max_pixel_count, kWidth * kHeight);
5511*d9f75844SAndroid Build Coastguard Worker
5512*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5513*d9f75844SAndroid Build Coastguard Worker }
5514*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,InitialFrameDropOffWithMaintainResolutionPreference)5515*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
5516*d9f75844SAndroid Build Coastguard Worker InitialFrameDropOffWithMaintainResolutionPreference) {
5517*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
5518*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
5519*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5520*d9f75844SAndroid Build Coastguard Worker kLowTargetBitrate, kLowTargetBitrate, kLowTargetBitrate, 0, 0, 0);
5521*d9f75844SAndroid Build Coastguard Worker
5522*d9f75844SAndroid Build Coastguard Worker // Set degradation preference.
5523*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
5524*d9f75844SAndroid Build Coastguard Worker &video_source_, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
5525*d9f75844SAndroid Build Coastguard Worker
5526*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
5527*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped, even if it's too large.
5528*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
5529*d9f75844SAndroid Build Coastguard Worker
5530*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5531*d9f75844SAndroid Build Coastguard Worker }
5532*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,InitialFrameDropOffWhenEncoderDisabledScaling)5533*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, InitialFrameDropOffWhenEncoderDisabledScaling) {
5534*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
5535*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
5536*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
5537*d9f75844SAndroid Build Coastguard Worker
5538*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
5539*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
5540*d9f75844SAndroid Build Coastguard Worker // Make format different, to force recreation of encoder.
5541*d9f75844SAndroid Build Coastguard Worker video_encoder_config.video_format.parameters["foo"] = "foo";
5542*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
5543*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5544*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5545*d9f75844SAndroid Build Coastguard Worker kLowTargetBitrate, kLowTargetBitrate, kLowTargetBitrate, 0, 0, 0);
5546*d9f75844SAndroid Build Coastguard Worker
5547*d9f75844SAndroid Build Coastguard Worker // Force quality scaler reconfiguration by resetting the source.
5548*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&video_source_,
5549*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
5550*d9f75844SAndroid Build Coastguard Worker
5551*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
5552*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped, even if it's too large.
5553*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
5554*d9f75844SAndroid Build Coastguard Worker
5555*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5556*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(true);
5557*d9f75844SAndroid Build Coastguard Worker }
5558*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,InitialFrameDropActivatesWhenBweDrops)5559*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, InitialFrameDropActivatesWhenBweDrops) {
5560*d9f75844SAndroid Build Coastguard Worker webrtc::test::ScopedKeyValueConfig field_trials(
5561*d9f75844SAndroid Build Coastguard Worker field_trials_,
5562*d9f75844SAndroid Build Coastguard Worker "WebRTC-Video-QualityScalerSettings/"
5563*d9f75844SAndroid Build Coastguard Worker "initial_bitrate_interval_ms:1000,initial_bitrate_factor:0.2/");
5564*d9f75844SAndroid Build Coastguard Worker // Reset encoder for field trials to take effect.
5565*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config_.Copy());
5566*d9f75844SAndroid Build Coastguard Worker const int kNotTooLowBitrateForFrameSizeBps = kTargetBitrate.bps() * 0.2;
5567*d9f75844SAndroid Build Coastguard Worker const int kTooLowBitrateForFrameSizeBps = kTargetBitrate.bps() * 0.19;
5568*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
5569*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
5570*d9f75844SAndroid Build Coastguard Worker
5571*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5572*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
5573*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
5574*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped.
5575*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
5576*d9f75844SAndroid Build Coastguard Worker
5577*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5578*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kNotTooLowBitrateForFrameSizeBps),
5579*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kNotTooLowBitrateForFrameSizeBps),
5580*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kNotTooLowBitrateForFrameSizeBps), 0, 0, 0);
5581*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
5582*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped.
5583*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
5584*d9f75844SAndroid Build Coastguard Worker
5585*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5586*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kTooLowBitrateForFrameSizeBps),
5587*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kTooLowBitrateForFrameSizeBps),
5588*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kTooLowBitrateForFrameSizeBps), 0, 0, 0);
5589*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
5590*d9f75844SAndroid Build Coastguard Worker // Expect to drop this frame, the wait should time out.
5591*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
5592*d9f75844SAndroid Build Coastguard Worker
5593*d9f75844SAndroid Build Coastguard Worker // Expect the sink_wants to specify a scaled frame.
5594*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(
5595*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants().max_pixel_count < kWidth * kHeight, 5000);
5596*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5597*d9f75844SAndroid Build Coastguard Worker }
5598*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,InitialFrameDropNotReactivatedWhenBweDropsWhenScalingDisabled)5599*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
5600*d9f75844SAndroid Build Coastguard Worker InitialFrameDropNotReactivatedWhenBweDropsWhenScalingDisabled) {
5601*d9f75844SAndroid Build Coastguard Worker webrtc::test::ScopedKeyValueConfig field_trials(
5602*d9f75844SAndroid Build Coastguard Worker field_trials_,
5603*d9f75844SAndroid Build Coastguard Worker "WebRTC-Video-QualityScalerSettings/"
5604*d9f75844SAndroid Build Coastguard Worker "initial_bitrate_interval_ms:1000,initial_bitrate_factor:0.2/");
5605*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
5606*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config_.Copy());
5607*d9f75844SAndroid Build Coastguard Worker const int kNotTooLowBitrateForFrameSizeBps = kTargetBitrate.bps() * 0.2;
5608*d9f75844SAndroid Build Coastguard Worker const int kTooLowBitrateForFrameSizeBps = kTargetBitrate.bps() * 0.19;
5609*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
5610*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
5611*d9f75844SAndroid Build Coastguard Worker
5612*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5613*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
5614*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
5615*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped.
5616*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
5617*d9f75844SAndroid Build Coastguard Worker
5618*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5619*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kNotTooLowBitrateForFrameSizeBps),
5620*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kNotTooLowBitrateForFrameSizeBps),
5621*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kNotTooLowBitrateForFrameSizeBps), 0, 0, 0);
5622*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
5623*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped.
5624*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
5625*d9f75844SAndroid Build Coastguard Worker
5626*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5627*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kTooLowBitrateForFrameSizeBps),
5628*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kTooLowBitrateForFrameSizeBps),
5629*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kTooLowBitrateForFrameSizeBps), 0, 0, 0);
5630*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
5631*d9f75844SAndroid Build Coastguard Worker // Not dropped since quality scaling is disabled.
5632*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
5633*d9f75844SAndroid Build Coastguard Worker
5634*d9f75844SAndroid Build Coastguard Worker // Expect the sink_wants to specify a scaled frame.
5635*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5636*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(), ResolutionMax());
5637*d9f75844SAndroid Build Coastguard Worker
5638*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5639*d9f75844SAndroid Build Coastguard Worker }
5640*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,InitialFrameDropActivatesWhenLayersChange)5641*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, InitialFrameDropActivatesWhenLayersChange) {
5642*d9f75844SAndroid Build Coastguard Worker const DataRate kLowTargetBitrate = DataRate::KilobitsPerSec(400);
5643*d9f75844SAndroid Build Coastguard Worker // Set simulcast.
5644*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", 3, 1, 1, false);
5645*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(true);
5646*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
5647*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
5648*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5649*d9f75844SAndroid Build Coastguard Worker kLowTargetBitrate, kLowTargetBitrate, kLowTargetBitrate, 0, 0, 0);
5650*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
5651*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped.
5652*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
5653*d9f75844SAndroid Build Coastguard Worker
5654*d9f75844SAndroid Build Coastguard Worker // Trigger QVGA "singlecast"
5655*d9f75844SAndroid Build Coastguard Worker // Update the config.
5656*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
5657*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoder::EncoderInfo encoder_info;
5658*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(PayloadStringToCodecType("VP8"), 3,
5659*d9f75844SAndroid Build Coastguard Worker &video_encoder_config);
5660*d9f75844SAndroid Build Coastguard Worker video_encoder_config.video_stream_factory =
5661*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<cricket::EncoderStreamFactory>(
5662*d9f75844SAndroid Build Coastguard Worker "VP8", /*max qp*/ 56, /*screencast*/ false,
5663*d9f75844SAndroid Build Coastguard Worker /*screenshare enabled*/ false, encoder_info);
5664*d9f75844SAndroid Build Coastguard Worker for (auto& layer : video_encoder_config.simulcast_layers) {
5665*d9f75844SAndroid Build Coastguard Worker layer.num_temporal_layers = 1;
5666*d9f75844SAndroid Build Coastguard Worker layer.max_framerate = kDefaultFramerate;
5667*d9f75844SAndroid Build Coastguard Worker }
5668*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kSimulcastTargetBitrate.bps();
5669*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
5670*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
5671*d9f75844SAndroid Build Coastguard Worker
5672*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].active = true;
5673*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[1].active = false;
5674*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = false;
5675*d9f75844SAndroid Build Coastguard Worker
5676*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
5677*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5678*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5679*d9f75844SAndroid Build Coastguard Worker
5680*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
5681*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped.
5682*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
5683*d9f75844SAndroid Build Coastguard Worker
5684*d9f75844SAndroid Build Coastguard Worker // Trigger HD "singlecast"
5685*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].active = false;
5686*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[1].active = false;
5687*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = true;
5688*d9f75844SAndroid Build Coastguard Worker
5689*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
5690*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5691*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5692*d9f75844SAndroid Build Coastguard Worker
5693*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
5694*d9f75844SAndroid Build Coastguard Worker // Frame should be dropped because of initial frame drop.
5695*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
5696*d9f75844SAndroid Build Coastguard Worker
5697*d9f75844SAndroid Build Coastguard Worker // Expect the sink_wants to specify a scaled frame.
5698*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(
5699*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants().max_pixel_count < kWidth * kHeight, 5000);
5700*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5701*d9f75844SAndroid Build Coastguard Worker }
5702*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,InitialFrameDropActivatesWhenSVCLayersChange)5703*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, InitialFrameDropActivatesWhenSVCLayersChange) {
5704*d9f75844SAndroid Build Coastguard Worker const DataRate kLowTargetBitrate = DataRate::KilobitsPerSec(400);
5705*d9f75844SAndroid Build Coastguard Worker // Set simulcast.
5706*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP9", 1, 1, 3, false);
5707*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(true);
5708*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
5709*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
5710*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
5711*d9f75844SAndroid Build Coastguard Worker kLowTargetBitrate, kLowTargetBitrate, kLowTargetBitrate, 0, 0, 0);
5712*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
5713*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped.
5714*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
5715*d9f75844SAndroid Build Coastguard Worker
5716*d9f75844SAndroid Build Coastguard Worker // Trigger QVGA "singlecast"
5717*d9f75844SAndroid Build Coastguard Worker // Update the config.
5718*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
5719*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(PayloadStringToCodecType("VP9"), 1,
5720*d9f75844SAndroid Build Coastguard Worker &video_encoder_config);
5721*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
5722*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = 3;
5723*d9f75844SAndroid Build Coastguard Worker // Since only one layer is active - automatic resize should be enabled.
5724*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = true;
5725*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
5726*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
5727*d9f75844SAndroid Build Coastguard Worker vp9_settings);
5728*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kSimulcastTargetBitrate.bps();
5729*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
5730*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
5731*d9f75844SAndroid Build Coastguard Worker // Currently simulcast layers `active` flags are used to inidicate
5732*d9f75844SAndroid Build Coastguard Worker // which SVC layers are active.
5733*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers.resize(3);
5734*d9f75844SAndroid Build Coastguard Worker
5735*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].active = true;
5736*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[1].active = false;
5737*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = false;
5738*d9f75844SAndroid Build Coastguard Worker
5739*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
5740*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5741*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5742*d9f75844SAndroid Build Coastguard Worker
5743*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
5744*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped.
5745*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
5746*d9f75844SAndroid Build Coastguard Worker
5747*d9f75844SAndroid Build Coastguard Worker // Trigger HD "singlecast"
5748*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].active = false;
5749*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[1].active = false;
5750*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = true;
5751*d9f75844SAndroid Build Coastguard Worker
5752*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
5753*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5754*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5755*d9f75844SAndroid Build Coastguard Worker
5756*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
5757*d9f75844SAndroid Build Coastguard Worker // Frame should be dropped because of initial frame drop.
5758*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
5759*d9f75844SAndroid Build Coastguard Worker
5760*d9f75844SAndroid Build Coastguard Worker // Expect the sink_wants to specify a scaled frame.
5761*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(
5762*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants().max_pixel_count < kWidth * kHeight, 5000);
5763*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5764*d9f75844SAndroid Build Coastguard Worker }
5765*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderMaxAndMinBitratesUsedIfMiddleStreamActive)5766*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
5767*d9f75844SAndroid Build Coastguard Worker EncoderMaxAndMinBitratesUsedIfMiddleStreamActive) {
5768*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits270p(
5769*d9f75844SAndroid Build Coastguard Worker 480 * 270, 34 * 1000, 12 * 1000, 1234 * 1000);
5770*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits360p(
5771*d9f75844SAndroid Build Coastguard Worker 640 * 360, 43 * 1000, 21 * 1000, 2345 * 1000);
5772*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits720p(
5773*d9f75844SAndroid Build Coastguard Worker 1280 * 720, 54 * 1000, 31 * 1000, 2500 * 1000);
5774*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits(
5775*d9f75844SAndroid Build Coastguard Worker {kEncoderLimits270p, kEncoderLimits360p, kEncoderLimits720p});
5776*d9f75844SAndroid Build Coastguard Worker
5777*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
5778*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(PayloadStringToCodecType("VP9"), 1,
5779*d9f75844SAndroid Build Coastguard Worker &video_encoder_config);
5780*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
5781*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = 3;
5782*d9f75844SAndroid Build Coastguard Worker // Since only one layer is active - automatic resize should be enabled.
5783*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = true;
5784*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
5785*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
5786*d9f75844SAndroid Build Coastguard Worker vp9_settings);
5787*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kSimulcastTargetBitrate.bps();
5788*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
5789*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
5790*d9f75844SAndroid Build Coastguard Worker // Simulcast layers are used to indicate which spatial layers are active.
5791*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers.resize(3);
5792*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].active = false;
5793*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[1].active = true;
5794*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = false;
5795*d9f75844SAndroid Build Coastguard Worker
5796*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
5797*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5798*d9f75844SAndroid Build Coastguard Worker
5799*d9f75844SAndroid Build Coastguard Worker // The encoder bitrate limits for 360p should be used.
5800*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
5801*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5802*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().numberOfSimulcastStreams, 1);
5803*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().codecType, VideoCodecType::kVideoCodecVP9);
5804*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().VP9().numberOfSpatialLayers, 2);
5805*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(fake_encoder_.config().spatialLayers[0].active);
5806*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(640, fake_encoder_.config().spatialLayers[0].width);
5807*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(360, fake_encoder_.config().spatialLayers[0].height);
5808*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits360p.min_bitrate_bps),
5809*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().spatialLayers[0].minBitrate * 1000);
5810*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits360p.max_bitrate_bps),
5811*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().spatialLayers[0].maxBitrate * 1000);
5812*d9f75844SAndroid Build Coastguard Worker
5813*d9f75844SAndroid Build Coastguard Worker // The encoder bitrate limits for 270p should be used.
5814*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, 960, 540));
5815*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5816*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().numberOfSimulcastStreams, 1);
5817*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().codecType, VideoCodecType::kVideoCodecVP9);
5818*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().VP9().numberOfSpatialLayers, 2);
5819*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(fake_encoder_.config().spatialLayers[0].active);
5820*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(480, fake_encoder_.config().spatialLayers[0].width);
5821*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(270, fake_encoder_.config().spatialLayers[0].height);
5822*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits270p.min_bitrate_bps),
5823*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().spatialLayers[0].minBitrate * 1000);
5824*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kEncoderLimits270p.max_bitrate_bps),
5825*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().spatialLayers[0].maxBitrate * 1000);
5826*d9f75844SAndroid Build Coastguard Worker
5827*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5828*d9f75844SAndroid Build Coastguard Worker }
5829*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DefaultMaxAndMinBitratesUsedIfMiddleStreamActive)5830*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
5831*d9f75844SAndroid Build Coastguard Worker DefaultMaxAndMinBitratesUsedIfMiddleStreamActive) {
5832*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
5833*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(PayloadStringToCodecType("VP9"), 1,
5834*d9f75844SAndroid Build Coastguard Worker &video_encoder_config);
5835*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
5836*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = 3;
5837*d9f75844SAndroid Build Coastguard Worker // Since only one layer is active - automatic resize should be enabled.
5838*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = true;
5839*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
5840*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
5841*d9f75844SAndroid Build Coastguard Worker vp9_settings);
5842*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kSimulcastTargetBitrate.bps();
5843*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
5844*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
5845*d9f75844SAndroid Build Coastguard Worker // Simulcast layers are used to indicate which spatial layers are active.
5846*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers.resize(3);
5847*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].active = false;
5848*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[1].active = true;
5849*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = false;
5850*d9f75844SAndroid Build Coastguard Worker
5851*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
5852*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5853*d9f75844SAndroid Build Coastguard Worker
5854*d9f75844SAndroid Build Coastguard Worker // The default bitrate limits for 360p should be used.
5855*d9f75844SAndroid Build Coastguard Worker const absl::optional<VideoEncoder::ResolutionBitrateLimits> kLimits360p =
5856*d9f75844SAndroid Build Coastguard Worker EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(
5857*d9f75844SAndroid Build Coastguard Worker kVideoCodecVP9, 640 * 360);
5858*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
5859*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5860*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().numberOfSimulcastStreams, 1);
5861*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().codecType, VideoCodecType::kVideoCodecVP9);
5862*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().VP9().numberOfSpatialLayers, 2);
5863*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(fake_encoder_.config().spatialLayers[0].active);
5864*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(640, fake_encoder_.config().spatialLayers[0].width);
5865*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(360, fake_encoder_.config().spatialLayers[0].height);
5866*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kLimits360p->min_bitrate_bps),
5867*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().spatialLayers[0].minBitrate * 1000);
5868*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kLimits360p->max_bitrate_bps),
5869*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().spatialLayers[0].maxBitrate * 1000);
5870*d9f75844SAndroid Build Coastguard Worker
5871*d9f75844SAndroid Build Coastguard Worker // The default bitrate limits for 270p should be used.
5872*d9f75844SAndroid Build Coastguard Worker const absl::optional<VideoEncoder::ResolutionBitrateLimits> kLimits270p =
5873*d9f75844SAndroid Build Coastguard Worker EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(
5874*d9f75844SAndroid Build Coastguard Worker kVideoCodecVP9, 480 * 270);
5875*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, 960, 540));
5876*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5877*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().numberOfSimulcastStreams, 1);
5878*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().codecType, VideoCodecType::kVideoCodecVP9);
5879*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().VP9().numberOfSpatialLayers, 2);
5880*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(fake_encoder_.config().spatialLayers[0].active);
5881*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(480, fake_encoder_.config().spatialLayers[0].width);
5882*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(270, fake_encoder_.config().spatialLayers[0].height);
5883*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kLimits270p->min_bitrate_bps),
5884*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().spatialLayers[0].minBitrate * 1000);
5885*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<uint32_t>(kLimits270p->max_bitrate_bps),
5886*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().spatialLayers[0].maxBitrate * 1000);
5887*d9f75844SAndroid Build Coastguard Worker
5888*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5889*d9f75844SAndroid Build Coastguard Worker }
5890*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DefaultMaxAndMinBitratesNotUsedIfDisabled)5891*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DefaultMaxAndMinBitratesNotUsedIfDisabled) {
5892*d9f75844SAndroid Build Coastguard Worker webrtc::test::ScopedKeyValueConfig field_trials(
5893*d9f75844SAndroid Build Coastguard Worker field_trials_, "WebRTC-DefaultBitrateLimitsKillSwitch/Enabled/");
5894*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
5895*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(PayloadStringToCodecType("VP9"), 1,
5896*d9f75844SAndroid Build Coastguard Worker &video_encoder_config);
5897*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
5898*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = 3;
5899*d9f75844SAndroid Build Coastguard Worker // Since only one layer is active - automatic resize should be enabled.
5900*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = true;
5901*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
5902*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
5903*d9f75844SAndroid Build Coastguard Worker vp9_settings);
5904*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kSimulcastTargetBitrate.bps();
5905*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
5906*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
5907*d9f75844SAndroid Build Coastguard Worker // Simulcast layers are used to indicate which spatial layers are active.
5908*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers.resize(3);
5909*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].active = false;
5910*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[1].active = true;
5911*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = false;
5912*d9f75844SAndroid Build Coastguard Worker
5913*d9f75844SAndroid Build Coastguard Worker // Reset encoder for field trials to take effect.
5914*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config.Copy());
5915*d9f75844SAndroid Build Coastguard Worker
5916*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
5917*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5918*d9f75844SAndroid Build Coastguard Worker
5919*d9f75844SAndroid Build Coastguard Worker // The default bitrate limits for 360p should not be used.
5920*d9f75844SAndroid Build Coastguard Worker const absl::optional<VideoEncoder::ResolutionBitrateLimits> kLimits360p =
5921*d9f75844SAndroid Build Coastguard Worker EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(
5922*d9f75844SAndroid Build Coastguard Worker kVideoCodecVP9, 640 * 360);
5923*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
5924*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5925*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().numberOfSimulcastStreams, 1);
5926*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().codecType, kVideoCodecVP9);
5927*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().VP9().numberOfSpatialLayers, 2);
5928*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(fake_encoder_.config().spatialLayers[0].active);
5929*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(640, fake_encoder_.config().spatialLayers[0].width);
5930*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(360, fake_encoder_.config().spatialLayers[0].height);
5931*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(kLimits360p->max_bitrate_bps),
5932*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().spatialLayers[0].maxBitrate * 1000);
5933*d9f75844SAndroid Build Coastguard Worker
5934*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5935*d9f75844SAndroid Build Coastguard Worker }
5936*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SinglecastBitrateLimitsNotUsedForOneStream)5937*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, SinglecastBitrateLimitsNotUsedForOneStream) {
5938*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP9", /*num_streams=*/1, /*num_temporal_layers=*/1,
5939*d9f75844SAndroid Build Coastguard Worker /*num_spatial_layers=*/1, /*screenshare=*/false);
5940*d9f75844SAndroid Build Coastguard Worker
5941*d9f75844SAndroid Build Coastguard Worker // The default singlecast bitrate limits for 720p should not be used.
5942*d9f75844SAndroid Build Coastguard Worker const absl::optional<VideoEncoder::ResolutionBitrateLimits> kLimits720p =
5943*d9f75844SAndroid Build Coastguard Worker EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(
5944*d9f75844SAndroid Build Coastguard Worker kVideoCodecVP9, 1280 * 720);
5945*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
5946*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5947*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().numberOfSimulcastStreams, 1);
5948*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().codecType, VideoCodecType::kVideoCodecVP9);
5949*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().VP9().numberOfSpatialLayers, 1);
5950*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(fake_encoder_.config().spatialLayers[0].active);
5951*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1280, fake_encoder_.config().spatialLayers[0].width);
5952*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(720, fake_encoder_.config().spatialLayers[0].height);
5953*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(kLimits720p->max_bitrate_bps),
5954*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().spatialLayers[0].maxBitrate * 1000);
5955*d9f75844SAndroid Build Coastguard Worker
5956*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
5957*d9f75844SAndroid Build Coastguard Worker }
5958*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderMaxAndMinBitratesNotUsedIfLowestStreamActive)5959*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
5960*d9f75844SAndroid Build Coastguard Worker EncoderMaxAndMinBitratesNotUsedIfLowestStreamActive) {
5961*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits180p(
5962*d9f75844SAndroid Build Coastguard Worker 320 * 180, 34 * 1000, 12 * 1000, 1234 * 1000);
5963*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits kEncoderLimits720p(
5964*d9f75844SAndroid Build Coastguard Worker 1280 * 720, 54 * 1000, 31 * 1000, 2500 * 1000);
5965*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits(
5966*d9f75844SAndroid Build Coastguard Worker {kEncoderLimits180p, kEncoderLimits720p});
5967*d9f75844SAndroid Build Coastguard Worker
5968*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
5969*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(PayloadStringToCodecType("VP9"), 1,
5970*d9f75844SAndroid Build Coastguard Worker &video_encoder_config);
5971*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
5972*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = 3;
5973*d9f75844SAndroid Build Coastguard Worker // Since only one layer is active - automatic resize should be enabled.
5974*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = true;
5975*d9f75844SAndroid Build Coastguard Worker video_encoder_config.encoder_specific_settings =
5976*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
5977*d9f75844SAndroid Build Coastguard Worker vp9_settings);
5978*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kSimulcastTargetBitrate.bps();
5979*d9f75844SAndroid Build Coastguard Worker video_encoder_config.content_type =
5980*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig::ContentType::kRealtimeVideo;
5981*d9f75844SAndroid Build Coastguard Worker // Simulcast layers are used to indicate which spatial layers are active.
5982*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers.resize(3);
5983*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].active = true;
5984*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[1].active = false;
5985*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[2].active = false;
5986*d9f75844SAndroid Build Coastguard Worker
5987*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
5988*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
5989*d9f75844SAndroid Build Coastguard Worker
5990*d9f75844SAndroid Build Coastguard Worker // Limits not applied on lowest stream, limits for 180p should not be used.
5991*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
5992*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
5993*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().numberOfSimulcastStreams, 1);
5994*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().codecType, VideoCodecType::kVideoCodecVP9);
5995*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.config().VP9().numberOfSpatialLayers, 3);
5996*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(fake_encoder_.config().spatialLayers[0].active);
5997*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(320, fake_encoder_.config().spatialLayers[0].width);
5998*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(180, fake_encoder_.config().spatialLayers[0].height);
5999*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(kEncoderLimits180p.min_bitrate_bps),
6000*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().spatialLayers[0].minBitrate * 1000);
6001*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(static_cast<uint32_t>(kEncoderLimits180p.max_bitrate_bps),
6002*d9f75844SAndroid Build Coastguard Worker fake_encoder_.config().spatialLayers[0].maxBitrate * 1000);
6003*d9f75844SAndroid Build Coastguard Worker
6004*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6005*d9f75844SAndroid Build Coastguard Worker }
6006*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,InitialFrameDropActivatesWhenResolutionIncreases)6007*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
6008*d9f75844SAndroid Build Coastguard Worker InitialFrameDropActivatesWhenResolutionIncreases) {
6009*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
6010*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
6011*d9f75844SAndroid Build Coastguard Worker
6012*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6013*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6014*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth / 2, kHeight / 2));
6015*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped.
6016*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
6017*d9f75844SAndroid Build Coastguard Worker
6018*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6019*d9f75844SAndroid Build Coastguard Worker kLowTargetBitrate, kLowTargetBitrate, kLowTargetBitrate, 0, 0, 0);
6020*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth / 2, kHeight / 2));
6021*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped, bitrate not too low for frame.
6022*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
6023*d9f75844SAndroid Build Coastguard Worker
6024*d9f75844SAndroid Build Coastguard Worker // Incoming resolution increases.
6025*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
6026*d9f75844SAndroid Build Coastguard Worker // Expect to drop this frame, bitrate too low for frame.
6027*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
6028*d9f75844SAndroid Build Coastguard Worker
6029*d9f75844SAndroid Build Coastguard Worker // Expect the sink_wants to specify a scaled frame.
6030*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(
6031*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants().max_pixel_count < kWidth * kHeight, 5000);
6032*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6033*d9f75844SAndroid Build Coastguard Worker }
6034*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,InitialFrameDropIsNotReactivatedWhenAdaptingUp)6035*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, InitialFrameDropIsNotReactivatedWhenAdaptingUp) {
6036*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
6037*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
6038*d9f75844SAndroid Build Coastguard Worker // So that quality scaling doesn't happen by itself.
6039*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQp(kQpHigh);
6040*d9f75844SAndroid Build Coastguard Worker
6041*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
6042*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
6043*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
6044*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
6045*d9f75844SAndroid Build Coastguard Worker
6046*d9f75844SAndroid Build Coastguard Worker int timestamp = 1;
6047*d9f75844SAndroid Build Coastguard Worker
6048*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6049*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6050*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp, kWidth, kHeight));
6051*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp);
6052*d9f75844SAndroid Build Coastguard Worker timestamp += 9000;
6053*d9f75844SAndroid Build Coastguard Worker // Long pause to disable all first BWE drop logic.
6054*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Millis(1000));
6055*d9f75844SAndroid Build Coastguard Worker
6056*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6057*d9f75844SAndroid Build Coastguard Worker kLowTargetBitrate, kLowTargetBitrate, kLowTargetBitrate, 0, 0, 0);
6058*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp, kWidth, kHeight));
6059*d9f75844SAndroid Build Coastguard Worker // Not dropped frame, as initial frame drop is disabled by now.
6060*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp);
6061*d9f75844SAndroid Build Coastguard Worker timestamp += 9000;
6062*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Millis(100));
6063*d9f75844SAndroid Build Coastguard Worker
6064*d9f75844SAndroid Build Coastguard Worker // Quality adaptation down.
6065*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6066*d9f75844SAndroid Build Coastguard Worker
6067*d9f75844SAndroid Build Coastguard Worker // Adaptation has an effect.
6068*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(source.sink_wants().max_pixel_count < kWidth * kHeight,
6069*d9f75844SAndroid Build Coastguard Worker 5000);
6070*d9f75844SAndroid Build Coastguard Worker
6071*d9f75844SAndroid Build Coastguard Worker // Frame isn't dropped as initial frame dropper is disabled.
6072*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp, kWidth, kHeight));
6073*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp);
6074*d9f75844SAndroid Build Coastguard Worker timestamp += 9000;
6075*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Millis(100));
6076*d9f75844SAndroid Build Coastguard Worker
6077*d9f75844SAndroid Build Coastguard Worker // Quality adaptation up.
6078*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6079*d9f75844SAndroid Build Coastguard Worker
6080*d9f75844SAndroid Build Coastguard Worker // Adaptation has an effect.
6081*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(source.sink_wants().max_pixel_count > kWidth * kHeight,
6082*d9f75844SAndroid Build Coastguard Worker 5000);
6083*d9f75844SAndroid Build Coastguard Worker
6084*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp, kWidth, kHeight));
6085*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped, as initial framedropper is off.
6086*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp);
6087*d9f75844SAndroid Build Coastguard Worker
6088*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6089*d9f75844SAndroid Build Coastguard Worker }
6090*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,FrameDroppedWhenResolutionIncreasesAndLinkAllocationIsLow)6091*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
6092*d9f75844SAndroid Build Coastguard Worker FrameDroppedWhenResolutionIncreasesAndLinkAllocationIsLow) {
6093*d9f75844SAndroid Build Coastguard Worker const int kMinStartBps360p = 222000;
6094*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits(
6095*d9f75844SAndroid Build Coastguard Worker {VideoEncoder::ResolutionBitrateLimits(320 * 180, 0, 30000, 400000),
6096*d9f75844SAndroid Build Coastguard Worker VideoEncoder::ResolutionBitrateLimits(640 * 360, kMinStartBps360p, 30000,
6097*d9f75844SAndroid Build Coastguard Worker 800000)});
6098*d9f75844SAndroid Build Coastguard Worker
6099*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6100*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kMinStartBps360p - 1), // target_bitrate
6101*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kMinStartBps360p - 1), // stable_target_bitrate
6102*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kMinStartBps360p - 1), // link_allocation
6103*d9f75844SAndroid Build Coastguard Worker 0, 0, 0);
6104*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped, bitrate not too low for frame.
6105*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 320, 180));
6106*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
6107*d9f75844SAndroid Build Coastguard Worker
6108*d9f75844SAndroid Build Coastguard Worker // Incoming resolution increases, initial frame drop activates.
6109*d9f75844SAndroid Build Coastguard Worker // Frame should be dropped, link allocation too low for frame.
6110*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
6111*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
6112*d9f75844SAndroid Build Coastguard Worker
6113*d9f75844SAndroid Build Coastguard Worker // Expect sink_wants to specify a scaled frame.
6114*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(video_source_.sink_wants().max_pixel_count < 640 * 360,
6115*d9f75844SAndroid Build Coastguard Worker 5000);
6116*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6117*d9f75844SAndroid Build Coastguard Worker }
6118*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,FrameNotDroppedWhenResolutionIncreasesAndLinkAllocationIsHigh)6119*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
6120*d9f75844SAndroid Build Coastguard Worker FrameNotDroppedWhenResolutionIncreasesAndLinkAllocationIsHigh) {
6121*d9f75844SAndroid Build Coastguard Worker const int kMinStartBps360p = 222000;
6122*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits(
6123*d9f75844SAndroid Build Coastguard Worker {VideoEncoder::ResolutionBitrateLimits(320 * 180, 0, 30000, 400000),
6124*d9f75844SAndroid Build Coastguard Worker VideoEncoder::ResolutionBitrateLimits(640 * 360, kMinStartBps360p, 30000,
6125*d9f75844SAndroid Build Coastguard Worker 800000)});
6126*d9f75844SAndroid Build Coastguard Worker
6127*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6128*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kMinStartBps360p - 1), // target_bitrate
6129*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kMinStartBps360p - 1), // stable_target_bitrate
6130*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(kMinStartBps360p), // link_allocation
6131*d9f75844SAndroid Build Coastguard Worker 0, 0, 0);
6132*d9f75844SAndroid Build Coastguard Worker // Frame should not be dropped, bitrate not too low for frame.
6133*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 320, 180));
6134*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
6135*d9f75844SAndroid Build Coastguard Worker
6136*d9f75844SAndroid Build Coastguard Worker // Incoming resolution increases, initial frame drop activates.
6137*d9f75844SAndroid Build Coastguard Worker // Frame should be dropped, link allocation not too low for frame.
6138*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
6139*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
6140*d9f75844SAndroid Build Coastguard Worker
6141*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6142*d9f75844SAndroid Build Coastguard Worker }
6143*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,RampsUpInQualityWhenBwIsHigh)6144*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, RampsUpInQualityWhenBwIsHigh) {
6145*d9f75844SAndroid Build Coastguard Worker webrtc::test::ScopedKeyValueConfig field_trials(
6146*d9f75844SAndroid Build Coastguard Worker field_trials_,
6147*d9f75844SAndroid Build Coastguard Worker "WebRTC-Video-QualityRampupSettings/"
6148*d9f75844SAndroid Build Coastguard Worker "min_pixels:921600,min_duration_ms:2000/");
6149*d9f75844SAndroid Build Coastguard Worker
6150*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
6151*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
6152*d9f75844SAndroid Build Coastguard Worker const int kFps = 10;
6153*d9f75844SAndroid Build Coastguard Worker max_framerate_ = kFps;
6154*d9f75844SAndroid Build Coastguard Worker
6155*d9f75844SAndroid Build Coastguard Worker // Reset encoder for field trials to take effect.
6156*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config = video_encoder_config_.Copy();
6157*d9f75844SAndroid Build Coastguard Worker config.max_bitrate_bps = kTargetBitrate.bps();
6158*d9f75844SAndroid Build Coastguard Worker DataRate max_bitrate = DataRate::BitsPerSec(config.max_bitrate_bps);
6159*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(config));
6160*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQp(kQpLow);
6161*d9f75844SAndroid Build Coastguard Worker
6162*d9f75844SAndroid Build Coastguard Worker // Enable MAINTAIN_FRAMERATE preference.
6163*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
6164*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
6165*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
6166*d9f75844SAndroid Build Coastguard Worker DegradationPreference::MAINTAIN_FRAMERATE);
6167*d9f75844SAndroid Build Coastguard Worker
6168*d9f75844SAndroid Build Coastguard Worker // Start at low bitrate.
6169*d9f75844SAndroid Build Coastguard Worker const DataRate kLowBitrate = DataRate::KilobitsPerSec(200);
6170*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6171*d9f75844SAndroid Build Coastguard Worker kLowBitrate, kLowBitrate, kLowBitrate, 0, 0, 0);
6172*d9f75844SAndroid Build Coastguard Worker
6173*d9f75844SAndroid Build Coastguard Worker // Expect first frame to be dropped and resolution to be limited.
6174*d9f75844SAndroid Build Coastguard Worker const int64_t kFrameIntervalMs = 1000 / kFps;
6175*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
6176*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6177*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
6178*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(source.sink_wants().max_pixel_count < kWidth * kHeight,
6179*d9f75844SAndroid Build Coastguard Worker 5000);
6180*d9f75844SAndroid Build Coastguard Worker
6181*d9f75844SAndroid Build Coastguard Worker // Increase bitrate to encoder max.
6182*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6183*d9f75844SAndroid Build Coastguard Worker max_bitrate, max_bitrate, max_bitrate, 0, 0, 0);
6184*d9f75844SAndroid Build Coastguard Worker
6185*d9f75844SAndroid Build Coastguard Worker // Insert frames and advance `min_duration_ms`.
6186*d9f75844SAndroid Build Coastguard Worker const int64_t start_bw_high_ms = CurrentTimeMs();
6187*d9f75844SAndroid Build Coastguard Worker for (size_t i = 1; i <= 10; i++) {
6188*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6189*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6190*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6191*d9f75844SAndroid Build Coastguard Worker }
6192*d9f75844SAndroid Build Coastguard Worker
6193*d9f75844SAndroid Build Coastguard Worker // Advance to `min_duration_ms` - 1, frame should not trigger high BW.
6194*d9f75844SAndroid Build Coastguard Worker int64_t elapsed_bw_high_ms = CurrentTimeMs() - start_bw_high_ms;
6195*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Millis(2000 - elapsed_bw_high_ms - 1));
6196*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6197*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6198*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6199*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6200*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(source.sink_wants().max_pixel_count, kWidth * kHeight);
6201*d9f75844SAndroid Build Coastguard Worker
6202*d9f75844SAndroid Build Coastguard Worker // Frame should trigger high BW and release quality limitation.
6203*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6204*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6205*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6206*d9f75844SAndroid Build Coastguard Worker // The ramp-up code involves the adaptation queue, give it time to execute.
6207*d9f75844SAndroid Build Coastguard Worker // TODO(hbos): Can we await an appropriate event instead?
6208*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
6209*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
6210*d9f75844SAndroid Build Coastguard Worker
6211*d9f75844SAndroid Build Coastguard Worker // Frame should not be adapted.
6212*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6213*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6214*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kWidth, kHeight);
6215*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6216*d9f75844SAndroid Build Coastguard Worker
6217*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6218*d9f75844SAndroid Build Coastguard Worker }
6219*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QualityScalerAdaptationsRemovedWhenQualityScalingDisabled)6220*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
6221*d9f75844SAndroid Build Coastguard Worker QualityScalerAdaptationsRemovedWhenQualityScalingDisabled) {
6222*d9f75844SAndroid Build Coastguard Worker webrtc::test::ScopedKeyValueConfig field_trials(
6223*d9f75844SAndroid Build Coastguard Worker field_trials_, "WebRTC-Video-QualityScaling/Disabled/");
6224*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
6225*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
6226*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
6227*d9f75844SAndroid Build Coastguard Worker DegradationPreference::MAINTAIN_FRAMERATE);
6228*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6229*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6230*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQp(kQpHigh + 1);
6231*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
6232*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
6233*d9f75844SAndroid Build Coastguard Worker const int64_t kFrameIntervalMs = 100;
6234*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
6235*d9f75844SAndroid Build Coastguard Worker for (size_t i = 1; i <= 100; i++) {
6236*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6237*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6238*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6239*d9f75844SAndroid Build Coastguard Worker }
6240*d9f75844SAndroid Build Coastguard Worker // Wait for QualityScaler, which will wait for 2000*2.5 ms until checking QP
6241*d9f75844SAndroid Build Coastguard Worker // for the first time.
6242*d9f75844SAndroid Build Coastguard Worker // TODO(eshr): We should avoid these waits by using threads with simulated
6243*d9f75844SAndroid Build Coastguard Worker // time.
6244*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(stats_proxy_->GetStats().bw_limited_resolution,
6245*d9f75844SAndroid Build Coastguard Worker 2000 * 2.5 * 2);
6246*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6247*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6248*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6249*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
6250*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), WantsMaxPixels(Lt(kWidth * kHeight)));
6251*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6252*d9f75844SAndroid Build Coastguard Worker
6253*d9f75844SAndroid Build Coastguard Worker // Disable Quality scaling by turning off scaler on the encoder and
6254*d9f75844SAndroid Build Coastguard Worker // reconfiguring.
6255*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
6256*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
6257*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
6258*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
6259*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Zero());
6260*d9f75844SAndroid Build Coastguard Worker // Since we turned off the quality scaler, the adaptations made by it are
6261*d9f75844SAndroid Build Coastguard Worker // removed.
6262*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), ResolutionMax());
6263*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6264*d9f75844SAndroid Build Coastguard Worker
6265*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6266*d9f75844SAndroid Build Coastguard Worker }
6267*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ResolutionNotAdaptedForTooSmallFrame_MaintainFramerateMode)6268*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
6269*d9f75844SAndroid Build Coastguard Worker ResolutionNotAdaptedForTooSmallFrame_MaintainFramerateMode) {
6270*d9f75844SAndroid Build Coastguard Worker const int kTooSmallWidth = 10;
6271*d9f75844SAndroid Build Coastguard Worker const int kTooSmallHeight = 10;
6272*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6273*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6274*d9f75844SAndroid Build Coastguard Worker
6275*d9f75844SAndroid Build Coastguard Worker // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
6276*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
6277*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
6278*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
6279*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), UnlimitedSinkWants());
6280*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
6281*d9f75844SAndroid Build Coastguard Worker
6282*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, too small frame, expect no change.
6283*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kTooSmallWidth, kTooSmallHeight));
6284*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
6285*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
6286*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
6287*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
6288*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6289*d9f75844SAndroid Build Coastguard Worker
6290*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6291*d9f75844SAndroid Build Coastguard Worker }
6292*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ResolutionNotAdaptedForTooSmallFrame_BalancedMode)6293*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
6294*d9f75844SAndroid Build Coastguard Worker ResolutionNotAdaptedForTooSmallFrame_BalancedMode) {
6295*d9f75844SAndroid Build Coastguard Worker const int kTooSmallWidth = 10;
6296*d9f75844SAndroid Build Coastguard Worker const int kTooSmallHeight = 10;
6297*d9f75844SAndroid Build Coastguard Worker const int kFpsLimit = 7;
6298*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6299*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6300*d9f75844SAndroid Build Coastguard Worker
6301*d9f75844SAndroid Build Coastguard Worker // Enable BALANCED preference, no initial limitation.
6302*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
6303*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
6304*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
6305*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), UnlimitedSinkWants());
6306*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6307*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6308*d9f75844SAndroid Build Coastguard Worker
6309*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect limited framerate.
6310*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, kTooSmallWidth, kTooSmallHeight));
6311*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
6312*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6313*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMatchesResolutionMax(Eq(kFpsLimit)));
6314*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6315*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6316*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6317*d9f75844SAndroid Build Coastguard Worker
6318*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, too small frame, expect no change.
6319*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(2, kTooSmallWidth, kTooSmallHeight));
6320*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
6321*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6322*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMatchesResolutionMax(Eq(kFpsLimit)));
6323*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6324*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6325*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6326*d9f75844SAndroid Build Coastguard Worker
6327*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6328*d9f75844SAndroid Build Coastguard Worker }
6329*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,FailingInitEncodeDoesntCauseCrash)6330*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, FailingInitEncodeDoesntCauseCrash) {
6331*d9f75844SAndroid Build Coastguard Worker fake_encoder_.ForceInitEncodeFailure(true);
6332*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6333*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6334*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", 2, 1, 1, false);
6335*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
6336*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
6337*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6338*d9f75844SAndroid Build Coastguard Worker CreateFrame(1, kFrameWidth, kFrameHeight));
6339*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
6340*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6341*d9f75844SAndroid Build Coastguard Worker }
6342*d9f75844SAndroid Build Coastguard Worker
6343*d9f75844SAndroid Build Coastguard Worker // TODO(sprang): Extend this with fps throttling and any "balanced" extensions.
TEST_F(VideoStreamEncoderTest,AdaptsResolutionOnOveruse_MaintainFramerateMode)6344*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
6345*d9f75844SAndroid Build Coastguard Worker AdaptsResolutionOnOveruse_MaintainFramerateMode) {
6346*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6347*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6348*d9f75844SAndroid Build Coastguard Worker
6349*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
6350*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
6351*d9f75844SAndroid Build Coastguard Worker // Enabled default VideoAdapter downscaling. First step is 3/4, not 3/5 as
6352*d9f75844SAndroid Build Coastguard Worker // requested by
6353*d9f75844SAndroid Build Coastguard Worker // VideoStreamEncoder::VideoSourceProxy::RequestResolutionLowerThan().
6354*d9f75844SAndroid Build Coastguard Worker video_source_.set_adaptation_enabled(true);
6355*d9f75844SAndroid Build Coastguard Worker
6356*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6357*d9f75844SAndroid Build Coastguard Worker CreateFrame(1 * kFrameIntervalMs, kFrameWidth, kFrameHeight));
6358*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kFrameWidth, kFrameHeight);
6359*d9f75844SAndroid Build Coastguard Worker
6360*d9f75844SAndroid Build Coastguard Worker // Trigger CPU overuse, downscale by 3/4.
6361*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
6362*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6363*d9f75844SAndroid Build Coastguard Worker CreateFrame(2 * kFrameIntervalMs, kFrameWidth, kFrameHeight));
6364*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame((kFrameWidth * 3) / 4, (kFrameHeight * 3) / 4);
6365*d9f75844SAndroid Build Coastguard Worker
6366*d9f75844SAndroid Build Coastguard Worker // Trigger CPU normal use, return to original resolution.
6367*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
6368*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6369*d9f75844SAndroid Build Coastguard Worker CreateFrame(3 * kFrameIntervalMs, kFrameWidth, kFrameHeight));
6370*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kFrameWidth, kFrameHeight);
6371*d9f75844SAndroid Build Coastguard Worker
6372*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6373*d9f75844SAndroid Build Coastguard Worker }
6374*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AdaptsFramerateOnOveruse_MaintainResolutionMode)6375*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
6376*d9f75844SAndroid Build Coastguard Worker AdaptsFramerateOnOveruse_MaintainResolutionMode) {
6377*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
6378*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
6379*d9f75844SAndroid Build Coastguard Worker
6380*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6381*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6382*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
6383*d9f75844SAndroid Build Coastguard Worker &video_source_, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
6384*d9f75844SAndroid Build Coastguard Worker video_source_.set_adaptation_enabled(true);
6385*d9f75844SAndroid Build Coastguard Worker
6386*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
6387*d9f75844SAndroid Build Coastguard Worker
6388*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6389*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
6390*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6391*d9f75844SAndroid Build Coastguard Worker
6392*d9f75844SAndroid Build Coastguard Worker // Try to trigger overuse. No fps estimate available => no effect.
6393*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
6394*d9f75844SAndroid Build Coastguard Worker
6395*d9f75844SAndroid Build Coastguard Worker // Insert frames for one second to get a stable estimate.
6396*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < max_framerate_; ++i) {
6397*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6398*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6399*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
6400*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6401*d9f75844SAndroid Build Coastguard Worker }
6402*d9f75844SAndroid Build Coastguard Worker
6403*d9f75844SAndroid Build Coastguard Worker // Trigger CPU overuse, reduce framerate by 2/3.
6404*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
6405*d9f75844SAndroid Build Coastguard Worker int num_frames_dropped = 0;
6406*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < max_framerate_; ++i) {
6407*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6408*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6409*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
6410*d9f75844SAndroid Build Coastguard Worker if (!WaitForFrame(kFrameTimeout)) {
6411*d9f75844SAndroid Build Coastguard Worker ++num_frames_dropped;
6412*d9f75844SAndroid Build Coastguard Worker } else {
6413*d9f75844SAndroid Build Coastguard Worker sink_.CheckLastFrameSizeMatches(kFrameWidth, kFrameHeight);
6414*d9f75844SAndroid Build Coastguard Worker }
6415*d9f75844SAndroid Build Coastguard Worker }
6416*d9f75844SAndroid Build Coastguard Worker
6417*d9f75844SAndroid Build Coastguard Worker // Add some slack to account for frames dropped by the frame dropper.
6418*d9f75844SAndroid Build Coastguard Worker const int kErrorMargin = 1;
6419*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(num_frames_dropped, max_framerate_ - (max_framerate_ * 2 / 3),
6420*d9f75844SAndroid Build Coastguard Worker kErrorMargin);
6421*d9f75844SAndroid Build Coastguard Worker
6422*d9f75844SAndroid Build Coastguard Worker // Trigger CPU overuse, reduce framerate by 2/3 again.
6423*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
6424*d9f75844SAndroid Build Coastguard Worker num_frames_dropped = 0;
6425*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i <= max_framerate_; ++i) {
6426*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6427*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6428*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
6429*d9f75844SAndroid Build Coastguard Worker if (!WaitForFrame(kFrameTimeout)) {
6430*d9f75844SAndroid Build Coastguard Worker ++num_frames_dropped;
6431*d9f75844SAndroid Build Coastguard Worker } else {
6432*d9f75844SAndroid Build Coastguard Worker sink_.CheckLastFrameSizeMatches(kFrameWidth, kFrameHeight);
6433*d9f75844SAndroid Build Coastguard Worker }
6434*d9f75844SAndroid Build Coastguard Worker }
6435*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(num_frames_dropped, max_framerate_ - (max_framerate_ * 4 / 9),
6436*d9f75844SAndroid Build Coastguard Worker kErrorMargin);
6437*d9f75844SAndroid Build Coastguard Worker
6438*d9f75844SAndroid Build Coastguard Worker // Go back up one step.
6439*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
6440*d9f75844SAndroid Build Coastguard Worker num_frames_dropped = 0;
6441*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < max_framerate_; ++i) {
6442*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6443*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6444*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
6445*d9f75844SAndroid Build Coastguard Worker if (!WaitForFrame(kFrameTimeout)) {
6446*d9f75844SAndroid Build Coastguard Worker ++num_frames_dropped;
6447*d9f75844SAndroid Build Coastguard Worker } else {
6448*d9f75844SAndroid Build Coastguard Worker sink_.CheckLastFrameSizeMatches(kFrameWidth, kFrameHeight);
6449*d9f75844SAndroid Build Coastguard Worker }
6450*d9f75844SAndroid Build Coastguard Worker }
6451*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(num_frames_dropped, max_framerate_ - (max_framerate_ * 2 / 3),
6452*d9f75844SAndroid Build Coastguard Worker kErrorMargin);
6453*d9f75844SAndroid Build Coastguard Worker
6454*d9f75844SAndroid Build Coastguard Worker // Go back up to original mode.
6455*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
6456*d9f75844SAndroid Build Coastguard Worker num_frames_dropped = 0;
6457*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < max_framerate_; ++i) {
6458*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6459*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6460*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
6461*d9f75844SAndroid Build Coastguard Worker if (!WaitForFrame(kFrameTimeout)) {
6462*d9f75844SAndroid Build Coastguard Worker ++num_frames_dropped;
6463*d9f75844SAndroid Build Coastguard Worker } else {
6464*d9f75844SAndroid Build Coastguard Worker sink_.CheckLastFrameSizeMatches(kFrameWidth, kFrameHeight);
6465*d9f75844SAndroid Build Coastguard Worker }
6466*d9f75844SAndroid Build Coastguard Worker }
6467*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(num_frames_dropped, 0, kErrorMargin);
6468*d9f75844SAndroid Build Coastguard Worker
6469*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6470*d9f75844SAndroid Build Coastguard Worker }
6471*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DoesntAdaptDownPastMinFramerate)6472*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DoesntAdaptDownPastMinFramerate) {
6473*d9f75844SAndroid Build Coastguard Worker const int kFramerateFps = 5;
6474*d9f75844SAndroid Build Coastguard Worker const int kFrameIntervalMs = rtc::kNumMillisecsPerSec / kFramerateFps;
6475*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
6476*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
6477*d9f75844SAndroid Build Coastguard Worker
6478*d9f75844SAndroid Build Coastguard Worker // Reconfigure encoder with two temporal layers and screensharing, which will
6479*d9f75844SAndroid Build Coastguard Worker // disable frame dropping and make testing easier.
6480*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", 1, 2, 1, true);
6481*d9f75844SAndroid Build Coastguard Worker
6482*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6483*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6484*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
6485*d9f75844SAndroid Build Coastguard Worker &video_source_, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
6486*d9f75844SAndroid Build Coastguard Worker video_source_.set_adaptation_enabled(true);
6487*d9f75844SAndroid Build Coastguard Worker
6488*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
6489*d9f75844SAndroid Build Coastguard Worker
6490*d9f75844SAndroid Build Coastguard Worker // Trigger overuse as much as we can.
6491*d9f75844SAndroid Build Coastguard Worker rtc::VideoSinkWants last_wants;
6492*d9f75844SAndroid Build Coastguard Worker do {
6493*d9f75844SAndroid Build Coastguard Worker last_wants = video_source_.sink_wants();
6494*d9f75844SAndroid Build Coastguard Worker
6495*d9f75844SAndroid Build Coastguard Worker // Insert frames to get a new fps estimate...
6496*d9f75844SAndroid Build Coastguard Worker for (int j = 0; j < kFramerateFps; ++j) {
6497*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6498*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
6499*d9f75844SAndroid Build Coastguard Worker if (video_source_.last_sent_width()) {
6500*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(timestamp_ms);
6501*d9f75844SAndroid Build Coastguard Worker }
6502*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6503*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Millis(kFrameIntervalMs));
6504*d9f75844SAndroid Build Coastguard Worker }
6505*d9f75844SAndroid Build Coastguard Worker // ...and then try to adapt again.
6506*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
6507*d9f75844SAndroid Build Coastguard Worker } while (video_source_.sink_wants().max_framerate_fps <
6508*d9f75844SAndroid Build Coastguard Worker last_wants.max_framerate_fps);
6509*d9f75844SAndroid Build Coastguard Worker
6510*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(),
6511*d9f75844SAndroid Build Coastguard Worker FpsMatchesResolutionMax(Eq(kMinFramerateFps)));
6512*d9f75844SAndroid Build Coastguard Worker
6513*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6514*d9f75844SAndroid Build Coastguard Worker }
6515*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AdaptsResolutionAndFramerateForLowQuality_BalancedMode)6516*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
6517*d9f75844SAndroid Build Coastguard Worker AdaptsResolutionAndFramerateForLowQuality_BalancedMode) {
6518*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
6519*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
6520*d9f75844SAndroid Build Coastguard Worker const int64_t kFrameIntervalMs = 150;
6521*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
6522*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6523*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6524*d9f75844SAndroid Build Coastguard Worker
6525*d9f75844SAndroid Build Coastguard Worker // Enable BALANCED preference, no initial limitation.
6526*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
6527*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
6528*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
6529*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
6530*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6531*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6532*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kWidth, kHeight);
6533*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
6534*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6535*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6536*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6537*d9f75844SAndroid Build Coastguard Worker
6538*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution (960x540@30fps).
6539*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6540*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6541*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6542*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6543*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(),
6544*d9f75844SAndroid Build Coastguard Worker FpsMaxResolutionMatches(Lt(kWidth * kHeight)));
6545*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6546*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6547*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6548*d9f75844SAndroid Build Coastguard Worker
6549*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution (640x360@30fps).
6550*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6551*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6552*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6553*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6554*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionLt(source.last_wants()));
6555*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6556*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6557*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6558*d9f75844SAndroid Build Coastguard Worker
6559*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect reduced fps (640x360@15fps).
6560*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6561*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6562*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6563*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6564*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsLtResolutionEq(source.last_wants()));
6565*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6566*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6567*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6568*d9f75844SAndroid Build Coastguard Worker
6569*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution (480x270@15fps).
6570*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6571*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6572*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6573*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6574*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsEqResolutionLt(source.last_wants()));
6575*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6576*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6577*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6578*d9f75844SAndroid Build Coastguard Worker
6579*d9f75844SAndroid Build Coastguard Worker // Restrict bitrate, trigger adapt down, expect reduced fps (480x270@10fps).
6580*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6581*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6582*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6583*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6584*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsLtResolutionEq(source.last_wants()));
6585*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6586*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6587*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(5, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6588*d9f75844SAndroid Build Coastguard Worker
6589*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect scaled down resolution (320x180@10fps).
6590*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6591*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6592*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6593*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6594*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsEqResolutionLt(source.last_wants()));
6595*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6596*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6597*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(6, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6598*d9f75844SAndroid Build Coastguard Worker
6599*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, expect reduced fps (320x180@7fps).
6600*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6601*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6602*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6603*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6604*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsLtResolutionEq(source.last_wants()));
6605*d9f75844SAndroid Build Coastguard Worker rtc::VideoSinkWants last_wants = source.sink_wants();
6606*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6607*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6608*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(7, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6609*d9f75844SAndroid Build Coastguard Worker
6610*d9f75844SAndroid Build Coastguard Worker // Trigger adapt down, min resolution reached, expect no change.
6611*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6612*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6613*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6614*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6615*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsEqResolutionEqTo(last_wants));
6616*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6617*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6618*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(7, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6619*d9f75844SAndroid Build Coastguard Worker
6620*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect increased fps (320x180@10fps).
6621*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6622*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6623*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6624*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6625*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsGtResolutionEq(source.last_wants()));
6626*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6627*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6628*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(8, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6629*d9f75844SAndroid Build Coastguard Worker
6630*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect upscaled resolution (480x270@10fps).
6631*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6632*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6633*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6634*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6635*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsEqResolutionGt(source.last_wants()));
6636*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6637*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6638*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(9, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6639*d9f75844SAndroid Build Coastguard Worker
6640*d9f75844SAndroid Build Coastguard Worker // Increase bitrate, trigger adapt up, expect increased fps (480x270@15fps).
6641*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6642*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6643*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6644*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6645*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsGtResolutionEq(source.last_wants()));
6646*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6647*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6648*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(10, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6649*d9f75844SAndroid Build Coastguard Worker
6650*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect upscaled resolution (640x360@15fps).
6651*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6652*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6653*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6654*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6655*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsEqResolutionGt(source.last_wants()));
6656*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6657*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6658*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(11, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6659*d9f75844SAndroid Build Coastguard Worker
6660*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect increased fps (640x360@30fps).
6661*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6662*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6663*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6664*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6665*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMax());
6666*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(source.sink_wants().max_pixel_count,
6667*d9f75844SAndroid Build Coastguard Worker source.last_wants().max_pixel_count);
6668*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6669*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6670*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(12, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6671*d9f75844SAndroid Build Coastguard Worker
6672*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect upscaled resolution (960x540@30fps).
6673*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6674*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6675*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6676*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6677*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionGt(source.last_wants()));
6678*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6679*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6680*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(13, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6681*d9f75844SAndroid Build Coastguard Worker
6682*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no restriction (1280x720fps@30fps).
6683*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6684*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6685*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6686*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kWidth, kHeight);
6687*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionGt(source.last_wants()));
6688*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
6689*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6690*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6691*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(14, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6692*d9f75844SAndroid Build Coastguard Worker
6693*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no change.
6694*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6695*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
6696*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(14, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6697*d9f75844SAndroid Build Coastguard Worker
6698*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6699*d9f75844SAndroid Build Coastguard Worker }
6700*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AdaptWithTwoReasonsAndDifferentOrder_Framerate)6701*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, AdaptWithTwoReasonsAndDifferentOrder_Framerate) {
6702*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1280;
6703*d9f75844SAndroid Build Coastguard Worker const int kHeight = 720;
6704*d9f75844SAndroid Build Coastguard Worker const int64_t kFrameIntervalMs = 150;
6705*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
6706*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6707*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6708*d9f75844SAndroid Build Coastguard Worker
6709*d9f75844SAndroid Build Coastguard Worker // Enable BALANCED preference, no initial limitation.
6710*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
6711*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
6712*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
6713*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
6714*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6715*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6716*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kWidth, kHeight);
6717*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
6718*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6719*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6720*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
6721*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
6722*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6723*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6724*d9f75844SAndroid Build Coastguard Worker
6725*d9f75844SAndroid Build Coastguard Worker // Trigger cpu adapt down, expect scaled down resolution (960x540@30fps).
6726*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
6727*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6728*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6729*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6730*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(),
6731*d9f75844SAndroid Build Coastguard Worker FpsMaxResolutionMatches(Lt(kWidth * kHeight)));
6732*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6733*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6734*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
6735*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
6736*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6737*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6738*d9f75844SAndroid Build Coastguard Worker
6739*d9f75844SAndroid Build Coastguard Worker // Trigger cpu adapt down, expect scaled down resolution (640x360@30fps).
6740*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
6741*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6742*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6743*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6744*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionLt(source.last_wants()));
6745*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6746*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6747*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
6748*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
6749*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6750*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6751*d9f75844SAndroid Build Coastguard Worker
6752*d9f75844SAndroid Build Coastguard Worker // Trigger quality adapt down, expect reduced fps (640x360@15fps).
6753*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6754*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6755*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6756*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6757*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsLtResolutionEq(source.last_wants()));
6758*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6759*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6760*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
6761*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
6762*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6763*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6764*d9f75844SAndroid Build Coastguard Worker
6765*d9f75844SAndroid Build Coastguard Worker // Trigger cpu adapt up, expect no change since QP is most limited.
6766*d9f75844SAndroid Build Coastguard Worker {
6767*d9f75844SAndroid Build Coastguard Worker // Store current sink wants since we expect no change and if there is no
6768*d9f75844SAndroid Build Coastguard Worker // change then last_wants() is not updated.
6769*d9f75844SAndroid Build Coastguard Worker auto previous_sink_wants = source.sink_wants();
6770*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
6771*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6772*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6773*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6774*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsEqResolutionEqTo(previous_sink_wants));
6775*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6776*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6777*d9f75844SAndroid Build Coastguard Worker }
6778*d9f75844SAndroid Build Coastguard Worker
6779*d9f75844SAndroid Build Coastguard Worker // Trigger quality adapt up, expect increased fps (640x360@30fps).
6780*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6781*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6782*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6783*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6784*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsGtResolutionEq(source.last_wants()));
6785*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6786*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6787*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
6788*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
6789*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6790*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6791*d9f75844SAndroid Build Coastguard Worker
6792*d9f75844SAndroid Build Coastguard Worker // Trigger quality adapt up and Cpu adapt up since both are most limited,
6793*d9f75844SAndroid Build Coastguard Worker // expect increased resolution (960x540@30fps).
6794*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6795*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
6796*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6797*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6798*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6799*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionGt(source.last_wants()));
6800*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6801*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6802*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
6803*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
6804*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6805*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6806*d9f75844SAndroid Build Coastguard Worker
6807*d9f75844SAndroid Build Coastguard Worker // Trigger quality adapt up and Cpu adapt up since both are most limited,
6808*d9f75844SAndroid Build Coastguard Worker // expect no restriction (1280x720fps@30fps).
6809*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6810*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
6811*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6812*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6813*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kWidth, kHeight);
6814*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionGt(source.last_wants()));
6815*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
6816*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6817*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6818*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
6819*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
6820*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6821*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6822*d9f75844SAndroid Build Coastguard Worker
6823*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no change.
6824*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6825*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
6826*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6827*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6828*d9f75844SAndroid Build Coastguard Worker
6829*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6830*d9f75844SAndroid Build Coastguard Worker }
6831*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AdaptWithTwoReasonsAndDifferentOrder_Resolution)6832*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
6833*d9f75844SAndroid Build Coastguard Worker AdaptWithTwoReasonsAndDifferentOrder_Resolution) {
6834*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
6835*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
6836*d9f75844SAndroid Build Coastguard Worker const int kFpsLimit = 15;
6837*d9f75844SAndroid Build Coastguard Worker const int64_t kFrameIntervalMs = 150;
6838*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
6839*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6840*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6841*d9f75844SAndroid Build Coastguard Worker
6842*d9f75844SAndroid Build Coastguard Worker // Enable BALANCED preference, no initial limitation.
6843*d9f75844SAndroid Build Coastguard Worker AdaptingFrameForwarder source(&time_controller_);
6844*d9f75844SAndroid Build Coastguard Worker source.set_adaptation_enabled(true);
6845*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
6846*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
6847*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6848*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6849*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kWidth, kHeight);
6850*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
6851*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6852*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6853*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
6854*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
6855*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6856*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6857*d9f75844SAndroid Build Coastguard Worker
6858*d9f75844SAndroid Build Coastguard Worker // Trigger cpu adapt down, expect scaled down framerate (640x360@15fps).
6859*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
6860*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6861*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6862*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6863*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMatchesResolutionMax(Eq(kFpsLimit)));
6864*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6865*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6866*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
6867*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_framerate);
6868*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6869*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6870*d9f75844SAndroid Build Coastguard Worker
6871*d9f75844SAndroid Build Coastguard Worker // Trigger quality adapt down, expect scaled down resolution (480x270@15fps).
6872*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
6873*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6874*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6875*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6876*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsEqResolutionLt(source.last_wants()));
6877*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
6878*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6879*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
6880*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_framerate);
6881*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6882*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6883*d9f75844SAndroid Build Coastguard Worker
6884*d9f75844SAndroid Build Coastguard Worker // Trigger cpu adapt up, expect no change because quality is most limited.
6885*d9f75844SAndroid Build Coastguard Worker {
6886*d9f75844SAndroid Build Coastguard Worker auto previous_sink_wants = source.sink_wants();
6887*d9f75844SAndroid Build Coastguard Worker // Store current sink wants since we expect no change ind if there is no
6888*d9f75844SAndroid Build Coastguard Worker // change then last__wants() is not updated.
6889*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
6890*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6891*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6892*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6893*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsEqResolutionEqTo(previous_sink_wants));
6894*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6895*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6896*d9f75844SAndroid Build Coastguard Worker }
6897*d9f75844SAndroid Build Coastguard Worker
6898*d9f75844SAndroid Build Coastguard Worker // Trigger quality adapt up, expect upscaled resolution (640x360@15fps).
6899*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6900*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6901*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6902*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6903*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsEqResolutionGt(source.last_wants()));
6904*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6905*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
6906*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
6907*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_framerate);
6908*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6909*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6910*d9f75844SAndroid Build Coastguard Worker
6911*d9f75844SAndroid Build Coastguard Worker // Trigger quality and cpu adapt up, expect increased fps (640x360@30fps).
6912*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6913*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuUnderuse();
6914*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
6915*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
6916*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6917*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
6918*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
6919*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
6920*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
6921*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
6922*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6923*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6924*d9f75844SAndroid Build Coastguard Worker
6925*d9f75844SAndroid Build Coastguard Worker // Trigger adapt up, expect no change.
6926*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityHigh();
6927*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), FpsMaxResolutionMax());
6928*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
6929*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
6930*d9f75844SAndroid Build Coastguard Worker
6931*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6932*d9f75844SAndroid Build Coastguard Worker }
6933*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AcceptsFullHdAdaptedDownSimulcastFrames)6934*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, AcceptsFullHdAdaptedDownSimulcastFrames) {
6935*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1920;
6936*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 1080;
6937*d9f75844SAndroid Build Coastguard Worker // 2/3 of 1920.
6938*d9f75844SAndroid Build Coastguard Worker const int kAdaptedFrameWidth = 1280;
6939*d9f75844SAndroid Build Coastguard Worker // 2/3 of 1080.
6940*d9f75844SAndroid Build Coastguard Worker const int kAdaptedFrameHeight = 720;
6941*d9f75844SAndroid Build Coastguard Worker const int kFramerate = 24;
6942*d9f75844SAndroid Build Coastguard Worker
6943*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6944*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6945*d9f75844SAndroid Build Coastguard Worker // Trigger reconfigure encoder (without resetting the entire instance).
6946*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
6947*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
6948*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].max_framerate = kFramerate;
6949*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = kTargetBitrate.bps();
6950*d9f75844SAndroid Build Coastguard Worker video_encoder_config.video_stream_factory =
6951*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<CroppingVideoStreamFactory>();
6952*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
6953*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
6954*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
6955*d9f75844SAndroid Build Coastguard Worker
6956*d9f75844SAndroid Build Coastguard Worker video_source_.set_adaptation_enabled(true);
6957*d9f75844SAndroid Build Coastguard Worker
6958*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6959*d9f75844SAndroid Build Coastguard Worker CreateFrame(1, kFrameWidth, kFrameHeight));
6960*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kFrameWidth, kFrameHeight);
6961*d9f75844SAndroid Build Coastguard Worker
6962*d9f75844SAndroid Build Coastguard Worker // Trigger CPU overuse, downscale by 3/4.
6963*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerCpuOveruse();
6964*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6965*d9f75844SAndroid Build Coastguard Worker CreateFrame(2, kFrameWidth, kFrameHeight));
6966*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kAdaptedFrameWidth, kAdaptedFrameHeight);
6967*d9f75844SAndroid Build Coastguard Worker
6968*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
6969*d9f75844SAndroid Build Coastguard Worker }
6970*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,PeriodicallyUpdatesChannelParameters)6971*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, PeriodicallyUpdatesChannelParameters) {
6972*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
6973*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
6974*d9f75844SAndroid Build Coastguard Worker const int kLowFps = 2;
6975*d9f75844SAndroid Build Coastguard Worker const int kHighFps = 30;
6976*d9f75844SAndroid Build Coastguard Worker
6977*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6978*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6979*d9f75844SAndroid Build Coastguard Worker
6980*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
6981*d9f75844SAndroid Build Coastguard Worker max_framerate_ = kLowFps;
6982*d9f75844SAndroid Build Coastguard Worker
6983*d9f75844SAndroid Build Coastguard Worker // Insert 2 seconds of 2fps video.
6984*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < kLowFps * 2; ++i) {
6985*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6986*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
6987*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6988*d9f75844SAndroid Build Coastguard Worker timestamp_ms += 1000 / kLowFps;
6989*d9f75844SAndroid Build Coastguard Worker }
6990*d9f75844SAndroid Build Coastguard Worker
6991*d9f75844SAndroid Build Coastguard Worker // Make sure encoder is updated with new target.
6992*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
6993*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
6994*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
6995*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
6996*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
6997*d9f75844SAndroid Build Coastguard Worker timestamp_ms += 1000 / kLowFps;
6998*d9f75844SAndroid Build Coastguard Worker
6999*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(kLowFps, fake_encoder_.GetConfiguredInputFramerate());
7000*d9f75844SAndroid Build Coastguard Worker
7001*d9f75844SAndroid Build Coastguard Worker // Insert 30fps frames for just a little more than the forced update period.
7002*d9f75844SAndroid Build Coastguard Worker const int kVcmTimerIntervalFrames = (kProcessIntervalMs * kHighFps) / 1000;
7003*d9f75844SAndroid Build Coastguard Worker constexpr TimeDelta kFrameInterval = TimeDelta::Seconds(1) / kHighFps;
7004*d9f75844SAndroid Build Coastguard Worker max_framerate_ = kHighFps;
7005*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < kVcmTimerIntervalFrames + 2; ++i) {
7006*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
7007*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
7008*d9f75844SAndroid Build Coastguard Worker // Wait for encoded frame, but skip ahead if it doesn't arrive as it might
7009*d9f75844SAndroid Build Coastguard Worker // be dropped if the encoder hans't been updated with the new higher target
7010*d9f75844SAndroid Build Coastguard Worker // framerate yet, causing it to overshoot the target bitrate and then
7011*d9f75844SAndroid Build Coastguard Worker // suffering the wrath of the media optimizer.
7012*d9f75844SAndroid Build Coastguard Worker TimedWaitForEncodedFrame(timestamp_ms, 2 * kFrameInterval);
7013*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameInterval.ms();
7014*d9f75844SAndroid Build Coastguard Worker }
7015*d9f75844SAndroid Build Coastguard Worker
7016*d9f75844SAndroid Build Coastguard Worker // Don expect correct measurement just yet, but it should be higher than
7017*d9f75844SAndroid Build Coastguard Worker // before.
7018*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(fake_encoder_.GetConfiguredInputFramerate(), kLowFps);
7019*d9f75844SAndroid Build Coastguard Worker
7020*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7021*d9f75844SAndroid Build Coastguard Worker }
7022*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DoesNotUpdateBitrateAllocationWhenSuspended)7023*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DoesNotUpdateBitrateAllocationWhenSuspended) {
7024*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
7025*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
7026*d9f75844SAndroid Build Coastguard Worker ResetEncoder("FAKE", 1, 1, 1, false,
7027*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
7028*d9f75844SAndroid Build Coastguard Worker kVideoBitrateAllocation);
7029*d9f75844SAndroid Build Coastguard Worker
7030*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7031*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7032*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
7033*d9f75844SAndroid Build Coastguard Worker
7034*d9f75844SAndroid Build Coastguard Worker // Insert a first video frame, causes another bitrate update.
7035*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
7036*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
7037*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
7038*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
7039*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_bitrate_allocations(), 1);
7040*d9f75844SAndroid Build Coastguard Worker
7041*d9f75844SAndroid Build Coastguard Worker // Next, simulate video suspension due to pacer queue overrun.
7042*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7043*d9f75844SAndroid Build Coastguard Worker DataRate::Zero(), DataRate::Zero(), DataRate::Zero(), 0, 1, 0);
7044*d9f75844SAndroid Build Coastguard Worker
7045*d9f75844SAndroid Build Coastguard Worker // Skip ahead until a new periodic parameter update should have occured.
7046*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kProcessIntervalMs;
7047*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Millis(kProcessIntervalMs));
7048*d9f75844SAndroid Build Coastguard Worker
7049*d9f75844SAndroid Build Coastguard Worker // No more allocations has been made.
7050*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
7051*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
7052*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
7053*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.number_of_bitrate_allocations(), 1);
7054*d9f75844SAndroid Build Coastguard Worker
7055*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7056*d9f75844SAndroid Build Coastguard Worker }
7057*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DefaultCpuAdaptationThresholdsForSoftwareEncoder)7058*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
7059*d9f75844SAndroid Build Coastguard Worker DefaultCpuAdaptationThresholdsForSoftwareEncoder) {
7060*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
7061*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
7062*d9f75844SAndroid Build Coastguard Worker const test::ScopedKeyValueConfig kFieldTrials;
7063*d9f75844SAndroid Build Coastguard Worker const CpuOveruseOptions default_options(kFieldTrials);
7064*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7065*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7066*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
7067*d9f75844SAndroid Build Coastguard Worker CreateFrame(1, kFrameWidth, kFrameHeight));
7068*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
7069*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
7070*d9f75844SAndroid Build Coastguard Worker .low_encode_usage_threshold_percent,
7071*d9f75844SAndroid Build Coastguard Worker default_options.low_encode_usage_threshold_percent);
7072*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
7073*d9f75844SAndroid Build Coastguard Worker .high_encode_usage_threshold_percent,
7074*d9f75844SAndroid Build Coastguard Worker default_options.high_encode_usage_threshold_percent);
7075*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7076*d9f75844SAndroid Build Coastguard Worker }
7077*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,HigherCpuAdaptationThresholdsForHardwareEncoder)7078*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
7079*d9f75844SAndroid Build Coastguard Worker HigherCpuAdaptationThresholdsForHardwareEncoder) {
7080*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
7081*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
7082*d9f75844SAndroid Build Coastguard Worker const test::ScopedKeyValueConfig kFieldTrials;
7083*d9f75844SAndroid Build Coastguard Worker CpuOveruseOptions hardware_options(kFieldTrials);
7084*d9f75844SAndroid Build Coastguard Worker hardware_options.low_encode_usage_threshold_percent = 150;
7085*d9f75844SAndroid Build Coastguard Worker hardware_options.high_encode_usage_threshold_percent = 200;
7086*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetIsHardwareAccelerated(true);
7087*d9f75844SAndroid Build Coastguard Worker
7088*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7089*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7090*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
7091*d9f75844SAndroid Build Coastguard Worker CreateFrame(1, kFrameWidth, kFrameHeight));
7092*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
7093*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
7094*d9f75844SAndroid Build Coastguard Worker .low_encode_usage_threshold_percent,
7095*d9f75844SAndroid Build Coastguard Worker hardware_options.low_encode_usage_threshold_percent);
7096*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
7097*d9f75844SAndroid Build Coastguard Worker .high_encode_usage_threshold_percent,
7098*d9f75844SAndroid Build Coastguard Worker hardware_options.high_encode_usage_threshold_percent);
7099*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7100*d9f75844SAndroid Build Coastguard Worker }
7101*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,CpuAdaptationThresholdsUpdatesWhenHardwareAccelerationChange)7102*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
7103*d9f75844SAndroid Build Coastguard Worker CpuAdaptationThresholdsUpdatesWhenHardwareAccelerationChange) {
7104*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
7105*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
7106*d9f75844SAndroid Build Coastguard Worker
7107*d9f75844SAndroid Build Coastguard Worker const test::ScopedKeyValueConfig kFieldTrials;
7108*d9f75844SAndroid Build Coastguard Worker const CpuOveruseOptions default_options(kFieldTrials);
7109*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7110*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7111*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
7112*d9f75844SAndroid Build Coastguard Worker CreateFrame(1, kFrameWidth, kFrameHeight));
7113*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
7114*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
7115*d9f75844SAndroid Build Coastguard Worker .low_encode_usage_threshold_percent,
7116*d9f75844SAndroid Build Coastguard Worker default_options.low_encode_usage_threshold_percent);
7117*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
7118*d9f75844SAndroid Build Coastguard Worker .high_encode_usage_threshold_percent,
7119*d9f75844SAndroid Build Coastguard Worker default_options.high_encode_usage_threshold_percent);
7120*d9f75844SAndroid Build Coastguard Worker
7121*d9f75844SAndroid Build Coastguard Worker CpuOveruseOptions hardware_options(kFieldTrials);
7122*d9f75844SAndroid Build Coastguard Worker hardware_options.low_encode_usage_threshold_percent = 150;
7123*d9f75844SAndroid Build Coastguard Worker hardware_options.high_encode_usage_threshold_percent = 200;
7124*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetIsHardwareAccelerated(true);
7125*d9f75844SAndroid Build Coastguard Worker
7126*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
7127*d9f75844SAndroid Build Coastguard Worker CreateFrame(2, kFrameWidth, kFrameHeight));
7128*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
7129*d9f75844SAndroid Build Coastguard Worker
7130*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
7131*d9f75844SAndroid Build Coastguard Worker .low_encode_usage_threshold_percent,
7132*d9f75844SAndroid Build Coastguard Worker hardware_options.low_encode_usage_threshold_percent);
7133*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_stream_encoder_->overuse_detector_proxy_->GetOptions()
7134*d9f75844SAndroid Build Coastguard Worker .high_encode_usage_threshold_percent,
7135*d9f75844SAndroid Build Coastguard Worker hardware_options.high_encode_usage_threshold_percent);
7136*d9f75844SAndroid Build Coastguard Worker
7137*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7138*d9f75844SAndroid Build Coastguard Worker }
7139*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DropsFramesWhenEncoderOvershoots)7140*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DropsFramesWhenEncoderOvershoots) {
7141*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 320;
7142*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 240;
7143*d9f75844SAndroid Build Coastguard Worker const int kFps = 30;
7144*d9f75844SAndroid Build Coastguard Worker const DataRate kTargetBitrate = DataRate::KilobitsPerSec(120);
7145*d9f75844SAndroid Build Coastguard Worker const int kNumFramesInRun = kFps * 5; // Runs of five seconds.
7146*d9f75844SAndroid Build Coastguard Worker
7147*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7148*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7149*d9f75844SAndroid Build Coastguard Worker
7150*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
7151*d9f75844SAndroid Build Coastguard Worker max_framerate_ = kFps;
7152*d9f75844SAndroid Build Coastguard Worker
7153*d9f75844SAndroid Build Coastguard Worker // Insert 3 seconds of video, verify number of drops with normal bitrate.
7154*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SimulateOvershoot(1.0);
7155*d9f75844SAndroid Build Coastguard Worker int num_dropped = 0;
7156*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < kNumFramesInRun; ++i) {
7157*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
7158*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
7159*d9f75844SAndroid Build Coastguard Worker // Wait up to two frame durations for a frame to arrive.
7160*d9f75844SAndroid Build Coastguard Worker if (!TimedWaitForEncodedFrame(timestamp_ms,
7161*d9f75844SAndroid Build Coastguard Worker 2 * TimeDelta::Seconds(1) / kFps)) {
7162*d9f75844SAndroid Build Coastguard Worker ++num_dropped;
7163*d9f75844SAndroid Build Coastguard Worker }
7164*d9f75844SAndroid Build Coastguard Worker timestamp_ms += 1000 / kFps;
7165*d9f75844SAndroid Build Coastguard Worker }
7166*d9f75844SAndroid Build Coastguard Worker
7167*d9f75844SAndroid Build Coastguard Worker // Framerate should be measured to be near the expected target rate.
7168*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(fake_encoder_.GetLastFramerate(), kFps, 1);
7169*d9f75844SAndroid Build Coastguard Worker
7170*d9f75844SAndroid Build Coastguard Worker // Frame drops should be within 5% of expected 0%.
7171*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(num_dropped, 0, 5 * kNumFramesInRun / 100);
7172*d9f75844SAndroid Build Coastguard Worker
7173*d9f75844SAndroid Build Coastguard Worker // Make encoder produce frames at double the expected bitrate during 3 seconds
7174*d9f75844SAndroid Build Coastguard Worker // of video, verify number of drops. Rate needs to be slightly changed in
7175*d9f75844SAndroid Build Coastguard Worker // order to force the rate to be reconfigured.
7176*d9f75844SAndroid Build Coastguard Worker double overshoot_factor = 2.0;
7177*d9f75844SAndroid Build Coastguard Worker const RateControlSettings trials =
7178*d9f75844SAndroid Build Coastguard Worker RateControlSettings::ParseFromFieldTrials();
7179*d9f75844SAndroid Build Coastguard Worker if (trials.UseEncoderBitrateAdjuster()) {
7180*d9f75844SAndroid Build Coastguard Worker // With bitrate adjuster, when need to overshoot even more to trigger
7181*d9f75844SAndroid Build Coastguard Worker // frame dropping since the adjuter will try to just lower the target
7182*d9f75844SAndroid Build Coastguard Worker // bitrate rather than drop frames. If network headroom can be used, it
7183*d9f75844SAndroid Build Coastguard Worker // doesn't push back as hard so we don't need quite as much overshoot.
7184*d9f75844SAndroid Build Coastguard Worker // These numbers are unfortunately a bit magical but there's not trivial
7185*d9f75844SAndroid Build Coastguard Worker // way to algebraically infer them.
7186*d9f75844SAndroid Build Coastguard Worker overshoot_factor = 3.0;
7187*d9f75844SAndroid Build Coastguard Worker }
7188*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SimulateOvershoot(overshoot_factor);
7189*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7190*d9f75844SAndroid Build Coastguard Worker kTargetBitrate + DataRate::KilobitsPerSec(1),
7191*d9f75844SAndroid Build Coastguard Worker kTargetBitrate + DataRate::KilobitsPerSec(1),
7192*d9f75844SAndroid Build Coastguard Worker kTargetBitrate + DataRate::KilobitsPerSec(1), 0, 0, 0);
7193*d9f75844SAndroid Build Coastguard Worker num_dropped = 0;
7194*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < kNumFramesInRun; ++i) {
7195*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
7196*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
7197*d9f75844SAndroid Build Coastguard Worker // Wait up to two frame durations for a frame to arrive.
7198*d9f75844SAndroid Build Coastguard Worker if (!TimedWaitForEncodedFrame(timestamp_ms,
7199*d9f75844SAndroid Build Coastguard Worker 2 * TimeDelta::Seconds(1) / kFps)) {
7200*d9f75844SAndroid Build Coastguard Worker ++num_dropped;
7201*d9f75844SAndroid Build Coastguard Worker }
7202*d9f75844SAndroid Build Coastguard Worker timestamp_ms += 1000 / kFps;
7203*d9f75844SAndroid Build Coastguard Worker }
7204*d9f75844SAndroid Build Coastguard Worker
7205*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7206*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7207*d9f75844SAndroid Build Coastguard Worker
7208*d9f75844SAndroid Build Coastguard Worker // Target framerate should be still be near the expected target, despite
7209*d9f75844SAndroid Build Coastguard Worker // the frame drops.
7210*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(fake_encoder_.GetLastFramerate(), kFps, 1);
7211*d9f75844SAndroid Build Coastguard Worker
7212*d9f75844SAndroid Build Coastguard Worker // Frame drops should be within 5% of expected 50%.
7213*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(num_dropped, kNumFramesInRun / 2, 5 * kNumFramesInRun / 100);
7214*d9f75844SAndroid Build Coastguard Worker
7215*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7216*d9f75844SAndroid Build Coastguard Worker }
7217*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ConfiguresCorrectFrameRate)7218*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, ConfiguresCorrectFrameRate) {
7219*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 320;
7220*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 240;
7221*d9f75844SAndroid Build Coastguard Worker const int kActualInputFps = 24;
7222*d9f75844SAndroid Build Coastguard Worker const DataRate kTargetBitrate = DataRate::KilobitsPerSec(120);
7223*d9f75844SAndroid Build Coastguard Worker
7224*d9f75844SAndroid Build Coastguard Worker ASSERT_GT(max_framerate_, kActualInputFps);
7225*d9f75844SAndroid Build Coastguard Worker
7226*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
7227*d9f75844SAndroid Build Coastguard Worker max_framerate_ = kActualInputFps;
7228*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7229*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7230*d9f75844SAndroid Build Coastguard Worker
7231*d9f75844SAndroid Build Coastguard Worker // Insert 3 seconds of video, with an input fps lower than configured max.
7232*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < kActualInputFps * 3; ++i) {
7233*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
7234*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
7235*d9f75844SAndroid Build Coastguard Worker // Wait up to two frame durations for a frame to arrive.
7236*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
7237*d9f75844SAndroid Build Coastguard Worker timestamp_ms += 1000 / kActualInputFps;
7238*d9f75844SAndroid Build Coastguard Worker }
7239*d9f75844SAndroid Build Coastguard Worker
7240*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(kActualInputFps, fake_encoder_.GetLastFramerate(), 1);
7241*d9f75844SAndroid Build Coastguard Worker
7242*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7243*d9f75844SAndroid Build Coastguard Worker }
7244*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AccumulatesUpdateRectOnDroppedFrames)7245*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, AccumulatesUpdateRectOnDroppedFrames) {
7246*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect rect;
7247*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
7248*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&source,
7249*d9f75844SAndroid Build Coastguard Worker DegradationPreference::MAINTAIN_FRAMERATE);
7250*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7251*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7252*d9f75844SAndroid Build Coastguard Worker
7253*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrameWithUpdatedPixel(1, nullptr, 0));
7254*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
7255*d9f75844SAndroid Build Coastguard Worker // On the very first frame full update should be forced.
7256*d9f75844SAndroid Build Coastguard Worker rect = fake_encoder_.GetLastUpdateRect();
7257*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rect.offset_x, 0);
7258*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rect.offset_y, 0);
7259*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rect.height, codec_height_);
7260*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rect.width, codec_width_);
7261*d9f75844SAndroid Build Coastguard Worker // Frame with NTP timestamp 2 will be dropped due to outstanding frames
7262*d9f75844SAndroid Build Coastguard Worker // scheduled for processing during encoder queue processing of frame 2.
7263*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrameWithUpdatedPixel(2, nullptr, 1));
7264*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrameWithUpdatedPixel(3, nullptr, 10));
7265*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
7266*d9f75844SAndroid Build Coastguard Worker // Updates to pixels 1 and 10 should be accumulated to one 10x1 rect.
7267*d9f75844SAndroid Build Coastguard Worker rect = fake_encoder_.GetLastUpdateRect();
7268*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rect.offset_x, 1);
7269*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rect.offset_y, 0);
7270*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rect.width, 10);
7271*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rect.height, 1);
7272*d9f75844SAndroid Build Coastguard Worker
7273*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrameWithUpdatedPixel(4, nullptr, 0));
7274*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(4);
7275*d9f75844SAndroid Build Coastguard Worker // Previous frame was encoded, so no accumulation should happen.
7276*d9f75844SAndroid Build Coastguard Worker rect = fake_encoder_.GetLastUpdateRect();
7277*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rect.offset_x, 0);
7278*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rect.offset_y, 0);
7279*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rect.width, 1);
7280*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rect.height, 1);
7281*d9f75844SAndroid Build Coastguard Worker
7282*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7283*d9f75844SAndroid Build Coastguard Worker }
7284*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SetsFrameTypes)7285*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, SetsFrameTypes) {
7286*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7287*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7288*d9f75844SAndroid Build Coastguard Worker
7289*d9f75844SAndroid Build Coastguard Worker // First frame is always keyframe.
7290*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
7291*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
7292*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(
7293*d9f75844SAndroid Build Coastguard Worker fake_encoder_.LastFrameTypes(),
7294*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAre(VideoFrameType{VideoFrameType::kVideoFrameKey}));
7295*d9f75844SAndroid Build Coastguard Worker
7296*d9f75844SAndroid Build Coastguard Worker // Insert delta frame.
7297*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
7298*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
7299*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(
7300*d9f75844SAndroid Build Coastguard Worker fake_encoder_.LastFrameTypes(),
7301*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAre(VideoFrameType{VideoFrameType::kVideoFrameDelta}));
7302*d9f75844SAndroid Build Coastguard Worker
7303*d9f75844SAndroid Build Coastguard Worker // Request next frame be a key-frame.
7304*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SendKeyFrame();
7305*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
7306*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
7307*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(
7308*d9f75844SAndroid Build Coastguard Worker fake_encoder_.LastFrameTypes(),
7309*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAre(VideoFrameType{VideoFrameType::kVideoFrameKey}));
7310*d9f75844SAndroid Build Coastguard Worker
7311*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7312*d9f75844SAndroid Build Coastguard Worker }
7313*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SetsFrameTypesSimulcast)7314*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, SetsFrameTypesSimulcast) {
7315*d9f75844SAndroid Build Coastguard Worker // Setup simulcast with three streams.
7316*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", 3, 1, 1, false);
7317*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7318*d9f75844SAndroid Build Coastguard Worker kSimulcastTargetBitrate, kSimulcastTargetBitrate, kSimulcastTargetBitrate,
7319*d9f75844SAndroid Build Coastguard Worker 0, 0, 0);
7320*d9f75844SAndroid Build Coastguard Worker // Wait for all three layers before triggering event.
7321*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(3);
7322*d9f75844SAndroid Build Coastguard Worker
7323*d9f75844SAndroid Build Coastguard Worker // First frame is always keyframe.
7324*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
7325*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
7326*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(fake_encoder_.LastFrameTypes(),
7327*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray({VideoFrameType::kVideoFrameKey,
7328*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameKey,
7329*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameKey}));
7330*d9f75844SAndroid Build Coastguard Worker
7331*d9f75844SAndroid Build Coastguard Worker // Insert delta frame.
7332*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
7333*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(2);
7334*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(fake_encoder_.LastFrameTypes(),
7335*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray({VideoFrameType::kVideoFrameDelta,
7336*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameDelta,
7337*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameDelta}));
7338*d9f75844SAndroid Build Coastguard Worker
7339*d9f75844SAndroid Build Coastguard Worker // Request next frame be a key-frame.
7340*d9f75844SAndroid Build Coastguard Worker // Only first stream is configured to produce key-frame.
7341*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SendKeyFrame();
7342*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
7343*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(3);
7344*d9f75844SAndroid Build Coastguard Worker
7345*d9f75844SAndroid Build Coastguard Worker // TODO(webrtc:10615): Map keyframe request to spatial layer. Currently
7346*d9f75844SAndroid Build Coastguard Worker // keyframe request on any layer triggers keyframe on all layers.
7347*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(fake_encoder_.LastFrameTypes(),
7348*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray({VideoFrameType::kVideoFrameKey,
7349*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameKey,
7350*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameKey}));
7351*d9f75844SAndroid Build Coastguard Worker
7352*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7353*d9f75844SAndroid Build Coastguard Worker }
7354*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,DoesNotRewriteH264BitstreamWithOptimalSps)7355*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, DoesNotRewriteH264BitstreamWithOptimalSps) {
7356*d9f75844SAndroid Build Coastguard Worker // SPS contains VUI with restrictions on the maximum number of reordered
7357*d9f75844SAndroid Build Coastguard Worker // pictures, there is no need to rewrite the bitstream to enable faster
7358*d9f75844SAndroid Build Coastguard Worker // decoding.
7359*d9f75844SAndroid Build Coastguard Worker ResetEncoder("H264", 1, 1, 1, false);
7360*d9f75844SAndroid Build Coastguard Worker
7361*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7362*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7363*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
7364*d9f75844SAndroid Build Coastguard Worker
7365*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetEncodedImageData(
7366*d9f75844SAndroid Build Coastguard Worker EncodedImageBuffer::Create(kOptimalSps, sizeof(kOptimalSps)));
7367*d9f75844SAndroid Build Coastguard Worker
7368*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
7369*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
7370*d9f75844SAndroid Build Coastguard Worker
7371*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(sink_.GetLastEncodedImageData(),
7372*d9f75844SAndroid Build Coastguard Worker testing::ElementsAreArray(kOptimalSps));
7373*d9f75844SAndroid Build Coastguard Worker
7374*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7375*d9f75844SAndroid Build Coastguard Worker }
7376*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,RewritesH264BitstreamWithNonOptimalSps)7377*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, RewritesH264BitstreamWithNonOptimalSps) {
7378*d9f75844SAndroid Build Coastguard Worker // SPS does not contain VUI, the bitstream is will be rewritten with added
7379*d9f75844SAndroid Build Coastguard Worker // VUI with restrictions on the maximum number of reordered pictures to
7380*d9f75844SAndroid Build Coastguard Worker // enable faster decoding.
7381*d9f75844SAndroid Build Coastguard Worker uint8_t original_sps[] = {0, 0, 0, 1, H264::NaluType::kSps,
7382*d9f75844SAndroid Build Coastguard Worker 0x00, 0x00, 0x03, 0x03, 0xF4,
7383*d9f75844SAndroid Build Coastguard Worker 0x05, 0x03, 0xC7, 0xC0};
7384*d9f75844SAndroid Build Coastguard Worker ResetEncoder("H264", 1, 1, 1, false);
7385*d9f75844SAndroid Build Coastguard Worker
7386*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7387*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7388*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
7389*d9f75844SAndroid Build Coastguard Worker
7390*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetEncodedImageData(
7391*d9f75844SAndroid Build Coastguard Worker EncodedImageBuffer::Create(original_sps, sizeof(original_sps)));
7392*d9f75844SAndroid Build Coastguard Worker
7393*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
7394*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
7395*d9f75844SAndroid Build Coastguard Worker
7396*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(sink_.GetLastEncodedImageData(),
7397*d9f75844SAndroid Build Coastguard Worker testing::ElementsAreArray(kOptimalSps));
7398*d9f75844SAndroid Build Coastguard Worker
7399*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7400*d9f75844SAndroid Build Coastguard Worker }
7401*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,CopiesVideoFrameMetadataAfterDownscale)7402*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, CopiesVideoFrameMetadataAfterDownscale) {
7403*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
7404*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
7405*d9f75844SAndroid Build Coastguard Worker const DataRate kTargetBitrate =
7406*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(300); // Too low for HD resolution.
7407*d9f75844SAndroid Build Coastguard Worker
7408*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7409*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7410*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
7411*d9f75844SAndroid Build Coastguard Worker
7412*d9f75844SAndroid Build Coastguard Worker // Insert a first video frame. It should be dropped because of downscale in
7413*d9f75844SAndroid Build Coastguard Worker // resolution.
7414*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
7415*d9f75844SAndroid Build Coastguard Worker VideoFrame frame = CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight);
7416*d9f75844SAndroid Build Coastguard Worker frame.set_rotation(kVideoRotation_270);
7417*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(frame);
7418*d9f75844SAndroid Build Coastguard Worker
7419*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
7420*d9f75844SAndroid Build Coastguard Worker
7421*d9f75844SAndroid Build Coastguard Worker // Second frame is downscaled.
7422*d9f75844SAndroid Build Coastguard Worker timestamp_ms = CurrentTimeMs();
7423*d9f75844SAndroid Build Coastguard Worker frame = CreateFrame(timestamp_ms, kFrameWidth / 2, kFrameHeight / 2);
7424*d9f75844SAndroid Build Coastguard Worker frame.set_rotation(kVideoRotation_90);
7425*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(frame);
7426*d9f75844SAndroid Build Coastguard Worker
7427*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
7428*d9f75844SAndroid Build Coastguard Worker sink_.CheckLastFrameRotationMatches(kVideoRotation_90);
7429*d9f75844SAndroid Build Coastguard Worker
7430*d9f75844SAndroid Build Coastguard Worker // Insert another frame, also downscaled.
7431*d9f75844SAndroid Build Coastguard Worker timestamp_ms = CurrentTimeMs();
7432*d9f75844SAndroid Build Coastguard Worker frame = CreateFrame(timestamp_ms, kFrameWidth / 2, kFrameHeight / 2);
7433*d9f75844SAndroid Build Coastguard Worker frame.set_rotation(kVideoRotation_180);
7434*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(frame);
7435*d9f75844SAndroid Build Coastguard Worker
7436*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
7437*d9f75844SAndroid Build Coastguard Worker sink_.CheckLastFrameRotationMatches(kVideoRotation_180);
7438*d9f75844SAndroid Build Coastguard Worker
7439*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7440*d9f75844SAndroid Build Coastguard Worker }
7441*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,BandwidthAllocationLowerBound)7442*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, BandwidthAllocationLowerBound) {
7443*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 320;
7444*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 180;
7445*d9f75844SAndroid Build Coastguard Worker
7446*d9f75844SAndroid Build Coastguard Worker // Initial rate.
7447*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7448*d9f75844SAndroid Build Coastguard Worker /*target_bitrate=*/DataRate::KilobitsPerSec(300),
7449*d9f75844SAndroid Build Coastguard Worker /*stable_target_bitrate=*/DataRate::KilobitsPerSec(300),
7450*d9f75844SAndroid Build Coastguard Worker /*link_allocation=*/DataRate::KilobitsPerSec(300),
7451*d9f75844SAndroid Build Coastguard Worker /*fraction_lost=*/0,
7452*d9f75844SAndroid Build Coastguard Worker /*round_trip_time_ms=*/0,
7453*d9f75844SAndroid Build Coastguard Worker /*cwnd_reduce_ratio=*/0);
7454*d9f75844SAndroid Build Coastguard Worker
7455*d9f75844SAndroid Build Coastguard Worker // Insert a first video frame so that encoder gets configured.
7456*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
7457*d9f75844SAndroid Build Coastguard Worker VideoFrame frame = CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight);
7458*d9f75844SAndroid Build Coastguard Worker frame.set_rotation(kVideoRotation_270);
7459*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(frame);
7460*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
7461*d9f75844SAndroid Build Coastguard Worker
7462*d9f75844SAndroid Build Coastguard Worker // Set a target rate below the minimum allowed by the codec settings.
7463*d9f75844SAndroid Build Coastguard Worker VideoCodec codec_config = fake_encoder_.config();
7464*d9f75844SAndroid Build Coastguard Worker DataRate min_rate = DataRate::KilobitsPerSec(codec_config.minBitrate);
7465*d9f75844SAndroid Build Coastguard Worker DataRate target_rate = min_rate - DataRate::KilobitsPerSec(1);
7466*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7467*d9f75844SAndroid Build Coastguard Worker /*target_bitrate=*/target_rate,
7468*d9f75844SAndroid Build Coastguard Worker /*stable_target_bitrate=*/target_rate,
7469*d9f75844SAndroid Build Coastguard Worker /*link_allocation=*/target_rate,
7470*d9f75844SAndroid Build Coastguard Worker /*fraction_lost=*/0,
7471*d9f75844SAndroid Build Coastguard Worker /*round_trip_time_ms=*/0,
7472*d9f75844SAndroid Build Coastguard Worker /*cwnd_reduce_ratio=*/0);
7473*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
7474*d9f75844SAndroid Build Coastguard Worker
7475*d9f75844SAndroid Build Coastguard Worker // Target bitrate and bandwidth allocation should both be capped at min_rate.
7476*d9f75844SAndroid Build Coastguard Worker auto rate_settings = fake_encoder_.GetAndResetLastRateControlSettings();
7477*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(rate_settings.has_value());
7478*d9f75844SAndroid Build Coastguard Worker DataRate allocation_sum =
7479*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(rate_settings->bitrate.get_sum_bps());
7480*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(min_rate, allocation_sum);
7481*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rate_settings->bandwidth_allocation, min_rate);
7482*d9f75844SAndroid Build Coastguard Worker
7483*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7484*d9f75844SAndroid Build Coastguard Worker }
7485*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderRatesPropagatedOnReconfigure)7486*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, EncoderRatesPropagatedOnReconfigure) {
7487*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7488*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7489*d9f75844SAndroid Build Coastguard Worker // Capture a frame and wait for it to synchronize with the encoder thread.
7490*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
7491*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(timestamp_ms, nullptr));
7492*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
7493*d9f75844SAndroid Build Coastguard Worker
7494*d9f75844SAndroid Build Coastguard Worker auto prev_rate_settings = fake_encoder_.GetAndResetLastRateControlSettings();
7495*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(prev_rate_settings.has_value());
7496*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<int>(prev_rate_settings->framerate_fps),
7497*d9f75844SAndroid Build Coastguard Worker kDefaultFramerate);
7498*d9f75844SAndroid Build Coastguard Worker
7499*d9f75844SAndroid Build Coastguard Worker // Send 1s of video to ensure the framerate is stable at kDefaultFramerate.
7500*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 2 * kDefaultFramerate; i++) {
7501*d9f75844SAndroid Build Coastguard Worker timestamp_ms += 1000 / kDefaultFramerate;
7502*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(timestamp_ms, nullptr));
7503*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
7504*d9f75844SAndroid Build Coastguard Worker }
7505*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(static_cast<int>(fake_encoder_.GetLastFramerate()),
7506*d9f75844SAndroid Build Coastguard Worker kDefaultFramerate);
7507*d9f75844SAndroid Build Coastguard Worker // Capture larger frame to trigger a reconfigure.
7508*d9f75844SAndroid Build Coastguard Worker codec_height_ *= 2;
7509*d9f75844SAndroid Build Coastguard Worker codec_width_ *= 2;
7510*d9f75844SAndroid Build Coastguard Worker timestamp_ms += 1000 / kDefaultFramerate;
7511*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(timestamp_ms, nullptr));
7512*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
7513*d9f75844SAndroid Build Coastguard Worker
7514*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, sink_.number_of_reconfigurations());
7515*d9f75844SAndroid Build Coastguard Worker auto current_rate_settings =
7516*d9f75844SAndroid Build Coastguard Worker fake_encoder_.GetAndResetLastRateControlSettings();
7517*d9f75844SAndroid Build Coastguard Worker // Ensure we have actually reconfigured twice
7518*d9f75844SAndroid Build Coastguard Worker // The rate settings should have been set again even though
7519*d9f75844SAndroid Build Coastguard Worker // they haven't changed.
7520*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(current_rate_settings.has_value());
7521*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(prev_rate_settings, current_rate_settings);
7522*d9f75844SAndroid Build Coastguard Worker
7523*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7524*d9f75844SAndroid Build Coastguard Worker }
7525*d9f75844SAndroid Build Coastguard Worker
7526*d9f75844SAndroid Build Coastguard Worker struct MockEncoderSwitchRequestCallback : public EncoderSwitchRequestCallback {
7527*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void, RequestEncoderFallback, (), (override));
7528*d9f75844SAndroid Build Coastguard Worker MOCK_METHOD(void,
7529*d9f75844SAndroid Build Coastguard Worker RequestEncoderSwitch,
7530*d9f75844SAndroid Build Coastguard Worker (const webrtc::SdpVideoFormat& format,
7531*d9f75844SAndroid Build Coastguard Worker bool allow_default_fallback),
7532*d9f75844SAndroid Build Coastguard Worker (override));
7533*d9f75844SAndroid Build Coastguard Worker };
7534*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderSelectorCurrentEncoderIsSignaled)7535*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, EncoderSelectorCurrentEncoderIsSignaled) {
7536*d9f75844SAndroid Build Coastguard Worker constexpr int kDontCare = 100;
7537*d9f75844SAndroid Build Coastguard Worker StrictMock<MockEncoderSelector> encoder_selector;
7538*d9f75844SAndroid Build Coastguard Worker auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>(
7539*d9f75844SAndroid Build Coastguard Worker &fake_encoder_, &encoder_selector);
7540*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_factory = encoder_factory.get();
7541*d9f75844SAndroid Build Coastguard Worker
7542*d9f75844SAndroid Build Coastguard Worker // Reset encoder for new configuration to take effect.
7543*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config_.Copy());
7544*d9f75844SAndroid Build Coastguard Worker
7545*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(encoder_selector, OnCurrentEncoder);
7546*d9f75844SAndroid Build Coastguard Worker
7547*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
7548*d9f75844SAndroid Build Coastguard Worker CreateFrame(kDontCare, kDontCare, kDontCare));
7549*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Zero());
7550*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7551*d9f75844SAndroid Build Coastguard Worker
7552*d9f75844SAndroid Build Coastguard Worker // The encoders produced by the VideoEncoderProxyFactory have a pointer back
7553*d9f75844SAndroid Build Coastguard Worker // to it's factory, so in order for the encoder instance in the
7554*d9f75844SAndroid Build Coastguard Worker // `video_stream_encoder_` to be destroyed before the `encoder_factory` we
7555*d9f75844SAndroid Build Coastguard Worker // reset the `video_stream_encoder_` here.
7556*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_.reset();
7557*d9f75844SAndroid Build Coastguard Worker }
7558*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderSelectorBitrateSwitch)7559*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, EncoderSelectorBitrateSwitch) {
7560*d9f75844SAndroid Build Coastguard Worker constexpr int kDontCare = 100;
7561*d9f75844SAndroid Build Coastguard Worker
7562*d9f75844SAndroid Build Coastguard Worker NiceMock<MockEncoderSelector> encoder_selector;
7563*d9f75844SAndroid Build Coastguard Worker StrictMock<MockEncoderSwitchRequestCallback> switch_callback;
7564*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_switch_request_callback =
7565*d9f75844SAndroid Build Coastguard Worker &switch_callback;
7566*d9f75844SAndroid Build Coastguard Worker auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>(
7567*d9f75844SAndroid Build Coastguard Worker &fake_encoder_, &encoder_selector);
7568*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_factory = encoder_factory.get();
7569*d9f75844SAndroid Build Coastguard Worker
7570*d9f75844SAndroid Build Coastguard Worker // Reset encoder for new configuration to take effect.
7571*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config_.Copy());
7572*d9f75844SAndroid Build Coastguard Worker
7573*d9f75844SAndroid Build Coastguard Worker ON_CALL(encoder_selector, OnAvailableBitrate)
7574*d9f75844SAndroid Build Coastguard Worker .WillByDefault(Return(SdpVideoFormat("AV1")));
7575*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(switch_callback,
7576*d9f75844SAndroid Build Coastguard Worker RequestEncoderSwitch(Field(&SdpVideoFormat::name, "AV1"),
7577*d9f75844SAndroid Build Coastguard Worker /*allow_default_fallback=*/false));
7578*d9f75844SAndroid Build Coastguard Worker
7579*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7580*d9f75844SAndroid Build Coastguard Worker /*target_bitrate=*/DataRate::KilobitsPerSec(50),
7581*d9f75844SAndroid Build Coastguard Worker /*stable_target_bitrate=*/DataRate::KilobitsPerSec(kDontCare),
7582*d9f75844SAndroid Build Coastguard Worker /*link_allocation=*/DataRate::KilobitsPerSec(kDontCare),
7583*d9f75844SAndroid Build Coastguard Worker /*fraction_lost=*/0,
7584*d9f75844SAndroid Build Coastguard Worker /*round_trip_time_ms=*/0,
7585*d9f75844SAndroid Build Coastguard Worker /*cwnd_reduce_ratio=*/0);
7586*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Zero());
7587*d9f75844SAndroid Build Coastguard Worker
7588*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7589*d9f75844SAndroid Build Coastguard Worker }
7590*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderSelectorResolutionSwitch)7591*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, EncoderSelectorResolutionSwitch) {
7592*d9f75844SAndroid Build Coastguard Worker NiceMock<MockEncoderSelector> encoder_selector;
7593*d9f75844SAndroid Build Coastguard Worker StrictMock<MockEncoderSwitchRequestCallback> switch_callback;
7594*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_switch_request_callback =
7595*d9f75844SAndroid Build Coastguard Worker &switch_callback;
7596*d9f75844SAndroid Build Coastguard Worker auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>(
7597*d9f75844SAndroid Build Coastguard Worker &fake_encoder_, &encoder_selector);
7598*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_factory = encoder_factory.get();
7599*d9f75844SAndroid Build Coastguard Worker
7600*d9f75844SAndroid Build Coastguard Worker // Reset encoder for new configuration to take effect.
7601*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config_.Copy());
7602*d9f75844SAndroid Build Coastguard Worker
7603*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(encoder_selector, OnResolutionChange(RenderResolution(640, 480)))
7604*d9f75844SAndroid Build Coastguard Worker .WillOnce(Return(absl::nullopt));
7605*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(encoder_selector, OnResolutionChange(RenderResolution(320, 240)))
7606*d9f75844SAndroid Build Coastguard Worker .WillOnce(Return(SdpVideoFormat("AV1")));
7607*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(switch_callback,
7608*d9f75844SAndroid Build Coastguard Worker RequestEncoderSwitch(Field(&SdpVideoFormat::name, "AV1"),
7609*d9f75844SAndroid Build Coastguard Worker /*allow_default_fallback=*/false));
7610*d9f75844SAndroid Build Coastguard Worker
7611*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7612*d9f75844SAndroid Build Coastguard Worker /*target_bitrate=*/DataRate::KilobitsPerSec(800),
7613*d9f75844SAndroid Build Coastguard Worker /*stable_target_bitrate=*/DataRate::KilobitsPerSec(1000),
7614*d9f75844SAndroid Build Coastguard Worker /*link_allocation=*/DataRate::KilobitsPerSec(1000),
7615*d9f75844SAndroid Build Coastguard Worker /*fraction_lost=*/0,
7616*d9f75844SAndroid Build Coastguard Worker /*round_trip_time_ms=*/0,
7617*d9f75844SAndroid Build Coastguard Worker /*cwnd_reduce_ratio=*/0);
7618*d9f75844SAndroid Build Coastguard Worker
7619*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, 640, 480));
7620*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 480));
7621*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(3, 320, 240));
7622*d9f75844SAndroid Build Coastguard Worker
7623*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Zero());
7624*d9f75844SAndroid Build Coastguard Worker
7625*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7626*d9f75844SAndroid Build Coastguard Worker }
7627*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderSelectorBrokenEncoderSwitch)7628*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, EncoderSelectorBrokenEncoderSwitch) {
7629*d9f75844SAndroid Build Coastguard Worker constexpr int kSufficientBitrateToNotDrop = 1000;
7630*d9f75844SAndroid Build Coastguard Worker constexpr int kDontCare = 100;
7631*d9f75844SAndroid Build Coastguard Worker
7632*d9f75844SAndroid Build Coastguard Worker NiceMock<MockVideoEncoder> video_encoder;
7633*d9f75844SAndroid Build Coastguard Worker NiceMock<MockEncoderSelector> encoder_selector;
7634*d9f75844SAndroid Build Coastguard Worker StrictMock<MockEncoderSwitchRequestCallback> switch_callback;
7635*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_switch_request_callback =
7636*d9f75844SAndroid Build Coastguard Worker &switch_callback;
7637*d9f75844SAndroid Build Coastguard Worker auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>(
7638*d9f75844SAndroid Build Coastguard Worker &video_encoder, &encoder_selector);
7639*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_factory = encoder_factory.get();
7640*d9f75844SAndroid Build Coastguard Worker
7641*d9f75844SAndroid Build Coastguard Worker // Reset encoder for new configuration to take effect.
7642*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config_.Copy());
7643*d9f75844SAndroid Build Coastguard Worker
7644*d9f75844SAndroid Build Coastguard Worker // The VideoStreamEncoder needs some bitrate before it can start encoding,
7645*d9f75844SAndroid Build Coastguard Worker // setting some bitrate so that subsequent calls to WaitForEncodedFrame does
7646*d9f75844SAndroid Build Coastguard Worker // not fail.
7647*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7648*d9f75844SAndroid Build Coastguard Worker /*target_bitrate=*/DataRate::KilobitsPerSec(kSufficientBitrateToNotDrop),
7649*d9f75844SAndroid Build Coastguard Worker /*stable_target_bitrate=*/
7650*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(kSufficientBitrateToNotDrop),
7651*d9f75844SAndroid Build Coastguard Worker /*link_allocation=*/DataRate::KilobitsPerSec(kSufficientBitrateToNotDrop),
7652*d9f75844SAndroid Build Coastguard Worker /*fraction_lost=*/0,
7653*d9f75844SAndroid Build Coastguard Worker /*round_trip_time_ms=*/0,
7654*d9f75844SAndroid Build Coastguard Worker /*cwnd_reduce_ratio=*/0);
7655*d9f75844SAndroid Build Coastguard Worker
7656*d9f75844SAndroid Build Coastguard Worker ON_CALL(video_encoder, Encode)
7657*d9f75844SAndroid Build Coastguard Worker .WillByDefault(Return(WEBRTC_VIDEO_CODEC_ENCODER_FAILURE));
7658*d9f75844SAndroid Build Coastguard Worker ON_CALL(encoder_selector, OnEncoderBroken)
7659*d9f75844SAndroid Build Coastguard Worker .WillByDefault(Return(SdpVideoFormat("AV2")));
7660*d9f75844SAndroid Build Coastguard Worker
7661*d9f75844SAndroid Build Coastguard Worker rtc::Event encode_attempted;
7662*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(switch_callback,
7663*d9f75844SAndroid Build Coastguard Worker RequestEncoderSwitch(Field(&SdpVideoFormat::name, "AV2"),
7664*d9f75844SAndroid Build Coastguard Worker /*allow_default_fallback=*/true))
7665*d9f75844SAndroid Build Coastguard Worker .WillOnce([&encode_attempted]() { encode_attempted.Set(); });
7666*d9f75844SAndroid Build Coastguard Worker
7667*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kDontCare, kDontCare));
7668*d9f75844SAndroid Build Coastguard Worker encode_attempted.Wait(TimeDelta::Seconds(3));
7669*d9f75844SAndroid Build Coastguard Worker
7670*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Zero());
7671*d9f75844SAndroid Build Coastguard Worker
7672*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7673*d9f75844SAndroid Build Coastguard Worker
7674*d9f75844SAndroid Build Coastguard Worker // The encoders produced by the VideoEncoderProxyFactory have a pointer back
7675*d9f75844SAndroid Build Coastguard Worker // to it's factory, so in order for the encoder instance in the
7676*d9f75844SAndroid Build Coastguard Worker // `video_stream_encoder_` to be destroyed before the `encoder_factory` we
7677*d9f75844SAndroid Build Coastguard Worker // reset the `video_stream_encoder_` here.
7678*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_.reset();
7679*d9f75844SAndroid Build Coastguard Worker }
7680*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SwitchEncoderOnInitFailureWithEncoderSelector)7681*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, SwitchEncoderOnInitFailureWithEncoderSelector) {
7682*d9f75844SAndroid Build Coastguard Worker NiceMock<MockVideoEncoder> video_encoder;
7683*d9f75844SAndroid Build Coastguard Worker NiceMock<MockEncoderSelector> encoder_selector;
7684*d9f75844SAndroid Build Coastguard Worker StrictMock<MockEncoderSwitchRequestCallback> switch_callback;
7685*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_switch_request_callback =
7686*d9f75844SAndroid Build Coastguard Worker &switch_callback;
7687*d9f75844SAndroid Build Coastguard Worker auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>(
7688*d9f75844SAndroid Build Coastguard Worker &video_encoder, &encoder_selector);
7689*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_factory = encoder_factory.get();
7690*d9f75844SAndroid Build Coastguard Worker
7691*d9f75844SAndroid Build Coastguard Worker // Reset encoder for new configuration to take effect.
7692*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config_.Copy());
7693*d9f75844SAndroid Build Coastguard Worker
7694*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7695*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, /*fraction_lost=*/0,
7696*d9f75844SAndroid Build Coastguard Worker /*round_trip_time_ms=*/0,
7697*d9f75844SAndroid Build Coastguard Worker /*cwnd_reduce_ratio=*/0);
7698*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(0, sink_.number_of_reconfigurations());
7699*d9f75844SAndroid Build Coastguard Worker
7700*d9f75844SAndroid Build Coastguard Worker ON_CALL(video_encoder, InitEncode(_, _))
7701*d9f75844SAndroid Build Coastguard Worker .WillByDefault(Return(WEBRTC_VIDEO_CODEC_ENCODER_FAILURE));
7702*d9f75844SAndroid Build Coastguard Worker ON_CALL(encoder_selector, OnEncoderBroken)
7703*d9f75844SAndroid Build Coastguard Worker .WillByDefault(Return(SdpVideoFormat("AV2")));
7704*d9f75844SAndroid Build Coastguard Worker
7705*d9f75844SAndroid Build Coastguard Worker rtc::Event encode_attempted;
7706*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(switch_callback,
7707*d9f75844SAndroid Build Coastguard Worker RequestEncoderSwitch(Field(&SdpVideoFormat::name, "AV2"),
7708*d9f75844SAndroid Build Coastguard Worker /*allow_default_fallback=*/true))
7709*d9f75844SAndroid Build Coastguard Worker .WillOnce([&encode_attempted]() { encode_attempted.Set(); });
7710*d9f75844SAndroid Build Coastguard Worker
7711*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
7712*d9f75844SAndroid Build Coastguard Worker encode_attempted.Wait(TimeDelta::Seconds(3));
7713*d9f75844SAndroid Build Coastguard Worker
7714*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Zero());
7715*d9f75844SAndroid Build Coastguard Worker
7716*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7717*d9f75844SAndroid Build Coastguard Worker
7718*d9f75844SAndroid Build Coastguard Worker // The encoders produced by the VideoEncoderProxyFactory have a pointer back
7719*d9f75844SAndroid Build Coastguard Worker // to it's factory, so in order for the encoder instance in the
7720*d9f75844SAndroid Build Coastguard Worker // `video_stream_encoder_` to be destroyed before the `encoder_factory` we
7721*d9f75844SAndroid Build Coastguard Worker // reset the `video_stream_encoder_` here.
7722*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_.reset();
7723*d9f75844SAndroid Build Coastguard Worker }
7724*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,SwitchEncoderOnInitFailureWithoutEncoderSelector)7725*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
7726*d9f75844SAndroid Build Coastguard Worker SwitchEncoderOnInitFailureWithoutEncoderSelector) {
7727*d9f75844SAndroid Build Coastguard Worker NiceMock<MockVideoEncoder> video_encoder;
7728*d9f75844SAndroid Build Coastguard Worker StrictMock<MockEncoderSwitchRequestCallback> switch_callback;
7729*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_switch_request_callback =
7730*d9f75844SAndroid Build Coastguard Worker &switch_callback;
7731*d9f75844SAndroid Build Coastguard Worker auto encoder_factory = std::make_unique<test::VideoEncoderProxyFactory>(
7732*d9f75844SAndroid Build Coastguard Worker &video_encoder, /*encoder_selector=*/nullptr);
7733*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_factory = encoder_factory.get();
7734*d9f75844SAndroid Build Coastguard Worker
7735*d9f75844SAndroid Build Coastguard Worker // Reset encoder for new configuration to take effect.
7736*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config_.Copy());
7737*d9f75844SAndroid Build Coastguard Worker
7738*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7739*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, /*fraction_lost=*/0,
7740*d9f75844SAndroid Build Coastguard Worker /*round_trip_time_ms=*/0,
7741*d9f75844SAndroid Build Coastguard Worker /*cwnd_reduce_ratio=*/0);
7742*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(0, sink_.number_of_reconfigurations());
7743*d9f75844SAndroid Build Coastguard Worker
7744*d9f75844SAndroid Build Coastguard Worker ON_CALL(video_encoder, InitEncode(_, _))
7745*d9f75844SAndroid Build Coastguard Worker .WillByDefault(Return(WEBRTC_VIDEO_CODEC_ENCODER_FAILURE));
7746*d9f75844SAndroid Build Coastguard Worker
7747*d9f75844SAndroid Build Coastguard Worker rtc::Event encode_attempted;
7748*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(switch_callback,
7749*d9f75844SAndroid Build Coastguard Worker RequestEncoderSwitch(Field(&SdpVideoFormat::name, "VP8"),
7750*d9f75844SAndroid Build Coastguard Worker /*allow_default_fallback=*/true))
7751*d9f75844SAndroid Build Coastguard Worker .WillOnce([&encode_attempted]() { encode_attempted.Set(); });
7752*d9f75844SAndroid Build Coastguard Worker
7753*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
7754*d9f75844SAndroid Build Coastguard Worker encode_attempted.Wait(TimeDelta::Seconds(3));
7755*d9f75844SAndroid Build Coastguard Worker
7756*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Zero());
7757*d9f75844SAndroid Build Coastguard Worker
7758*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7759*d9f75844SAndroid Build Coastguard Worker
7760*d9f75844SAndroid Build Coastguard Worker // The encoders produced by the VideoEncoderProxyFactory have a pointer back
7761*d9f75844SAndroid Build Coastguard Worker // to it's factory, so in order for the encoder instance in the
7762*d9f75844SAndroid Build Coastguard Worker // `video_stream_encoder_` to be destroyed before the `encoder_factory` we
7763*d9f75844SAndroid Build Coastguard Worker // reset the `video_stream_encoder_` here.
7764*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_.reset();
7765*d9f75844SAndroid Build Coastguard Worker }
7766*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NullEncoderReturnSwitch)7767*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, NullEncoderReturnSwitch) {
7768*d9f75844SAndroid Build Coastguard Worker // As a variant of EncoderSelectorBrokenEncoderSwitch, when a null
7769*d9f75844SAndroid Build Coastguard Worker // VideoEncoder is passed in encoder_factory, it checks whether
7770*d9f75844SAndroid Build Coastguard Worker // Codec Switch occurs without a crash.
7771*d9f75844SAndroid Build Coastguard Worker constexpr int kSufficientBitrateToNotDrop = 1000;
7772*d9f75844SAndroid Build Coastguard Worker constexpr int kDontCare = 100;
7773*d9f75844SAndroid Build Coastguard Worker
7774*d9f75844SAndroid Build Coastguard Worker NiceMock<MockEncoderSelector> encoder_selector;
7775*d9f75844SAndroid Build Coastguard Worker StrictMock<MockEncoderSwitchRequestCallback> switch_callback;
7776*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_switch_request_callback =
7777*d9f75844SAndroid Build Coastguard Worker &switch_callback;
7778*d9f75844SAndroid Build Coastguard Worker auto encoder_factory =
7779*d9f75844SAndroid Build Coastguard Worker std::make_unique<test::VideoEncoderNullableProxyFactory>(
7780*d9f75844SAndroid Build Coastguard Worker /*encoder=*/nullptr, &encoder_selector);
7781*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_factory = encoder_factory.get();
7782*d9f75844SAndroid Build Coastguard Worker
7783*d9f75844SAndroid Build Coastguard Worker // Reset encoder for new configuration to take effect.
7784*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config_.Copy());
7785*d9f75844SAndroid Build Coastguard Worker // The VideoStreamEncoder needs some bitrate before it can start encoding,
7786*d9f75844SAndroid Build Coastguard Worker // setting some bitrate so that subsequent calls to WaitForEncodedFrame does
7787*d9f75844SAndroid Build Coastguard Worker // not fail.
7788*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7789*d9f75844SAndroid Build Coastguard Worker /*target_bitrate=*/DataRate::KilobitsPerSec(kSufficientBitrateToNotDrop),
7790*d9f75844SAndroid Build Coastguard Worker /*stable_target_bitrate=*/
7791*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(kSufficientBitrateToNotDrop),
7792*d9f75844SAndroid Build Coastguard Worker /*link_allocation=*/DataRate::KilobitsPerSec(kSufficientBitrateToNotDrop),
7793*d9f75844SAndroid Build Coastguard Worker /*fraction_lost=*/0,
7794*d9f75844SAndroid Build Coastguard Worker /*round_trip_time_ms=*/0,
7795*d9f75844SAndroid Build Coastguard Worker /*cwnd_reduce_ratio=*/0);
7796*d9f75844SAndroid Build Coastguard Worker ON_CALL(encoder_selector, OnEncoderBroken)
7797*d9f75844SAndroid Build Coastguard Worker .WillByDefault(Return(SdpVideoFormat("AV2")));
7798*d9f75844SAndroid Build Coastguard Worker rtc::Event encode_attempted;
7799*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(switch_callback,
7800*d9f75844SAndroid Build Coastguard Worker RequestEncoderSwitch(Field(&SdpVideoFormat::name, "AV2"),
7801*d9f75844SAndroid Build Coastguard Worker /*allow_default_fallback=*/_))
7802*d9f75844SAndroid Build Coastguard Worker .WillOnce([&encode_attempted]() { encode_attempted.Set(); });
7803*d9f75844SAndroid Build Coastguard Worker
7804*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, kDontCare, kDontCare));
7805*d9f75844SAndroid Build Coastguard Worker encode_attempted.Wait(TimeDelta::Seconds(3));
7806*d9f75844SAndroid Build Coastguard Worker
7807*d9f75844SAndroid Build Coastguard Worker AdvanceTime(TimeDelta::Zero());
7808*d9f75844SAndroid Build Coastguard Worker
7809*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7810*d9f75844SAndroid Build Coastguard Worker
7811*d9f75844SAndroid Build Coastguard Worker // The encoders produced by the VideoEncoderProxyFactory have a pointer back
7812*d9f75844SAndroid Build Coastguard Worker // to it's factory, so in order for the encoder instance in the
7813*d9f75844SAndroid Build Coastguard Worker // `video_stream_encoder_` to be destroyed before the `encoder_factory` we
7814*d9f75844SAndroid Build Coastguard Worker // reset the `video_stream_encoder_` here.
7815*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_.reset();
7816*d9f75844SAndroid Build Coastguard Worker }
7817*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AllocationPropagatedToEncoderWhenTargetRateChanged)7818*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
7819*d9f75844SAndroid Build Coastguard Worker AllocationPropagatedToEncoderWhenTargetRateChanged) {
7820*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 320;
7821*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 180;
7822*d9f75844SAndroid Build Coastguard Worker
7823*d9f75844SAndroid Build Coastguard Worker // Set initial rate.
7824*d9f75844SAndroid Build Coastguard Worker auto rate = DataRate::KilobitsPerSec(100);
7825*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7826*d9f75844SAndroid Build Coastguard Worker /*target_bitrate=*/rate,
7827*d9f75844SAndroid Build Coastguard Worker /*stable_target_bitrate=*/rate,
7828*d9f75844SAndroid Build Coastguard Worker /*link_allocation=*/rate,
7829*d9f75844SAndroid Build Coastguard Worker /*fraction_lost=*/0,
7830*d9f75844SAndroid Build Coastguard Worker /*round_trip_time_ms=*/0,
7831*d9f75844SAndroid Build Coastguard Worker /*cwnd_reduce_ratio=*/0);
7832*d9f75844SAndroid Build Coastguard Worker
7833*d9f75844SAndroid Build Coastguard Worker // Insert a first video frame so that encoder gets configured.
7834*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
7835*d9f75844SAndroid Build Coastguard Worker VideoFrame frame = CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight);
7836*d9f75844SAndroid Build Coastguard Worker frame.set_rotation(kVideoRotation_270);
7837*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(frame);
7838*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
7839*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, fake_encoder_.GetNumSetRates());
7840*d9f75844SAndroid Build Coastguard Worker
7841*d9f75844SAndroid Build Coastguard Worker // Change of target bitrate propagates to the encoder.
7842*d9f75844SAndroid Build Coastguard Worker auto new_stable_rate = rate - DataRate::KilobitsPerSec(5);
7843*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7844*d9f75844SAndroid Build Coastguard Worker /*target_bitrate=*/new_stable_rate,
7845*d9f75844SAndroid Build Coastguard Worker /*stable_target_bitrate=*/new_stable_rate,
7846*d9f75844SAndroid Build Coastguard Worker /*link_allocation=*/rate,
7847*d9f75844SAndroid Build Coastguard Worker /*fraction_lost=*/0,
7848*d9f75844SAndroid Build Coastguard Worker /*round_trip_time_ms=*/0,
7849*d9f75844SAndroid Build Coastguard Worker /*cwnd_reduce_ratio=*/0);
7850*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
7851*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, fake_encoder_.GetNumSetRates());
7852*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7853*d9f75844SAndroid Build Coastguard Worker }
7854*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AllocationNotPropagatedToEncoderWhenTargetRateUnchanged)7855*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
7856*d9f75844SAndroid Build Coastguard Worker AllocationNotPropagatedToEncoderWhenTargetRateUnchanged) {
7857*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 320;
7858*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 180;
7859*d9f75844SAndroid Build Coastguard Worker
7860*d9f75844SAndroid Build Coastguard Worker // Set initial rate.
7861*d9f75844SAndroid Build Coastguard Worker auto rate = DataRate::KilobitsPerSec(100);
7862*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7863*d9f75844SAndroid Build Coastguard Worker /*target_bitrate=*/rate,
7864*d9f75844SAndroid Build Coastguard Worker /*stable_target_bitrate=*/rate,
7865*d9f75844SAndroid Build Coastguard Worker /*link_allocation=*/rate,
7866*d9f75844SAndroid Build Coastguard Worker /*fraction_lost=*/0,
7867*d9f75844SAndroid Build Coastguard Worker /*round_trip_time_ms=*/0,
7868*d9f75844SAndroid Build Coastguard Worker /*cwnd_reduce_ratio=*/0);
7869*d9f75844SAndroid Build Coastguard Worker
7870*d9f75844SAndroid Build Coastguard Worker // Insert a first video frame so that encoder gets configured.
7871*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
7872*d9f75844SAndroid Build Coastguard Worker VideoFrame frame = CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight);
7873*d9f75844SAndroid Build Coastguard Worker frame.set_rotation(kVideoRotation_270);
7874*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(frame);
7875*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
7876*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, fake_encoder_.GetNumSetRates());
7877*d9f75844SAndroid Build Coastguard Worker
7878*d9f75844SAndroid Build Coastguard Worker // Set a higher target rate without changing the link_allocation. Should not
7879*d9f75844SAndroid Build Coastguard Worker // reset encoder's rate.
7880*d9f75844SAndroid Build Coastguard Worker auto new_stable_rate = rate - DataRate::KilobitsPerSec(5);
7881*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7882*d9f75844SAndroid Build Coastguard Worker /*target_bitrate=*/rate,
7883*d9f75844SAndroid Build Coastguard Worker /*stable_target_bitrate=*/new_stable_rate,
7884*d9f75844SAndroid Build Coastguard Worker /*link_allocation=*/rate,
7885*d9f75844SAndroid Build Coastguard Worker /*fraction_lost=*/0,
7886*d9f75844SAndroid Build Coastguard Worker /*round_trip_time_ms=*/0,
7887*d9f75844SAndroid Build Coastguard Worker /*cwnd_reduce_ratio=*/0);
7888*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
7889*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, fake_encoder_.GetNumSetRates());
7890*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7891*d9f75844SAndroid Build Coastguard Worker }
7892*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,AutomaticAnimationDetection)7893*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, AutomaticAnimationDetection) {
7894*d9f75844SAndroid Build Coastguard Worker test::ScopedKeyValueConfig field_trials(
7895*d9f75844SAndroid Build Coastguard Worker field_trials_,
7896*d9f75844SAndroid Build Coastguard Worker "WebRTC-AutomaticAnimationDetectionScreenshare/"
7897*d9f75844SAndroid Build Coastguard Worker "enabled:true,min_fps:20,min_duration_ms:1000,min_area_ratio:0.8/");
7898*d9f75844SAndroid Build Coastguard Worker const int kFramerateFps = 30;
7899*d9f75844SAndroid Build Coastguard Worker const int kWidth = 1920;
7900*d9f75844SAndroid Build Coastguard Worker const int kHeight = 1080;
7901*d9f75844SAndroid Build Coastguard Worker const int kNumFrames = 2 * kFramerateFps; // >1 seconds of frames.
7902*d9f75844SAndroid Build Coastguard Worker // Works on screenshare mode.
7903*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", 1, 1, 1, /*screenshare*/ true);
7904*d9f75844SAndroid Build Coastguard Worker // We rely on the automatic resolution adaptation, but we handle framerate
7905*d9f75844SAndroid Build Coastguard Worker // adaptation manually by mocking the stats proxy.
7906*d9f75844SAndroid Build Coastguard Worker video_source_.set_adaptation_enabled(true);
7907*d9f75844SAndroid Build Coastguard Worker
7908*d9f75844SAndroid Build Coastguard Worker // BALANCED degradation preference is required for this feature.
7909*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7910*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7911*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(&video_source_,
7912*d9f75844SAndroid Build Coastguard Worker webrtc::DegradationPreference::BALANCED);
7913*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(), UnlimitedSinkWants());
7914*d9f75844SAndroid Build Coastguard Worker
7915*d9f75844SAndroid Build Coastguard Worker VideoFrame frame = CreateFrame(1, kWidth, kHeight);
7916*d9f75844SAndroid Build Coastguard Worker frame.set_update_rect(VideoFrame::UpdateRect{0, 0, kWidth, kHeight});
7917*d9f75844SAndroid Build Coastguard Worker
7918*d9f75844SAndroid Build Coastguard Worker // Pass enough frames with the full update to trigger animation detection.
7919*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < kNumFrames; ++i) {
7920*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
7921*d9f75844SAndroid Build Coastguard Worker frame.set_ntp_time_ms(timestamp_ms);
7922*d9f75844SAndroid Build Coastguard Worker frame.set_timestamp_us(timestamp_ms * 1000);
7923*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(frame);
7924*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
7925*d9f75844SAndroid Build Coastguard Worker }
7926*d9f75844SAndroid Build Coastguard Worker
7927*d9f75844SAndroid Build Coastguard Worker // Resolution should be limited.
7928*d9f75844SAndroid Build Coastguard Worker rtc::VideoSinkWants expected;
7929*d9f75844SAndroid Build Coastguard Worker expected.max_framerate_fps = kFramerateFps;
7930*d9f75844SAndroid Build Coastguard Worker expected.max_pixel_count = 1280 * 720 + 1;
7931*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(), FpsEqResolutionLt(expected));
7932*d9f75844SAndroid Build Coastguard Worker
7933*d9f75844SAndroid Build Coastguard Worker // Pass one frame with no known update.
7934*d9f75844SAndroid Build Coastguard Worker // Resolution cap should be removed immediately.
7935*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
7936*d9f75844SAndroid Build Coastguard Worker frame.set_ntp_time_ms(timestamp_ms);
7937*d9f75844SAndroid Build Coastguard Worker frame.set_timestamp_us(timestamp_ms * 1000);
7938*d9f75844SAndroid Build Coastguard Worker frame.clear_update_rect();
7939*d9f75844SAndroid Build Coastguard Worker
7940*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(frame);
7941*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
7942*d9f75844SAndroid Build Coastguard Worker
7943*d9f75844SAndroid Build Coastguard Worker // Resolution should be unlimited now.
7944*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants(),
7945*d9f75844SAndroid Build Coastguard Worker FpsMatchesResolutionMax(Eq(kFramerateFps)));
7946*d9f75844SAndroid Build Coastguard Worker
7947*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7948*d9f75844SAndroid Build Coastguard Worker }
7949*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,ConfiguresVp9SvcAtOddResolutions)7950*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, ConfiguresVp9SvcAtOddResolutions) {
7951*d9f75844SAndroid Build Coastguard Worker const int kWidth = 720; // 540p adapted down.
7952*d9f75844SAndroid Build Coastguard Worker const int kHeight = 405;
7953*d9f75844SAndroid Build Coastguard Worker const int kNumFrames = 3;
7954*d9f75844SAndroid Build Coastguard Worker // Works on screenshare mode.
7955*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP9", /*num_streams=*/1, /*num_temporal_layers=*/1,
7956*d9f75844SAndroid Build Coastguard Worker /*num_spatial_layers=*/2, /*screenshare=*/true);
7957*d9f75844SAndroid Build Coastguard Worker
7958*d9f75844SAndroid Build Coastguard Worker video_source_.set_adaptation_enabled(true);
7959*d9f75844SAndroid Build Coastguard Worker
7960*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7961*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
7962*d9f75844SAndroid Build Coastguard Worker
7963*d9f75844SAndroid Build Coastguard Worker VideoFrame frame = CreateFrame(1, kWidth, kHeight);
7964*d9f75844SAndroid Build Coastguard Worker
7965*d9f75844SAndroid Build Coastguard Worker // Pass enough frames with the full update to trigger animation detection.
7966*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < kNumFrames; ++i) {
7967*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = CurrentTimeMs();
7968*d9f75844SAndroid Build Coastguard Worker frame.set_ntp_time_ms(timestamp_ms);
7969*d9f75844SAndroid Build Coastguard Worker frame.set_timestamp_us(timestamp_ms * 1000);
7970*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(frame);
7971*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
7972*d9f75844SAndroid Build Coastguard Worker }
7973*d9f75844SAndroid Build Coastguard Worker
7974*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
7975*d9f75844SAndroid Build Coastguard Worker }
7976*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderResetAccordingToParameterChange)7977*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, EncoderResetAccordingToParameterChange) {
7978*d9f75844SAndroid Build Coastguard Worker const float downscale_factors[] = {4.0, 2.0, 1.0};
7979*d9f75844SAndroid Build Coastguard Worker const int number_layers =
7980*d9f75844SAndroid Build Coastguard Worker sizeof(downscale_factors) / sizeof(downscale_factors[0]);
7981*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
7982*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoder::EncoderInfo encoder_info;
7983*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, number_layers, &config);
7984*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < number_layers; ++i) {
7985*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[i].scale_resolution_down_by = downscale_factors[i];
7986*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[i].active = true;
7987*d9f75844SAndroid Build Coastguard Worker }
7988*d9f75844SAndroid Build Coastguard Worker config.video_stream_factory =
7989*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<cricket::EncoderStreamFactory>(
7990*d9f75844SAndroid Build Coastguard Worker "VP8", /*max qp*/ 56, /*screencast*/ false,
7991*d9f75844SAndroid Build Coastguard Worker /*screenshare enabled*/ false, encoder_info);
7992*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
7993*d9f75844SAndroid Build Coastguard Worker kSimulcastTargetBitrate, kSimulcastTargetBitrate, kSimulcastTargetBitrate,
7994*d9f75844SAndroid Build Coastguard Worker 0, 0, 0);
7995*d9f75844SAndroid Build Coastguard Worker
7996*d9f75844SAndroid Build Coastguard Worker // First initialization.
7997*d9f75844SAndroid Build Coastguard Worker // Encoder should be initialized. Next frame should be key frame.
7998*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
7999*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(number_layers);
8000*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
8001*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(timestamp_ms, 1280, 720));
8002*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
8003*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, fake_encoder_.GetNumInitializations());
8004*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(fake_encoder_.LastFrameTypes(),
8005*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray({VideoFrameType::kVideoFrameKey,
8006*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameKey,
8007*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameKey}));
8008*d9f75844SAndroid Build Coastguard Worker
8009*d9f75844SAndroid Build Coastguard Worker // Disable top layer.
8010*d9f75844SAndroid Build Coastguard Worker // Encoder shouldn't be re-initialized. Next frame should be delta frame.
8011*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[number_layers - 1].active = false;
8012*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
8013*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(number_layers - 1);
8014*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
8015*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(timestamp_ms, 1280, 720));
8016*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
8017*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, fake_encoder_.GetNumInitializations());
8018*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(fake_encoder_.LastFrameTypes(),
8019*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray({VideoFrameType::kVideoFrameDelta,
8020*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameDelta,
8021*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameDelta}));
8022*d9f75844SAndroid Build Coastguard Worker
8023*d9f75844SAndroid Build Coastguard Worker // Re-enable top layer.
8024*d9f75844SAndroid Build Coastguard Worker // Encoder should be re-initialized. Next frame should be key frame.
8025*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[number_layers - 1].active = true;
8026*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
8027*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(number_layers);
8028*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
8029*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(timestamp_ms, 1280, 720));
8030*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
8031*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, fake_encoder_.GetNumInitializations());
8032*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(fake_encoder_.LastFrameTypes(),
8033*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray({VideoFrameType::kVideoFrameKey,
8034*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameKey,
8035*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameKey}));
8036*d9f75844SAndroid Build Coastguard Worker
8037*d9f75844SAndroid Build Coastguard Worker // Top layer max rate change.
8038*d9f75844SAndroid Build Coastguard Worker // Encoder shouldn't be re-initialized. Next frame should be delta frame.
8039*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[number_layers - 1].max_bitrate_bps -= 100;
8040*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
8041*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(number_layers);
8042*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
8043*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(timestamp_ms, 1280, 720));
8044*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
8045*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, fake_encoder_.GetNumInitializations());
8046*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(fake_encoder_.LastFrameTypes(),
8047*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray({VideoFrameType::kVideoFrameDelta,
8048*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameDelta,
8049*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameDelta}));
8050*d9f75844SAndroid Build Coastguard Worker
8051*d9f75844SAndroid Build Coastguard Worker // Top layer resolution change.
8052*d9f75844SAndroid Build Coastguard Worker // Encoder should be re-initialized. Next frame should be key frame.
8053*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[number_layers - 1].scale_resolution_down_by += 0.1;
8054*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
8055*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(number_layers);
8056*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
8057*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(timestamp_ms, 1280, 720));
8058*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
8059*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(3, fake_encoder_.GetNumInitializations());
8060*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(fake_encoder_.LastFrameTypes(),
8061*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray({VideoFrameType::kVideoFrameKey,
8062*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameKey,
8063*d9f75844SAndroid Build Coastguard Worker VideoFrameType::kVideoFrameKey}));
8064*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8065*d9f75844SAndroid Build Coastguard Worker }
8066*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderResolutionsExposedInSinglecast)8067*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, EncoderResolutionsExposedInSinglecast) {
8068*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
8069*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
8070*d9f75844SAndroid Build Coastguard Worker
8071*d9f75844SAndroid Build Coastguard Worker SetUp();
8072*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8073*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8074*d9f75844SAndroid Build Coastguard Worker
8075*d9f75844SAndroid Build Coastguard Worker // Capturing a frame should reconfigure the encoder and expose the encoder
8076*d9f75844SAndroid Build Coastguard Worker // resolution, which is the same as the input frame.
8077*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
8078*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8079*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
8080*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
8081*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8082*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants().resolutions,
8083*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray(
8084*d9f75844SAndroid Build Coastguard Worker {rtc::VideoSinkWants::FrameSize(kFrameWidth, kFrameHeight)}));
8085*d9f75844SAndroid Build Coastguard Worker
8086*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8087*d9f75844SAndroid Build Coastguard Worker }
8088*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderResolutionsExposedInSimulcast)8089*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, EncoderResolutionsExposedInSimulcast) {
8090*d9f75844SAndroid Build Coastguard Worker // Pick downscale factors such that we never encode at full resolution - this
8091*d9f75844SAndroid Build Coastguard Worker // is an interesting use case. The frame resolution influences the encoder
8092*d9f75844SAndroid Build Coastguard Worker // resolutions, but if no layer has `scale_resolution_down_by` == 1 then the
8093*d9f75844SAndroid Build Coastguard Worker // encoder should not ask for the frame resolution. This allows video frames
8094*d9f75844SAndroid Build Coastguard Worker // to have the appearence of one resolution but optimize its internal buffers
8095*d9f75844SAndroid Build Coastguard Worker // for what is actually encoded.
8096*d9f75844SAndroid Build Coastguard Worker const size_t kNumSimulcastLayers = 3u;
8097*d9f75844SAndroid Build Coastguard Worker const float kDownscaleFactors[] = {8.0, 4.0, 2.0};
8098*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
8099*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
8100*d9f75844SAndroid Build Coastguard Worker const rtc::VideoSinkWants::FrameSize kLayer0Size(
8101*d9f75844SAndroid Build Coastguard Worker kFrameWidth / kDownscaleFactors[0], kFrameHeight / kDownscaleFactors[0]);
8102*d9f75844SAndroid Build Coastguard Worker const rtc::VideoSinkWants::FrameSize kLayer1Size(
8103*d9f75844SAndroid Build Coastguard Worker kFrameWidth / kDownscaleFactors[1], kFrameHeight / kDownscaleFactors[1]);
8104*d9f75844SAndroid Build Coastguard Worker const rtc::VideoSinkWants::FrameSize kLayer2Size(
8105*d9f75844SAndroid Build Coastguard Worker kFrameWidth / kDownscaleFactors[2], kFrameHeight / kDownscaleFactors[2]);
8106*d9f75844SAndroid Build Coastguard Worker
8107*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
8108*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoder::EncoderInfo encoder_info;
8109*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, kNumSimulcastLayers, &config);
8110*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kNumSimulcastLayers; ++i) {
8111*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[i].scale_resolution_down_by = kDownscaleFactors[i];
8112*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[i].active = true;
8113*d9f75844SAndroid Build Coastguard Worker }
8114*d9f75844SAndroid Build Coastguard Worker config.video_stream_factory =
8115*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<cricket::EncoderStreamFactory>(
8116*d9f75844SAndroid Build Coastguard Worker "VP8", /*max qp*/ 56, /*screencast*/ false,
8117*d9f75844SAndroid Build Coastguard Worker /*screenshare enabled*/ false, encoder_info);
8118*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8119*d9f75844SAndroid Build Coastguard Worker kSimulcastTargetBitrate, kSimulcastTargetBitrate, kSimulcastTargetBitrate,
8120*d9f75844SAndroid Build Coastguard Worker 0, 0, 0);
8121*d9f75844SAndroid Build Coastguard Worker
8122*d9f75844SAndroid Build Coastguard Worker // Capture a frame with all layers active.
8123*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
8124*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(kNumSimulcastLayers);
8125*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
8126*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8127*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
8128*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
8129*d9f75844SAndroid Build Coastguard Worker // Expect encoded resolutions to match the expected simulcast layers.
8130*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8131*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(
8132*d9f75844SAndroid Build Coastguard Worker video_source_.sink_wants().resolutions,
8133*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray({kLayer0Size, kLayer1Size, kLayer2Size}));
8134*d9f75844SAndroid Build Coastguard Worker
8135*d9f75844SAndroid Build Coastguard Worker // Capture a frame with one of the layers inactive.
8136*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
8137*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[2].active = false;
8138*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(kNumSimulcastLayers - 1);
8139*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
8140*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8141*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
8142*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
8143*d9f75844SAndroid Build Coastguard Worker
8144*d9f75844SAndroid Build Coastguard Worker // Expect encoded resolutions to match the expected simulcast layers.
8145*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8146*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants().resolutions,
8147*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray({kLayer0Size, kLayer1Size}));
8148*d9f75844SAndroid Build Coastguard Worker
8149*d9f75844SAndroid Build Coastguard Worker // Capture a frame with all but one layer turned off.
8150*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
8151*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[1].active = false;
8152*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(kNumSimulcastLayers - 2);
8153*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
8154*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8155*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
8156*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(timestamp_ms);
8157*d9f75844SAndroid Build Coastguard Worker
8158*d9f75844SAndroid Build Coastguard Worker // Expect encoded resolutions to match the expected simulcast layers.
8159*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8160*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(video_source_.sink_wants().resolutions,
8161*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray({kLayer0Size}));
8162*d9f75844SAndroid Build Coastguard Worker
8163*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8164*d9f75844SAndroid Build Coastguard Worker }
8165*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QpPresent_QpKept)8166*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, QpPresent_QpKept) {
8167*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", 1, 1, 1, false);
8168*d9f75844SAndroid Build Coastguard Worker
8169*d9f75844SAndroid Build Coastguard Worker // Force encoder reconfig.
8170*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8171*d9f75844SAndroid Build Coastguard Worker CreateFrame(1, codec_width_, codec_height_));
8172*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8173*d9f75844SAndroid Build Coastguard Worker
8174*d9f75844SAndroid Build Coastguard Worker // Set QP on encoded frame and pass the frame to encode complete callback.
8175*d9f75844SAndroid Build Coastguard Worker // Since QP is present QP parsing won't be triggered and the original value
8176*d9f75844SAndroid Build Coastguard Worker // should be kept.
8177*d9f75844SAndroid Build Coastguard Worker EncodedImage encoded_image;
8178*d9f75844SAndroid Build Coastguard Worker encoded_image.qp_ = 123;
8179*d9f75844SAndroid Build Coastguard Worker encoded_image.SetEncodedData(EncodedImageBuffer::Create(
8180*d9f75844SAndroid Build Coastguard Worker kCodedFrameVp8Qp25, sizeof(kCodedFrameVp8Qp25)));
8181*d9f75844SAndroid Build Coastguard Worker CodecSpecificInfo codec_info;
8182*d9f75844SAndroid Build Coastguard Worker codec_info.codecType = kVideoCodecVP8;
8183*d9f75844SAndroid Build Coastguard Worker fake_encoder_.InjectEncodedImage(encoded_image, &codec_info);
8184*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(sink_.WaitForFrame(kDefaultTimeout));
8185*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.GetLastEncodedImage().qp_, 123);
8186*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8187*d9f75844SAndroid Build Coastguard Worker }
8188*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QpAbsent_QpParsed)8189*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, QpAbsent_QpParsed) {
8190*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", 1, 1, 1, false);
8191*d9f75844SAndroid Build Coastguard Worker
8192*d9f75844SAndroid Build Coastguard Worker // Force encoder reconfig.
8193*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8194*d9f75844SAndroid Build Coastguard Worker CreateFrame(1, codec_width_, codec_height_));
8195*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8196*d9f75844SAndroid Build Coastguard Worker
8197*d9f75844SAndroid Build Coastguard Worker // Pass an encoded frame without QP to encode complete callback. QP should be
8198*d9f75844SAndroid Build Coastguard Worker // parsed and set.
8199*d9f75844SAndroid Build Coastguard Worker EncodedImage encoded_image;
8200*d9f75844SAndroid Build Coastguard Worker encoded_image.qp_ = -1;
8201*d9f75844SAndroid Build Coastguard Worker encoded_image.SetEncodedData(EncodedImageBuffer::Create(
8202*d9f75844SAndroid Build Coastguard Worker kCodedFrameVp8Qp25, sizeof(kCodedFrameVp8Qp25)));
8203*d9f75844SAndroid Build Coastguard Worker CodecSpecificInfo codec_info;
8204*d9f75844SAndroid Build Coastguard Worker codec_info.codecType = kVideoCodecVP8;
8205*d9f75844SAndroid Build Coastguard Worker fake_encoder_.InjectEncodedImage(encoded_image, &codec_info);
8206*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(sink_.WaitForFrame(kDefaultTimeout));
8207*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.GetLastEncodedImage().qp_, 25);
8208*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8209*d9f75844SAndroid Build Coastguard Worker }
8210*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QpAbsentParsingDisabled_QpAbsent)8211*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, QpAbsentParsingDisabled_QpAbsent) {
8212*d9f75844SAndroid Build Coastguard Worker webrtc::test::ScopedKeyValueConfig field_trials(
8213*d9f75844SAndroid Build Coastguard Worker field_trials_, "WebRTC-QpParsingKillSwitch/Enabled/");
8214*d9f75844SAndroid Build Coastguard Worker
8215*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP8", 1, 1, 1, false);
8216*d9f75844SAndroid Build Coastguard Worker
8217*d9f75844SAndroid Build Coastguard Worker // Force encoder reconfig.
8218*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8219*d9f75844SAndroid Build Coastguard Worker CreateFrame(1, codec_width_, codec_height_));
8220*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8221*d9f75844SAndroid Build Coastguard Worker
8222*d9f75844SAndroid Build Coastguard Worker EncodedImage encoded_image;
8223*d9f75844SAndroid Build Coastguard Worker encoded_image.qp_ = -1;
8224*d9f75844SAndroid Build Coastguard Worker encoded_image.SetEncodedData(EncodedImageBuffer::Create(
8225*d9f75844SAndroid Build Coastguard Worker kCodedFrameVp8Qp25, sizeof(kCodedFrameVp8Qp25)));
8226*d9f75844SAndroid Build Coastguard Worker CodecSpecificInfo codec_info;
8227*d9f75844SAndroid Build Coastguard Worker codec_info.codecType = kVideoCodecVP8;
8228*d9f75844SAndroid Build Coastguard Worker fake_encoder_.InjectEncodedImage(encoded_image, &codec_info);
8229*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(sink_.WaitForFrame(kDefaultTimeout));
8230*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sink_.GetLastEncodedImage().qp_, -1);
8231*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8232*d9f75844SAndroid Build Coastguard Worker }
8233*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QualityScalingNotAllowed_QualityScalingDisabled)8234*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
8235*d9f75844SAndroid Build Coastguard Worker QualityScalingNotAllowed_QualityScalingDisabled) {
8236*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config = video_encoder_config_.Copy();
8237*d9f75844SAndroid Build Coastguard Worker
8238*d9f75844SAndroid Build Coastguard Worker // Disable scaling settings in encoder info.
8239*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
8240*d9f75844SAndroid Build Coastguard Worker // Disable quality scaling in encoder config.
8241*d9f75844SAndroid Build Coastguard Worker video_encoder_config.is_quality_scaling_allowed = false;
8242*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config));
8243*d9f75844SAndroid Build Coastguard Worker
8244*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8245*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8246*d9f75844SAndroid Build Coastguard Worker
8247*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
8248*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
8249*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
8250*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), UnlimitedSinkWants());
8251*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8252*d9f75844SAndroid Build Coastguard Worker
8253*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
8254*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8255*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
8256*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8257*d9f75844SAndroid Build Coastguard Worker
8258*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8259*d9f75844SAndroid Build Coastguard Worker }
8260*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QualityScalingNotAllowed_IsQpTrustedSetTrue)8261*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, QualityScalingNotAllowed_IsQpTrustedSetTrue) {
8262*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config = video_encoder_config_.Copy();
8263*d9f75844SAndroid Build Coastguard Worker
8264*d9f75844SAndroid Build Coastguard Worker // Disable scaling settings in encoder info.
8265*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
8266*d9f75844SAndroid Build Coastguard Worker // Set QP trusted in encoder info.
8267*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetIsQpTrusted(true);
8268*d9f75844SAndroid Build Coastguard Worker // Enable quality scaling in encoder config.
8269*d9f75844SAndroid Build Coastguard Worker video_encoder_config.is_quality_scaling_allowed = false;
8270*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config));
8271*d9f75844SAndroid Build Coastguard Worker
8272*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8273*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8274*d9f75844SAndroid Build Coastguard Worker
8275*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
8276*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
8277*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
8278*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), UnlimitedSinkWants());
8279*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8280*d9f75844SAndroid Build Coastguard Worker
8281*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
8282*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8283*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
8284*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8285*d9f75844SAndroid Build Coastguard Worker
8286*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8287*d9f75844SAndroid Build Coastguard Worker }
8288*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QualityScalingNotAllowedAndQPIsTrusted_BandwidthScalerDisable)8289*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
8290*d9f75844SAndroid Build Coastguard Worker QualityScalingNotAllowedAndQPIsTrusted_BandwidthScalerDisable) {
8291*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config = video_encoder_config_.Copy();
8292*d9f75844SAndroid Build Coastguard Worker
8293*d9f75844SAndroid Build Coastguard Worker // Disable scaling settings in encoder info.
8294*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
8295*d9f75844SAndroid Build Coastguard Worker // Set QP trusted in encoder info.
8296*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetIsQpTrusted(true);
8297*d9f75844SAndroid Build Coastguard Worker // Enable quality scaling in encoder config.
8298*d9f75844SAndroid Build Coastguard Worker video_encoder_config.is_quality_scaling_allowed = false;
8299*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config));
8300*d9f75844SAndroid Build Coastguard Worker
8301*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8302*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8303*d9f75844SAndroid Build Coastguard Worker
8304*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
8305*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
8306*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
8307*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), UnlimitedSinkWants());
8308*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8309*d9f75844SAndroid Build Coastguard Worker
8310*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
8311*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8312*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
8313*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8314*d9f75844SAndroid Build Coastguard Worker
8315*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8316*d9f75844SAndroid Build Coastguard Worker }
8317*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QualityScalingNotAllowedAndQPIsNotTrusted_BandwidthScalerDisable)8318*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
8319*d9f75844SAndroid Build Coastguard Worker QualityScalingNotAllowedAndQPIsNotTrusted_BandwidthScalerDisable) {
8320*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config = video_encoder_config_.Copy();
8321*d9f75844SAndroid Build Coastguard Worker
8322*d9f75844SAndroid Build Coastguard Worker // Disable scaling settings in encoder info.
8323*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
8324*d9f75844SAndroid Build Coastguard Worker // Set QP trusted in encoder info.
8325*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetIsQpTrusted(false);
8326*d9f75844SAndroid Build Coastguard Worker // Enable quality scaling in encoder config.
8327*d9f75844SAndroid Build Coastguard Worker video_encoder_config.is_quality_scaling_allowed = false;
8328*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config));
8329*d9f75844SAndroid Build Coastguard Worker
8330*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8331*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8332*d9f75844SAndroid Build Coastguard Worker
8333*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
8334*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
8335*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
8336*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), UnlimitedSinkWants());
8337*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8338*d9f75844SAndroid Build Coastguard Worker
8339*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
8340*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8341*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
8342*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8343*d9f75844SAndroid Build Coastguard Worker
8344*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8345*d9f75844SAndroid Build Coastguard Worker }
8346*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderProvideLimitsWhenQPIsNotTrusted)8347*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, EncoderProvideLimitsWhenQPIsNotTrusted) {
8348*d9f75844SAndroid Build Coastguard Worker // Set QP trusted in encoder info.
8349*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetIsQpTrusted(false);
8350*d9f75844SAndroid Build Coastguard Worker
8351*d9f75844SAndroid Build Coastguard Worker const int MinEncBitrateKbps = 30;
8352*d9f75844SAndroid Build Coastguard Worker const int MaxEncBitrateKbps = 100;
8353*d9f75844SAndroid Build Coastguard Worker const int MinStartBitrateKbp = 50;
8354*d9f75844SAndroid Build Coastguard Worker const VideoEncoder::ResolutionBitrateLimits encoder_bitrate_limits(
8355*d9f75844SAndroid Build Coastguard Worker /*frame_size_pixels=*/codec_width_ * codec_height_,
8356*d9f75844SAndroid Build Coastguard Worker /*min_start_bitrate_bps=*/MinStartBitrateKbp,
8357*d9f75844SAndroid Build Coastguard Worker /*min_bitrate_bps=*/MinEncBitrateKbps * 1000,
8358*d9f75844SAndroid Build Coastguard Worker /*max_bitrate_bps=*/MaxEncBitrateKbps * 1000);
8359*d9f75844SAndroid Build Coastguard Worker
8360*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8361*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8362*d9f75844SAndroid Build Coastguard Worker
8363*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetResolutionBitrateLimits({encoder_bitrate_limits});
8364*d9f75844SAndroid Build Coastguard Worker
8365*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
8366*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecH264, 1, &video_encoder_config);
8367*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = MaxEncBitrateKbps * 1000;
8368*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].min_bitrate_bps =
8369*d9f75844SAndroid Build Coastguard Worker MinEncBitrateKbps * 1000;
8370*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
8371*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
8372*d9f75844SAndroid Build Coastguard Worker
8373*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
8374*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8375*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
8376*d9f75844SAndroid Build Coastguard Worker MaxEncBitrateKbps,
8377*d9f75844SAndroid Build Coastguard Worker static_cast<int>(bitrate_allocator_factory_.codec_config().maxBitrate));
8378*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
8379*d9f75844SAndroid Build Coastguard Worker MinEncBitrateKbps,
8380*d9f75844SAndroid Build Coastguard Worker static_cast<int>(bitrate_allocator_factory_.codec_config().minBitrate));
8381*d9f75844SAndroid Build Coastguard Worker
8382*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8383*d9f75844SAndroid Build Coastguard Worker }
8384*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,EncoderDoesnotProvideLimitsWhenQPIsNotTrusted)8385*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, EncoderDoesnotProvideLimitsWhenQPIsNotTrusted) {
8386*d9f75844SAndroid Build Coastguard Worker // Set QP trusted in encoder info.
8387*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetIsQpTrusted(false);
8388*d9f75844SAndroid Build Coastguard Worker
8389*d9f75844SAndroid Build Coastguard Worker absl::optional<VideoEncoder::ResolutionBitrateLimits> suitable_bitrate_limit =
8390*d9f75844SAndroid Build Coastguard Worker EncoderInfoSettings::
8391*d9f75844SAndroid Build Coastguard Worker GetSinglecastBitrateLimitForResolutionWhenQpIsUntrusted(
8392*d9f75844SAndroid Build Coastguard Worker codec_width_ * codec_height_,
8393*d9f75844SAndroid Build Coastguard Worker EncoderInfoSettings::
8394*d9f75844SAndroid Build Coastguard Worker GetDefaultSinglecastBitrateLimitsWhenQpIsUntrusted());
8395*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(suitable_bitrate_limit.has_value());
8396*d9f75844SAndroid Build Coastguard Worker
8397*d9f75844SAndroid Build Coastguard Worker const int MaxEncBitrate = suitable_bitrate_limit->max_bitrate_bps;
8398*d9f75844SAndroid Build Coastguard Worker const int MinEncBitrate = suitable_bitrate_limit->min_bitrate_bps;
8399*d9f75844SAndroid Build Coastguard Worker const int TargetEncBitrate = MaxEncBitrate;
8400*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8401*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(TargetEncBitrate),
8402*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(TargetEncBitrate),
8403*d9f75844SAndroid Build Coastguard Worker DataRate::BitsPerSec(TargetEncBitrate), 0, 0, 0);
8404*d9f75844SAndroid Build Coastguard Worker
8405*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
8406*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecH264, 1, &video_encoder_config);
8407*d9f75844SAndroid Build Coastguard Worker video_encoder_config.max_bitrate_bps = MaxEncBitrate;
8408*d9f75844SAndroid Build Coastguard Worker video_encoder_config.simulcast_layers[0].min_bitrate_bps = MinEncBitrate;
8409*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
8410*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
8411*d9f75844SAndroid Build Coastguard Worker
8412*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
8413*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8414*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
8415*d9f75844SAndroid Build Coastguard Worker MaxEncBitrate / 1000,
8416*d9f75844SAndroid Build Coastguard Worker static_cast<int>(bitrate_allocator_factory_.codec_config().maxBitrate));
8417*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
8418*d9f75844SAndroid Build Coastguard Worker MinEncBitrate / 1000,
8419*d9f75844SAndroid Build Coastguard Worker static_cast<int>(bitrate_allocator_factory_.codec_config().minBitrate));
8420*d9f75844SAndroid Build Coastguard Worker
8421*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8422*d9f75844SAndroid Build Coastguard Worker }
8423*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NormalComplexityWithMoreThanTwoCores)8424*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, NormalComplexityWithMoreThanTwoCores) {
8425*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP9", /*num_stream=*/1, /*num_temporal_layers=*/1,
8426*d9f75844SAndroid Build Coastguard Worker /*num_spatial_layers=*/1,
8427*d9f75844SAndroid Build Coastguard Worker /*screenshare=*/false, /*allocation_callback_type=*/
8428*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
8429*d9f75844SAndroid Build Coastguard Worker kVideoBitrateAllocationWhenScreenSharing,
8430*d9f75844SAndroid Build Coastguard Worker /*num_cores=*/3);
8431*d9f75844SAndroid Build Coastguard Worker
8432*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8433*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8434*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8435*d9f75844SAndroid Build Coastguard Worker CreateFrame(1, /*width=*/320, /*height=*/180));
8436*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8437*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.LastEncoderComplexity(),
8438*d9f75844SAndroid Build Coastguard Worker VideoCodecComplexity::kComplexityNormal);
8439*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8440*d9f75844SAndroid Build Coastguard Worker }
8441*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,NormalComplexityWhenLowTierOptimizationsAreDisabled)8442*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
8443*d9f75844SAndroid Build Coastguard Worker NormalComplexityWhenLowTierOptimizationsAreDisabled) {
8444*d9f75844SAndroid Build Coastguard Worker webrtc::test::ScopedKeyValueConfig field_trials(
8445*d9f75844SAndroid Build Coastguard Worker field_trials_, "WebRTC-VP9-LowTierOptimizations/Disabled/");
8446*d9f75844SAndroid Build Coastguard Worker
8447*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP9", /*num_stream=*/1, /*num_temporal_layers=*/1,
8448*d9f75844SAndroid Build Coastguard Worker /*num_spatial_layers=*/1,
8449*d9f75844SAndroid Build Coastguard Worker /*screenshare=*/false, /*allocation_callback_type=*/
8450*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
8451*d9f75844SAndroid Build Coastguard Worker kVideoBitrateAllocationWhenScreenSharing,
8452*d9f75844SAndroid Build Coastguard Worker /*num_cores=*/2);
8453*d9f75844SAndroid Build Coastguard Worker
8454*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8455*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8456*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8457*d9f75844SAndroid Build Coastguard Worker CreateFrame(1, /*width=*/320, /*height=*/180));
8458*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8459*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.LastEncoderComplexity(),
8460*d9f75844SAndroid Build Coastguard Worker VideoCodecComplexity::kComplexityNormal);
8461*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8462*d9f75844SAndroid Build Coastguard Worker }
8463*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,LowComplexityWithTwoCores)8464*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, LowComplexityWithTwoCores) {
8465*d9f75844SAndroid Build Coastguard Worker ResetEncoder("VP9", /*num_stream=*/1, /*num_temporal_layers=*/1,
8466*d9f75844SAndroid Build Coastguard Worker /*num_spatial_layers=*/1,
8467*d9f75844SAndroid Build Coastguard Worker /*screenshare=*/false, /*allocation_callback_type=*/
8468*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
8469*d9f75844SAndroid Build Coastguard Worker kVideoBitrateAllocationWhenScreenSharing,
8470*d9f75844SAndroid Build Coastguard Worker /*num_cores=*/2);
8471*d9f75844SAndroid Build Coastguard Worker
8472*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8473*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8474*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8475*d9f75844SAndroid Build Coastguard Worker CreateFrame(1, /*width=*/320, /*height=*/180));
8476*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8477*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(fake_encoder_.LastEncoderComplexity(),
8478*d9f75844SAndroid Build Coastguard Worker VideoCodecComplexity::kComplexityLow);
8479*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8480*d9f75844SAndroid Build Coastguard Worker }
8481*d9f75844SAndroid Build Coastguard Worker
8482*d9f75844SAndroid Build Coastguard Worker #if !defined(WEBRTC_IOS)
8483*d9f75844SAndroid Build Coastguard Worker // TODO(bugs.webrtc.org/12401): Disabled because WebRTC-Video-QualityScaling is
8484*d9f75844SAndroid Build Coastguard Worker // disabled by default on iOS.
TEST_F(VideoStreamEncoderTest,QualityScalingAllowed_QualityScalingEnabled)8485*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, QualityScalingAllowed_QualityScalingEnabled) {
8486*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config = video_encoder_config_.Copy();
8487*d9f75844SAndroid Build Coastguard Worker
8488*d9f75844SAndroid Build Coastguard Worker // Disable scaling settings in encoder info.
8489*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
8490*d9f75844SAndroid Build Coastguard Worker // Enable quality scaling in encoder config.
8491*d9f75844SAndroid Build Coastguard Worker video_encoder_config.is_quality_scaling_allowed = true;
8492*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config));
8493*d9f75844SAndroid Build Coastguard Worker
8494*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8495*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8496*d9f75844SAndroid Build Coastguard Worker
8497*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
8498*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
8499*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
8500*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), UnlimitedSinkWants());
8501*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8502*d9f75844SAndroid Build Coastguard Worker
8503*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
8504*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8505*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
8506*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
8507*d9f75844SAndroid Build Coastguard Worker
8508*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8509*d9f75844SAndroid Build Coastguard Worker }
8510*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QualityScalingAllowed_IsQpTrustedSetTrue)8511*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, QualityScalingAllowed_IsQpTrustedSetTrue) {
8512*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config = video_encoder_config_.Copy();
8513*d9f75844SAndroid Build Coastguard Worker
8514*d9f75844SAndroid Build Coastguard Worker // Disable scaling settings in encoder info.
8515*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
8516*d9f75844SAndroid Build Coastguard Worker // Set QP trusted in encoder info.
8517*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetIsQpTrusted(true);
8518*d9f75844SAndroid Build Coastguard Worker // Enable quality scaling in encoder config.
8519*d9f75844SAndroid Build Coastguard Worker video_encoder_config.is_quality_scaling_allowed = true;
8520*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config));
8521*d9f75844SAndroid Build Coastguard Worker
8522*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8523*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8524*d9f75844SAndroid Build Coastguard Worker
8525*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
8526*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
8527*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
8528*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), UnlimitedSinkWants());
8529*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8530*d9f75844SAndroid Build Coastguard Worker
8531*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
8532*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8533*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
8534*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
8535*d9f75844SAndroid Build Coastguard Worker
8536*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8537*d9f75844SAndroid Build Coastguard Worker }
8538*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QualityScalingAllowed_IsQpTrustedSetFalse)8539*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest, QualityScalingAllowed_IsQpTrustedSetFalse) {
8540*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config = video_encoder_config_.Copy();
8541*d9f75844SAndroid Build Coastguard Worker
8542*d9f75844SAndroid Build Coastguard Worker // Disable scaling settings in encoder info.
8543*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
8544*d9f75844SAndroid Build Coastguard Worker // Set QP not trusted in encoder info.
8545*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetIsQpTrusted(false);
8546*d9f75844SAndroid Build Coastguard Worker // Enable quality scaling in encoder config.
8547*d9f75844SAndroid Build Coastguard Worker video_encoder_config.is_quality_scaling_allowed = true;
8548*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config));
8549*d9f75844SAndroid Build Coastguard Worker
8550*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8551*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8552*d9f75844SAndroid Build Coastguard Worker
8553*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
8554*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
8555*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
8556*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), UnlimitedSinkWants());
8557*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8558*d9f75844SAndroid Build Coastguard Worker
8559*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
8560*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8561*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
8562*d9f75844SAndroid Build Coastguard Worker // When quality_scaler doesn't work and is_quality_scaling_allowed is
8563*d9f75844SAndroid Build Coastguard Worker // true,the bandwidth_quality_scaler_ works,so bw_limited_resolution is true.
8564*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
8565*d9f75844SAndroid Build Coastguard Worker
8566*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8567*d9f75844SAndroid Build Coastguard Worker }
8568*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QualityScalingAllowedAndQPIsTrusted_BandwidthScalerDisable)8569*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
8570*d9f75844SAndroid Build Coastguard Worker QualityScalingAllowedAndQPIsTrusted_BandwidthScalerDisable) {
8571*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config = video_encoder_config_.Copy();
8572*d9f75844SAndroid Build Coastguard Worker
8573*d9f75844SAndroid Build Coastguard Worker // Disable scaling settings in encoder info.
8574*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
8575*d9f75844SAndroid Build Coastguard Worker // Set QP trusted in encoder info.
8576*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetIsQpTrusted(true);
8577*d9f75844SAndroid Build Coastguard Worker // Enable quality scaling in encoder config.
8578*d9f75844SAndroid Build Coastguard Worker video_encoder_config.is_quality_scaling_allowed = true;
8579*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config));
8580*d9f75844SAndroid Build Coastguard Worker
8581*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8582*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8583*d9f75844SAndroid Build Coastguard Worker
8584*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
8585*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
8586*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
8587*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), UnlimitedSinkWants());
8588*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8589*d9f75844SAndroid Build Coastguard Worker
8590*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
8591*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8592*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
8593*d9f75844SAndroid Build Coastguard Worker // bandwidth_quality_scaler isn't working, but quality_scaler is working.
8594*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
8595*d9f75844SAndroid Build Coastguard Worker
8596*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8597*d9f75844SAndroid Build Coastguard Worker }
8598*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,QualityScalingAllowedAndQPIsNotTrusted_BandwidthScalerEnabled)8599*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
8600*d9f75844SAndroid Build Coastguard Worker QualityScalingAllowedAndQPIsNotTrusted_BandwidthScalerEnabled) {
8601*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config = video_encoder_config_.Copy();
8602*d9f75844SAndroid Build Coastguard Worker
8603*d9f75844SAndroid Build Coastguard Worker // Disable scaling settings in encoder info.
8604*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetQualityScaling(false);
8605*d9f75844SAndroid Build Coastguard Worker // Set QP trusted in encoder info.
8606*d9f75844SAndroid Build Coastguard Worker fake_encoder_.SetIsQpTrusted(false);
8607*d9f75844SAndroid Build Coastguard Worker // Enable quality scaling in encoder config.
8608*d9f75844SAndroid Build Coastguard Worker video_encoder_config.is_quality_scaling_allowed = true;
8609*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(std::move(video_encoder_config));
8610*d9f75844SAndroid Build Coastguard Worker
8611*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8612*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8613*d9f75844SAndroid Build Coastguard Worker
8614*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder source;
8615*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->SetSource(
8616*d9f75844SAndroid Build Coastguard Worker &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
8617*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(source.sink_wants(), UnlimitedSinkWants());
8618*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
8619*d9f75844SAndroid Build Coastguard Worker
8620*d9f75844SAndroid Build Coastguard Worker source.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
8621*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(1);
8622*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->TriggerQualityLow();
8623*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
8624*d9f75844SAndroid Build Coastguard Worker
8625*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8626*d9f75844SAndroid Build Coastguard Worker }
8627*d9f75844SAndroid Build Coastguard Worker
TEST_F(VideoStreamEncoderTest,RequestsRefreshFrameAfterEarlyDroppedNativeFrame)8628*d9f75844SAndroid Build Coastguard Worker TEST_F(VideoStreamEncoderTest,
8629*d9f75844SAndroid Build Coastguard Worker RequestsRefreshFrameAfterEarlyDroppedNativeFrame) {
8630*d9f75844SAndroid Build Coastguard Worker // Send a native frame before encoder rates have been set. The encoder is
8631*d9f75844SAndroid Build Coastguard Worker // seen as paused at this time.
8632*d9f75844SAndroid Build Coastguard Worker rtc::Event frame_destroyed_event;
8633*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(CreateFakeNativeFrame(
8634*d9f75844SAndroid Build Coastguard Worker /*ntp_time_ms=*/1, &frame_destroyed_event, codec_width_, codec_height_));
8635*d9f75844SAndroid Build Coastguard Worker
8636*d9f75844SAndroid Build Coastguard Worker // Frame should be dropped and destroyed.
8637*d9f75844SAndroid Build Coastguard Worker ExpectDroppedFrame();
8638*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeout));
8639*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_source_.refresh_frames_requested_, 0);
8640*d9f75844SAndroid Build Coastguard Worker
8641*d9f75844SAndroid Build Coastguard Worker // Set bitrates, unpausing the encoder and triggering a request for a refresh
8642*d9f75844SAndroid Build Coastguard Worker // frame.
8643*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8644*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8645*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8646*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(video_source_.refresh_frames_requested_, 1);
8647*d9f75844SAndroid Build Coastguard Worker
8648*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8649*d9f75844SAndroid Build Coastguard Worker }
8650*d9f75844SAndroid Build Coastguard Worker
8651*d9f75844SAndroid Build Coastguard Worker #endif // !defined(WEBRTC_IOS)
8652*d9f75844SAndroid Build Coastguard Worker
8653*d9f75844SAndroid Build Coastguard Worker // Test parameters: (VideoCodecType codec, bool allow_i420_conversion)
8654*d9f75844SAndroid Build Coastguard Worker class VideoStreamEncoderWithRealEncoderTest
8655*d9f75844SAndroid Build Coastguard Worker : public VideoStreamEncoderTest,
8656*d9f75844SAndroid Build Coastguard Worker public ::testing::WithParamInterface<std::pair<VideoCodecType, bool>> {
8657*d9f75844SAndroid Build Coastguard Worker public:
VideoStreamEncoderWithRealEncoderTest()8658*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoderWithRealEncoderTest()
8659*d9f75844SAndroid Build Coastguard Worker : VideoStreamEncoderTest(),
8660*d9f75844SAndroid Build Coastguard Worker codec_type_(std::get<0>(GetParam())),
8661*d9f75844SAndroid Build Coastguard Worker allow_i420_conversion_(std::get<1>(GetParam())) {}
8662*d9f75844SAndroid Build Coastguard Worker
SetUp()8663*d9f75844SAndroid Build Coastguard Worker void SetUp() override {
8664*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoderTest::SetUp();
8665*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<VideoEncoder> encoder;
8666*d9f75844SAndroid Build Coastguard Worker switch (codec_type_) {
8667*d9f75844SAndroid Build Coastguard Worker case kVideoCodecVP8:
8668*d9f75844SAndroid Build Coastguard Worker encoder = VP8Encoder::Create();
8669*d9f75844SAndroid Build Coastguard Worker break;
8670*d9f75844SAndroid Build Coastguard Worker case kVideoCodecVP9:
8671*d9f75844SAndroid Build Coastguard Worker encoder = VP9Encoder::Create();
8672*d9f75844SAndroid Build Coastguard Worker break;
8673*d9f75844SAndroid Build Coastguard Worker case kVideoCodecAV1:
8674*d9f75844SAndroid Build Coastguard Worker encoder = CreateLibaomAv1Encoder();
8675*d9f75844SAndroid Build Coastguard Worker break;
8676*d9f75844SAndroid Build Coastguard Worker case kVideoCodecH264:
8677*d9f75844SAndroid Build Coastguard Worker encoder =
8678*d9f75844SAndroid Build Coastguard Worker H264Encoder::Create(cricket::VideoCodec(cricket::kH264CodecName));
8679*d9f75844SAndroid Build Coastguard Worker break;
8680*d9f75844SAndroid Build Coastguard Worker case kVideoCodecMultiplex:
8681*d9f75844SAndroid Build Coastguard Worker mock_encoder_factory_for_multiplex_ =
8682*d9f75844SAndroid Build Coastguard Worker std::make_unique<MockVideoEncoderFactory>();
8683*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*mock_encoder_factory_for_multiplex_, Die);
8684*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*mock_encoder_factory_for_multiplex_, CreateVideoEncoder)
8685*d9f75844SAndroid Build Coastguard Worker .WillRepeatedly([] { return VP8Encoder::Create(); });
8686*d9f75844SAndroid Build Coastguard Worker encoder = std::make_unique<MultiplexEncoderAdapter>(
8687*d9f75844SAndroid Build Coastguard Worker mock_encoder_factory_for_multiplex_.get(), SdpVideoFormat("VP8"),
8688*d9f75844SAndroid Build Coastguard Worker false);
8689*d9f75844SAndroid Build Coastguard Worker break;
8690*d9f75844SAndroid Build Coastguard Worker default:
8691*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
8692*d9f75844SAndroid Build Coastguard Worker }
8693*d9f75844SAndroid Build Coastguard Worker ConfigureEncoderAndBitrate(codec_type_, std::move(encoder));
8694*d9f75844SAndroid Build Coastguard Worker }
8695*d9f75844SAndroid Build Coastguard Worker
TearDown()8696*d9f75844SAndroid Build Coastguard Worker void TearDown() override {
8697*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8698*d9f75844SAndroid Build Coastguard Worker // Ensure `video_stream_encoder_` is destroyed before
8699*d9f75844SAndroid Build Coastguard Worker // `encoder_proxy_factory_`.
8700*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_.reset();
8701*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoderTest::TearDown();
8702*d9f75844SAndroid Build Coastguard Worker }
8703*d9f75844SAndroid Build Coastguard Worker
8704*d9f75844SAndroid Build Coastguard Worker protected:
ConfigureEncoderAndBitrate(VideoCodecType codec_type,std::unique_ptr<VideoEncoder> encoder)8705*d9f75844SAndroid Build Coastguard Worker void ConfigureEncoderAndBitrate(VideoCodecType codec_type,
8706*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<VideoEncoder> encoder) {
8707*d9f75844SAndroid Build Coastguard Worker // Configure VSE to use the encoder.
8708*d9f75844SAndroid Build Coastguard Worker encoder_ = std::move(encoder);
8709*d9f75844SAndroid Build Coastguard Worker encoder_proxy_factory_ = std::make_unique<test::VideoEncoderProxyFactory>(
8710*d9f75844SAndroid Build Coastguard Worker encoder_.get(), &encoder_selector_);
8711*d9f75844SAndroid Build Coastguard Worker video_send_config_.encoder_settings.encoder_factory =
8712*d9f75844SAndroid Build Coastguard Worker encoder_proxy_factory_.get();
8713*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
8714*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(codec_type, 1, &video_encoder_config);
8715*d9f75844SAndroid Build Coastguard Worker video_encoder_config_ = video_encoder_config.Copy();
8716*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(video_encoder_config_.Copy());
8717*d9f75844SAndroid Build Coastguard Worker
8718*d9f75844SAndroid Build Coastguard Worker // Set bitrate to ensure frame is not dropped.
8719*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8720*d9f75844SAndroid Build Coastguard Worker kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
8721*d9f75844SAndroid Build Coastguard Worker }
8722*d9f75844SAndroid Build Coastguard Worker
8723*d9f75844SAndroid Build Coastguard Worker const VideoCodecType codec_type_;
8724*d9f75844SAndroid Build Coastguard Worker const bool allow_i420_conversion_;
8725*d9f75844SAndroid Build Coastguard Worker NiceMock<MockEncoderSelector> encoder_selector_;
8726*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<test::VideoEncoderProxyFactory> encoder_proxy_factory_;
8727*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<VideoEncoder> encoder_;
8728*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<MockVideoEncoderFactory> mock_encoder_factory_for_multiplex_;
8729*d9f75844SAndroid Build Coastguard Worker };
8730*d9f75844SAndroid Build Coastguard Worker
TEST_P(VideoStreamEncoderWithRealEncoderTest,EncoderMapsNativeI420)8731*d9f75844SAndroid Build Coastguard Worker TEST_P(VideoStreamEncoderWithRealEncoderTest, EncoderMapsNativeI420) {
8732*d9f75844SAndroid Build Coastguard Worker auto native_i420_frame = test::CreateMappableNativeFrame(
8733*d9f75844SAndroid Build Coastguard Worker 1, VideoFrameBuffer::Type::kI420, codec_width_, codec_height_);
8734*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(native_i420_frame);
8735*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(codec_width_, codec_height_);
8736*d9f75844SAndroid Build Coastguard Worker
8737*d9f75844SAndroid Build Coastguard Worker auto mappable_native_buffer =
8738*d9f75844SAndroid Build Coastguard Worker test::GetMappableNativeBufferFromVideoFrame(native_i420_frame);
8739*d9f75844SAndroid Build Coastguard Worker std::vector<rtc::scoped_refptr<VideoFrameBuffer>> mapped_frame_buffers =
8740*d9f75844SAndroid Build Coastguard Worker mappable_native_buffer->GetMappedFramedBuffers();
8741*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(mapped_frame_buffers.size(), 1u);
8742*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(mapped_frame_buffers[0]->width(), codec_width_);
8743*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(mapped_frame_buffers[0]->height(), codec_height_);
8744*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(mapped_frame_buffers[0]->type(), VideoFrameBuffer::Type::kI420);
8745*d9f75844SAndroid Build Coastguard Worker }
8746*d9f75844SAndroid Build Coastguard Worker
TEST_P(VideoStreamEncoderWithRealEncoderTest,EncoderMapsNativeNV12)8747*d9f75844SAndroid Build Coastguard Worker TEST_P(VideoStreamEncoderWithRealEncoderTest, EncoderMapsNativeNV12) {
8748*d9f75844SAndroid Build Coastguard Worker auto native_nv12_frame = test::CreateMappableNativeFrame(
8749*d9f75844SAndroid Build Coastguard Worker 1, VideoFrameBuffer::Type::kNV12, codec_width_, codec_height_);
8750*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(native_nv12_frame);
8751*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(codec_width_, codec_height_);
8752*d9f75844SAndroid Build Coastguard Worker
8753*d9f75844SAndroid Build Coastguard Worker auto mappable_native_buffer =
8754*d9f75844SAndroid Build Coastguard Worker test::GetMappableNativeBufferFromVideoFrame(native_nv12_frame);
8755*d9f75844SAndroid Build Coastguard Worker std::vector<rtc::scoped_refptr<VideoFrameBuffer>> mapped_frame_buffers =
8756*d9f75844SAndroid Build Coastguard Worker mappable_native_buffer->GetMappedFramedBuffers();
8757*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(mapped_frame_buffers.size(), 1u);
8758*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(mapped_frame_buffers[0]->width(), codec_width_);
8759*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(mapped_frame_buffers[0]->height(), codec_height_);
8760*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(mapped_frame_buffers[0]->type(), VideoFrameBuffer::Type::kNV12);
8761*d9f75844SAndroid Build Coastguard Worker
8762*d9f75844SAndroid Build Coastguard Worker if (!allow_i420_conversion_) {
8763*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(mappable_native_buffer->DidConvertToI420());
8764*d9f75844SAndroid Build Coastguard Worker }
8765*d9f75844SAndroid Build Coastguard Worker }
8766*d9f75844SAndroid Build Coastguard Worker
TEST_P(VideoStreamEncoderWithRealEncoderTest,HandlesLayerToggling)8767*d9f75844SAndroid Build Coastguard Worker TEST_P(VideoStreamEncoderWithRealEncoderTest, HandlesLayerToggling) {
8768*d9f75844SAndroid Build Coastguard Worker if (codec_type_ == kVideoCodecMultiplex) {
8769*d9f75844SAndroid Build Coastguard Worker // Multiplex codec here uses wrapped mock codecs, ignore for this test.
8770*d9f75844SAndroid Build Coastguard Worker return;
8771*d9f75844SAndroid Build Coastguard Worker }
8772*d9f75844SAndroid Build Coastguard Worker
8773*d9f75844SAndroid Build Coastguard Worker const size_t kNumSpatialLayers = 3u;
8774*d9f75844SAndroid Build Coastguard Worker const float kDownscaleFactors[] = {4.0, 2.0, 1.0};
8775*d9f75844SAndroid Build Coastguard Worker const int kFrameWidth = 1280;
8776*d9f75844SAndroid Build Coastguard Worker const int kFrameHeight = 720;
8777*d9f75844SAndroid Build Coastguard Worker const rtc::VideoSinkWants::FrameSize kLayer0Size(
8778*d9f75844SAndroid Build Coastguard Worker kFrameWidth / kDownscaleFactors[0], kFrameHeight / kDownscaleFactors[0]);
8779*d9f75844SAndroid Build Coastguard Worker const rtc::VideoSinkWants::FrameSize kLayer1Size(
8780*d9f75844SAndroid Build Coastguard Worker kFrameWidth / kDownscaleFactors[1], kFrameHeight / kDownscaleFactors[1]);
8781*d9f75844SAndroid Build Coastguard Worker const rtc::VideoSinkWants::FrameSize kLayer2Size(
8782*d9f75844SAndroid Build Coastguard Worker kFrameWidth / kDownscaleFactors[2], kFrameHeight / kDownscaleFactors[2]);
8783*d9f75844SAndroid Build Coastguard Worker
8784*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
8785*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoder::EncoderInfo encoder_info;
8786*d9f75844SAndroid Build Coastguard Worker if (codec_type_ == VideoCodecType::kVideoCodecVP9) {
8787*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(codec_type_, 1, &config);
8788*d9f75844SAndroid Build Coastguard Worker config.max_bitrate_bps = kSimulcastTargetBitrate.bps();
8789*d9f75844SAndroid Build Coastguard Worker VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
8790*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfSpatialLayers = kNumSpatialLayers;
8791*d9f75844SAndroid Build Coastguard Worker vp9_settings.numberOfTemporalLayers = 3;
8792*d9f75844SAndroid Build Coastguard Worker vp9_settings.automaticResizeOn = false;
8793*d9f75844SAndroid Build Coastguard Worker config.encoder_specific_settings =
8794*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
8795*d9f75844SAndroid Build Coastguard Worker vp9_settings);
8796*d9f75844SAndroid Build Coastguard Worker config.spatial_layers = GetSvcConfig(kFrameWidth, kFrameHeight,
8797*d9f75844SAndroid Build Coastguard Worker /*fps=*/30.0,
8798*d9f75844SAndroid Build Coastguard Worker /*first_active_layer=*/0,
8799*d9f75844SAndroid Build Coastguard Worker /*num_spatial_layers=*/3,
8800*d9f75844SAndroid Build Coastguard Worker /*num_temporal_layers=*/3,
8801*d9f75844SAndroid Build Coastguard Worker /*is_screenshare=*/false);
8802*d9f75844SAndroid Build Coastguard Worker } else if (codec_type_ == VideoCodecType::kVideoCodecAV1) {
8803*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(codec_type_, 1, &config);
8804*d9f75844SAndroid Build Coastguard Worker config.max_bitrate_bps = kSimulcastTargetBitrate.bps();
8805*d9f75844SAndroid Build Coastguard Worker config.spatial_layers = GetSvcConfig(kFrameWidth, kFrameHeight,
8806*d9f75844SAndroid Build Coastguard Worker /*fps=*/30.0,
8807*d9f75844SAndroid Build Coastguard Worker /*first_active_layer=*/0,
8808*d9f75844SAndroid Build Coastguard Worker /*num_spatial_layers=*/3,
8809*d9f75844SAndroid Build Coastguard Worker /*num_temporal_layers=*/3,
8810*d9f75844SAndroid Build Coastguard Worker /*is_screenshare=*/false);
8811*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[0].scalability_mode = ScalabilityMode::kL3T3_KEY;
8812*d9f75844SAndroid Build Coastguard Worker } else {
8813*d9f75844SAndroid Build Coastguard Worker // Simulcast for VP8/H264.
8814*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(codec_type_, kNumSpatialLayers, &config);
8815*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kNumSpatialLayers; ++i) {
8816*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[i].scale_resolution_down_by =
8817*d9f75844SAndroid Build Coastguard Worker kDownscaleFactors[i];
8818*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[i].active = true;
8819*d9f75844SAndroid Build Coastguard Worker }
8820*d9f75844SAndroid Build Coastguard Worker if (codec_type_ == VideoCodecType::kVideoCodecH264) {
8821*d9f75844SAndroid Build Coastguard Worker // Turn off frame dropping to prevent flakiness.
8822*d9f75844SAndroid Build Coastguard Worker config.frame_drop_enabled = false;
8823*d9f75844SAndroid Build Coastguard Worker }
8824*d9f75844SAndroid Build Coastguard Worker }
8825*d9f75844SAndroid Build Coastguard Worker
8826*d9f75844SAndroid Build Coastguard Worker auto set_layer_active = [&](int layer_idx, bool active) {
8827*d9f75844SAndroid Build Coastguard Worker if (codec_type_ == VideoCodecType::kVideoCodecVP9 ||
8828*d9f75844SAndroid Build Coastguard Worker codec_type_ == VideoCodecType::kVideoCodecAV1) {
8829*d9f75844SAndroid Build Coastguard Worker config.spatial_layers[layer_idx].active = active;
8830*d9f75844SAndroid Build Coastguard Worker } else {
8831*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[layer_idx].active = active;
8832*d9f75844SAndroid Build Coastguard Worker }
8833*d9f75844SAndroid Build Coastguard Worker };
8834*d9f75844SAndroid Build Coastguard Worker
8835*d9f75844SAndroid Build Coastguard Worker config.video_stream_factory =
8836*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<cricket::EncoderStreamFactory>(
8837*d9f75844SAndroid Build Coastguard Worker CodecTypeToPayloadString(codec_type_), /*max qp*/ 56,
8838*d9f75844SAndroid Build Coastguard Worker /*screencast*/ false,
8839*d9f75844SAndroid Build Coastguard Worker /*screenshare enabled*/ false, encoder_info);
8840*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8841*d9f75844SAndroid Build Coastguard Worker kSimulcastTargetBitrate, kSimulcastTargetBitrate, kSimulcastTargetBitrate,
8842*d9f75844SAndroid Build Coastguard Worker 0, 0, 0);
8843*d9f75844SAndroid Build Coastguard Worker
8844*d9f75844SAndroid Build Coastguard Worker // Capture a frame with all layers active.
8845*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(kNumSpatialLayers);
8846*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
8847*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms = kFrameIntervalMs;
8848*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8849*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
8850*d9f75844SAndroid Build Coastguard Worker
8851*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kLayer2Size.width, kLayer2Size.height);
8852*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8853*d9f75844SAndroid Build Coastguard Worker
8854*d9f75844SAndroid Build Coastguard Worker // Capture a frame with one of the layers inactive.
8855*d9f75844SAndroid Build Coastguard Worker set_layer_active(2, false);
8856*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(kNumSpatialLayers - 1);
8857*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
8858*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
8859*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8860*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
8861*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kLayer1Size.width, kLayer1Size.height);
8862*d9f75844SAndroid Build Coastguard Worker
8863*d9f75844SAndroid Build Coastguard Worker // New target bitrates signaled based on lower resolution.
8864*d9f75844SAndroid Build Coastguard Worker DataRate kTwoLayerBitrate = DataRate::KilobitsPerSec(833);
8865*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8866*d9f75844SAndroid Build Coastguard Worker kTwoLayerBitrate, kTwoLayerBitrate, kTwoLayerBitrate, 0, 0, 0);
8867*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8868*d9f75844SAndroid Build Coastguard Worker
8869*d9f75844SAndroid Build Coastguard Worker // Re-enable the top layer.
8870*d9f75844SAndroid Build Coastguard Worker set_layer_active(2, true);
8871*d9f75844SAndroid Build Coastguard Worker sink_.SetNumExpectedLayers(kNumSpatialLayers);
8872*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
8873*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8874*d9f75844SAndroid Build Coastguard Worker
8875*d9f75844SAndroid Build Coastguard Worker // Bitrate target adjusted back up to enable HD layer...
8876*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8877*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(1800), DataRate::KilobitsPerSec(1800),
8878*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(1800), 0, 0, 0);
8879*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8880*d9f75844SAndroid Build Coastguard Worker
8881*d9f75844SAndroid Build Coastguard Worker // ...then add a new frame.
8882*d9f75844SAndroid Build Coastguard Worker timestamp_ms += kFrameIntervalMs;
8883*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
8884*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
8885*d9f75844SAndroid Build Coastguard Worker WaitForEncodedFrame(kLayer2Size.width, kLayer2Size.height);
8886*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->WaitUntilTaskQueueIsIdle();
8887*d9f75844SAndroid Build Coastguard Worker
8888*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8889*d9f75844SAndroid Build Coastguard Worker }
8890*d9f75844SAndroid Build Coastguard Worker
TestParametersVideoCodecAndAllowI420ConversionToString(testing::TestParamInfo<std::pair<VideoCodecType,bool>> info)8891*d9f75844SAndroid Build Coastguard Worker std::string TestParametersVideoCodecAndAllowI420ConversionToString(
8892*d9f75844SAndroid Build Coastguard Worker testing::TestParamInfo<std::pair<VideoCodecType, bool>> info) {
8893*d9f75844SAndroid Build Coastguard Worker VideoCodecType codec_type = std::get<0>(info.param);
8894*d9f75844SAndroid Build Coastguard Worker bool allow_i420_conversion = std::get<1>(info.param);
8895*d9f75844SAndroid Build Coastguard Worker std::string str;
8896*d9f75844SAndroid Build Coastguard Worker switch (codec_type) {
8897*d9f75844SAndroid Build Coastguard Worker case kVideoCodecGeneric:
8898*d9f75844SAndroid Build Coastguard Worker str = "Generic";
8899*d9f75844SAndroid Build Coastguard Worker break;
8900*d9f75844SAndroid Build Coastguard Worker case kVideoCodecVP8:
8901*d9f75844SAndroid Build Coastguard Worker str = "VP8";
8902*d9f75844SAndroid Build Coastguard Worker break;
8903*d9f75844SAndroid Build Coastguard Worker case kVideoCodecVP9:
8904*d9f75844SAndroid Build Coastguard Worker str = "VP9";
8905*d9f75844SAndroid Build Coastguard Worker break;
8906*d9f75844SAndroid Build Coastguard Worker case kVideoCodecAV1:
8907*d9f75844SAndroid Build Coastguard Worker str = "AV1";
8908*d9f75844SAndroid Build Coastguard Worker break;
8909*d9f75844SAndroid Build Coastguard Worker case kVideoCodecH264:
8910*d9f75844SAndroid Build Coastguard Worker str = "H264";
8911*d9f75844SAndroid Build Coastguard Worker break;
8912*d9f75844SAndroid Build Coastguard Worker case kVideoCodecMultiplex:
8913*d9f75844SAndroid Build Coastguard Worker str = "Multiplex";
8914*d9f75844SAndroid Build Coastguard Worker break;
8915*d9f75844SAndroid Build Coastguard Worker default:
8916*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
8917*d9f75844SAndroid Build Coastguard Worker }
8918*d9f75844SAndroid Build Coastguard Worker str += allow_i420_conversion ? "_AllowToI420" : "_DisallowToI420";
8919*d9f75844SAndroid Build Coastguard Worker return str;
8920*d9f75844SAndroid Build Coastguard Worker }
8921*d9f75844SAndroid Build Coastguard Worker
8922*d9f75844SAndroid Build Coastguard Worker constexpr std::pair<VideoCodecType, bool> kVP8DisallowConversion =
8923*d9f75844SAndroid Build Coastguard Worker std::make_pair(kVideoCodecVP8, /*allow_i420_conversion=*/false);
8924*d9f75844SAndroid Build Coastguard Worker constexpr std::pair<VideoCodecType, bool> kVP9DisallowConversion =
8925*d9f75844SAndroid Build Coastguard Worker std::make_pair(kVideoCodecVP9, /*allow_i420_conversion=*/false);
8926*d9f75844SAndroid Build Coastguard Worker constexpr std::pair<VideoCodecType, bool> kAV1AllowConversion =
8927*d9f75844SAndroid Build Coastguard Worker std::make_pair(kVideoCodecAV1, /*allow_i420_conversion=*/false);
8928*d9f75844SAndroid Build Coastguard Worker constexpr std::pair<VideoCodecType, bool> kMultiplexDisallowConversion =
8929*d9f75844SAndroid Build Coastguard Worker std::make_pair(kVideoCodecMultiplex, /*allow_i420_conversion=*/false);
8930*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_USE_H264)
8931*d9f75844SAndroid Build Coastguard Worker constexpr std::pair<VideoCodecType, bool> kH264AllowConversion =
8932*d9f75844SAndroid Build Coastguard Worker std::make_pair(kVideoCodecH264, /*allow_i420_conversion=*/true);
8933*d9f75844SAndroid Build Coastguard Worker
8934*d9f75844SAndroid Build Coastguard Worker // The windows compiler does not tolerate #if statements inside the
8935*d9f75844SAndroid Build Coastguard Worker // INSTANTIATE_TEST_SUITE_P() macro, so we have to have two definitions (with
8936*d9f75844SAndroid Build Coastguard Worker // and without H264).
8937*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
8938*d9f75844SAndroid Build Coastguard Worker All,
8939*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoderWithRealEncoderTest,
8940*d9f75844SAndroid Build Coastguard Worker ::testing::Values(kVP8DisallowConversion,
8941*d9f75844SAndroid Build Coastguard Worker kVP9DisallowConversion,
8942*d9f75844SAndroid Build Coastguard Worker kAV1AllowConversion,
8943*d9f75844SAndroid Build Coastguard Worker kMultiplexDisallowConversion,
8944*d9f75844SAndroid Build Coastguard Worker kH264AllowConversion),
8945*d9f75844SAndroid Build Coastguard Worker TestParametersVideoCodecAndAllowI420ConversionToString);
8946*d9f75844SAndroid Build Coastguard Worker #else
8947*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
8948*d9f75844SAndroid Build Coastguard Worker All,
8949*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoderWithRealEncoderTest,
8950*d9f75844SAndroid Build Coastguard Worker ::testing::Values(kVP8DisallowConversion,
8951*d9f75844SAndroid Build Coastguard Worker kVP9DisallowConversion,
8952*d9f75844SAndroid Build Coastguard Worker kAV1AllowConversion,
8953*d9f75844SAndroid Build Coastguard Worker kMultiplexDisallowConversion),
8954*d9f75844SAndroid Build Coastguard Worker TestParametersVideoCodecAndAllowI420ConversionToString);
8955*d9f75844SAndroid Build Coastguard Worker #endif
8956*d9f75844SAndroid Build Coastguard Worker
8957*d9f75844SAndroid Build Coastguard Worker class ReconfigureEncoderTest : public VideoStreamEncoderTest {
8958*d9f75844SAndroid Build Coastguard Worker protected:
RunTest(const std::vector<VideoStream> & configs,const int expected_num_init_encode)8959*d9f75844SAndroid Build Coastguard Worker void RunTest(const std::vector<VideoStream>& configs,
8960*d9f75844SAndroid Build Coastguard Worker const int expected_num_init_encode) {
8961*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(configs[0]);
8962*d9f75844SAndroid Build Coastguard Worker OnBitrateUpdated(kTargetBitrate);
8963*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
8964*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, sink_.number_of_reconfigurations());
8965*d9f75844SAndroid Build Coastguard Worker ExpectEqual(bitrate_allocator_factory_.codec_config(), configs[0]);
8966*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1, fake_encoder_.GetNumInitializations());
8967*d9f75844SAndroid Build Coastguard Worker ExpectEqual(fake_encoder_.config(), configs[0]);
8968*d9f75844SAndroid Build Coastguard Worker
8969*d9f75844SAndroid Build Coastguard Worker // Reconfigure encoder, the encoder should only be reconfigured if needed.
8970*d9f75844SAndroid Build Coastguard Worker ConfigureEncoder(configs[1]);
8971*d9f75844SAndroid Build Coastguard Worker InsertFrameAndWaitForEncoded();
8972*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2, sink_.number_of_reconfigurations());
8973*d9f75844SAndroid Build Coastguard Worker ExpectEqual(bitrate_allocator_factory_.codec_config(), configs[1]);
8974*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(expected_num_init_encode, fake_encoder_.GetNumInitializations());
8975*d9f75844SAndroid Build Coastguard Worker if (expected_num_init_encode > 1)
8976*d9f75844SAndroid Build Coastguard Worker ExpectEqual(fake_encoder_.config(), configs[1]);
8977*d9f75844SAndroid Build Coastguard Worker
8978*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->Stop();
8979*d9f75844SAndroid Build Coastguard Worker }
8980*d9f75844SAndroid Build Coastguard Worker
ConfigureEncoder(const VideoStream & stream)8981*d9f75844SAndroid Build Coastguard Worker void ConfigureEncoder(const VideoStream& stream) {
8982*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
8983*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoder::EncoderInfo encoder_info;
8984*d9f75844SAndroid Build Coastguard Worker
8985*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, /*num_streams=*/1, &config);
8986*d9f75844SAndroid Build Coastguard Worker config.max_bitrate_bps = stream.max_bitrate_bps;
8987*d9f75844SAndroid Build Coastguard Worker config.simulcast_layers[0] = stream;
8988*d9f75844SAndroid Build Coastguard Worker config.video_stream_factory =
8989*d9f75844SAndroid Build Coastguard Worker rtc::make_ref_counted<cricket::EncoderStreamFactory>(
8990*d9f75844SAndroid Build Coastguard Worker /*codec_name=*/"VP8", /*max_qp=*/0, /*is_screenshare=*/false,
8991*d9f75844SAndroid Build Coastguard Worker /*conference_mode=*/false, encoder_info);
8992*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->ConfigureEncoder(std::move(config),
8993*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
8994*d9f75844SAndroid Build Coastguard Worker }
8995*d9f75844SAndroid Build Coastguard Worker
OnBitrateUpdated(DataRate bitrate)8996*d9f75844SAndroid Build Coastguard Worker void OnBitrateUpdated(DataRate bitrate) {
8997*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
8998*d9f75844SAndroid Build Coastguard Worker bitrate, bitrate, bitrate, 0, 0, 0);
8999*d9f75844SAndroid Build Coastguard Worker }
9000*d9f75844SAndroid Build Coastguard Worker
InsertFrameAndWaitForEncoded()9001*d9f75844SAndroid Build Coastguard Worker void InsertFrameAndWaitForEncoded() {
9002*d9f75844SAndroid Build Coastguard Worker timestamp_ms_ += kFrameIntervalMs;
9003*d9f75844SAndroid Build Coastguard Worker video_source_.IncomingCapturedFrame(
9004*d9f75844SAndroid Build Coastguard Worker CreateFrame(timestamp_ms_, kWidth, kHeight));
9005*d9f75844SAndroid Build Coastguard Worker sink_.WaitForEncodedFrame(timestamp_ms_);
9006*d9f75844SAndroid Build Coastguard Worker }
9007*d9f75844SAndroid Build Coastguard Worker
ExpectEqual(const VideoCodec & actual,const VideoStream & expected) const9008*d9f75844SAndroid Build Coastguard Worker void ExpectEqual(const VideoCodec& actual,
9009*d9f75844SAndroid Build Coastguard Worker const VideoStream& expected) const {
9010*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(actual.numberOfSimulcastStreams, 1);
9011*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(actual.simulcastStream[0].maxFramerate, expected.max_framerate);
9012*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(actual.simulcastStream[0].minBitrate * 1000,
9013*d9f75844SAndroid Build Coastguard Worker static_cast<unsigned int>(expected.min_bitrate_bps));
9014*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(actual.simulcastStream[0].maxBitrate * 1000,
9015*d9f75844SAndroid Build Coastguard Worker static_cast<unsigned int>(expected.max_bitrate_bps));
9016*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(actual.simulcastStream[0].width,
9017*d9f75844SAndroid Build Coastguard Worker kWidth / expected.scale_resolution_down_by);
9018*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(actual.simulcastStream[0].height,
9019*d9f75844SAndroid Build Coastguard Worker kHeight / expected.scale_resolution_down_by);
9020*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(actual.simulcastStream[0].numberOfTemporalLayers,
9021*d9f75844SAndroid Build Coastguard Worker expected.num_temporal_layers);
9022*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(actual.GetScalabilityMode(), expected.scalability_mode);
9023*d9f75844SAndroid Build Coastguard Worker }
9024*d9f75844SAndroid Build Coastguard Worker
DefaultConfig() const9025*d9f75844SAndroid Build Coastguard Worker VideoStream DefaultConfig() const {
9026*d9f75844SAndroid Build Coastguard Worker VideoStream stream;
9027*d9f75844SAndroid Build Coastguard Worker stream.max_framerate = 25;
9028*d9f75844SAndroid Build Coastguard Worker stream.min_bitrate_bps = 35000;
9029*d9f75844SAndroid Build Coastguard Worker stream.max_bitrate_bps = 900000;
9030*d9f75844SAndroid Build Coastguard Worker stream.scale_resolution_down_by = 1.0;
9031*d9f75844SAndroid Build Coastguard Worker stream.num_temporal_layers = 1;
9032*d9f75844SAndroid Build Coastguard Worker stream.bitrate_priority = 1.0;
9033*d9f75844SAndroid Build Coastguard Worker stream.scalability_mode = absl::nullopt;
9034*d9f75844SAndroid Build Coastguard Worker return stream;
9035*d9f75844SAndroid Build Coastguard Worker }
9036*d9f75844SAndroid Build Coastguard Worker
9037*d9f75844SAndroid Build Coastguard Worker const int kWidth = 640;
9038*d9f75844SAndroid Build Coastguard Worker const int kHeight = 360;
9039*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_ms_ = 0;
9040*d9f75844SAndroid Build Coastguard Worker };
9041*d9f75844SAndroid Build Coastguard Worker
TEST_F(ReconfigureEncoderTest,NotReconfiguredIfMaxFramerateChanges)9042*d9f75844SAndroid Build Coastguard Worker TEST_F(ReconfigureEncoderTest, NotReconfiguredIfMaxFramerateChanges) {
9043*d9f75844SAndroid Build Coastguard Worker VideoStream config1 = DefaultConfig();
9044*d9f75844SAndroid Build Coastguard Worker VideoStream config2 = config1;
9045*d9f75844SAndroid Build Coastguard Worker config2.max_framerate++;
9046*d9f75844SAndroid Build Coastguard Worker
9047*d9f75844SAndroid Build Coastguard Worker RunTest({config1, config2}, /*expected_num_init_encode=*/1);
9048*d9f75844SAndroid Build Coastguard Worker }
9049*d9f75844SAndroid Build Coastguard Worker
TEST_F(ReconfigureEncoderTest,NotReconfiguredIfMinBitrateChanges)9050*d9f75844SAndroid Build Coastguard Worker TEST_F(ReconfigureEncoderTest, NotReconfiguredIfMinBitrateChanges) {
9051*d9f75844SAndroid Build Coastguard Worker VideoStream config1 = DefaultConfig();
9052*d9f75844SAndroid Build Coastguard Worker VideoStream config2 = config1;
9053*d9f75844SAndroid Build Coastguard Worker config2.min_bitrate_bps += 10000;
9054*d9f75844SAndroid Build Coastguard Worker
9055*d9f75844SAndroid Build Coastguard Worker RunTest({config1, config2}, /*expected_num_init_encode=*/1);
9056*d9f75844SAndroid Build Coastguard Worker }
9057*d9f75844SAndroid Build Coastguard Worker
TEST_F(ReconfigureEncoderTest,NotReconfiguredIfMaxBitrateChanges)9058*d9f75844SAndroid Build Coastguard Worker TEST_F(ReconfigureEncoderTest, NotReconfiguredIfMaxBitrateChanges) {
9059*d9f75844SAndroid Build Coastguard Worker VideoStream config1 = DefaultConfig();
9060*d9f75844SAndroid Build Coastguard Worker VideoStream config2 = config1;
9061*d9f75844SAndroid Build Coastguard Worker config2.max_bitrate_bps += 100000;
9062*d9f75844SAndroid Build Coastguard Worker
9063*d9f75844SAndroid Build Coastguard Worker RunTest({config1, config2}, /*expected_num_init_encode=*/1);
9064*d9f75844SAndroid Build Coastguard Worker }
9065*d9f75844SAndroid Build Coastguard Worker
TEST_F(ReconfigureEncoderTest,NotReconfiguredIfBitratePriorityChanges)9066*d9f75844SAndroid Build Coastguard Worker TEST_F(ReconfigureEncoderTest, NotReconfiguredIfBitratePriorityChanges) {
9067*d9f75844SAndroid Build Coastguard Worker VideoStream config1 = DefaultConfig();
9068*d9f75844SAndroid Build Coastguard Worker VideoStream config2 = config1;
9069*d9f75844SAndroid Build Coastguard Worker config2.bitrate_priority = config1.bitrate_priority.value() * 2.0;
9070*d9f75844SAndroid Build Coastguard Worker
9071*d9f75844SAndroid Build Coastguard Worker RunTest({config1, config2}, /*expected_num_init_encode=*/1);
9072*d9f75844SAndroid Build Coastguard Worker }
9073*d9f75844SAndroid Build Coastguard Worker
TEST_F(ReconfigureEncoderTest,ReconfiguredIfResolutionChanges)9074*d9f75844SAndroid Build Coastguard Worker TEST_F(ReconfigureEncoderTest, ReconfiguredIfResolutionChanges) {
9075*d9f75844SAndroid Build Coastguard Worker VideoStream config1 = DefaultConfig();
9076*d9f75844SAndroid Build Coastguard Worker VideoStream config2 = config1;
9077*d9f75844SAndroid Build Coastguard Worker config2.scale_resolution_down_by *= 2;
9078*d9f75844SAndroid Build Coastguard Worker
9079*d9f75844SAndroid Build Coastguard Worker RunTest({config1, config2}, /*expected_num_init_encode=*/2);
9080*d9f75844SAndroid Build Coastguard Worker }
9081*d9f75844SAndroid Build Coastguard Worker
TEST_F(ReconfigureEncoderTest,ReconfiguredIfNumTemporalLayerChanges)9082*d9f75844SAndroid Build Coastguard Worker TEST_F(ReconfigureEncoderTest, ReconfiguredIfNumTemporalLayerChanges) {
9083*d9f75844SAndroid Build Coastguard Worker VideoStream config1 = DefaultConfig();
9084*d9f75844SAndroid Build Coastguard Worker VideoStream config2 = config1;
9085*d9f75844SAndroid Build Coastguard Worker config2.num_temporal_layers = config1.num_temporal_layers.value() + 1;
9086*d9f75844SAndroid Build Coastguard Worker
9087*d9f75844SAndroid Build Coastguard Worker RunTest({config1, config2}, /*expected_num_init_encode=*/2);
9088*d9f75844SAndroid Build Coastguard Worker }
9089*d9f75844SAndroid Build Coastguard Worker
TEST_F(ReconfigureEncoderTest,ReconfiguredIfScalabilityModeChanges)9090*d9f75844SAndroid Build Coastguard Worker TEST_F(ReconfigureEncoderTest, ReconfiguredIfScalabilityModeChanges) {
9091*d9f75844SAndroid Build Coastguard Worker VideoStream config1 = DefaultConfig();
9092*d9f75844SAndroid Build Coastguard Worker VideoStream config2 = config1;
9093*d9f75844SAndroid Build Coastguard Worker config2.scalability_mode = ScalabilityMode::kL2T1;
9094*d9f75844SAndroid Build Coastguard Worker
9095*d9f75844SAndroid Build Coastguard Worker RunTest({config1, config2}, /*expected_num_init_encode=*/2);
9096*d9f75844SAndroid Build Coastguard Worker }
9097*d9f75844SAndroid Build Coastguard Worker
TEST_F(ReconfigureEncoderTest,UpdatesNumTemporalLayersFromScalabilityModeChanges)9098*d9f75844SAndroid Build Coastguard Worker TEST_F(ReconfigureEncoderTest,
9099*d9f75844SAndroid Build Coastguard Worker UpdatesNumTemporalLayersFromScalabilityModeChanges) {
9100*d9f75844SAndroid Build Coastguard Worker VideoStream config1 = DefaultConfig();
9101*d9f75844SAndroid Build Coastguard Worker VideoStream config2 = config1;
9102*d9f75844SAndroid Build Coastguard Worker config2.scalability_mode = ScalabilityMode::kL1T2;
9103*d9f75844SAndroid Build Coastguard Worker config2.num_temporal_layers = 2;
9104*d9f75844SAndroid Build Coastguard Worker
9105*d9f75844SAndroid Build Coastguard Worker RunTest({config1, config2}, /*expected_num_init_encode=*/2);
9106*d9f75844SAndroid Build Coastguard Worker }
9107*d9f75844SAndroid Build Coastguard Worker
9108*d9f75844SAndroid Build Coastguard Worker // Simple test that just creates and then immediately destroys an encoder.
9109*d9f75844SAndroid Build Coastguard Worker // The purpose of the test is to make sure that nothing bad happens if the
9110*d9f75844SAndroid Build Coastguard Worker // initialization step on the encoder queue, doesn't run.
TEST(VideoStreamEncoderSimpleTest,CreateDestroy)9111*d9f75844SAndroid Build Coastguard Worker TEST(VideoStreamEncoderSimpleTest, CreateDestroy) {
9112*d9f75844SAndroid Build Coastguard Worker class SuperLazyTaskQueue : public webrtc::TaskQueueBase {
9113*d9f75844SAndroid Build Coastguard Worker public:
9114*d9f75844SAndroid Build Coastguard Worker SuperLazyTaskQueue() = default;
9115*d9f75844SAndroid Build Coastguard Worker ~SuperLazyTaskQueue() override = default;
9116*d9f75844SAndroid Build Coastguard Worker
9117*d9f75844SAndroid Build Coastguard Worker private:
9118*d9f75844SAndroid Build Coastguard Worker void Delete() override { delete this; }
9119*d9f75844SAndroid Build Coastguard Worker void PostTask(absl::AnyInvocable<void() &&> task) override {
9120*d9f75844SAndroid Build Coastguard Worker // meh.
9121*d9f75844SAndroid Build Coastguard Worker }
9122*d9f75844SAndroid Build Coastguard Worker void PostDelayedTask(absl::AnyInvocable<void() &&> task,
9123*d9f75844SAndroid Build Coastguard Worker TimeDelta delay) override {
9124*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(false);
9125*d9f75844SAndroid Build Coastguard Worker }
9126*d9f75844SAndroid Build Coastguard Worker void PostDelayedHighPrecisionTask(absl::AnyInvocable<void() &&> task,
9127*d9f75844SAndroid Build Coastguard Worker TimeDelta delay) override {
9128*d9f75844SAndroid Build Coastguard Worker ADD_FAILURE();
9129*d9f75844SAndroid Build Coastguard Worker }
9130*d9f75844SAndroid Build Coastguard Worker };
9131*d9f75844SAndroid Build Coastguard Worker
9132*d9f75844SAndroid Build Coastguard Worker // Lots of boiler plate.
9133*d9f75844SAndroid Build Coastguard Worker test::ScopedKeyValueConfig field_trials;
9134*d9f75844SAndroid Build Coastguard Worker GlobalSimulatedTimeController time_controller(Timestamp::Zero());
9135*d9f75844SAndroid Build Coastguard Worker auto stats_proxy = std::make_unique<MockableSendStatisticsProxy>(
9136*d9f75844SAndroid Build Coastguard Worker time_controller.GetClock(), VideoSendStream::Config(nullptr),
9137*d9f75844SAndroid Build Coastguard Worker webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo, field_trials);
9138*d9f75844SAndroid Build Coastguard Worker SimpleVideoStreamEncoderFactory::MockFakeEncoder mock_fake_encoder(
9139*d9f75844SAndroid Build Coastguard Worker time_controller.GetClock());
9140*d9f75844SAndroid Build Coastguard Worker test::VideoEncoderProxyFactory encoder_factory(&mock_fake_encoder);
9141*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<VideoBitrateAllocatorFactory> bitrate_allocator_factory =
9142*d9f75844SAndroid Build Coastguard Worker CreateBuiltinVideoBitrateAllocatorFactory();
9143*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoderSettings encoder_settings{
9144*d9f75844SAndroid Build Coastguard Worker VideoEncoder::Capabilities(/*loss_notification=*/false)};
9145*d9f75844SAndroid Build Coastguard Worker encoder_settings.encoder_factory = &encoder_factory;
9146*d9f75844SAndroid Build Coastguard Worker encoder_settings.bitrate_allocator_factory = bitrate_allocator_factory.get();
9147*d9f75844SAndroid Build Coastguard Worker
9148*d9f75844SAndroid Build Coastguard Worker auto adapter = std::make_unique<MockFrameCadenceAdapter>();
9149*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL((*adapter.get()), Initialize).WillOnce(Return());
9150*d9f75844SAndroid Build Coastguard Worker
9151*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
9152*d9f75844SAndroid Build Coastguard Worker encoder_queue(new SuperLazyTaskQueue());
9153*d9f75844SAndroid Build Coastguard Worker
9154*d9f75844SAndroid Build Coastguard Worker // Construct a VideoStreamEncoder instance and let it go out of scope without
9155*d9f75844SAndroid Build Coastguard Worker // doing anything else (including calling Stop()). This should be fine since
9156*d9f75844SAndroid Build Coastguard Worker // the posted init task will simply be deleted.
9157*d9f75844SAndroid Build Coastguard Worker auto encoder = std::make_unique<VideoStreamEncoder>(
9158*d9f75844SAndroid Build Coastguard Worker time_controller.GetClock(), 1, stats_proxy.get(), encoder_settings,
9159*d9f75844SAndroid Build Coastguard Worker std::make_unique<CpuOveruseDetectorProxy>(stats_proxy.get(),
9160*d9f75844SAndroid Build Coastguard Worker field_trials),
9161*d9f75844SAndroid Build Coastguard Worker std::move(adapter), std::move(encoder_queue),
9162*d9f75844SAndroid Build Coastguard Worker VideoStreamEncoder::BitrateAllocationCallbackType::
9163*d9f75844SAndroid Build Coastguard Worker kVideoBitrateAllocation,
9164*d9f75844SAndroid Build Coastguard Worker field_trials);
9165*d9f75844SAndroid Build Coastguard Worker
9166*d9f75844SAndroid Build Coastguard Worker // Stop the encoder explicitly. This additional step tests if we could
9167*d9f75844SAndroid Build Coastguard Worker // hang when calling stop and the TQ has been stopped and/or isn't accepting
9168*d9f75844SAndroid Build Coastguard Worker // any more tasks.
9169*d9f75844SAndroid Build Coastguard Worker encoder->Stop();
9170*d9f75844SAndroid Build Coastguard Worker }
9171*d9f75844SAndroid Build Coastguard Worker
TEST(VideoStreamEncoderFrameCadenceTest,ActivatesFrameCadenceOnContentType)9172*d9f75844SAndroid Build Coastguard Worker TEST(VideoStreamEncoderFrameCadenceTest, ActivatesFrameCadenceOnContentType) {
9173*d9f75844SAndroid Build Coastguard Worker auto adapter = std::make_unique<MockFrameCadenceAdapter>();
9174*d9f75844SAndroid Build Coastguard Worker auto* adapter_ptr = adapter.get();
9175*d9f75844SAndroid Build Coastguard Worker SimpleVideoStreamEncoderFactory factory;
9176*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::Callback* video_stream_encoder_callback =
9177*d9f75844SAndroid Build Coastguard Worker nullptr;
9178*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, Initialize)
9179*d9f75844SAndroid Build Coastguard Worker .WillOnce(Invoke([&video_stream_encoder_callback](
9180*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::Callback* callback) {
9181*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_callback = callback;
9182*d9f75844SAndroid Build Coastguard Worker }));
9183*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* encoder_queue = nullptr;
9184*d9f75844SAndroid Build Coastguard Worker auto video_stream_encoder =
9185*d9f75844SAndroid Build Coastguard Worker factory.Create(std::move(adapter), &encoder_queue);
9186*d9f75844SAndroid Build Coastguard Worker
9187*d9f75844SAndroid Build Coastguard Worker // First a call before we know the frame size and hence cannot compute the
9188*d9f75844SAndroid Build Coastguard Worker // number of simulcast layers.
9189*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, SetZeroHertzModeEnabled(Optional(Field(
9190*d9f75844SAndroid Build Coastguard Worker &FrameCadenceAdapterInterface::
9191*d9f75844SAndroid Build Coastguard Worker ZeroHertzModeParams::num_simulcast_layers,
9192*d9f75844SAndroid Build Coastguard Worker Eq(0u)))));
9193*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
9194*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &config);
9195*d9f75844SAndroid Build Coastguard Worker config.content_type = VideoEncoderConfig::ContentType::kScreen;
9196*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->ConfigureEncoder(std::move(config), 0);
9197*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9198*d9f75844SAndroid Build Coastguard Worker
9199*d9f75844SAndroid Build Coastguard Worker // Then a call as we've computed the number of simulcast layers after a passed
9200*d9f75844SAndroid Build Coastguard Worker // frame.
9201*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, SetZeroHertzModeEnabled(Optional(Field(
9202*d9f75844SAndroid Build Coastguard Worker &FrameCadenceAdapterInterface::
9203*d9f75844SAndroid Build Coastguard Worker ZeroHertzModeParams::num_simulcast_layers,
9204*d9f75844SAndroid Build Coastguard Worker Gt(0u)))));
9205*d9f75844SAndroid Build Coastguard Worker PassAFrame(encoder_queue, video_stream_encoder_callback, /*ntp_time_ms=*/1);
9206*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9207*d9f75844SAndroid Build Coastguard Worker Mock::VerifyAndClearExpectations(adapter_ptr);
9208*d9f75844SAndroid Build Coastguard Worker
9209*d9f75844SAndroid Build Coastguard Worker // Expect a disabled zero-hertz mode after passing realtime video.
9210*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, SetZeroHertzModeEnabled(Eq(absl::nullopt)));
9211*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config2;
9212*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &config2);
9213*d9f75844SAndroid Build Coastguard Worker config2.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
9214*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->ConfigureEncoder(std::move(config2), 0);
9215*d9f75844SAndroid Build Coastguard Worker PassAFrame(encoder_queue, video_stream_encoder_callback, /*ntp_time_ms=*/2);
9216*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9217*d9f75844SAndroid Build Coastguard Worker }
9218*d9f75844SAndroid Build Coastguard Worker
TEST(VideoStreamEncoderFrameCadenceTest,ForwardsFramesIntoFrameCadenceAdapter)9219*d9f75844SAndroid Build Coastguard Worker TEST(VideoStreamEncoderFrameCadenceTest,
9220*d9f75844SAndroid Build Coastguard Worker ForwardsFramesIntoFrameCadenceAdapter) {
9221*d9f75844SAndroid Build Coastguard Worker auto adapter = std::make_unique<MockFrameCadenceAdapter>();
9222*d9f75844SAndroid Build Coastguard Worker auto* adapter_ptr = adapter.get();
9223*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder video_source;
9224*d9f75844SAndroid Build Coastguard Worker SimpleVideoStreamEncoderFactory factory;
9225*d9f75844SAndroid Build Coastguard Worker auto video_stream_encoder = factory.Create(std::move(adapter));
9226*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->SetSource(
9227*d9f75844SAndroid Build Coastguard Worker &video_source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
9228*d9f75844SAndroid Build Coastguard Worker
9229*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, OnFrame);
9230*d9f75844SAndroid Build Coastguard Worker auto buffer = rtc::make_ref_counted<NV12Buffer>(/*width=*/16, /*height=*/16);
9231*d9f75844SAndroid Build Coastguard Worker video_source.IncomingCapturedFrame(
9232*d9f75844SAndroid Build Coastguard Worker VideoFrame::Builder().set_video_frame_buffer(std::move(buffer)).build());
9233*d9f75844SAndroid Build Coastguard Worker }
9234*d9f75844SAndroid Build Coastguard Worker
TEST(VideoStreamEncoderFrameCadenceTest,UsesFrameCadenceAdapterForFrameRate)9235*d9f75844SAndroid Build Coastguard Worker TEST(VideoStreamEncoderFrameCadenceTest, UsesFrameCadenceAdapterForFrameRate) {
9236*d9f75844SAndroid Build Coastguard Worker auto adapter = std::make_unique<MockFrameCadenceAdapter>();
9237*d9f75844SAndroid Build Coastguard Worker auto* adapter_ptr = adapter.get();
9238*d9f75844SAndroid Build Coastguard Worker test::FrameForwarder video_source;
9239*d9f75844SAndroid Build Coastguard Worker SimpleVideoStreamEncoderFactory factory;
9240*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::Callback* video_stream_encoder_callback =
9241*d9f75844SAndroid Build Coastguard Worker nullptr;
9242*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, Initialize)
9243*d9f75844SAndroid Build Coastguard Worker .WillOnce(Invoke([&video_stream_encoder_callback](
9244*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::Callback* callback) {
9245*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_callback = callback;
9246*d9f75844SAndroid Build Coastguard Worker }));
9247*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* encoder_queue = nullptr;
9248*d9f75844SAndroid Build Coastguard Worker auto video_stream_encoder =
9249*d9f75844SAndroid Build Coastguard Worker factory.Create(std::move(adapter), &encoder_queue);
9250*d9f75844SAndroid Build Coastguard Worker
9251*d9f75844SAndroid Build Coastguard Worker // This is just to make the VSE operational. We'll feed a frame directly by
9252*d9f75844SAndroid Build Coastguard Worker // the callback interface.
9253*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->SetSource(
9254*d9f75844SAndroid Build Coastguard Worker &video_source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
9255*d9f75844SAndroid Build Coastguard Worker
9256*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
9257*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecGeneric, 1, &video_encoder_config);
9258*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->ConfigureEncoder(std::move(video_encoder_config),
9259*d9f75844SAndroid Build Coastguard Worker /*max_data_payload_length=*/1000);
9260*d9f75844SAndroid Build Coastguard Worker
9261*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, GetInputFrameRateFps);
9262*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateFrameRate);
9263*d9f75844SAndroid Build Coastguard Worker PassAFrame(encoder_queue, video_stream_encoder_callback, /*ntp_time_ms=*/1);
9264*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9265*d9f75844SAndroid Build Coastguard Worker }
9266*d9f75844SAndroid Build Coastguard Worker
TEST(VideoStreamEncoderFrameCadenceTest,DeactivatesActivatesLayersOnBitrateChanges)9267*d9f75844SAndroid Build Coastguard Worker TEST(VideoStreamEncoderFrameCadenceTest,
9268*d9f75844SAndroid Build Coastguard Worker DeactivatesActivatesLayersOnBitrateChanges) {
9269*d9f75844SAndroid Build Coastguard Worker auto adapter = std::make_unique<MockFrameCadenceAdapter>();
9270*d9f75844SAndroid Build Coastguard Worker auto* adapter_ptr = adapter.get();
9271*d9f75844SAndroid Build Coastguard Worker SimpleVideoStreamEncoderFactory factory;
9272*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::Callback* video_stream_encoder_callback =
9273*d9f75844SAndroid Build Coastguard Worker nullptr;
9274*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, Initialize)
9275*d9f75844SAndroid Build Coastguard Worker .WillOnce(Invoke([&video_stream_encoder_callback](
9276*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::Callback* callback) {
9277*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_callback = callback;
9278*d9f75844SAndroid Build Coastguard Worker }));
9279*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* encoder_queue = nullptr;
9280*d9f75844SAndroid Build Coastguard Worker auto video_stream_encoder =
9281*d9f75844SAndroid Build Coastguard Worker factory.Create(std::move(adapter), &encoder_queue);
9282*d9f75844SAndroid Build Coastguard Worker
9283*d9f75844SAndroid Build Coastguard Worker // Configure 2 simulcast layers. FillEncoderConfiguration sets min bitrates to
9284*d9f75844SAndroid Build Coastguard Worker // {150000, 450000}.
9285*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
9286*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 2, &video_encoder_config);
9287*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->ConfigureEncoder(video_encoder_config.Copy(),
9288*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
9289*d9f75844SAndroid Build Coastguard Worker // Ensure an encoder is created.
9290*d9f75844SAndroid Build Coastguard Worker PassAFrame(encoder_queue, video_stream_encoder_callback, /*ntp_time_ms=*/1);
9291*d9f75844SAndroid Build Coastguard Worker
9292*d9f75844SAndroid Build Coastguard Worker // Both layers enabled at 1 MBit/s.
9293*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->OnBitrateUpdated(
9294*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(1000), DataRate::KilobitsPerSec(1000),
9295*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(1000), 0, 0, 0);
9296*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateLayerStatus(0, /*enabled=*/true));
9297*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateLayerStatus(1, /*enabled=*/true));
9298*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9299*d9f75844SAndroid Build Coastguard Worker Mock::VerifyAndClearExpectations(adapter_ptr);
9300*d9f75844SAndroid Build Coastguard Worker
9301*d9f75844SAndroid Build Coastguard Worker // Layer 1 disabled at 200 KBit/s.
9302*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->OnBitrateUpdated(
9303*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(200), DataRate::KilobitsPerSec(200),
9304*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(200), 0, 0, 0);
9305*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateLayerStatus(0, /*enabled=*/true));
9306*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateLayerStatus(1, /*enabled=*/false));
9307*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9308*d9f75844SAndroid Build Coastguard Worker Mock::VerifyAndClearExpectations(adapter_ptr);
9309*d9f75844SAndroid Build Coastguard Worker
9310*d9f75844SAndroid Build Coastguard Worker // All layers off at suspended video.
9311*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->OnBitrateUpdated(DataRate::Zero(), DataRate::Zero(),
9312*d9f75844SAndroid Build Coastguard Worker DataRate::Zero(), 0, 0, 0);
9313*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateLayerStatus(0, /*enabled=*/false));
9314*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateLayerStatus(1, /*enabled=*/false));
9315*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9316*d9f75844SAndroid Build Coastguard Worker Mock::VerifyAndClearExpectations(adapter_ptr);
9317*d9f75844SAndroid Build Coastguard Worker
9318*d9f75844SAndroid Build Coastguard Worker // Both layers enabled again back at 1 MBit/s.
9319*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->OnBitrateUpdated(
9320*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(1000), DataRate::KilobitsPerSec(1000),
9321*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(1000), 0, 0, 0);
9322*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateLayerStatus(0, /*enabled=*/true));
9323*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateLayerStatus(1, /*enabled=*/true));
9324*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9325*d9f75844SAndroid Build Coastguard Worker }
9326*d9f75844SAndroid Build Coastguard Worker
TEST(VideoStreamEncoderFrameCadenceTest,UpdatesQualityConvergence)9327*d9f75844SAndroid Build Coastguard Worker TEST(VideoStreamEncoderFrameCadenceTest, UpdatesQualityConvergence) {
9328*d9f75844SAndroid Build Coastguard Worker auto adapter = std::make_unique<MockFrameCadenceAdapter>();
9329*d9f75844SAndroid Build Coastguard Worker auto* adapter_ptr = adapter.get();
9330*d9f75844SAndroid Build Coastguard Worker SimpleVideoStreamEncoderFactory factory;
9331*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::Callback* video_stream_encoder_callback =
9332*d9f75844SAndroid Build Coastguard Worker nullptr;
9333*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, Initialize)
9334*d9f75844SAndroid Build Coastguard Worker .WillOnce(Invoke([&video_stream_encoder_callback](
9335*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::Callback* callback) {
9336*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_callback = callback;
9337*d9f75844SAndroid Build Coastguard Worker }));
9338*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* encoder_queue = nullptr;
9339*d9f75844SAndroid Build Coastguard Worker auto video_stream_encoder =
9340*d9f75844SAndroid Build Coastguard Worker factory.Create(std::move(adapter), &encoder_queue);
9341*d9f75844SAndroid Build Coastguard Worker
9342*d9f75844SAndroid Build Coastguard Worker // Configure 2 simulcast layers and setup 1 MBit/s to unpause the encoder.
9343*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig video_encoder_config;
9344*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 2, &video_encoder_config);
9345*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->ConfigureEncoder(video_encoder_config.Copy(),
9346*d9f75844SAndroid Build Coastguard Worker kMaxPayloadLength);
9347*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->OnBitrateUpdated(
9348*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(1000), DataRate::KilobitsPerSec(1000),
9349*d9f75844SAndroid Build Coastguard Worker DataRate::KilobitsPerSec(1000), 0, 0, 0);
9350*d9f75844SAndroid Build Coastguard Worker
9351*d9f75844SAndroid Build Coastguard Worker // Pass a frame which has unconverged results.
9352*d9f75844SAndroid Build Coastguard Worker PassAFrame(encoder_queue, video_stream_encoder_callback, /*ntp_time_ms=*/1);
9353*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(factory.GetMockFakeEncoder(), EncodeHook)
9354*d9f75844SAndroid Build Coastguard Worker .WillRepeatedly(Invoke([](EncodedImage& encoded_image,
9355*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<EncodedImageBuffer> buffer) {
9356*d9f75844SAndroid Build Coastguard Worker encoded_image.qp_ = kVp8SteadyStateQpThreshold + 1;
9357*d9f75844SAndroid Build Coastguard Worker CodecSpecificInfo codec_specific;
9358*d9f75844SAndroid Build Coastguard Worker codec_specific.codecType = kVideoCodecVP8;
9359*d9f75844SAndroid Build Coastguard Worker return codec_specific;
9360*d9f75844SAndroid Build Coastguard Worker }));
9361*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateLayerQualityConvergence(0, false));
9362*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateLayerQualityConvergence(1, false));
9363*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9364*d9f75844SAndroid Build Coastguard Worker Mock::VerifyAndClearExpectations(adapter_ptr);
9365*d9f75844SAndroid Build Coastguard Worker Mock::VerifyAndClearExpectations(&factory.GetMockFakeEncoder());
9366*d9f75844SAndroid Build Coastguard Worker
9367*d9f75844SAndroid Build Coastguard Worker // Pass a frame which converges in layer 0 and not in layer 1.
9368*d9f75844SAndroid Build Coastguard Worker PassAFrame(encoder_queue, video_stream_encoder_callback, /*ntp_time_ms=*/2);
9369*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(factory.GetMockFakeEncoder(), EncodeHook)
9370*d9f75844SAndroid Build Coastguard Worker .WillRepeatedly(Invoke([](EncodedImage& encoded_image,
9371*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<EncodedImageBuffer> buffer) {
9372*d9f75844SAndroid Build Coastguard Worker // This sets spatial index 0 content to be at target quality, while
9373*d9f75844SAndroid Build Coastguard Worker // index 1 content is not.
9374*d9f75844SAndroid Build Coastguard Worker encoded_image.qp_ = kVp8SteadyStateQpThreshold +
9375*d9f75844SAndroid Build Coastguard Worker (encoded_image.SpatialIndex() == 0 ? 0 : 1);
9376*d9f75844SAndroid Build Coastguard Worker CodecSpecificInfo codec_specific;
9377*d9f75844SAndroid Build Coastguard Worker codec_specific.codecType = kVideoCodecVP8;
9378*d9f75844SAndroid Build Coastguard Worker return codec_specific;
9379*d9f75844SAndroid Build Coastguard Worker }));
9380*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateLayerQualityConvergence(0, true));
9381*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, UpdateLayerQualityConvergence(1, false));
9382*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9383*d9f75844SAndroid Build Coastguard Worker Mock::VerifyAndClearExpectations(adapter_ptr);
9384*d9f75844SAndroid Build Coastguard Worker Mock::VerifyAndClearExpectations(&factory.GetMockFakeEncoder());
9385*d9f75844SAndroid Build Coastguard Worker }
9386*d9f75844SAndroid Build Coastguard Worker
TEST(VideoStreamEncoderFrameCadenceTest,RequestsRefreshFramesWhenCadenceAdapterInstructs)9387*d9f75844SAndroid Build Coastguard Worker TEST(VideoStreamEncoderFrameCadenceTest,
9388*d9f75844SAndroid Build Coastguard Worker RequestsRefreshFramesWhenCadenceAdapterInstructs) {
9389*d9f75844SAndroid Build Coastguard Worker auto adapter = std::make_unique<MockFrameCadenceAdapter>();
9390*d9f75844SAndroid Build Coastguard Worker auto* adapter_ptr = adapter.get();
9391*d9f75844SAndroid Build Coastguard Worker MockVideoSourceInterface mock_source;
9392*d9f75844SAndroid Build Coastguard Worker SimpleVideoStreamEncoderFactory factory;
9393*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::Callback* video_stream_encoder_callback =
9394*d9f75844SAndroid Build Coastguard Worker nullptr;
9395*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, Initialize)
9396*d9f75844SAndroid Build Coastguard Worker .WillOnce(Invoke([&video_stream_encoder_callback](
9397*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::Callback* callback) {
9398*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_callback = callback;
9399*d9f75844SAndroid Build Coastguard Worker }));
9400*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* encoder_queue = nullptr;
9401*d9f75844SAndroid Build Coastguard Worker auto video_stream_encoder =
9402*d9f75844SAndroid Build Coastguard Worker factory.Create(std::move(adapter), &encoder_queue);
9403*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->SetSource(
9404*d9f75844SAndroid Build Coastguard Worker &mock_source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
9405*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
9406*d9f75844SAndroid Build Coastguard Worker config.content_type = VideoEncoderConfig::ContentType::kScreen;
9407*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &config);
9408*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->ConfigureEncoder(std::move(config), 0);
9409*d9f75844SAndroid Build Coastguard Worker PassAFrame(encoder_queue, video_stream_encoder_callback, /*ntp_time_ms=*/2);
9410*d9f75844SAndroid Build Coastguard Worker // Ensure the encoder is set up.
9411*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9412*d9f75844SAndroid Build Coastguard Worker
9413*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, ProcessKeyFrameRequest)
9414*d9f75844SAndroid Build Coastguard Worker .WillOnce(Invoke([video_stream_encoder_callback] {
9415*d9f75844SAndroid Build Coastguard Worker video_stream_encoder_callback->RequestRefreshFrame();
9416*d9f75844SAndroid Build Coastguard Worker }));
9417*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(mock_source, RequestRefreshFrame);
9418*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->SendKeyFrame();
9419*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9420*d9f75844SAndroid Build Coastguard Worker Mock::VerifyAndClearExpectations(adapter_ptr);
9421*d9f75844SAndroid Build Coastguard Worker Mock::VerifyAndClearExpectations(&mock_source);
9422*d9f75844SAndroid Build Coastguard Worker
9423*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(*adapter_ptr, ProcessKeyFrameRequest);
9424*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(mock_source, RequestRefreshFrame).Times(0);
9425*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->SendKeyFrame();
9426*d9f75844SAndroid Build Coastguard Worker factory.DepleteTaskQueues();
9427*d9f75844SAndroid Build Coastguard Worker }
9428*d9f75844SAndroid Build Coastguard Worker
TEST(VideoStreamEncoderFrameCadenceTest,RequestsRefreshFrameForEarlyZeroHertzKeyFrameRequest)9429*d9f75844SAndroid Build Coastguard Worker TEST(VideoStreamEncoderFrameCadenceTest,
9430*d9f75844SAndroid Build Coastguard Worker RequestsRefreshFrameForEarlyZeroHertzKeyFrameRequest) {
9431*d9f75844SAndroid Build Coastguard Worker SimpleVideoStreamEncoderFactory factory;
9432*d9f75844SAndroid Build Coastguard Worker auto encoder_queue =
9433*d9f75844SAndroid Build Coastguard Worker factory.GetTimeController()->GetTaskQueueFactory()->CreateTaskQueue(
9434*d9f75844SAndroid Build Coastguard Worker "EncoderQueue", TaskQueueFactory::Priority::NORMAL);
9435*d9f75844SAndroid Build Coastguard Worker
9436*d9f75844SAndroid Build Coastguard Worker // Enables zero-hertz mode.
9437*d9f75844SAndroid Build Coastguard Worker test::ScopedKeyValueConfig field_trials(
9438*d9f75844SAndroid Build Coastguard Worker "WebRTC-ZeroHertzScreenshare/Enabled/");
9439*d9f75844SAndroid Build Coastguard Worker auto adapter = FrameCadenceAdapterInterface::Create(
9440*d9f75844SAndroid Build Coastguard Worker factory.GetTimeController()->GetClock(), encoder_queue.get(),
9441*d9f75844SAndroid Build Coastguard Worker field_trials);
9442*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface* adapter_ptr = adapter.get();
9443*d9f75844SAndroid Build Coastguard Worker
9444*d9f75844SAndroid Build Coastguard Worker MockVideoSourceInterface mock_source;
9445*d9f75844SAndroid Build Coastguard Worker auto video_stream_encoder = factory.CreateWithEncoderQueue(
9446*d9f75844SAndroid Build Coastguard Worker std::move(adapter), std::move(encoder_queue), &field_trials);
9447*d9f75844SAndroid Build Coastguard Worker
9448*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->SetSource(
9449*d9f75844SAndroid Build Coastguard Worker &mock_source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
9450*d9f75844SAndroid Build Coastguard Worker VideoEncoderConfig config;
9451*d9f75844SAndroid Build Coastguard Worker config.content_type = VideoEncoderConfig::ContentType::kScreen;
9452*d9f75844SAndroid Build Coastguard Worker test::FillEncoderConfiguration(kVideoCodecVP8, 1, &config);
9453*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->ConfigureEncoder(std::move(config), 0);
9454*d9f75844SAndroid Build Coastguard Worker
9455*d9f75844SAndroid Build Coastguard Worker // Eventually expect a refresh frame request when requesting a key frame
9456*d9f75844SAndroid Build Coastguard Worker // before initializing zero-hertz mode. This can happen in reality because the
9457*d9f75844SAndroid Build Coastguard Worker // threads invoking key frame requests and constraints setup aren't
9458*d9f75844SAndroid Build Coastguard Worker // synchronized.
9459*d9f75844SAndroid Build Coastguard Worker EXPECT_CALL(mock_source, RequestRefreshFrame);
9460*d9f75844SAndroid Build Coastguard Worker video_stream_encoder->SendKeyFrame();
9461*d9f75844SAndroid Build Coastguard Worker constexpr int kMaxFps = 30;
9462*d9f75844SAndroid Build Coastguard Worker adapter_ptr->OnConstraintsChanged(VideoTrackSourceConstraints{0, kMaxFps});
9463*d9f75844SAndroid Build Coastguard Worker factory.GetTimeController()->AdvanceTime(
9464*d9f75844SAndroid Build Coastguard Worker TimeDelta::Seconds(1) *
9465*d9f75844SAndroid Build Coastguard Worker FrameCadenceAdapterInterface::kOnDiscardedFrameRefreshFramePeriod /
9466*d9f75844SAndroid Build Coastguard Worker kMaxFps);
9467*d9f75844SAndroid Build Coastguard Worker }
9468*d9f75844SAndroid Build Coastguard Worker
9469*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
9470