Hide libvpx vp8 encoder behind an interface and add mock for testing.

Bug: webrtc:9809
Change-Id: I27baa0309511cbd849c09c5d063a64d1fb1fcebf
Reviewed-on: https://webrtc-review.googlesource.com/c/103442
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25005}
This commit is contained in:
Erik Språng
2018-10-04 17:52:36 +02:00
committed by Commit Bot
parent 78cdde3df6
commit 5fbc0e0b33
10 changed files with 468 additions and 58 deletions

View File

@ -23,7 +23,7 @@ namespace webrtc {
// This class provides fallback to SimulcastEncoderAdapter if default VP8Encoder
// doesn't support simulcast for provided settings.
class VP8EncoderSimulcastProxy : public VP8Encoder {
class VP8EncoderSimulcastProxy : public VideoEncoder {
public:
VP8EncoderSimulcastProxy(VideoEncoderFactory* factory,
const SdpVideoFormat& format);

View File

@ -396,6 +396,8 @@ rtc_static_library("webrtc_vp8") {
"codecs/vp8/include/temporal_layers_checker.h",
"codecs/vp8/include/vp8.h",
"codecs/vp8/include/vp8_temporal_layers.h",
"codecs/vp8/libvpx_interface.cc",
"codecs/vp8/libvpx_interface.h",
"codecs/vp8/libvpx_vp8_decoder.cc",
"codecs/vp8/libvpx_vp8_decoder.h",
"codecs/vp8/libvpx_vp8_encoder.cc",
@ -708,6 +710,7 @@ if (rtc_include_tests) {
"codecs/test/video_encoder_decoder_instantiation_tests.cc",
"codecs/test/videocodec_test_libvpx.cc",
"codecs/test/videocodec_test_parameterized.cc",
"codecs/vp8/test/mock_libvpx_interface.h",
"codecs/vp8/test/vp8_impl_unittest.cc",
"codecs/vp9/test/vp9_impl_unittest.cc",
]

View File

@ -19,18 +19,14 @@
namespace webrtc {
class VP8Encoder : public VideoEncoder {
class VP8Encoder {
public:
static std::unique_ptr<VP8Encoder> Create();
~VP8Encoder() override {}
static std::unique_ptr<VideoEncoder> Create();
}; // end of VP8Encoder class
class VP8Decoder : public VideoDecoder {
class VP8Decoder {
public:
static std::unique_ptr<VP8Decoder> Create();
~VP8Decoder() override {}
static std::unique_ptr<VideoDecoder> Create();
}; // end of VP8Decoder class
} // namespace webrtc

View File

@ -0,0 +1,204 @@
/*
* Copyright (c) 2018 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.
*/
#include "modules/video_coding/codecs/vp8/libvpx_interface.h"
#include "absl/memory/memory.h"
#include "rtc_base/checks.h"
namespace webrtc {
namespace {
class LibvpxVp8Facade : public LibvpxInterface {
public:
LibvpxVp8Facade() = default;
~LibvpxVp8Facade() override = default;
vpx_image_t* img_alloc(vpx_image_t* img,
vpx_img_fmt_t fmt,
unsigned int d_w,
unsigned int d_h,
unsigned int align) const override {
return ::vpx_img_alloc(img, fmt, d_w, d_h, align);
}
vpx_image_t* img_wrap(vpx_image_t* img,
vpx_img_fmt_t fmt,
unsigned int d_w,
unsigned int d_h,
unsigned int stride_align,
unsigned char* img_data) const override {
return ::vpx_img_wrap(img, fmt, d_w, d_h, stride_align, img_data);
}
void img_free(vpx_image_t* img) const override { ::vpx_img_free(img); }
vpx_codec_err_t codec_enc_config_set(
vpx_codec_ctx_t* ctx,
const vpx_codec_enc_cfg_t* cfg) const override {
return ::vpx_codec_enc_config_set(ctx, cfg);
}
vpx_codec_err_t codec_enc_config_default(vpx_codec_iface_t* iface,
vpx_codec_enc_cfg_t* cfg,
unsigned int usage) const override {
return ::vpx_codec_enc_config_default(iface, cfg, usage);
}
vpx_codec_err_t codec_enc_init(vpx_codec_ctx_t* ctx,
vpx_codec_iface_t* iface,
const vpx_codec_enc_cfg_t* cfg,
vpx_codec_flags_t flags) const override {
return ::vpx_codec_enc_init(ctx, iface, cfg, flags);
}
vpx_codec_err_t codec_enc_init_multi(vpx_codec_ctx_t* ctx,
vpx_codec_iface_t* iface,
vpx_codec_enc_cfg_t* cfg,
int num_enc,
vpx_codec_flags_t flags,
vpx_rational_t* dsf) const override {
return ::vpx_codec_enc_init_multi(ctx, iface, cfg, num_enc, flags, dsf);
}
vpx_codec_err_t codec_destroy(vpx_codec_ctx_t* ctx) const override {
return ::vpx_codec_destroy(ctx);
}
// For types related to these parameters, see section
// "VP8 encoder control function parameter type" in vpx/vp8cx.h.
vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
uint32_t param) const override {
// We need an explicit call for each type since vpx_codec_control is a
// macro that gets expanded into another call based on the parameter name.
switch (ctrl_id) {
case VP8E_SET_ENABLEAUTOALTREF:
return vpx_codec_control(ctx, VP8E_SET_ENABLEAUTOALTREF, param);
case VP8E_SET_NOISE_SENSITIVITY:
return vpx_codec_control(ctx, VP8E_SET_NOISE_SENSITIVITY, param);
case VP8E_SET_SHARPNESS:
return vpx_codec_control(ctx, VP8E_SET_SHARPNESS, param);
case VP8E_SET_STATIC_THRESHOLD:
return vpx_codec_control(ctx, VP8E_SET_STATIC_THRESHOLD, param);
case VP8E_SET_ARNR_MAXFRAMES:
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 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);
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,
int param) const override {
switch (ctrl_id) {
case VP8E_SET_FRAME_FLAGS:
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 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);
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,
int* param) const override {
switch (ctrl_id) {
case VP8E_GET_LAST_QUANTIZER:
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);
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_roi_map* param) const override {
switch (ctrl_id) {
case VP8E_SET_ROI_MAP:
return vpx_codec_control(ctx, VP8E_SET_ROI_MAP, 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_active_map* param) const override {
switch (ctrl_id) {
case VP8E_SET_ACTIVEMAP:
return vpx_codec_control(ctx, VP8E_SET_ACTIVEMAP, 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_scaling_mode* param) const override {
switch (ctrl_id) {
case VP8E_SET_SCALEMODE:
return vpx_codec_control(ctx, VP8E_SET_SCALEMODE, 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,
uint64_t duration,
vpx_enc_frame_flags_t flags,
uint64_t deadline) const override {
return ::vpx_codec_encode(ctx, img, pts, duration, flags, deadline);
}
const vpx_codec_cx_pkt_t* codec_get_cx_data(
vpx_codec_ctx_t* ctx,
vpx_codec_iter_t* iter) const override {
return ::vpx_codec_get_cx_data(ctx, iter);
}
};
} // namespace
std::unique_ptr<LibvpxInterface> LibvpxInterface::CreateEncoder() {
return absl::make_unique<LibvpxVp8Facade>();
}
} // namespace webrtc

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2018 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 MODULES_VIDEO_CODING_CODECS_VP8_LIBVPX_INTERFACE_H_
#define MODULES_VIDEO_CODING_CODECS_VP8_LIBVPX_INTERFACE_H_
#include <memory>
#include "vpx/vp8cx.h"
#include "vpx/vpx_encoder.h"
namespace webrtc {
// This interface is a proxy to to the static libvpx functions, so that they
// can be mocked for testing. Currently supports VP8 encoder functions.
// TODO(sprang): Extend this to VP8 decoder and VP9 encoder/decoder too.
class LibvpxInterface {
public:
LibvpxInterface() = default;
virtual ~LibvpxInterface() = default;
virtual vpx_image_t* img_alloc(vpx_image_t* img,
vpx_img_fmt_t fmt,
unsigned int d_w,
unsigned int d_h,
unsigned int align) const = 0;
virtual vpx_image_t* img_wrap(vpx_image_t* img,
vpx_img_fmt_t fmt,
unsigned int d_w,
unsigned int d_h,
unsigned int stride_align,
unsigned char* img_data) const = 0;
virtual void img_free(vpx_image_t* img) const = 0;
virtual vpx_codec_err_t codec_enc_config_set(
vpx_codec_ctx_t* ctx,
const vpx_codec_enc_cfg_t* cfg) const = 0;
virtual vpx_codec_err_t codec_enc_config_default(
vpx_codec_iface_t* iface,
vpx_codec_enc_cfg_t* cfg,
unsigned int usage) const = 0;
virtual vpx_codec_err_t codec_enc_init(vpx_codec_ctx_t* ctx,
vpx_codec_iface_t* iface,
const vpx_codec_enc_cfg_t* cfg,
vpx_codec_flags_t flags) const = 0;
virtual vpx_codec_err_t codec_enc_init_multi(vpx_codec_ctx_t* ctx,
vpx_codec_iface_t* iface,
vpx_codec_enc_cfg_t* cfg,
int num_enc,
vpx_codec_flags_t flags,
vpx_rational_t* dsf) const = 0;
virtual vpx_codec_err_t codec_destroy(vpx_codec_ctx_t* ctx) const = 0;
virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
uint32_t param) const = 0;
virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
int param) const = 0;
virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
int* param) const = 0;
virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_roi_map* param) const = 0;
virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
vp8e_enc_control_id ctrl_id,
vpx_active_map* param) const = 0;
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_encode(vpx_codec_ctx_t* ctx,
const vpx_image_t* img,
vpx_codec_pts_t pts,
uint64_t duration,
vpx_enc_frame_flags_t flags,
uint64_t deadline) const = 0;
virtual const vpx_codec_cx_pkt_t* codec_get_cx_data(
vpx_codec_ctx_t* ctx,
vpx_codec_iter_t* iter) const = 0;
// Returns interface wrapping the actual libvpx functions.
static std::unique_ptr<LibvpxInterface> CreateEncoder();
};
} // namespace webrtc
#endif // MODULES_VIDEO_CODING_CODECS_VP8_LIBVPX_INTERFACE_H_

View File

@ -55,7 +55,7 @@ void GetPostProcParamsFromFieldTrialGroup(
} // namespace
std::unique_ptr<VP8Decoder> VP8Decoder::Create() {
std::unique_ptr<VideoDecoder> VP8Decoder::Create() {
return absl::make_unique<LibvpxVp8Decoder>();
}

View File

@ -25,7 +25,7 @@
namespace webrtc {
class LibvpxVp8Decoder : public VP8Decoder {
class LibvpxVp8Decoder : public VideoDecoder {
public:
LibvpxVp8Decoder();
~LibvpxVp8Decoder() override;

View File

@ -10,6 +10,7 @@
#include <algorithm>
#include <string>
#include <utility>
#include <vector>
#include "absl/memory/memory.h"
@ -37,7 +38,7 @@ constexpr int kTokenPartitions = VP8_ONE_TOKENPARTITION;
constexpr uint32_t kVp832ByteAlign = 32u;
// VP8 denoiser states.
enum denoiserState {
enum denoiserState : uint32_t {
kDenoiserOff,
kDenoiserOnYOnly,
kDenoiserOnYUV,
@ -123,7 +124,7 @@ bool UpdateVpxConfiguration(TemporalLayers* temporal_layers,
} // namespace
std::unique_ptr<VP8Encoder> VP8Encoder::Create() {
std::unique_ptr<VideoEncoder> VP8Encoder::Create() {
return absl::make_unique<LibvpxVp8Encoder>();
}
@ -152,7 +153,11 @@ vpx_enc_frame_flags_t LibvpxVp8Encoder::EncodeFlags(
}
LibvpxVp8Encoder::LibvpxVp8Encoder()
: use_gf_boost_(webrtc::field_trial::IsEnabled(kVp8GfBoostFieldTrial)),
: LibvpxVp8Encoder(LibvpxInterface::CreateEncoder()) {}
LibvpxVp8Encoder::LibvpxVp8Encoder(std::unique_ptr<LibvpxInterface> interface)
: libvpx_(std::move(interface)),
use_gf_boost_(webrtc::field_trial::IsEnabled(kVp8GfBoostFieldTrial)),
encoded_complete_callback_(nullptr),
inited_(false),
timestamp_(0),
@ -187,7 +192,7 @@ int LibvpxVp8Encoder::Release() {
while (!encoders_.empty()) {
vpx_codec_ctx_t& encoder = encoders_.back();
if (inited_) {
if (vpx_codec_destroy(&encoder)) {
if (libvpx_->codec_destroy(&encoder)) {
ret_val = WEBRTC_VIDEO_CODEC_MEMORY;
}
}
@ -197,7 +202,7 @@ int LibvpxVp8Encoder::Release() {
send_stream_.clear();
cpu_speed_.clear();
while (!raw_images_.empty()) {
vpx_img_free(&raw_images_.back());
libvpx_->img_free(&raw_images_.back());
raw_images_.pop_back();
}
temporal_layers_.clear();
@ -266,7 +271,7 @@ int LibvpxVp8Encoder::SetRateAllocation(const VideoBitrateAllocation& bitrate,
UpdateVpxConfiguration(temporal_layers_[stream_idx].get(),
&configurations_[i]);
if (vpx_codec_enc_config_set(&encoders_[i], &configurations_[i])) {
if (libvpx_->codec_enc_config_set(&encoders_[i], &configurations_[i])) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
}
@ -389,7 +394,7 @@ int LibvpxVp8Encoder::InitEncode(const VideoCodec* inst,
encoded_images_[i]._completeFrame = true;
}
// populate encoder configuration with default values
if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &configurations_[0],
if (libvpx_->codec_enc_config_default(vpx_codec_vp8_cx(), &configurations_[0],
0)) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
@ -465,8 +470,8 @@ int LibvpxVp8Encoder::InitEncode(const VideoCodec* inst,
// Creating a wrapper to the image - setting image data to NULL.
// Actual pointer will be set in encode. Setting align to 1, as it
// is meaningless (no memory allocation is done here).
vpx_img_wrap(&raw_images_[0], VPX_IMG_FMT_I420, inst->width, inst->height, 1,
NULL);
libvpx_->img_wrap(&raw_images_[0], VPX_IMG_FMT_I420, inst->width,
inst->height, 1, NULL);
// Note the order we use is different from webm, we have lowest resolution
// at position 0 and they have highest resolution at position 0.
@ -505,9 +510,10 @@ int LibvpxVp8Encoder::InitEncode(const VideoCodec* inst,
// Setting alignment to 32 - as that ensures at least 16 for all
// planes (32 for Y, 16 for U,V). Libvpx sets the requested stride for
// the y plane, but only half of it to the u and v planes.
vpx_img_alloc(&raw_images_[i], VPX_IMG_FMT_I420,
libvpx_->img_alloc(&raw_images_[i], VPX_IMG_FMT_I420,
inst->simulcastStream[stream_idx].width,
inst->simulcastStream[stream_idx].height, kVp832ByteAlign);
inst->simulcastStream[stream_idx].height,
kVp832ByteAlign);
SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx);
configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx];
if (stream_bitrates[stream_idx] > 0) {
@ -588,14 +594,14 @@ int LibvpxVp8Encoder::InitAndSetControlSettings() {
flags |= VPX_CODEC_USE_OUTPUT_PARTITION;
if (encoders_.size() > 1) {
int error = vpx_codec_enc_init_multi(&encoders_[0], vpx_codec_vp8_cx(),
&configurations_[0], encoders_.size(),
flags, &downsampling_factors_[0]);
int error = libvpx_->codec_enc_init_multi(
&encoders_[0], vpx_codec_vp8_cx(), &configurations_[0],
encoders_.size(), flags, &downsampling_factors_[0]);
if (error) {
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
}
} else {
if (vpx_codec_enc_init(&encoders_[0], vpx_codec_vp8_cx(),
if (libvpx_->codec_enc_init(&encoders_[0], vpx_codec_vp8_cx(),
&configurations_[0], flags)) {
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
}
@ -614,31 +620,35 @@ int LibvpxVp8Encoder::InitAndSetControlSettings() {
#else
denoiser_state = kDenoiserOnAdaptive;
#endif
vpx_codec_control(&encoders_[0], VP8E_SET_NOISE_SENSITIVITY,
libvpx_->codec_control(
&encoders_[0], VP8E_SET_NOISE_SENSITIVITY,
codec_.VP8()->denoisingOn ? denoiser_state : kDenoiserOff);
if (encoders_.size() > 2) {
vpx_codec_control(
libvpx_->codec_control(
&encoders_[1], VP8E_SET_NOISE_SENSITIVITY,
codec_.VP8()->denoisingOn ? denoiser_state : kDenoiserOff);
}
for (size_t i = 0; i < encoders_.size(); ++i) {
// Allow more screen content to be detected as static.
vpx_codec_control(&(encoders_[i]), VP8E_SET_STATIC_THRESHOLD,
codec_.mode == VideoCodecMode::kScreensharing ? 300 : 1);
vpx_codec_control(&(encoders_[i]), VP8E_SET_CPUUSED, cpu_speed_[i]);
vpx_codec_control(&(encoders_[i]), VP8E_SET_TOKEN_PARTITIONS,
libvpx_->codec_control(
&(encoders_[i]), VP8E_SET_STATIC_THRESHOLD,
codec_.mode == VideoCodecMode::kScreensharing ? 300u : 1u);
libvpx_->codec_control(&(encoders_[i]), VP8E_SET_CPUUSED, cpu_speed_[i]);
libvpx_->codec_control(
&(encoders_[i]), VP8E_SET_TOKEN_PARTITIONS,
static_cast<vp8e_token_partitions>(kTokenPartitions));
vpx_codec_control(&(encoders_[i]), VP8E_SET_MAX_INTRA_BITRATE_PCT,
libvpx_->codec_control(&(encoders_[i]), VP8E_SET_MAX_INTRA_BITRATE_PCT,
rc_max_intra_target_);
// VP8E_SET_SCREEN_CONTENT_MODE 2 = screen content with more aggressive
// rate control (drop frames on large target bitrate overshoot)
vpx_codec_control(&(encoders_[i]), VP8E_SET_SCREEN_CONTENT_MODE,
codec_.mode == VideoCodecMode::kScreensharing ? 2 : 0);
libvpx_->codec_control(
&(encoders_[i]), VP8E_SET_SCREEN_CONTENT_MODE,
codec_.mode == VideoCodecMode::kScreensharing ? 2u : 0u);
// Apply boost on golden frames (has only effect when resilience is off).
if (use_gf_boost_ && configurations_[0].g_error_resilient == 0) {
int gf_boost_percent;
if (GetGfBoostPercentageFromFieldTrialGroup(&gf_boost_percent)) {
vpx_codec_control(&(encoders_[i]), VP8E_SET_GF_CBR_BOOST_PCT,
libvpx_->codec_control(&(encoders_[i]), VP8E_SET_GF_CBR_BOOST_PCT,
gf_boost_percent);
}
}
@ -759,7 +769,7 @@ int LibvpxVp8Encoder::Encode(const VideoFrame& frame,
codec_.mode == VideoCodecMode::kScreensharing &&
codec_.VP8()->numberOfTemporalLayers <= 1) {
const uint32_t forceKeyFrameIntraTh = 100;
vpx_codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT,
libvpx_->codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT,
forceKeyFrameIntraTh);
}
// Key frame request from caller.
@ -783,12 +793,13 @@ int LibvpxVp8Encoder::Encode(const VideoFrame& frame,
memcpy(&temp_config, &configurations_[i], sizeof(vpx_codec_enc_cfg_t));
if (UpdateVpxConfiguration(temporal_layers_[stream_idx].get(),
&temp_config)) {
if (vpx_codec_enc_config_set(&encoders_[i], &temp_config))
if (libvpx_->codec_enc_config_set(&encoders_[i], &temp_config))
return WEBRTC_VIDEO_CODEC_ERROR;
}
vpx_codec_control(&encoders_[i], VP8E_SET_FRAME_FLAGS, flags[stream_idx]);
vpx_codec_control(&encoders_[i], VP8E_SET_TEMPORAL_LAYER_ID,
libvpx_->codec_control(&encoders_[i], VP8E_SET_FRAME_FLAGS,
static_cast<int>(flags[stream_idx]));
libvpx_->codec_control(&encoders_[i], VP8E_SET_TEMPORAL_LAYER_ID,
tl_configs[i].encoder_layer_id);
}
// TODO(holmer): Ideally the duration should be the timestamp diff of this
@ -809,12 +820,13 @@ int LibvpxVp8Encoder::Encode(const VideoFrame& frame,
error == WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT)) {
++num_tries;
// Note we must pass 0 for |flags| field in encode call below since they are
// set above in |vpx_codec_control| function for each encoder/spatial layer.
error = vpx_codec_encode(&encoders_[0], &raw_images_[0], timestamp_,
// set above in |libvpx_interface_->vpx_codec_control_| function for each
// encoder/spatial layer.
error = libvpx_->codec_encode(&encoders_[0], &raw_images_[0], timestamp_,
duration, 0, VPX_DL_REALTIME);
// Reset specific intra frame thresholds, following the key frame.
if (send_key_frame) {
vpx_codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT,
libvpx_->codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT,
rc_max_intra_target_);
}
if (error)
@ -860,7 +872,7 @@ int LibvpxVp8Encoder::GetEncodedPartitions(const VideoFrame& input_image) {
CodecSpecificInfo codec_specific;
bool is_keyframe = false;
const vpx_codec_cx_pkt_t* pkt = NULL;
while ((pkt = vpx_codec_get_cx_data(&encoders_[encoder_idx], &iter)) !=
while ((pkt = libvpx_->codec_get_cx_data(&encoders_[encoder_idx], &iter)) !=
NULL) {
switch (pkt->kind) {
case VPX_CODEC_CX_FRAME_PKT: {
@ -919,7 +931,7 @@ int LibvpxVp8Encoder::GetEncodedPartitions(const VideoFrame& input_image) {
encoded_images_[encoder_idx]._encodedWidth =
codec_.simulcastStream[stream_idx].width;
int qp_128 = -1;
vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER,
libvpx_->codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER,
&qp_128);
encoded_images_[encoder_idx].qp_ = qp_128;
encoded_complete_callback_->OnEncodedImage(encoded_images_[encoder_idx],

View File

@ -21,6 +21,7 @@
#include "modules/video_coding/codecs/vp8/include/temporal_layers_checker.h"
#include "modules/video_coding/codecs/vp8/include/vp8.h"
#include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
#include "modules/video_coding/codecs/vp8/libvpx_interface.h"
#include "modules/video_coding/include/video_codec_interface.h"
#include "vpx/vp8cx.h"
@ -28,9 +29,10 @@
namespace webrtc {
class LibvpxVp8Encoder : public VP8Encoder {
class LibvpxVp8Encoder : public VideoEncoder {
public:
LibvpxVp8Encoder();
explicit LibvpxVp8Encoder(std::unique_ptr<LibvpxInterface> interface);
~LibvpxVp8Encoder() override;
int Release() override;
@ -84,6 +86,7 @@ class LibvpxVp8Encoder : public VP8Encoder {
uint32_t FrameDropThreshold(size_t spatial_idx) const;
const std::unique_ptr<LibvpxInterface> libvpx_;
const bool use_gf_boost_;
EncodedImageCallback* encoded_complete_callback_;

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2018 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 MODULES_VIDEO_CODING_CODECS_VP8_TEST_MOCK_LIBVPX_INTERFACE_H_
#define MODULES_VIDEO_CODING_CODECS_VP8_TEST_MOCK_LIBVPX_INTERFACE_H_
#include "modules/video_coding/codecs/vp8/libvpx_interface.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
class MockLibvpxVp8Interface : public LibvpxInterface {
public:
MOCK_CONST_METHOD5(img_alloc,
vpx_image_t*(vpx_image_t*,
vpx_img_fmt_t,
unsigned int,
unsigned int,
unsigned int));
MOCK_CONST_METHOD6(img_wrap,
vpx_image_t*(vpx_image_t*,
vpx_img_fmt_t,
unsigned int,
unsigned int,
unsigned int,
unsigned char*));
MOCK_CONST_METHOD1(img_free, vpx_codec_err_t(const vpx_codec_enc_cfg_t*));
MOCK_CONST_METHOD2(codec_enc_config_set,
vpx_codec_err_t(vpx_codec_ctx_t*,
const vpx_codec_enc_cfg_t*));
MOCK_CONST_METHOD3(codec_enc_config_default,
vpx_codec_err_t(vpx_codec_iface_t*,
vpx_codec_enc_cfg_t*,
unsigned int));
MOCK_CONST_METHOD4(codec_enc_init,
vpx_codec_err_t(vpx_codec_ctx_t*,
vpx_codec_iface_t*,
const vpx_codec_enc_cfg_t*,
vpx_codec_flags_t));
MOCK_CONST_METHOD6(codec_enc_init_multi,
vpx_codec_err_t(vpx_codec_ctx_t*,
vpx_codec_iface_t*,
vpx_codec_enc_cfg_t*,
int,
vpx_codec_flags_t,
vpx_rational_t*));
MOCK_CONST_METHOD1(codec_destroy, vpx_codec_err_t(vpx_codec_ctx_t*));
MOCK_CONST_METHOD3(codec_control,
vpx_codec_err_t(vpx_codec_ctx_t*,
vp8e_enc_control_id,
uint32_t));
MOCK_CONST_METHOD3(codec_control,
vpx_codec_err_t(vpx_codec_ctx_t*,
vp8e_enc_control_id,
int));
MOCK_CONST_METHOD3(codec_control,
vpx_codec_err_t(vpx_codec_ctx_t*,
vp8e_enc_control_id,
int*));
MOCK_CONST_METHOD3(codec_control,
vpx_codec_err_t(vpx_codec_ctx_t*,
vp8e_enc_control_id,
vpx_roi_map*));
MOCK_CONST_METHOD3(codec_control,
vpx_codec_err_t(vpx_codec_ctx_t*,
vp8e_enc_control_id,
vpx_active_map*));
MOCK_CONST_METHOD3(codec_control,
vpx_codec_err_t(vpx_codec_ctx_t*,
vp8e_enc_control_id,
vpx_scaling_mode*));
MOCK_CONST_METHOD6(codec_encode,
vpx_codec_err_t(vpx_codec_ctx_t*,
const vpx_image_t*,
vpx_codec_pts_t,
uint64_t,
vpx_enc_frame_flags_t,
uint64_t));
MOCK_CONST_METHOD3(codec_get_cx_data,
const vpx_codec_cx_pkt_t*(vpx_codec_ctx_t*,
vpx_codec_iter_t*));
};
} // namespace webrtc
#endif // MODULES_VIDEO_CODING_CODECS_VP8_TEST_MOCK_LIBVPX_INTERFACE_H_