1 /*
2  *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "video/adaptation/quality_scaler_resource.h"
12 
13 #include <utility>
14 
15 #include "rtc_base/checks.h"
16 #include "rtc_base/experiments/balanced_degradation_settings.h"
17 #include "rtc_base/ref_counted_object.h"
18 #include "rtc_base/task_utils/to_queued_task.h"
19 #include "rtc_base/time_utils.h"
20 
21 namespace webrtc {
22 
23 // static
Create()24 rtc::scoped_refptr<QualityScalerResource> QualityScalerResource::Create() {
25   return new rtc::RefCountedObject<QualityScalerResource>();
26 }
27 
QualityScalerResource()28 QualityScalerResource::QualityScalerResource()
29     : VideoStreamEncoderResource("QualityScalerResource"),
30       quality_scaler_(nullptr) {}
31 
~QualityScalerResource()32 QualityScalerResource::~QualityScalerResource() {
33   RTC_DCHECK(!quality_scaler_);
34 }
35 
is_started() const36 bool QualityScalerResource::is_started() const {
37   RTC_DCHECK_RUN_ON(encoder_queue());
38   return quality_scaler_.get();
39 }
40 
StartCheckForOveruse(VideoEncoder::QpThresholds qp_thresholds)41 void QualityScalerResource::StartCheckForOveruse(
42     VideoEncoder::QpThresholds qp_thresholds) {
43   RTC_DCHECK_RUN_ON(encoder_queue());
44   RTC_DCHECK(!is_started());
45   quality_scaler_ =
46       std::make_unique<QualityScaler>(this, std::move(qp_thresholds));
47 }
48 
StopCheckForOveruse()49 void QualityScalerResource::StopCheckForOveruse() {
50   RTC_DCHECK_RUN_ON(encoder_queue());
51   RTC_DCHECK(is_started());
52   // Ensure we have no pending callbacks. This makes it safe to destroy the
53   // QualityScaler and even task queues with tasks in-flight.
54   quality_scaler_.reset();
55 }
56 
SetQpThresholds(VideoEncoder::QpThresholds qp_thresholds)57 void QualityScalerResource::SetQpThresholds(
58     VideoEncoder::QpThresholds qp_thresholds) {
59   RTC_DCHECK_RUN_ON(encoder_queue());
60   RTC_DCHECK(is_started());
61   quality_scaler_->SetQpThresholds(std::move(qp_thresholds));
62 }
63 
QpFastFilterLow()64 bool QualityScalerResource::QpFastFilterLow() {
65   RTC_DCHECK_RUN_ON(encoder_queue());
66   RTC_DCHECK(is_started());
67   return quality_scaler_->QpFastFilterLow();
68 }
69 
OnEncodeCompleted(const EncodedImage & encoded_image,int64_t time_sent_in_us)70 void QualityScalerResource::OnEncodeCompleted(const EncodedImage& encoded_image,
71                                               int64_t time_sent_in_us) {
72   RTC_DCHECK_RUN_ON(encoder_queue());
73   if (quality_scaler_ && encoded_image.qp_ >= 0) {
74     quality_scaler_->ReportQp(encoded_image.qp_, time_sent_in_us);
75   }
76 }
77 
OnFrameDropped(EncodedImageCallback::DropReason reason)78 void QualityScalerResource::OnFrameDropped(
79     EncodedImageCallback::DropReason reason) {
80   RTC_DCHECK_RUN_ON(encoder_queue());
81   if (!quality_scaler_)
82     return;
83   switch (reason) {
84     case EncodedImageCallback::DropReason::kDroppedByMediaOptimizations:
85       quality_scaler_->ReportDroppedFrameByMediaOpt();
86       break;
87     case EncodedImageCallback::DropReason::kDroppedByEncoder:
88       quality_scaler_->ReportDroppedFrameByEncoder();
89       break;
90   }
91 }
92 
OnReportQpUsageHigh()93 void QualityScalerResource::OnReportQpUsageHigh() {
94   OnResourceUsageStateMeasured(ResourceUsageState::kOveruse);
95 }
96 
OnReportQpUsageLow()97 void QualityScalerResource::OnReportQpUsageLow() {
98   OnResourceUsageStateMeasured(ResourceUsageState::kUnderuse);
99 }
100 
101 }  // namespace webrtc
102