Extend LibvpxInterface with VP9 support and use it from LibvpxVp9Encoder

Bug: webrtc:12274
Change-Id: I7a66a91f6a21ba482347af3c8af53544f9eb2269
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196900
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32822}
This commit is contained in:
Erik Språng
2020-12-13 14:50:59 +01:00
committed by Commit Bot
parent 9325d343e5
commit cc02721090
4 changed files with 287 additions and 56 deletions

View File

@ -93,17 +93,45 @@ class LibvpxFacade : public LibvpxInterface {
return vpx_codec_control(ctx, VP8E_SET_ARNR_MAXFRAMES, param);
case VP8E_SET_ARNR_STRENGTH:
return vpx_codec_control(ctx, VP8E_SET_ARNR_STRENGTH, param);
case VP8E_SET_ARNR_TYPE:
RTC_NOTREACHED() << "VP8E_SET_ARNR_TYPE is deprecated.";
return VPX_CODEC_UNSUP_FEATURE;
case VP8E_SET_CQ_LEVEL:
return vpx_codec_control(ctx, VP8E_SET_CQ_LEVEL, param);
case VP8E_SET_MAX_INTRA_BITRATE_PCT:
return vpx_codec_control(ctx, VP8E_SET_MAX_INTRA_BITRATE_PCT, param);
case VP9E_SET_MAX_INTER_BITRATE_PCT:
return vpx_codec_control(ctx, VP9E_SET_MAX_INTER_BITRATE_PCT, param);
case VP8E_SET_GF_CBR_BOOST_PCT:
return vpx_codec_control(ctx, VP8E_SET_GF_CBR_BOOST_PCT, param);
case VP8E_SET_SCREEN_CONTENT_MODE:
return vpx_codec_control(ctx, VP8E_SET_SCREEN_CONTENT_MODE, param);
case VP9E_SET_GF_CBR_BOOST_PCT:
return vpx_codec_control(ctx, VP9E_SET_GF_CBR_BOOST_PCT, param);
case VP9E_SET_LOSSLESS:
return vpx_codec_control(ctx, VP9E_SET_LOSSLESS, param);
case VP9E_SET_FRAME_PARALLEL_DECODING:
return vpx_codec_control(ctx, VP9E_SET_FRAME_PARALLEL_DECODING, param);
case VP9E_SET_AQ_MODE:
return vpx_codec_control(ctx, VP9E_SET_AQ_MODE, param);
case VP9E_SET_FRAME_PERIODIC_BOOST:
return vpx_codec_control(ctx, VP9E_SET_FRAME_PERIODIC_BOOST, param);
case VP9E_SET_NOISE_SENSITIVITY:
return vpx_codec_control(ctx, VP9E_SET_NOISE_SENSITIVITY, param);
case VP9E_SET_MIN_GF_INTERVAL:
return vpx_codec_control(ctx, VP9E_SET_MIN_GF_INTERVAL, param);
case VP9E_SET_MAX_GF_INTERVAL:
return vpx_codec_control(ctx, VP9E_SET_MAX_GF_INTERVAL, param);
case VP9E_SET_TARGET_LEVEL:
return vpx_codec_control(ctx, VP9E_SET_TARGET_LEVEL, param);
case VP9E_SET_ROW_MT:
return vpx_codec_control(ctx, VP9E_SET_ROW_MT, param);
case VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST:
return vpx_codec_control(ctx, VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST,
param);
case VP9E_SET_SVC_INTER_LAYER_PRED:
return vpx_codec_control(ctx, VP9E_SET_SVC_INTER_LAYER_PRED, param);
case VP9E_SET_SVC_GF_TEMPORAL_REF:
return vpx_codec_control(ctx, VP9E_SET_SVC_GF_TEMPORAL_REF, param);
case VP9E_SET_POSTENCODE_DROP:
return vpx_codec_control(ctx, VP9E_SET_POSTENCODE_DROP, param);
default:
RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
}
@ -118,14 +146,41 @@ class LibvpxFacade : public LibvpxInterface {
return vpx_codec_control(ctx, VP8E_SET_FRAME_FLAGS, param);
case VP8E_SET_TEMPORAL_LAYER_ID:
return vpx_codec_control(ctx, VP8E_SET_TEMPORAL_LAYER_ID, param);
case VP9E_SET_SVC:
return vpx_codec_control(ctx, VP9E_SET_SVC, param);
case VP8E_SET_CPUUSED:
return vpx_codec_control(ctx, VP8E_SET_CPUUSED, param);
case VP8E_SET_TOKEN_PARTITIONS:
return vpx_codec_control(ctx, VP8E_SET_TOKEN_PARTITIONS, param);
case VP8E_SET_TUNING:
return vpx_codec_control(ctx, VP8E_SET_TUNING, param);
case VP9E_SET_TILE_COLUMNS:
return vpx_codec_control(ctx, VP9E_SET_TILE_COLUMNS, param);
case VP9E_SET_TILE_ROWS:
return vpx_codec_control(ctx, VP9E_SET_TILE_ROWS, param);
case VP9E_SET_TPL:
return vpx_codec_control(ctx, VP9E_SET_TPL, param);
case VP9E_SET_ALT_REF_AQ:
return vpx_codec_control(ctx, VP9E_SET_ALT_REF_AQ, param);
case VP9E_SET_TUNE_CONTENT:
return vpx_codec_control(ctx, VP9E_SET_TUNE_CONTENT, param);
case VP9E_SET_COLOR_SPACE:
return vpx_codec_control(ctx, VP9E_SET_COLOR_SPACE, param);
case VP9E_SET_COLOR_RANGE:
return vpx_codec_control(ctx, VP9E_SET_COLOR_RANGE, param);
case VP9E_SET_DELTA_Q_UV:
return vpx_codec_control(ctx, VP9E_SET_DELTA_Q_UV, param);
case VP9E_SET_DISABLE_OVERSHOOT_MAXQ_CBR:
return vpx_codec_control(ctx, VP9E_SET_DISABLE_OVERSHOOT_MAXQ_CBR,
param);
case VP9E_SET_DISABLE_LOOPFILTER:
return vpx_codec_control(ctx, VP9E_SET_DISABLE_LOOPFILTER, param);
default:
if (param >= 0) {
// Might be intended for uint32_t but int literal used, try fallback.
return codec_control(ctx, ctrl_id, static_cast<uint32_t>(param));
}
RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
}
return VPX_CODEC_ERROR;
@ -139,6 +194,10 @@ class LibvpxFacade : public LibvpxInterface {
return vpx_codec_control(ctx, VP8E_GET_LAST_QUANTIZER, param);
case VP8E_GET_LAST_QUANTIZER_64:
return vpx_codec_control(ctx, VP8E_GET_LAST_QUANTIZER_64, param);
case VP9E_SET_RENDER_SIZE:
return vpx_codec_control(ctx, VP9E_SET_RENDER_SIZE, param);
case VP9E_GET_LEVEL:
return vpx_codec_control(ctx, VP9E_GET_LEVEL, param);
default:
RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
}
@ -151,6 +210,8 @@ class LibvpxFacade : public LibvpxInterface {
switch (ctrl_id) {
case VP8E_SET_ROI_MAP:
return vpx_codec_control(ctx, VP8E_SET_ROI_MAP, param);
case VP9E_SET_ROI_MAP:
return vpx_codec_control(ctx, VP9E_SET_ROI_MAP, param);
default:
RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
}
@ -163,6 +224,8 @@ class LibvpxFacade : public LibvpxInterface {
switch (ctrl_id) {
case VP8E_SET_ACTIVEMAP:
return vpx_codec_control(ctx, VP8E_SET_ACTIVEMAP, param);
case VP9E_GET_ACTIVEMAP:
return vpx_codec_control(ctx, VP8E_SET_ACTIVEMAP, param);
default:
RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
}
@ -181,6 +244,98 @@ class LibvpxFacade : public LibvpxInterface {
return VPX_CODEC_ERROR;
}
vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_svc_extra_cfg_t* param) const override {
switch (ctrl_id) {
case VP9E_SET_SVC_PARAMETERS:
return vpx_codec_control_(ctx, VP9E_SET_SVC_PARAMETERS, param);
default:
RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
}
return VPX_CODEC_ERROR;
}
vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_svc_frame_drop_t* param) const override {
switch (ctrl_id) {
case VP9E_SET_SVC_FRAME_DROP_LAYER:
return vpx_codec_control_(ctx, VP9E_SET_SVC_FRAME_DROP_LAYER, param);
default:
RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
}
return VPX_CODEC_ERROR;
}
vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
void* param) const override {
switch (ctrl_id) {
case VP9E_SET_SVC_PARAMETERS:
return vpx_codec_control_(ctx, VP9E_SET_SVC_PARAMETERS, param);
case VP9E_REGISTER_CX_CALLBACK:
return vpx_codec_control_(ctx, VP9E_REGISTER_CX_CALLBACK, param);
default:
RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
}
return VPX_CODEC_ERROR;
}
vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_svc_layer_id_t* param) const override {
switch (ctrl_id) {
case VP9E_SET_SVC_LAYER_ID:
return vpx_codec_control_(ctx, VP9E_SET_SVC_LAYER_ID, param);
case VP9E_GET_SVC_LAYER_ID:
return vpx_codec_control_(ctx, VP9E_GET_SVC_LAYER_ID, param);
default:
RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
}
return VPX_CODEC_ERROR;
}
vpx_codec_err_t codec_control(
vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_svc_ref_frame_config_t* param) const override {
switch (ctrl_id) {
case VP9E_SET_SVC_REF_FRAME_CONFIG:
return vpx_codec_control_(ctx, VP9E_SET_SVC_REF_FRAME_CONFIG, param);
case VP9E_GET_SVC_REF_FRAME_CONFIG:
return vpx_codec_control_(ctx, VP9E_GET_SVC_REF_FRAME_CONFIG, param);
default:
RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
}
return VPX_CODEC_ERROR;
}
vpx_codec_err_t codec_control(
vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_svc_spatial_layer_sync_t* param) const override {
switch (ctrl_id) {
case VP9E_SET_SVC_SPATIAL_LAYER_SYNC:
return vpx_codec_control_(ctx, VP9E_SET_SVC_SPATIAL_LAYER_SYNC, param);
default:
RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
}
return VPX_CODEC_ERROR;
}
vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_rc_funcs_t* param) const override {
switch (ctrl_id) {
case VP9E_SET_EXTERNAL_RATE_CONTROL:
return vpx_codec_control_(ctx, VP9E_SET_EXTERNAL_RATE_CONTROL, param);
default:
RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
}
return VPX_CODEC_ERROR;
}
vpx_codec_err_t codec_encode(vpx_codec_ctx_t* ctx,
const vpx_image_t* img,
vpx_codec_pts_t pts,
@ -199,6 +354,14 @@ class LibvpxFacade : public LibvpxInterface {
const char* codec_error_detail(vpx_codec_ctx_t* ctx) const override {
return ::vpx_codec_error_detail(ctx);
}
const char* codec_error(vpx_codec_ctx_t* ctx) const override {
return ::vpx_codec_error(ctx);
}
const char* codec_err_to_string(vpx_codec_err_t err) const override {
return ::vpx_codec_err_to_string(err);
}
};
} // namespace

View File

@ -81,7 +81,29 @@ class LibvpxInterface {
virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_scaling_mode* param) const = 0;
virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_svc_extra_cfg_t* param) const = 0;
virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_svc_frame_drop_t* param) const = 0;
virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
void* param) const = 0;
virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_svc_layer_id_t* param) const = 0;
virtual vpx_codec_err_t codec_control(
vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_svc_ref_frame_config_t* param) const = 0;
virtual vpx_codec_err_t codec_control(
vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_svc_spatial_layer_sync_t* param) const = 0;
virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_rc_funcs_t* param) const = 0;
virtual vpx_codec_err_t codec_encode(vpx_codec_ctx_t* ctx,
const vpx_image_t* img,
vpx_codec_pts_t pts,
@ -94,6 +116,8 @@ class LibvpxInterface {
vpx_codec_iter_t* iter) const = 0;
virtual const char* codec_error_detail(vpx_codec_ctx_t* ctx) const = 0;
virtual const char* codec_error(vpx_codec_ctx_t* ctx) const = 0;
virtual const char* codec_err_to_string(vpx_codec_err_t err) const = 0;
// Returns interface wrapping the actual libvpx functions.
static std::unique_ptr<LibvpxInterface> Create();

View File

@ -86,6 +86,38 @@ class MockLibvpxInterface : public LibvpxInterface {
codec_control,
(vpx_codec_ctx_t*, vp8e_enc_control_id, vpx_scaling_mode*),
(const, override));
MOCK_METHOD(vpx_codec_err_t,
codec_control,
(vpx_codec_ctx_t*, vp8e_enc_control_id, vpx_svc_extra_cfg_t*),
(const, override));
MOCK_METHOD(vpx_codec_err_t,
codec_control,
(vpx_codec_ctx_t*, vp8e_enc_control_id, vpx_svc_frame_drop_t*),
(const, override));
MOCK_METHOD(vpx_codec_err_t,
codec_control,
(vpx_codec_ctx_t*, vp8e_enc_control_id, void*),
(const, override));
MOCK_METHOD(vpx_codec_err_t,
codec_control,
(vpx_codec_ctx_t*, vp8e_enc_control_id, vpx_svc_layer_id_t*),
(const, override));
MOCK_METHOD(vpx_codec_err_t,
codec_control,
(vpx_codec_ctx_t*,
vp8e_enc_control_id,
vpx_svc_ref_frame_config_t*),
(const, override));
MOCK_METHOD(vpx_codec_err_t,
codec_control,
(vpx_codec_ctx_t*,
vp8e_enc_control_id,
vpx_svc_spatial_layer_sync_t*),
(const, override));
MOCK_METHOD(vpx_codec_err_t,
codec_control,
(vpx_codec_ctx_t*, vp8e_enc_control_id, vpx_rc_funcs_t*),
(const, override));
MOCK_METHOD(vpx_codec_err_t,
codec_encode,
(vpx_codec_ctx_t*,
@ -103,6 +135,11 @@ class MockLibvpxInterface : public LibvpxInterface {
codec_error_detail,
(vpx_codec_ctx_t*),
(const, override));
MOCK_METHOD(const char*, codec_error, (vpx_codec_ctx_t*), (const, override));
MOCK_METHOD(const char*,
codec_err_to_string,
(vpx_codec_err_t),
(const, override));
};
} // namespace webrtc

View File

@ -257,7 +257,7 @@ int LibvpxVp9Encoder::Release() {
if (encoder_ != nullptr) {
if (inited_) {
if (vpx_codec_destroy(encoder_)) {
if (libvpx_->codec_destroy(encoder_)) {
ret_val = WEBRTC_VIDEO_CODEC_MEMORY;
}
}
@ -269,7 +269,7 @@ int LibvpxVp9Encoder::Release() {
config_ = nullptr;
}
if (raw_ != nullptr) {
vpx_img_free(raw_);
libvpx_->img_free(raw_);
raw_ = nullptr;
}
inited_ = false;
@ -501,7 +501,7 @@ int LibvpxVp9Encoder::InitEncode(const VideoCodec* inst,
is_svc_ = (num_spatial_layers_ > 1 || num_temporal_layers_ > 1);
// Populate encoder configuration with default values.
if (vpx_codec_enc_config_default(vpx_codec_vp9_cx(), config_, 0)) {
if (libvpx_->codec_enc_config_default(vpx_codec_vp9_cx(), config_, 0)) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
@ -532,8 +532,8 @@ int LibvpxVp9Encoder::InitEncode(const VideoCodec* inst,
// Creating a wrapper to the image - setting image data to nullptr. Actual
// pointer will be set in encode. Setting align to 1, as it is meaningless
// (actual memory is not allocated).
raw_ =
vpx_img_wrap(nullptr, img_fmt, codec_.width, codec_.height, 1, nullptr);
raw_ = libvpx_->img_wrap(nullptr, img_fmt, codec_.width, codec_.height, 1,
nullptr);
raw_->bit_depth = bits_for_storage;
config_->g_w = codec_.width;
@ -728,11 +728,11 @@ int LibvpxVp9Encoder::InitAndSetControlSettings(const VideoCodec* inst) {
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
}
const vpx_codec_err_t rv = vpx_codec_enc_init(
const vpx_codec_err_t rv = libvpx_->codec_enc_init(
encoder_, vpx_codec_vp9_cx(), config_,
config_->g_bit_depth == VPX_BITS_8 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH);
if (rv != VPX_CODEC_OK) {
RTC_LOG(LS_ERROR) << "Init error: " << vpx_codec_err_to_string(rv);
RTC_LOG(LS_ERROR) << "Init error: " << libvpx_->codec_err_to_string(rv);
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
}
@ -748,20 +748,20 @@ int LibvpxVp9Encoder::InitAndSetControlSettings(const VideoCodec* inst) {
}
}
vpx_codec_control(encoder_, VP8E_SET_MAX_INTRA_BITRATE_PCT,
libvpx_->codec_control(encoder_, VP8E_SET_MAX_INTRA_BITRATE_PCT,
rc_max_intra_target_);
vpx_codec_control(encoder_, VP9E_SET_AQ_MODE,
libvpx_->codec_control(encoder_, VP9E_SET_AQ_MODE,
inst->VP9().adaptiveQpMode ? 3 : 0);
vpx_codec_control(encoder_, VP9E_SET_FRAME_PARALLEL_DECODING, 0);
vpx_codec_control(encoder_, VP9E_SET_SVC_GF_TEMPORAL_REF, 0);
libvpx_->codec_control(encoder_, VP9E_SET_FRAME_PARALLEL_DECODING, 0);
libvpx_->codec_control(encoder_, VP9E_SET_SVC_GF_TEMPORAL_REF, 0);
if (is_svc_) {
vpx_codec_control(encoder_, VP9E_SET_SVC, 1);
vpx_codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, &svc_params_);
libvpx_->codec_control(encoder_, VP9E_SET_SVC, 1);
libvpx_->codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, &svc_params_);
}
if (!performance_flags_.use_per_layer_speed) {
vpx_codec_control(
libvpx_->codec_control(
encoder_, VP8E_SET_CPUUSED,
performance_flags_by_spatial_index_.rbegin()->base_layer_speed);
}
@ -769,13 +769,13 @@ int LibvpxVp9Encoder::InitAndSetControlSettings(const VideoCodec* inst) {
if (num_spatial_layers_ > 1) {
switch (inter_layer_pred_) {
case InterLayerPredMode::kOn:
vpx_codec_control(encoder_, VP9E_SET_SVC_INTER_LAYER_PRED, 0);
libvpx_->codec_control(encoder_, VP9E_SET_SVC_INTER_LAYER_PRED, 0);
break;
case InterLayerPredMode::kOff:
vpx_codec_control(encoder_, VP9E_SET_SVC_INTER_LAYER_PRED, 1);
libvpx_->codec_control(encoder_, VP9E_SET_SVC_INTER_LAYER_PRED, 1);
break;
case InterLayerPredMode::kOnKeyPic:
vpx_codec_control(encoder_, VP9E_SET_SVC_INTER_LAYER_PRED, 2);
libvpx_->codec_control(encoder_, VP9E_SET_SVC_INTER_LAYER_PRED, 2);
break;
default:
RTC_NOTREACHED();
@ -812,7 +812,7 @@ int LibvpxVp9Encoder::InitAndSetControlSettings(const VideoCodec* inst) {
svc_drop_frame_.framedrop_thresh[i] = config_->rc_dropframe_thresh;
}
}
vpx_codec_control(encoder_, VP9E_SET_SVC_FRAME_DROP_LAYER,
libvpx_->codec_control(encoder_, VP9E_SET_SVC_FRAME_DROP_LAYER,
&svc_drop_frame_);
}
@ -820,32 +820,33 @@ int LibvpxVp9Encoder::InitAndSetControlSettings(const VideoCodec* inst) {
vpx_codec_priv_output_cx_pkt_cb_pair_t cbp = {
LibvpxVp9Encoder::EncoderOutputCodedPacketCallback,
reinterpret_cast<void*>(this)};
vpx_codec_control(encoder_, VP9E_REGISTER_CX_CALLBACK,
libvpx_->codec_control(encoder_, VP9E_REGISTER_CX_CALLBACK,
reinterpret_cast<void*>(&cbp));
// Control function to set the number of column tiles in encoding a frame, in
// log2 unit: e.g., 0 = 1 tile column, 1 = 2 tile columns, 2 = 4 tile columns.
// The number tile columns will be capped by the encoder based on image size
// (minimum width of tile column is 256 pixels, maximum is 4096).
vpx_codec_control(encoder_, VP9E_SET_TILE_COLUMNS, (config_->g_threads >> 1));
libvpx_->codec_control(encoder_, VP9E_SET_TILE_COLUMNS,
static_cast<int>((config_->g_threads >> 1)));
// Turn on row-based multithreading.
vpx_codec_control(encoder_, VP9E_SET_ROW_MT, 1);
libvpx_->codec_control(encoder_, VP9E_SET_ROW_MT, 1);
#if !defined(WEBRTC_ARCH_ARM) && !defined(WEBRTC_ARCH_ARM64) && \
!defined(ANDROID)
// Do not enable the denoiser on ARM since optimization is pending.
// Denoiser is on by default on other platforms.
vpx_codec_control(encoder_, VP9E_SET_NOISE_SENSITIVITY,
libvpx_->codec_control(encoder_, VP9E_SET_NOISE_SENSITIVITY,
inst->VP9().denoisingOn ? 1 : 0);
#endif
if (codec_.mode == VideoCodecMode::kScreensharing) {
// Adjust internal parameters to screen content.
vpx_codec_control(encoder_, VP9E_SET_TUNE_CONTENT, 1);
libvpx_->codec_control(encoder_, VP9E_SET_TUNE_CONTENT, 1);
}
// Enable encoder skip of static/low content blocks.
vpx_codec_control(encoder_, VP8E_SET_STATIC_THRESHOLD, 1);
libvpx_->codec_control(encoder_, VP8E_SET_STATIC_THRESHOLD, 1);
inited_ = true;
config_changed_ = true;
return WEBRTC_VIDEO_CODEC_OK;
@ -992,20 +993,20 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image,
}
}
if (speed_updated) {
vpx_codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, &svc_params_);
libvpx_->codec_control(encoder_, VP9E_SET_SVC_PARAMETERS, &svc_params_);
}
}
vpx_codec_control(encoder_, VP9E_SET_SVC_LAYER_ID, &layer_id);
libvpx_->codec_control(encoder_, VP9E_SET_SVC_LAYER_ID, &layer_id);
if (num_spatial_layers_ > 1) {
// Update frame dropping settings as they may change on per-frame basis.
vpx_codec_control(encoder_, VP9E_SET_SVC_FRAME_DROP_LAYER,
libvpx_->codec_control(encoder_, VP9E_SET_SVC_FRAME_DROP_LAYER,
&svc_drop_frame_);
}
if (config_changed_) {
if (vpx_codec_enc_config_set(encoder_, config_)) {
if (libvpx_->codec_enc_config_set(encoder_, config_)) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
@ -1022,7 +1023,7 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image,
std::prev(performance_flags_.settings_by_resolution.lower_bound(
width * height))
->second.base_layer_speed;
vpx_codec_control(encoder_, VP8E_SET_CPUUSED, speed);
libvpx_->codec_control(encoder_, VP8E_SET_CPUUSED, speed);
break;
}
}
@ -1111,7 +1112,8 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image,
if (svc_controller_) {
vpx_svc_ref_frame_config_t ref_config = Vp9References(layer_frames_);
vpx_codec_control(encoder_, VP9E_SET_SVC_REF_FRAME_CONFIG, &ref_config);
libvpx_->codec_control(encoder_, VP9E_SET_SVC_REF_FRAME_CONFIG,
&ref_config);
} else if (external_ref_control_) {
vpx_svc_ref_frame_config_t ref_config =
SetReferences(force_key_frame_, layer_id.spatial_layer_id);
@ -1124,7 +1126,8 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image,
}
}
vpx_codec_control(encoder_, VP9E_SET_SVC_REF_FRAME_CONFIG, &ref_config);
libvpx_->codec_control(encoder_, VP9E_SET_SVC_REF_FRAME_CONFIG,
&ref_config);
}
first_frame_in_picture_ = true;
@ -1144,14 +1147,14 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image,
.GetTargetRate())
: codec_.maxFramerate;
uint32_t duration = static_cast<uint32_t>(90000 / target_framerate_fps);
const vpx_codec_err_t rv = vpx_codec_encode(encoder_, raw_, timestamp_,
duration, flags, VPX_DL_REALTIME);
const vpx_codec_err_t rv = libvpx_->codec_encode(
encoder_, raw_, timestamp_, duration, flags, VPX_DL_REALTIME);
if (rv != VPX_CODEC_OK) {
RTC_LOG(LS_ERROR) << "Encoding error: " << vpx_codec_err_to_string(rv)
RTC_LOG(LS_ERROR) << "Encoding error: " << libvpx_->codec_err_to_string(rv)
<< "\n"
"Details: "
<< vpx_codec_error(encoder_) << "\n"
<< vpx_codec_error_detail(encoder_);
<< libvpx_->codec_error(encoder_) << "\n"
<< libvpx_->codec_error_detail(encoder_);
return WEBRTC_VIDEO_CODEC_ERROR;
}
timestamp_ += duration;
@ -1182,7 +1185,7 @@ void LibvpxVp9Encoder::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
}
vpx_svc_layer_id_t layer_id = {0};
vpx_codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
libvpx_->codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
// Can't have keyframe with non-zero temporal layer.
RTC_DCHECK(pics_since_key_ != 0 || layer_id.temporal_layer_id == 0);
@ -1310,7 +1313,7 @@ void LibvpxVp9Encoder::FillReferenceIndices(const vpx_codec_cx_pkt& pkt,
const bool inter_layer_predicted,
CodecSpecificInfoVP9* vp9_info) {
vpx_svc_layer_id_t layer_id = {0};
vpx_codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
libvpx_->codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
const bool is_key_frame =
(pkt.data.frame.flags & VPX_FRAME_IS_KEY) ? true : false;
@ -1319,7 +1322,8 @@ void LibvpxVp9Encoder::FillReferenceIndices(const vpx_codec_cx_pkt& pkt,
if (is_svc_) {
vpx_svc_ref_frame_config_t enc_layer_conf = {{0}};
vpx_codec_control(encoder_, VP9E_GET_SVC_REF_FRAME_CONFIG, &enc_layer_conf);
libvpx_->codec_control(encoder_, VP9E_GET_SVC_REF_FRAME_CONFIG,
&enc_layer_conf);
int ref_buf_flags = 0;
if (enc_layer_conf.reference_last[layer_id.spatial_layer_id]) {
@ -1427,14 +1431,15 @@ void LibvpxVp9Encoder::FillReferenceIndices(const vpx_codec_cx_pkt& pkt,
void LibvpxVp9Encoder::UpdateReferenceBuffers(const vpx_codec_cx_pkt& pkt,
const size_t pic_num) {
vpx_svc_layer_id_t layer_id = {0};
vpx_codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
libvpx_->codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
RefFrameBuffer frame_buf(pic_num, layer_id.spatial_layer_id,
layer_id.temporal_layer_id);
if (is_svc_) {
vpx_svc_ref_frame_config_t enc_layer_conf = {{0}};
vpx_codec_control(encoder_, VP9E_GET_SVC_REF_FRAME_CONFIG, &enc_layer_conf);
libvpx_->codec_control(encoder_, VP9E_GET_SVC_REF_FRAME_CONFIG,
&enc_layer_conf);
const int update_buffer_slot =
enc_layer_conf.update_buffer_slot[layer_id.spatial_layer_id];
@ -1567,7 +1572,7 @@ int LibvpxVp9Encoder::GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt) {
}
vpx_svc_layer_id_t layer_id = {0};
vpx_codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
libvpx_->codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
if (layer_buffering_) {
// Deliver buffered low spatial layer frame.
@ -1607,7 +1612,7 @@ int LibvpxVp9Encoder::GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt) {
encoded_image_._encodedWidth =
pkt->data.frame.width[layer_id.spatial_layer_id];
int qp = -1;
vpx_codec_control(encoder_, VP8E_GET_LAST_QUANTIZER, &qp);
libvpx_->codec_control(encoder_, VP8E_GET_LAST_QUANTIZER, &qp);
encoded_image_.qp_ = qp;
if (!layer_buffering_) {
@ -1863,12 +1868,14 @@ LibvpxVp9Encoder::GetDefaultPerformanceFlags() {
void LibvpxVp9Encoder::MaybeRewrapRawWithFormat(const vpx_img_fmt fmt) {
if (!raw_) {
raw_ = vpx_img_wrap(nullptr, fmt, codec_.width, codec_.height, 1, nullptr);
raw_ = libvpx_->img_wrap(nullptr, fmt, codec_.width, codec_.height, 1,
nullptr);
} else if (raw_->fmt != fmt) {
RTC_LOG(INFO) << "Switching VP9 encoder pixel format to "
<< (fmt == VPX_IMG_FMT_NV12 ? "NV12" : "I420");
vpx_img_free(raw_);
raw_ = vpx_img_wrap(nullptr, fmt, codec_.width, codec_.height, 1, nullptr);
libvpx_->img_free(raw_);
raw_ = libvpx_->img_wrap(nullptr, fmt, codec_.width, codec_.height, 1,
nullptr);
}
// else no-op since the image is already in the right format.
}