Update VideoEncoderSoftwareFallbackWrapper to take VideoEncoder as arg

VideoEncoderSoftwareFallbackWrapper is updated to take a VideoEncoder as
argument instead relying on built-in SW codecs. The purpose is to make
VideoEncoderSoftwareFallbackWrapper more modular and not depend on
built-in SW encoders.

Bug: webrtc:7925
Change-Id: I99896f0751cfb77e01efd29c97d3bd07bdb2c7c0
Reviewed-on: https://webrtc-review.googlesource.com/22320
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Anders Carlsson <andersc@webrtc.org>
Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20671}
This commit is contained in:
Magnus Jedvert
2017-11-13 15:26:17 +01:00
committed by Commit Bot
parent d4f01c1e87
commit ee92d626bd
5 changed files with 67 additions and 92 deletions

View File

@ -27,6 +27,7 @@
#include "media/engine/webrtcvideodecoderfactory.h" #include "media/engine/webrtcvideodecoderfactory.h"
#include "media/engine/webrtcvideoencoderfactory.h" #include "media/engine/webrtcvideoencoderfactory.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/ptr_util.h"
namespace cricket { namespace cricket {
@ -95,44 +96,39 @@ class EncoderAdapter : public webrtc::VideoEncoderFactory {
std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder( std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
const webrtc::SdpVideoFormat& format) { const webrtc::SdpVideoFormat& format) {
const VideoCodec codec(format); const VideoCodec codec(format);
// Try creating internal encoder.
std::unique_ptr<webrtc::VideoEncoder> internal_encoder;
if (FindMatchingCodec(internal_encoder_factory_->supported_codecs(),
codec)) {
internal_encoder =
CodecNamesEq(format.name.c_str(), kVp8CodecName)
? rtc::MakeUnique<webrtc::VP8EncoderSimulcastProxy>(
internal_encoder_factory_.get())
: std::unique_ptr<webrtc::VideoEncoder>(
internal_encoder_factory_->CreateVideoEncoder(codec));
}
// Try creating external encoder. // Try creating external encoder.
std::unique_ptr<webrtc::VideoEncoder> external_encoder;
if (external_encoder_factory_ != nullptr && if (external_encoder_factory_ != nullptr &&
FindMatchingCodec(external_encoder_factory_->supported_codecs(), FindMatchingCodec(external_encoder_factory_->supported_codecs(),
codec)) { codec)) {
std::unique_ptr<webrtc::VideoEncoder> external_encoder; external_encoder = CodecNamesEq(format.name.c_str(), kVp8CodecName)
if (CodecNamesEq(codec.name.c_str(), kVp8CodecName)) { ? rtc::MakeUnique<webrtc::SimulcastEncoderAdapter>(
// If it's a codec type we can simulcast, create a wrapped encoder. external_encoder_factory_.get())
external_encoder = std::unique_ptr<webrtc::VideoEncoder>( : CreateScopedVideoEncoder(
new webrtc::SimulcastEncoderAdapter( external_encoder_factory_.get(), codec);
external_encoder_factory_.get()));
} else {
external_encoder =
CreateScopedVideoEncoder(external_encoder_factory_.get(), codec);
}
if (external_encoder) {
return std::unique_ptr<webrtc::VideoEncoder>(
new webrtc::VideoEncoderSoftwareFallbackWrapper(
codec, std::move(external_encoder)));
}
} }
// Try creating internal encoder. if (internal_encoder && external_encoder) {
if (FindMatchingCodec(internal_encoder_factory_->supported_codecs(), // Both internal SW encoder and external HW encoder available - create
codec)) { // fallback encoder.
if (CodecNamesEq(codec.name.c_str(), kVp8CodecName)) { return rtc::MakeUnique<webrtc::VideoEncoderSoftwareFallbackWrapper>(
return std::unique_ptr<webrtc::VideoEncoder>( std::move(internal_encoder), std::move(external_encoder));
new webrtc::VP8EncoderSimulcastProxy(
internal_encoder_factory_.get()));
} else {
return std::unique_ptr<webrtc::VideoEncoder>(
internal_encoder_factory_->CreateVideoEncoder(codec));
}
} }
return external_encoder ? std::move(external_encoder)
// This shouldn't happen, we should not be trying to create something we : std::move(internal_encoder);
// don't support.
RTC_NOTREACHED();
return nullptr;
} }
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const { std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const {

View File

@ -25,11 +25,8 @@ namespace {
const char kVp8ForceFallbackEncoderFieldTrial[] = const char kVp8ForceFallbackEncoderFieldTrial[] =
"WebRTC-VP8-Forced-Fallback-Encoder-v2"; "WebRTC-VP8-Forced-Fallback-Encoder-v2";
bool EnableForcedFallback(const cricket::VideoCodec& codec) { bool EnableForcedFallback() {
if (!webrtc::field_trial::IsEnabled(kVp8ForceFallbackEncoderFieldTrial)) return field_trial::IsEnabled(kVp8ForceFallbackEncoderFieldTrial);
return false;
return (PayloadStringToCodecType(codec.name) == kVideoCodecVP8);
} }
bool IsForcedFallbackPossible(const VideoCodec& codec_settings) { bool IsForcedFallbackPossible(const VideoCodec& codec_settings) {
@ -68,8 +65,8 @@ void GetForcedFallbackParamsFromFieldTrialGroup(int* param_min_pixels,
} // namespace } // namespace
VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper( VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper(
const cricket::VideoCodec& codec, std::unique_ptr<webrtc::VideoEncoder> sw_encoder,
std::unique_ptr<webrtc::VideoEncoder> encoder) std::unique_ptr<webrtc::VideoEncoder> hw_encoder)
: number_of_cores_(0), : number_of_cores_(0),
max_payload_size_(0), max_payload_size_(0),
rates_set_(false), rates_set_(false),
@ -77,10 +74,11 @@ VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper(
channel_parameters_set_(false), channel_parameters_set_(false),
packet_loss_(0), packet_loss_(0),
rtt_(0), rtt_(0),
codec_(codec), use_fallback_encoder_(false),
encoder_(std::move(encoder)), encoder_(std::move(hw_encoder)),
fallback_encoder_(std::move(sw_encoder)),
callback_(nullptr), callback_(nullptr),
forced_fallback_possible_(EnableForcedFallback(codec)) { forced_fallback_possible_(EnableForcedFallback()) {
if (forced_fallback_possible_) { if (forced_fallback_possible_) {
GetForcedFallbackParamsFromFieldTrialGroup( GetForcedFallbackParamsFromFieldTrialGroup(
&forced_fallback_.min_pixels_, &forced_fallback_.max_pixels_, &forced_fallback_.min_pixels_, &forced_fallback_.max_pixels_,
@ -91,20 +89,13 @@ VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper(
bool VideoEncoderSoftwareFallbackWrapper::InitFallbackEncoder() { bool VideoEncoderSoftwareFallbackWrapper::InitFallbackEncoder() {
RTC_LOG(LS_WARNING) << "Encoder falling back to software encoding."; RTC_LOG(LS_WARNING) << "Encoder falling back to software encoding.";
MaybeModifyCodecForFallback();
cricket::InternalEncoderFactory internal_factory; const int ret = fallback_encoder_->InitEncode(
if (!FindMatchingCodec(internal_factory.supported_codecs(), codec_)) { &codec_settings_, number_of_cores_, max_payload_size_);
RTC_LOG(LS_WARNING) use_fallback_encoder_ = (ret == WEBRTC_VIDEO_CODEC_OK);
<< "Encoder requesting fallback to codec not supported in software."; if (!use_fallback_encoder_) {
return false;
}
fallback_encoder_.reset(internal_factory.CreateVideoEncoder(codec_));
if (fallback_encoder_->InitEncode(&codec_settings_, number_of_cores_,
max_payload_size_) !=
WEBRTC_VIDEO_CODEC_OK) {
RTC_LOG(LS_ERROR) << "Failed to initialize software-encoder fallback."; RTC_LOG(LS_ERROR) << "Failed to initialize software-encoder fallback.";
fallback_encoder_->Release(); fallback_encoder_->Release();
fallback_encoder_.reset();
return false; return false;
} }
// Replay callback, rates, and channel parameters. // Replay callback, rates, and channel parameters.
@ -148,13 +139,13 @@ int32_t VideoEncoderSoftwareFallbackWrapper::InitEncode(
int32_t ret = int32_t ret =
encoder_->InitEncode(codec_settings, number_of_cores, max_payload_size); encoder_->InitEncode(codec_settings, number_of_cores, max_payload_size);
if (ret == WEBRTC_VIDEO_CODEC_OK || codec_.name.empty()) { if (ret == WEBRTC_VIDEO_CODEC_OK) {
if (fallback_encoder_) { if (use_fallback_encoder_) {
RTC_LOG(LS_WARNING) RTC_LOG(LS_WARNING)
<< "InitEncode OK, no longer using the software fallback encoder."; << "InitEncode OK, no longer using the software fallback encoder.";
fallback_encoder_->Release(); fallback_encoder_->Release();
use_fallback_encoder_ = false;
} }
fallback_encoder_.reset();
if (callback_) if (callback_)
encoder_->RegisterEncodeCompleteCallback(callback_); encoder_->RegisterEncodeCompleteCallback(callback_);
return ret; return ret;
@ -171,25 +162,21 @@ int32_t VideoEncoderSoftwareFallbackWrapper::RegisterEncodeCompleteCallback(
EncodedImageCallback* callback) { EncodedImageCallback* callback) {
callback_ = callback; callback_ = callback;
int32_t ret = encoder_->RegisterEncodeCompleteCallback(callback); int32_t ret = encoder_->RegisterEncodeCompleteCallback(callback);
if (fallback_encoder_) if (use_fallback_encoder_)
return fallback_encoder_->RegisterEncodeCompleteCallback(callback); return fallback_encoder_->RegisterEncodeCompleteCallback(callback);
return ret; return ret;
} }
int32_t VideoEncoderSoftwareFallbackWrapper::Release() { int32_t VideoEncoderSoftwareFallbackWrapper::Release() {
// If the fallback_encoder_ is non-null, it means it was created via return use_fallback_encoder_ ? fallback_encoder_->Release()
// InitFallbackEncoder which has Release()d encoder_, so we should only ever : encoder_->Release();
// need to Release() whichever one is active.
if (fallback_encoder_)
return fallback_encoder_->Release();
return encoder_->Release();
} }
int32_t VideoEncoderSoftwareFallbackWrapper::Encode( int32_t VideoEncoderSoftwareFallbackWrapper::Encode(
const VideoFrame& frame, const VideoFrame& frame,
const CodecSpecificInfo* codec_specific_info, const CodecSpecificInfo* codec_specific_info,
const std::vector<FrameType>* frame_types) { const std::vector<FrameType>* frame_types) {
if (fallback_encoder_) if (use_fallback_encoder_)
return fallback_encoder_->Encode(frame, codec_specific_info, frame_types); return fallback_encoder_->Encode(frame, codec_specific_info, frame_types);
int32_t ret = encoder_->Encode(frame, codec_specific_info, frame_types); int32_t ret = encoder_->Encode(frame, codec_specific_info, frame_types);
// If requested, try a software fallback. // If requested, try a software fallback.
@ -215,7 +202,7 @@ int32_t VideoEncoderSoftwareFallbackWrapper::SetChannelParameters(
packet_loss_ = packet_loss; packet_loss_ = packet_loss;
rtt_ = rtt; rtt_ = rtt;
int32_t ret = encoder_->SetChannelParameters(packet_loss, rtt); int32_t ret = encoder_->SetChannelParameters(packet_loss, rtt);
if (fallback_encoder_) if (use_fallback_encoder_)
return fallback_encoder_->SetChannelParameters(packet_loss, rtt); return fallback_encoder_->SetChannelParameters(packet_loss, rtt);
return ret; return ret;
} }
@ -227,15 +214,14 @@ int32_t VideoEncoderSoftwareFallbackWrapper::SetRateAllocation(
bitrate_allocation_ = bitrate_allocation; bitrate_allocation_ = bitrate_allocation;
framerate_ = framerate; framerate_ = framerate;
int32_t ret = encoder_->SetRateAllocation(bitrate_allocation_, framerate); int32_t ret = encoder_->SetRateAllocation(bitrate_allocation_, framerate);
if (fallback_encoder_) if (use_fallback_encoder_)
return fallback_encoder_->SetRateAllocation(bitrate_allocation_, framerate); return fallback_encoder_->SetRateAllocation(bitrate_allocation_, framerate);
return ret; return ret;
} }
bool VideoEncoderSoftwareFallbackWrapper::SupportsNativeHandle() const { bool VideoEncoderSoftwareFallbackWrapper::SupportsNativeHandle() const {
if (fallback_encoder_) return use_fallback_encoder_ ? fallback_encoder_->SupportsNativeHandle()
return fallback_encoder_->SupportsNativeHandle(); : encoder_->SupportsNativeHandle();
return encoder_->SupportsNativeHandle();
} }
VideoEncoder::ScalingSettings VideoEncoder::ScalingSettings
@ -258,19 +244,18 @@ VideoEncoderSoftwareFallbackWrapper::GetScalingSettings() const {
return encoder_->GetScalingSettings(); return encoder_->GetScalingSettings();
} }
const char *VideoEncoderSoftwareFallbackWrapper::ImplementationName() const { const char* VideoEncoderSoftwareFallbackWrapper::ImplementationName() const {
if (fallback_encoder_) return use_fallback_encoder_ ? fallback_encoder_->ImplementationName()
return fallback_encoder_->ImplementationName(); : encoder_->ImplementationName();
return encoder_->ImplementationName();
} }
bool VideoEncoderSoftwareFallbackWrapper::IsForcedFallbackActive() const { bool VideoEncoderSoftwareFallbackWrapper::IsForcedFallbackActive() const {
return (forced_fallback_possible_ && fallback_encoder_ && return (forced_fallback_possible_ && use_fallback_encoder_ &&
forced_fallback_.active_); forced_fallback_.active_);
} }
bool VideoEncoderSoftwareFallbackWrapper::TryInitForcedFallbackEncoder() { bool VideoEncoderSoftwareFallbackWrapper::TryInitForcedFallbackEncoder() {
if (!forced_fallback_possible_ || fallback_encoder_) { if (!forced_fallback_possible_ || use_fallback_encoder_) {
return false; return false;
} }
// Fallback not active. // Fallback not active.
@ -313,20 +298,11 @@ void VideoEncoderSoftwareFallbackWrapper::ValidateSettingsForForcedFallback() {
if (!IsForcedFallbackPossible(codec_settings_)) { if (!IsForcedFallbackPossible(codec_settings_)) {
if (IsForcedFallbackActive()) { if (IsForcedFallbackActive()) {
fallback_encoder_->Release(); fallback_encoder_->Release();
fallback_encoder_.reset(); use_fallback_encoder_ = false;
} }
RTC_LOG(LS_INFO) << "Disable forced_fallback_possible_ due to settings."; RTC_LOG(LS_INFO) << "Disable forced_fallback_possible_ due to settings.";
forced_fallback_possible_ = false; forced_fallback_possible_ = false;
} }
} }
void VideoEncoderSoftwareFallbackWrapper::MaybeModifyCodecForFallback() {
// We have a specific case for H264 ConstrainedBaseline because that is the
// only supported profile in Sw fallback.
if (!cricket::CodecNamesEq(codec_.name.c_str(), cricket::kH264CodecName))
return;
codec_.SetParam(cricket::kH264FmtpProfileLevelId,
cricket::kH264ProfileLevelConstrainedBaseline);
}
} // namespace webrtc } // namespace webrtc

View File

@ -26,8 +26,8 @@ namespace webrtc {
class VideoEncoderSoftwareFallbackWrapper : public VideoEncoder { class VideoEncoderSoftwareFallbackWrapper : public VideoEncoder {
public: public:
VideoEncoderSoftwareFallbackWrapper( VideoEncoderSoftwareFallbackWrapper(
const cricket::VideoCodec& codec, std::unique_ptr<webrtc::VideoEncoder> sw_encoder,
std::unique_ptr<webrtc::VideoEncoder> encoder); std::unique_ptr<webrtc::VideoEncoder> hw_encoder);
int32_t InitEncode(const VideoCodec* codec_settings, int32_t InitEncode(const VideoCodec* codec_settings,
int32_t number_of_cores, int32_t number_of_cores,
@ -87,10 +87,10 @@ class VideoEncoderSoftwareFallbackWrapper : public VideoEncoder {
uint32_t packet_loss_; uint32_t packet_loss_;
int64_t rtt_; int64_t rtt_;
cricket::VideoCodec codec_; bool use_fallback_encoder_;
std::unique_ptr<webrtc::VideoEncoder> encoder_; const std::unique_ptr<webrtc::VideoEncoder> encoder_;
std::unique_ptr<webrtc::VideoEncoder> fallback_encoder_; const std::unique_ptr<webrtc::VideoEncoder> fallback_encoder_;
EncodedImageCallback* callback_; EncodedImageCallback* callback_;
bool forced_fallback_possible_; bool forced_fallback_possible_;

View File

@ -13,6 +13,7 @@
#include <utility> #include <utility>
#include "api/video/i420_buffer.h" #include "api/video/i420_buffer.h"
#include "modules/video_coding/codecs/vp8/include/vp8.h"
#include "modules/video_coding/codecs/vp8/simulcast_rate_allocator.h" #include "modules/video_coding/codecs/vp8/simulcast_rate_allocator.h"
#include "modules/video_coding/codecs/vp8/temporal_layers.h" #include "modules/video_coding/codecs/vp8/temporal_layers.h"
#include "modules/video_coding/include/video_codec_interface.h" #include "modules/video_coding/include/video_codec_interface.h"
@ -42,7 +43,7 @@ class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test {
const std::string& field_trials) const std::string& field_trials)
: override_field_trials_(field_trials), : override_field_trials_(field_trials),
fake_encoder_(new CountingFakeEncoder()), fake_encoder_(new CountingFakeEncoder()),
fallback_wrapper_(cricket::VideoCodec("VP8"), fallback_wrapper_(std::unique_ptr<VideoEncoder>(VP8Encoder::Create()),
std::unique_ptr<VideoEncoder>(fake_encoder_)) {} std::unique_ptr<VideoEncoder>(fake_encoder_)) {}
class CountingFakeEncoder : public VideoEncoder { class CountingFakeEncoder : public VideoEncoder {

View File

@ -382,7 +382,9 @@ void VideoProcessorIntegrationTest::CreateEncoderAndDecoder() {
if (config_.sw_fallback_encoder) { if (config_.sw_fallback_encoder) {
encoder_ = rtc::MakeUnique<VideoEncoderSoftwareFallbackWrapper>( encoder_ = rtc::MakeUnique<VideoEncoderSoftwareFallbackWrapper>(
codec, std::move(encoder_)); std::unique_ptr<VideoEncoder>(
cricket::InternalEncoderFactory().CreateVideoEncoder(codec)),
std::move(encoder_));
} }
if (config_.sw_fallback_decoder) { if (config_.sw_fallback_decoder) {
decoder_ = rtc::MakeUnique<VideoDecoderSoftwareFallbackWrapper>( decoder_ = rtc::MakeUnique<VideoDecoderSoftwareFallbackWrapper>(