Move the QP scaling thresholds to the relevant encoders.
Also provide a new set of thresholds for the VideoToolbox encoder. The new thresholds were experimentally determined to work well on the iPhone 6S, and also adequately on the iPhone 5S. BUG=webrtc:5678 Review-Url: https://codereview.webrtc.org/2309743002 Cr-Commit-Position: refs/heads/master@{#14420}
This commit is contained in:
@ -395,16 +395,9 @@ int32_t MediaCodecVideoEncoder::InitEncode(
|
|||||||
ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled");
|
ALOGD << "Encoder automatic resize " << (scale_ ? "enabled" : "disabled");
|
||||||
|
|
||||||
if (scale_) {
|
if (scale_) {
|
||||||
if (codecType_ == kVideoCodecVP8) {
|
if (codecType_ == kVideoCodecVP8 || codecType_ == kVideoCodecH264) {
|
||||||
quality_scaler_.Init(
|
quality_scaler_.Init(codecType_, codec_settings->startBitrate,
|
||||||
QualityScaler::kLowVp8QpThreshold, QualityScaler::kBadVp8QpThreshold,
|
codec_settings->width, codec_settings->height,
|
||||||
codec_settings->startBitrate, codec_settings->width,
|
|
||||||
codec_settings->height, codec_settings->maxFramerate);
|
|
||||||
} else if (codecType_ == kVideoCodecH264) {
|
|
||||||
quality_scaler_.Init(QualityScaler::kLowH264QpThreshold,
|
|
||||||
QualityScaler::kBadH264QpThreshold,
|
|
||||||
codec_settings->startBitrate, codec_settings->width,
|
|
||||||
codec_settings->height,
|
|
||||||
codec_settings->maxFramerate);
|
codec_settings->maxFramerate);
|
||||||
} else {
|
} else {
|
||||||
// When adding codec support to additional hardware codecs, also configure
|
// When adding codec support to additional hardware codecs, also configure
|
||||||
|
|||||||
@ -213,10 +213,9 @@ int32_t H264EncoderImpl::InitEncode(const VideoCodec* codec_settings,
|
|||||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||||
}
|
}
|
||||||
// TODO(pbos): Base init params on these values before submitting.
|
// TODO(pbos): Base init params on these values before submitting.
|
||||||
quality_scaler_.Init(QualityScaler::kLowH264QpThreshold,
|
quality_scaler_.Init(codec_settings_.codecType, codec_settings_.startBitrate,
|
||||||
QualityScaler::kBadH264QpThreshold,
|
codec_settings_.width, codec_settings_.height,
|
||||||
codec_settings_.startBitrate, codec_settings_.width,
|
codec_settings_.maxFramerate);
|
||||||
codec_settings_.height, codec_settings_.maxFramerate);
|
|
||||||
int video_format = EVideoFormatType::videoFormatI420;
|
int video_format = EVideoFormatType::videoFormatI420;
|
||||||
openh264_encoder_->SetOption(ENCODER_OPTION_DATAFORMAT,
|
openh264_encoder_->SetOption(ENCODER_OPTION_DATAFORMAT,
|
||||||
&video_format);
|
&video_format);
|
||||||
|
|||||||
@ -33,6 +33,10 @@ namespace internal {
|
|||||||
// kVTCompressionPropertyKey_AverageBitRate. The data rate limit is set higher
|
// kVTCompressionPropertyKey_AverageBitRate. The data rate limit is set higher
|
||||||
// than the average bit rate to avoid undershooting the target.
|
// than the average bit rate to avoid undershooting the target.
|
||||||
const float kLimitToAverageBitRateFactor = 1.5f;
|
const float kLimitToAverageBitRateFactor = 1.5f;
|
||||||
|
// These thresholds deviate from the default h264 QP thresholds, as they
|
||||||
|
// have been found to work better on devices that support VideoToolbox
|
||||||
|
const int kLowH264QpThreshold = 28;
|
||||||
|
const int kHighH264QpThreshold = 39;
|
||||||
|
|
||||||
// Convenience function for creating a dictionary.
|
// Convenience function for creating a dictionary.
|
||||||
inline CFDictionaryRef CreateCFDictionary(CFTypeRef* keys,
|
inline CFDictionaryRef CreateCFDictionary(CFTypeRef* keys,
|
||||||
@ -232,8 +236,8 @@ int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings,
|
|||||||
RTC_DCHECK_EQ(codec_settings->codecType, kVideoCodecH264);
|
RTC_DCHECK_EQ(codec_settings->codecType, kVideoCodecH264);
|
||||||
{
|
{
|
||||||
rtc::CritScope lock(&quality_scaler_crit_);
|
rtc::CritScope lock(&quality_scaler_crit_);
|
||||||
quality_scaler_.Init(QualityScaler::kLowH264QpThreshold,
|
quality_scaler_.Init(internal::kLowH264QpThreshold,
|
||||||
QualityScaler::kBadH264QpThreshold,
|
internal::kHighH264QpThreshold,
|
||||||
codec_settings->startBitrate, codec_settings->width,
|
codec_settings->startBitrate, codec_settings->width,
|
||||||
codec_settings->height, codec_settings->maxFramerate);
|
codec_settings->height, codec_settings->maxFramerate);
|
||||||
QualityScaler::Resolution res = quality_scaler_.GetScaledResolution();
|
QualityScaler::Resolution res = quality_scaler_.GetScaledResolution();
|
||||||
|
|||||||
@ -562,9 +562,8 @@ int VP8EncoderImpl::InitEncode(const VideoCodec* inst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rps_.Init();
|
rps_.Init();
|
||||||
quality_scaler_.Init(QualityScaler::kLowVp8QpThreshold,
|
quality_scaler_.Init(codec_.codecType, codec_.startBitrate, codec_.width,
|
||||||
QualityScaler::kBadVp8QpThreshold, codec_.startBitrate,
|
codec_.height, codec_.maxFramerate);
|
||||||
codec_.width, codec_.height, codec_.maxFramerate);
|
|
||||||
|
|
||||||
// Only apply scaling to improve for single-layer streams. The scaling metrics
|
// Only apply scaling to improve for single-layer streams. The scaling metrics
|
||||||
// use frame drops as a signal and is only applicable when we drop frames.
|
// use frame drops as a signal and is only applicable when we drop frames.
|
||||||
|
|||||||
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "webrtc/base/checks.h"
|
||||||
|
|
||||||
// TODO(kthelgason): Some versions of Android have issues with log2.
|
// TODO(kthelgason): Some versions of Android have issues with log2.
|
||||||
// See https://code.google.com/p/android/issues/detail?id=212634 for details
|
// See https://code.google.com/p/android/issues/detail?id=212634 for details
|
||||||
#if defined(WEBRTC_ANDROID)
|
#if defined(WEBRTC_ANDROID)
|
||||||
@ -38,42 +40,54 @@ static const int kVgaBitrateThresholdKbps = 500;
|
|||||||
static const int kVgaNumPixels = 700 * 500; // 640x480
|
static const int kVgaNumPixels = 700 * 500; // 640x480
|
||||||
static const int kQvgaBitrateThresholdKbps = 250;
|
static const int kQvgaBitrateThresholdKbps = 250;
|
||||||
static const int kQvgaNumPixels = 400 * 300; // 320x240
|
static const int kQvgaNumPixels = 400 * 300; // 320x240
|
||||||
|
|
||||||
|
// QP scaling threshold defaults:
|
||||||
|
static const int kLowH264QpThreshold = 24;
|
||||||
|
static const int kHighH264QpThreshold = 37;
|
||||||
|
// QP is obtained from VP8-bitstream for HW, so the QP corresponds to the
|
||||||
|
// bitstream range of [0, 127] and not the user-level range of [0,63].
|
||||||
|
static const int kLowVp8QpThreshold = 29;
|
||||||
|
static const int kHighVp8QpThreshold = 95;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// QP thresholds are chosen to be high enough to be hit in practice when quality
|
|
||||||
// is good, but also low enough to not cause a flip-flop behavior (e.g. going up
|
|
||||||
// in resolution shouldn't give so bad quality that we should go back down).
|
|
||||||
|
|
||||||
const int QualityScaler::kLowVp8QpThreshold = 29;
|
|
||||||
const int QualityScaler::kBadVp8QpThreshold = 95;
|
|
||||||
|
|
||||||
#if defined(WEBRTC_IOS)
|
|
||||||
const int QualityScaler::kLowH264QpThreshold = 32;
|
|
||||||
const int QualityScaler::kBadH264QpThreshold = 42;
|
|
||||||
#else
|
|
||||||
const int QualityScaler::kLowH264QpThreshold = 24;
|
|
||||||
const int QualityScaler::kBadH264QpThreshold = 37;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Default values. Should immediately get set to something more sensible.
|
// Default values. Should immediately get set to something more sensible.
|
||||||
QualityScaler::QualityScaler()
|
QualityScaler::QualityScaler()
|
||||||
: average_qp_(kMeasureSecondsUpscale * 30),
|
: average_qp_(kMeasureSecondsUpscale * 30),
|
||||||
framedrop_percent_(kMeasureSecondsUpscale * 30),
|
framedrop_percent_(kMeasureSecondsUpscale * 30),
|
||||||
low_qp_threshold_(-1) {}
|
low_qp_threshold_(-1) {}
|
||||||
|
|
||||||
|
void QualityScaler::Init(VideoCodecType codec_type,
|
||||||
|
int initial_bitrate_kbps,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int fps) {
|
||||||
|
int low = -1, high = -1;
|
||||||
|
switch (codec_type) {
|
||||||
|
case kVideoCodecH264:
|
||||||
|
low = kLowH264QpThreshold;
|
||||||
|
high = kHighH264QpThreshold;
|
||||||
|
break;
|
||||||
|
case kVideoCodecVP8:
|
||||||
|
low = kLowVp8QpThreshold;
|
||||||
|
high = kHighVp8QpThreshold;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
RTC_NOTREACHED() << "Invalid codec type for QualityScaler.";
|
||||||
|
}
|
||||||
|
Init(low, high, initial_bitrate_kbps, width, height, fps);
|
||||||
|
}
|
||||||
|
|
||||||
void QualityScaler::Init(int low_qp_threshold,
|
void QualityScaler::Init(int low_qp_threshold,
|
||||||
int high_qp_threshold,
|
int high_qp_threshold,
|
||||||
int initial_bitrate_kbps,
|
int initial_bitrate_kbps,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
int fps) {
|
int fps) {
|
||||||
|
ClearSamples();
|
||||||
low_qp_threshold_ = low_qp_threshold;
|
low_qp_threshold_ = low_qp_threshold;
|
||||||
high_qp_threshold_ = high_qp_threshold;
|
high_qp_threshold_ = high_qp_threshold;
|
||||||
downscale_shift_ = 0;
|
downscale_shift_ = 0;
|
||||||
|
|
||||||
fast_rampup_ = true;
|
fast_rampup_ = true;
|
||||||
|
|
||||||
ClearSamples();
|
|
||||||
ReportFramerate(fps);
|
ReportFramerate(fps);
|
||||||
|
|
||||||
const int init_width = width;
|
const int init_width = width;
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#ifndef WEBRTC_MODULES_VIDEO_CODING_UTILITY_QUALITY_SCALER_H_
|
#ifndef WEBRTC_MODULES_VIDEO_CODING_UTILITY_QUALITY_SCALER_H_
|
||||||
#define WEBRTC_MODULES_VIDEO_CODING_UTILITY_QUALITY_SCALER_H_
|
#define WEBRTC_MODULES_VIDEO_CODING_UTILITY_QUALITY_SCALER_H_
|
||||||
|
|
||||||
|
#include "webrtc/common_types.h"
|
||||||
#include "webrtc/common_video/include/i420_buffer_pool.h"
|
#include "webrtc/common_video/include/i420_buffer_pool.h"
|
||||||
#include "webrtc/modules/video_coding/utility/moving_average.h"
|
#include "webrtc/modules/video_coding/utility/moving_average.h"
|
||||||
|
|
||||||
@ -23,6 +24,11 @@ class QualityScaler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
QualityScaler();
|
QualityScaler();
|
||||||
|
void Init(VideoCodecType codec_type,
|
||||||
|
int initial_bitrate_kbps,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int fps);
|
||||||
void Init(int low_qp_threshold,
|
void Init(int low_qp_threshold,
|
||||||
int high_qp_threshold,
|
int high_qp_threshold,
|
||||||
int initial_bitrate_kbps,
|
int initial_bitrate_kbps,
|
||||||
@ -38,15 +44,6 @@ class QualityScaler {
|
|||||||
const rtc::scoped_refptr<VideoFrameBuffer>& frame);
|
const rtc::scoped_refptr<VideoFrameBuffer>& frame);
|
||||||
int downscale_shift() const { return downscale_shift_; }
|
int downscale_shift() const { return downscale_shift_; }
|
||||||
|
|
||||||
// QP is obtained from VP8-bitstream for HW, so the QP corresponds to the
|
|
||||||
// bitstream range of [0, 127] and not the user-level range of [0,63].
|
|
||||||
static const int kLowVp8QpThreshold;
|
|
||||||
static const int kBadVp8QpThreshold;
|
|
||||||
|
|
||||||
// H264 QP is in the range [0, 51].
|
|
||||||
static const int kLowH264QpThreshold;
|
|
||||||
static const int kBadH264QpThreshold;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ClearSamples();
|
void ClearSamples();
|
||||||
void ScaleUp();
|
void ScaleUp();
|
||||||
|
|||||||
Reference in New Issue
Block a user