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:
@ -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);
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
204
modules/video_coding/codecs/vp8/libvpx_interface.cc
Normal file
204
modules/video_coding/codecs/vp8/libvpx_interface.cc
Normal 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
|
||||
98
modules/video_coding/codecs/vp8/libvpx_interface.h
Normal file
98
modules/video_coding/codecs/vp8/libvpx_interface.h
Normal 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_
|
||||
@ -55,7 +55,7 @@ void GetPostProcParamsFromFieldTrialGroup(
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<VP8Decoder> VP8Decoder::Create() {
|
||||
std::unique_ptr<VideoDecoder> VP8Decoder::Create() {
|
||||
return absl::make_unique<LibvpxVp8Decoder>();
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class LibvpxVp8Decoder : public VP8Decoder {
|
||||
class LibvpxVp8Decoder : public VideoDecoder {
|
||||
public:
|
||||
LibvpxVp8Decoder();
|
||||
~LibvpxVp8Decoder() override;
|
||||
|
||||
@ -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],
|
||||
|
||||
@ -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_;
|
||||
|
||||
94
modules/video_coding/codecs/vp8/test/mock_libvpx_interface.h
Normal file
94
modules/video_coding/codecs/vp8/test/mock_libvpx_interface.h
Normal 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_
|
||||
Reference in New Issue
Block a user