Dynamic resolution change for VP8 HW encode.
Off by default for now.
BUG=
R=glaznev@webrtc.org, stefan@webrtc.org
TBR=mflodman@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/45849004
Cr-Commit-Position: refs/heads/master@{#9045}
diff --git a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
index 081387e..00e6a38 100644
--- a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
+++ b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
@@ -34,6 +34,7 @@
#include "webrtc/base/logging.h"
#include "webrtc/base/thread.h"
#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
+#include "webrtc/modules/video_coding/utility/include/quality_scaler.h"
#include "webrtc/system_wrappers/interface/logcat_trace_context.h"
#include "third_party/libyuv/include/libyuv/convert.h"
#include "third_party/libyuv/include/libyuv/convert_from.h"
@@ -96,6 +97,8 @@
// rtc::MessageHandler implementation.
void OnMessage(rtc::Message* msg) override;
+ void OnDroppedFrame() override;
+
private:
// CHECK-fail if not running on |codec_thread_|.
void CheckOnCodecThread();
@@ -171,7 +174,6 @@
int frames_received_; // Number of frames received by encoder.
int frames_encoded_; // Number of frames encoded by encoder.
int frames_dropped_; // Number of frames dropped by encoder.
- int frames_resolution_update_; // Number of frames with new codec resolution.
int frames_in_queue_; // Number of frames in encoder queue.
int64_t start_time_ms_; // Start time for statistics.
int current_frames_; // Number of frames in the current statistics interval.
@@ -193,6 +195,11 @@
bool drop_next_input_frame_;
// Global references; must be deleted in Release().
std::vector<jobject> input_buffers_;
+ scoped_ptr<webrtc::QualityScaler> quality_scaler_;
+ // Target frame size in bytes.
+ int target_framesize_;
+ // Dynamic resolution change, off by default.
+ bool scale_;
};
MediaCodecVideoEncoder::~MediaCodecVideoEncoder() {
@@ -207,6 +214,7 @@
inited_(false),
picture_id_(0),
codec_thread_(new Thread()),
+ quality_scaler_(new webrtc::QualityScaler()),
j_media_codec_video_encoder_class_(
jni,
FindClass(jni, "org/webrtc/MediaCodecVideoEncoder")),
@@ -270,6 +278,8 @@
const webrtc::VideoCodec* codec_settings,
int32_t /* number_of_cores */,
size_t /* max_payload_size */) {
+ const int kMinWidth = 320;
+ const int kMinHeight = 180;
if (codec_settings == NULL) {
ALOGE("NULL VideoCodec instance");
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
@@ -279,6 +289,16 @@
codec_settings->codecType << " for " << codecType_;
ALOGD("InitEncode request");
+ scale_ = false;
+ quality_scaler_->Init(0);
+ quality_scaler_->SetMinResolution(kMinWidth, kMinHeight);
+ quality_scaler_->ReportFramerate(codec_settings->maxFramerate);
+ if (codec_settings->maxFramerate > 0) {
+ target_framesize_ = codec_settings->startBitrate * 1000 /
+ codec_settings->maxFramerate / 8;
+ } else {
+ target_framesize_ = 0;
+ }
return codec_thread_->Invoke<int32_t>(
Bind(&MediaCodecVideoEncoder::InitEncodeOnCodecThread,
this,
@@ -317,6 +337,12 @@
int32_t MediaCodecVideoEncoder::SetRates(uint32_t new_bit_rate,
uint32_t frame_rate) {
+ quality_scaler_->ReportFramerate(frame_rate);
+ if (frame_rate > 0) {
+ target_framesize_ = new_bit_rate * 1000 / frame_rate / 8;
+ } else {
+ target_framesize_ = 0;
+ }
return codec_thread_->Invoke<int32_t>(
Bind(&MediaCodecVideoEncoder::SetRatesOnCodecThread,
this,
@@ -384,7 +410,6 @@
frames_received_ = 0;
frames_encoded_ = 0;
frames_dropped_ = 0;
- frames_resolution_update_ = 0;
frames_in_queue_ = 0;
current_timestamp_us_ = 0;
start_time_ms_ = GetCurrentTimeMs();
@@ -472,20 +497,18 @@
}
CHECK(frame_types->size() == 1) << "Unexpected stream count";
- if (frame.width() != width_ || frame.height() != height_) {
- frames_resolution_update_++;
- ALOGD("Unexpected frame resolution change from %d x %d to %d x %d",
- width_, height_, frame.width(), frame.height());
- if (frames_resolution_update_ > 3) {
- // Reset codec if we received more than 3 frames with new resolution.
- width_ = frame.width();
- height_ = frame.height();
- frames_resolution_update_ = 0;
- ResetCodec();
- }
+ const I420VideoFrame& input_frame =
+ (scale_ && codecType_ == kVideoCodecVP8) ?
+ quality_scaler_->GetScaledFrame(frame) : frame;
+
+ if (input_frame.width() != width_ || input_frame.height() != height_) {
+ ALOGD("Frame resolution change from %d x %d to %d x %d",
+ width_, height_, input_frame.width(), input_frame.height());
+ width_ = input_frame.width();
+ height_ = input_frame.height();
+ ResetCodec();
return WEBRTC_VIDEO_CODEC_OK;
}
- frames_resolution_update_ = 0;
bool key_frame = frame_types->front() != webrtc::kDeltaFrame;
@@ -498,6 +521,8 @@
ALOGD("Drop frame - encoder is behind by %d ms. Q size: %d",
encoder_latency_ms, frames_in_queue_);
frames_dropped_++;
+ // Report dropped frame to quality_scaler_.
+ OnDroppedFrame();
return WEBRTC_VIDEO_CODEC_OK;
}
}
@@ -509,6 +534,8 @@
// Video codec falls behind - no input buffer available.
ALOGV("Encoder drop frame - no input buffers available");
frames_dropped_++;
+ // Report dropped frame to quality_scaler_.
+ OnDroppedFrame();
return WEBRTC_VIDEO_CODEC_OK; // TODO(fischman): see webrtc bug 2887.
}
if (j_input_buffer_index == -2) {
@@ -525,9 +552,12 @@
CHECK_EXCEPTION(jni);
CHECK(yuv_buffer) << "Indirect buffer??";
CHECK(!libyuv::ConvertFromI420(
- frame.buffer(webrtc::kYPlane), frame.stride(webrtc::kYPlane),
- frame.buffer(webrtc::kUPlane), frame.stride(webrtc::kUPlane),
- frame.buffer(webrtc::kVPlane), frame.stride(webrtc::kVPlane),
+ input_frame.buffer(webrtc::kYPlane),
+ input_frame.stride(webrtc::kYPlane),
+ input_frame.buffer(webrtc::kUPlane),
+ input_frame.stride(webrtc::kUPlane),
+ input_frame.buffer(webrtc::kVPlane),
+ input_frame.stride(webrtc::kVPlane),
yuv_buffer, width_,
width_, height_,
encoder_fourcc_))
@@ -536,8 +566,8 @@
frames_in_queue_++;
// Save input image timestamps for later output
- timestamps_.push_back(frame.timestamp());
- render_times_ms_.push_back(frame.render_time_ms());
+ timestamps_.push_back(input_frame.timestamp());
+ render_times_ms_.push_back(input_frame.render_time_ms());
frame_rtc_times_ms_.push_back(GetCurrentTimeMs());
bool encode_status = jni->CallBooleanMethod(*j_media_codec_video_encoder_,
@@ -686,6 +716,17 @@
last_input_timestamp_ms_ - last_output_timestamp_ms_,
frame_encoding_time_ms);
+ if (payload_size) {
+ double framesize_deviation = 0.0;
+ if (target_framesize_ > 0) {
+ framesize_deviation =
+ (double)abs((int)payload_size - target_framesize_) /
+ target_framesize_;
+ }
+ quality_scaler_->ReportNormalizedFrameSizeFluctuation(
+ framesize_deviation);
+ }
+
// Calculate and print encoding statistics - every 3 seconds.
frames_encoded_++;
current_frames_++;
@@ -830,6 +871,9 @@
return -1;
}
+void MediaCodecVideoEncoder::OnDroppedFrame() {
+ quality_scaler_->ReportDroppedFrame();
+}
MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() {
JNIEnv* jni = AttachCurrentThreadIfNeeded();
diff --git a/webrtc/modules/video_coding/BUILD.gn b/webrtc/modules/video_coding/BUILD.gn
index 340a203..bf04adf 100644
--- a/webrtc/modules/video_coding/BUILD.gn
+++ b/webrtc/modules/video_coding/BUILD.gn
@@ -94,8 +94,9 @@
sources = [
"utility/frame_dropper.cc",
"utility/include/frame_dropper.h",
+ "utility/include/moving_average.h",
+ "utility/include/quality_scaler.h",
"utility/quality_scaler.cc",
- "utility/quality_scaler.h",
]
configs += [ "../..:common_config" ]
diff --git a/webrtc/modules/video_coding/codecs/i420/main/interface/i420.h b/webrtc/modules/video_coding/codecs/i420/main/interface/i420.h
index f115907..e1a13df 100644
--- a/webrtc/modules/video_coding/codecs/i420/main/interface/i420.h
+++ b/webrtc/modules/video_coding/codecs/i420/main/interface/i420.h
@@ -77,6 +77,8 @@
return WEBRTC_VIDEO_CODEC_OK;
}
+ void OnDroppedFrame() override {}
+
private:
static uint8_t* InsertHeader(uint8_t* buffer, uint16_t width,
uint16_t height);
diff --git a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
index 7ab9f67..aa73569 100644
--- a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
+++ b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
@@ -501,4 +501,8 @@
return !streaminfos_.empty();
}
+void SimulcastEncoderAdapter::OnDroppedFrame() {
+ streaminfos_[0].encoder->OnDroppedFrame();
+}
+
} // namespace webrtc
diff --git a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h
index 430d406..aeaa72a 100644
--- a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h
+++ b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h
@@ -55,6 +55,8 @@
const CodecSpecificInfo* codecSpecificInfo = NULL,
const RTPFragmentationHeader* fragmentation = NULL);
+ void OnDroppedFrame() override;
+
private:
struct StreamInfo {
StreamInfo()
diff --git a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
index 4f3678f..d8ec286 100644
--- a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
+++ b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
@@ -1035,7 +1035,7 @@
if (encoded_images_[0]._length > 0) {
int qp;
vpx_codec_control(&encoders_[0], VP8E_GET_LAST_QUANTIZER_64, &qp);
- quality_scaler_.ReportEncodedFrame(qp);
+ quality_scaler_.ReportNormalizedQP(qp);
} else {
quality_scaler_.ReportDroppedFrame();
}
diff --git a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h
index 2ddae4b..d9c4f4b 100644
--- a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h
+++ b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h
@@ -27,7 +27,7 @@
#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
#include "webrtc/modules/video_coding/codecs/vp8/reference_picture_selection.h"
#include "webrtc/modules/video_coding/utility/include/frame_dropper.h"
-#include "webrtc/modules/video_coding/utility/quality_scaler.h"
+#include "webrtc/modules/video_coding/utility/include/quality_scaler.h"
#include "webrtc/video_frame.h"
namespace webrtc {
@@ -56,6 +56,8 @@
virtual int SetRates(uint32_t new_bitrate_kbit, uint32_t frame_rate);
+ void OnDroppedFrame() override {}
+
private:
void SetupTemporalLayers(int num_streams, int num_temporal_layers,
const VideoCodec& codec);
diff --git a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h
index 019e73e..28b9ecc 100644
--- a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h
+++ b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h
@@ -41,6 +41,8 @@
int SetRates(uint32_t new_bitrate_kbit, uint32_t frame_rate) override;
+ void OnDroppedFrame() override {}
+
private:
// Determine number of encoder threads to use.
int NumberOfThreads(int width, int height, int number_of_cores);
diff --git a/webrtc/modules/video_coding/main/source/generic_encoder.cc b/webrtc/modules/video_coding/main/source/generic_encoder.cc
index 58fdda1..fb51cd3 100644
--- a/webrtc/modules/video_coding/main/source/generic_encoder.cc
+++ b/webrtc/modules/video_coding/main/source/generic_encoder.cc
@@ -197,6 +197,10 @@
return internal_source_;
}
+void VCMGenericEncoder::OnDroppedFrame() {
+ encoder_->OnDroppedFrame();
+}
+
/***************************
* Callback Implementation
***************************/
diff --git a/webrtc/modules/video_coding/main/source/generic_encoder.h b/webrtc/modules/video_coding/main/source/generic_encoder.h
index ce037d1..15fd0c6 100644
--- a/webrtc/modules/video_coding/main/source/generic_encoder.h
+++ b/webrtc/modules/video_coding/main/source/generic_encoder.h
@@ -136,6 +136,8 @@
bool InternalSource() const;
+ void OnDroppedFrame();
+
private:
VideoEncoder* const encoder_;
VideoEncoderRateObserver* const rate_observer_;
diff --git a/webrtc/modules/video_coding/main/source/video_sender.cc b/webrtc/modules/video_coding/main/source/video_sender.cc
index a153ac9..df504cd 100644
--- a/webrtc/modules/video_coding/main/source/video_sender.cc
+++ b/webrtc/modules/video_coding/main/source/video_sender.cc
@@ -17,6 +17,7 @@
#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
#include "webrtc/modules/video_coding/main/source/video_coding_impl.h"
+#include "webrtc/modules/video_coding/utility/include/quality_scaler.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/logging.h"
@@ -346,6 +347,7 @@
return VCM_OK;
}
if (_mediaOpt.DropFrame()) {
+ _encoder->OnDroppedFrame();
return VCM_OK;
}
_mediaOpt.UpdateContentData(contentMetrics);
diff --git a/webrtc/modules/video_coding/utility/include/moving_average.h b/webrtc/modules/video_coding/utility/include/moving_average.h
new file mode 100644
index 0000000..49c42c4
--- /dev/null
+++ b/webrtc/modules/video_coding/utility/include/moving_average.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_VIDEO_CODING_UTILITY_MOVING_AVERAGE_H_
+#define WEBRTC_MODULES_VIDEO_CODING_UTILITY_MOVING_AVERAGE_H_
+
+#include <list>
+
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+template<class T>
+class MovingAverage {
+ public:
+ MovingAverage();
+ void AddSample(T sample);
+ bool GetAverage(size_t num_samples, T* average);
+ void Reset();
+ int size();
+
+ private:
+ T sum_;
+ std::list<T> samples_;
+};
+
+template<class T>
+MovingAverage<T>::MovingAverage() : sum_(static_cast<T>(0)) {
+}
+
+template<class T>
+void MovingAverage<T>::AddSample(T sample) {
+ samples_.push_back(sample);
+ sum_ += sample;
+}
+
+template<class T>
+bool MovingAverage<T>::GetAverage(size_t num_samples, T* avg) {
+ if (num_samples > samples_.size())
+ return false;
+
+ // Remove old samples.
+ while (num_samples < samples_.size()) {
+ sum_ -= samples_.front();
+ samples_.pop_front();
+ }
+
+ *avg = sum_ / static_cast<T>(num_samples);
+ return true;
+}
+
+template<class T>
+void MovingAverage<T>::Reset() {
+ sum_ = static_cast<T>(0);
+ samples_.clear();
+}
+
+template<class T>
+int MovingAverage<T>::size() {
+ return samples_.size();
+}
+
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_VIDEO_CODING_MOVING_AVERAGE_SCALER_H_
diff --git a/webrtc/modules/video_coding/utility/quality_scaler.h b/webrtc/modules/video_coding/utility/include/quality_scaler.h
similarity index 65%
rename from webrtc/modules/video_coding/utility/quality_scaler.h
rename to webrtc/modules/video_coding/utility/include/quality_scaler.h
index 47d6cb1..326d887 100644
--- a/webrtc/modules/video_coding/utility/quality_scaler.h
+++ b/webrtc/modules/video_coding/utility/include/quality_scaler.h
@@ -11,9 +11,8 @@
#ifndef WEBRTC_MODULES_VIDEO_CODING_UTILITY_QUALITY_SCALER_H_
#define WEBRTC_MODULES_VIDEO_CODING_UTILITY_QUALITY_SCALER_H_
-#include <list>
-
#include "webrtc/common_video/libyuv/include/scaler.h"
+#include "webrtc/modules/video_coding/utility/include/moving_average.h"
namespace webrtc {
class QualityScaler {
@@ -25,27 +24,20 @@
QualityScaler();
void Init(int max_qp);
-
+ void SetMinResolution(int min_width, int min_height);
void ReportFramerate(int framerate);
- void ReportEncodedFrame(int qp);
- void ReportDroppedFrame();
+ // Report QP for SW encoder, report framesize fluctuation for HW encoder,
+ // only one of these two functions should be called, framesize fluctuation
+ // is to be used only if qp isn't available.
+ void ReportNormalizedQP(int qp);
+ void ReportNormalizedFrameSizeFluctuation(double framesize_deviation);
+ void ReportDroppedFrame();
+ void Reset(int framerate, int bitrate, int width, int height);
Resolution GetScaledResolution(const I420VideoFrame& frame);
const I420VideoFrame& GetScaledFrame(const I420VideoFrame& frame);
private:
- class MovingAverage {
- public:
- MovingAverage();
- void AddSample(int sample);
- bool GetAverage(size_t num_samples, int* average);
- void Reset();
-
- private:
- int sum_;
- std::list<int> samples_;
- };
-
void AdjustScale(bool up);
void ClearSamples();
@@ -53,11 +45,14 @@
I420VideoFrame scaled_frame_;
size_t num_samples_;
+ int target_framesize_;
int low_qp_threshold_;
- MovingAverage average_qp_;
- MovingAverage framedrop_percent_;
+ MovingAverage<int> framedrop_percent_;
+ MovingAverage<double> frame_quality_;
int downscale_shift_;
+ int min_width_;
+ int min_height_;
};
} // namespace webrtc
diff --git a/webrtc/modules/video_coding/utility/quality_scaler.cc b/webrtc/modules/video_coding/utility/quality_scaler.cc
index 327748d..38b582b 100644
--- a/webrtc/modules/video_coding/utility/quality_scaler.cc
+++ b/webrtc/modules/video_coding/utility/quality_scaler.cc
@@ -7,8 +7,7 @@
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
-
-#include "webrtc/modules/video_coding/utility/quality_scaler.h"
+#include "webrtc/modules/video_coding/utility/include/quality_scaler.h"
namespace webrtc {
@@ -16,25 +15,41 @@
static const int kMeasureSeconds = 5;
static const int kFramedropPercentThreshold = 60;
static const int kLowQpThresholdDenominator = 3;
+static const double kFramesizeFlucThreshold = 0.11;
QualityScaler::QualityScaler()
- : num_samples_(0), low_qp_threshold_(-1), downscale_shift_(0) {
+ : num_samples_(0), low_qp_threshold_(-1), downscale_shift_(0),
+ min_width_(0), min_height_(0) {
}
void QualityScaler::Init(int max_qp) {
ClearSamples();
- downscale_shift_ = 0;
- low_qp_threshold_ = max_qp / kLowQpThresholdDenominator ;
+ low_qp_threshold_ = max_qp / kLowQpThresholdDenominator;
}
+void QualityScaler::SetMinResolution(int min_width, int min_height) {
+ min_width_ = min_width;
+ min_height_ = min_height;
+}
+
+// TODO(jackychen): target_framesize should be calculated from average bitrate
+// in the measured period of time.
+// Report framerate(fps) and target_bitrate(kbit/s) to estimate # of samples
+// and get target_framesize_.
void QualityScaler::ReportFramerate(int framerate) {
num_samples_ = static_cast<size_t>(
kMeasureSeconds * (framerate < kMinFps ? kMinFps : framerate));
}
-void QualityScaler::ReportEncodedFrame(int qp) {
- average_qp_.AddSample(qp);
+void QualityScaler::ReportNormalizedQP(int qp) {
framedrop_percent_.AddSample(0);
+ frame_quality_.AddSample(static_cast<double>(qp) / low_qp_threshold_);
+}
+
+void QualityScaler::ReportNormalizedFrameSizeFluctuation(
+ double framesize_deviation) {
+ framedrop_percent_.AddSample(0);
+ frame_quality_.AddSample(framesize_deviation / kFramesizeFlucThreshold);
}
void QualityScaler::ReportDroppedFrame() {
@@ -43,23 +58,25 @@
QualityScaler::Resolution QualityScaler::GetScaledResolution(
const I420VideoFrame& frame) {
- // Both of these should be set through InitEncode -> Should be set by now.
+ // Should be set through InitEncode -> Should be set by now.
assert(low_qp_threshold_ >= 0);
assert(num_samples_ > 0);
- // Update scale factor.
- int avg;
- if (framedrop_percent_.GetAverage(num_samples_, &avg) &&
- avg >= kFramedropPercentThreshold) {
- AdjustScale(false);
- } else if (average_qp_.GetAverage(num_samples_, &avg) &&
- avg <= low_qp_threshold_) {
- AdjustScale(true);
- }
Resolution res;
res.width = frame.width();
res.height = frame.height();
+ // Update scale factor.
+ int avg_drop;
+ double avg_quality;
+ if (framedrop_percent_.GetAverage(num_samples_, &avg_drop) &&
+ avg_drop >= kFramedropPercentThreshold) {
+ AdjustScale(false);
+ } else if (frame_quality_.GetAverage(num_samples_, &avg_quality) &&
+ avg_quality <= 1.0) {
+ AdjustScale(true);
+ }
+
assert(downscale_shift_ >= 0);
for (int shift = downscale_shift_;
shift > 0 && res.width > 1 && res.height > 1;
@@ -68,6 +85,12 @@
res.height >>= 1;
}
+ // Set this limitation for VP8 HW encoder to avoid crash.
+ if (min_width_ > 0 && res.width * res.height < min_width_ * min_height_) {
+ res.width = min_width_;
+ res.height = min_height_;
+ }
+
return res;
}
@@ -94,37 +117,9 @@
return scaled_frame_;
}
-QualityScaler::MovingAverage::MovingAverage() : sum_(0) {
-}
-
-void QualityScaler::MovingAverage::AddSample(int sample) {
- samples_.push_back(sample);
- sum_ += sample;
-}
-
-bool QualityScaler::MovingAverage::GetAverage(size_t num_samples, int* avg) {
- assert(num_samples > 0);
- if (num_samples > samples_.size())
- return false;
-
- // Remove old samples.
- while (num_samples < samples_.size()) {
- sum_ -= samples_.front();
- samples_.pop_front();
- }
-
- *avg = sum_ / static_cast<int>(num_samples);
- return true;
-}
-
-void QualityScaler::MovingAverage::Reset() {
- sum_ = 0;
- samples_.clear();
-}
-
void QualityScaler::ClearSamples() {
- average_qp_.Reset();
framedrop_percent_.Reset();
+ frame_quality_.Reset();
}
void QualityScaler::AdjustScale(bool up) {
diff --git a/webrtc/modules/video_coding/utility/quality_scaler_unittest.cc b/webrtc/modules/video_coding/utility/quality_scaler_unittest.cc
index 381b959..509b248 100644
--- a/webrtc/modules/video_coding/utility/quality_scaler_unittest.cc
+++ b/webrtc/modules/video_coding/utility/quality_scaler_unittest.cc
@@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
-#include "webrtc/modules/video_coding/utility/quality_scaler.h"
+#include "webrtc/modules/video_coding/utility/include/quality_scaler.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -40,7 +40,7 @@
for (int i = 0; i < kFramerate * kNumSeconds; ++i) {
switch (scale_direction) {
case kScaleUp:
- qs_.ReportEncodedFrame(kLowQp);
+ qs_.ReportNormalizedQP(kLowQp);
break;
case kScaleDown:
qs_.ReportDroppedFrame();
@@ -93,7 +93,7 @@
TEST_F(QualityScalerTest, DownscalesAfterTwoThirdsFramedrop) {
for (int i = 0; i < kFramerate * kNumSeconds / 3; ++i) {
- qs_.ReportEncodedFrame(kNormalQp);
+ qs_.ReportNormalizedQP(kNormalQp);
qs_.ReportDroppedFrame();
qs_.ReportDroppedFrame();
if (qs_.GetScaledResolution(input_frame_).width < input_frame_.width())
@@ -105,7 +105,7 @@
TEST_F(QualityScalerTest, DoesNotDownscaleOnNormalQp) {
for (int i = 0; i < kFramerate * kNumSeconds; ++i) {
- qs_.ReportEncodedFrame(kNormalQp);
+ qs_.ReportNormalizedQP(kNormalQp);
ASSERT_EQ(input_frame_.width(), qs_.GetScaledResolution(input_frame_).width)
<< "Unexpected scale on half framedrop.";
}
@@ -113,7 +113,7 @@
TEST_F(QualityScalerTest, DoesNotDownscaleAfterHalfFramedrop) {
for (int i = 0; i < kFramerate * kNumSeconds / 2; ++i) {
- qs_.ReportEncodedFrame(kNormalQp);
+ qs_.ReportNormalizedQP(kNormalQp);
ASSERT_EQ(input_frame_.width(), qs_.GetScaledResolution(input_frame_).width)
<< "Unexpected scale on half framedrop.";
@@ -153,7 +153,7 @@
// Verify we don't start upscaling after further low use.
for (int i = 0; i < kFramerate * kNumSeconds; ++i) {
- qs_.ReportEncodedFrame(kLowQp);
+ qs_.ReportNormalizedQP(kLowQp);
ExpectOriginalFrame();
}
}
diff --git a/webrtc/modules/video_coding/utility/video_coding_utility.gyp b/webrtc/modules/video_coding/utility/video_coding_utility.gyp
index eccc4da..c3649c6 100644
--- a/webrtc/modules/video_coding/utility/video_coding_utility.gyp
+++ b/webrtc/modules/video_coding/utility/video_coding_utility.gyp
@@ -20,8 +20,9 @@
'sources': [
'frame_dropper.cc',
'include/frame_dropper.h',
+ 'include/moving_average.h',
'quality_scaler.cc',
- 'quality_scaler.h',
+ 'include/quality_scaler.h',
],
},
], # targets
diff --git a/webrtc/video_encoder.h b/webrtc/video_encoder.h
index c933a33..ce2569b 100644
--- a/webrtc/video_encoder.h
+++ b/webrtc/video_encoder.h
@@ -122,6 +122,7 @@
virtual int32_t CodecConfigParameters(uint8_t* /*buffer*/, int32_t /*size*/) {
return -1;
}
+ virtual void OnDroppedFrame() {};
};
} // namespace webrtc