From ee92d626bde9ab5dd075fc0b2f1ac61a5649cef1 Mon Sep 17 00:00:00 2001 From: Magnus Jedvert Date: Mon, 13 Nov 2017 15:26:17 +0100 Subject: [PATCH] Update VideoEncoderSoftwareFallbackWrapper to take VideoEncoder as arg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Anders Carlsson Commit-Queue: Magnus Jedvert Cr-Commit-Position: refs/heads/master@{#20671} --- media/engine/convert_legacy_video_factory.cc | 58 ++++++------- .../videoencodersoftwarefallbackwrapper.cc | 84 +++++++------------ .../videoencodersoftwarefallbackwrapper.h | 10 +-- ...encodersoftwarefallbackwrapper_unittest.cc | 3 +- .../test/videoprocessor_integrationtest.cc | 4 +- 5 files changed, 67 insertions(+), 92 deletions(-) diff --git a/media/engine/convert_legacy_video_factory.cc b/media/engine/convert_legacy_video_factory.cc index d40f8699dd..f3638ee025 100644 --- a/media/engine/convert_legacy_video_factory.cc +++ b/media/engine/convert_legacy_video_factory.cc @@ -27,6 +27,7 @@ #include "media/engine/webrtcvideodecoderfactory.h" #include "media/engine/webrtcvideoencoderfactory.h" #include "rtc_base/checks.h" +#include "rtc_base/ptr_util.h" namespace cricket { @@ -95,44 +96,39 @@ class EncoderAdapter : public webrtc::VideoEncoderFactory { std::unique_ptr CreateVideoEncoder( const webrtc::SdpVideoFormat& format) { const VideoCodec codec(format); + + // Try creating internal encoder. + std::unique_ptr internal_encoder; + if (FindMatchingCodec(internal_encoder_factory_->supported_codecs(), + codec)) { + internal_encoder = + CodecNamesEq(format.name.c_str(), kVp8CodecName) + ? rtc::MakeUnique( + internal_encoder_factory_.get()) + : std::unique_ptr( + internal_encoder_factory_->CreateVideoEncoder(codec)); + } + // Try creating external encoder. + std::unique_ptr external_encoder; if (external_encoder_factory_ != nullptr && FindMatchingCodec(external_encoder_factory_->supported_codecs(), codec)) { - std::unique_ptr external_encoder; - if (CodecNamesEq(codec.name.c_str(), kVp8CodecName)) { - // If it's a codec type we can simulcast, create a wrapped encoder. - external_encoder = std::unique_ptr( - new webrtc::SimulcastEncoderAdapter( - external_encoder_factory_.get())); - } else { - external_encoder = - CreateScopedVideoEncoder(external_encoder_factory_.get(), codec); - } - if (external_encoder) { - return std::unique_ptr( - new webrtc::VideoEncoderSoftwareFallbackWrapper( - codec, std::move(external_encoder))); - } + external_encoder = CodecNamesEq(format.name.c_str(), kVp8CodecName) + ? rtc::MakeUnique( + external_encoder_factory_.get()) + : CreateScopedVideoEncoder( + external_encoder_factory_.get(), codec); } - // Try creating internal encoder. - if (FindMatchingCodec(internal_encoder_factory_->supported_codecs(), - codec)) { - if (CodecNamesEq(codec.name.c_str(), kVp8CodecName)) { - return std::unique_ptr( - new webrtc::VP8EncoderSimulcastProxy( - internal_encoder_factory_.get())); - } else { - return std::unique_ptr( - internal_encoder_factory_->CreateVideoEncoder(codec)); - } + if (internal_encoder && external_encoder) { + // Both internal SW encoder and external HW encoder available - create + // fallback encoder. + return rtc::MakeUnique( + std::move(internal_encoder), std::move(external_encoder)); } - - // This shouldn't happen, we should not be trying to create something we - // don't support. - RTC_NOTREACHED(); - return nullptr; + return external_encoder ? std::move(external_encoder) + : std::move(internal_encoder); } std::vector GetSupportedFormats() const { diff --git a/media/engine/videoencodersoftwarefallbackwrapper.cc b/media/engine/videoencodersoftwarefallbackwrapper.cc index 5e57c557f2..69254f5fb5 100644 --- a/media/engine/videoencodersoftwarefallbackwrapper.cc +++ b/media/engine/videoencodersoftwarefallbackwrapper.cc @@ -25,11 +25,8 @@ namespace { const char kVp8ForceFallbackEncoderFieldTrial[] = "WebRTC-VP8-Forced-Fallback-Encoder-v2"; -bool EnableForcedFallback(const cricket::VideoCodec& codec) { - if (!webrtc::field_trial::IsEnabled(kVp8ForceFallbackEncoderFieldTrial)) - return false; - - return (PayloadStringToCodecType(codec.name) == kVideoCodecVP8); +bool EnableForcedFallback() { + return field_trial::IsEnabled(kVp8ForceFallbackEncoderFieldTrial); } bool IsForcedFallbackPossible(const VideoCodec& codec_settings) { @@ -68,8 +65,8 @@ void GetForcedFallbackParamsFromFieldTrialGroup(int* param_min_pixels, } // namespace VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper( - const cricket::VideoCodec& codec, - std::unique_ptr encoder) + std::unique_ptr sw_encoder, + std::unique_ptr hw_encoder) : number_of_cores_(0), max_payload_size_(0), rates_set_(false), @@ -77,10 +74,11 @@ VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper( channel_parameters_set_(false), packet_loss_(0), rtt_(0), - codec_(codec), - encoder_(std::move(encoder)), + use_fallback_encoder_(false), + encoder_(std::move(hw_encoder)), + fallback_encoder_(std::move(sw_encoder)), callback_(nullptr), - forced_fallback_possible_(EnableForcedFallback(codec)) { + forced_fallback_possible_(EnableForcedFallback()) { if (forced_fallback_possible_) { GetForcedFallbackParamsFromFieldTrialGroup( &forced_fallback_.min_pixels_, &forced_fallback_.max_pixels_, @@ -91,20 +89,13 @@ VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper( bool VideoEncoderSoftwareFallbackWrapper::InitFallbackEncoder() { RTC_LOG(LS_WARNING) << "Encoder falling back to software encoding."; - MaybeModifyCodecForFallback(); - cricket::InternalEncoderFactory internal_factory; - if (!FindMatchingCodec(internal_factory.supported_codecs(), codec_)) { - RTC_LOG(LS_WARNING) - << "Encoder requesting fallback to codec not supported in software."; - 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) { + + const int ret = fallback_encoder_->InitEncode( + &codec_settings_, number_of_cores_, max_payload_size_); + use_fallback_encoder_ = (ret == WEBRTC_VIDEO_CODEC_OK); + if (!use_fallback_encoder_) { RTC_LOG(LS_ERROR) << "Failed to initialize software-encoder fallback."; fallback_encoder_->Release(); - fallback_encoder_.reset(); return false; } // Replay callback, rates, and channel parameters. @@ -148,13 +139,13 @@ int32_t VideoEncoderSoftwareFallbackWrapper::InitEncode( int32_t ret = encoder_->InitEncode(codec_settings, number_of_cores, max_payload_size); - if (ret == WEBRTC_VIDEO_CODEC_OK || codec_.name.empty()) { - if (fallback_encoder_) { + if (ret == WEBRTC_VIDEO_CODEC_OK) { + if (use_fallback_encoder_) { RTC_LOG(LS_WARNING) << "InitEncode OK, no longer using the software fallback encoder."; fallback_encoder_->Release(); + use_fallback_encoder_ = false; } - fallback_encoder_.reset(); if (callback_) encoder_->RegisterEncodeCompleteCallback(callback_); return ret; @@ -171,25 +162,21 @@ int32_t VideoEncoderSoftwareFallbackWrapper::RegisterEncodeCompleteCallback( EncodedImageCallback* callback) { callback_ = callback; int32_t ret = encoder_->RegisterEncodeCompleteCallback(callback); - if (fallback_encoder_) + if (use_fallback_encoder_) return fallback_encoder_->RegisterEncodeCompleteCallback(callback); return ret; } int32_t VideoEncoderSoftwareFallbackWrapper::Release() { - // If the fallback_encoder_ is non-null, it means it was created via - // InitFallbackEncoder which has Release()d encoder_, so we should only ever - // need to Release() whichever one is active. - if (fallback_encoder_) - return fallback_encoder_->Release(); - return encoder_->Release(); + return use_fallback_encoder_ ? fallback_encoder_->Release() + : encoder_->Release(); } int32_t VideoEncoderSoftwareFallbackWrapper::Encode( const VideoFrame& frame, const CodecSpecificInfo* codec_specific_info, const std::vector* frame_types) { - if (fallback_encoder_) + if (use_fallback_encoder_) return fallback_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. @@ -215,7 +202,7 @@ int32_t VideoEncoderSoftwareFallbackWrapper::SetChannelParameters( packet_loss_ = packet_loss; rtt_ = rtt; int32_t ret = encoder_->SetChannelParameters(packet_loss, rtt); - if (fallback_encoder_) + if (use_fallback_encoder_) return fallback_encoder_->SetChannelParameters(packet_loss, rtt); return ret; } @@ -227,15 +214,14 @@ int32_t VideoEncoderSoftwareFallbackWrapper::SetRateAllocation( bitrate_allocation_ = bitrate_allocation; framerate_ = framerate; int32_t ret = encoder_->SetRateAllocation(bitrate_allocation_, framerate); - if (fallback_encoder_) + if (use_fallback_encoder_) return fallback_encoder_->SetRateAllocation(bitrate_allocation_, framerate); return ret; } bool VideoEncoderSoftwareFallbackWrapper::SupportsNativeHandle() const { - if (fallback_encoder_) - return fallback_encoder_->SupportsNativeHandle(); - return encoder_->SupportsNativeHandle(); + return use_fallback_encoder_ ? fallback_encoder_->SupportsNativeHandle() + : encoder_->SupportsNativeHandle(); } VideoEncoder::ScalingSettings @@ -258,19 +244,18 @@ VideoEncoderSoftwareFallbackWrapper::GetScalingSettings() const { return encoder_->GetScalingSettings(); } -const char *VideoEncoderSoftwareFallbackWrapper::ImplementationName() const { - if (fallback_encoder_) - return fallback_encoder_->ImplementationName(); - return encoder_->ImplementationName(); +const char* VideoEncoderSoftwareFallbackWrapper::ImplementationName() const { + return use_fallback_encoder_ ? fallback_encoder_->ImplementationName() + : encoder_->ImplementationName(); } bool VideoEncoderSoftwareFallbackWrapper::IsForcedFallbackActive() const { - return (forced_fallback_possible_ && fallback_encoder_ && + return (forced_fallback_possible_ && use_fallback_encoder_ && forced_fallback_.active_); } bool VideoEncoderSoftwareFallbackWrapper::TryInitForcedFallbackEncoder() { - if (!forced_fallback_possible_ || fallback_encoder_) { + if (!forced_fallback_possible_ || use_fallback_encoder_) { return false; } // Fallback not active. @@ -313,20 +298,11 @@ void VideoEncoderSoftwareFallbackWrapper::ValidateSettingsForForcedFallback() { if (!IsForcedFallbackPossible(codec_settings_)) { if (IsForcedFallbackActive()) { fallback_encoder_->Release(); - fallback_encoder_.reset(); + use_fallback_encoder_ = false; } RTC_LOG(LS_INFO) << "Disable forced_fallback_possible_ due to settings."; 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 diff --git a/media/engine/videoencodersoftwarefallbackwrapper.h b/media/engine/videoencodersoftwarefallbackwrapper.h index 632298281b..a9a349c221 100644 --- a/media/engine/videoencodersoftwarefallbackwrapper.h +++ b/media/engine/videoencodersoftwarefallbackwrapper.h @@ -26,8 +26,8 @@ namespace webrtc { class VideoEncoderSoftwareFallbackWrapper : public VideoEncoder { public: VideoEncoderSoftwareFallbackWrapper( - const cricket::VideoCodec& codec, - std::unique_ptr encoder); + std::unique_ptr sw_encoder, + std::unique_ptr hw_encoder); int32_t InitEncode(const VideoCodec* codec_settings, int32_t number_of_cores, @@ -87,10 +87,10 @@ class VideoEncoderSoftwareFallbackWrapper : public VideoEncoder { uint32_t packet_loss_; int64_t rtt_; - cricket::VideoCodec codec_; - std::unique_ptr encoder_; + bool use_fallback_encoder_; + const std::unique_ptr encoder_; - std::unique_ptr fallback_encoder_; + const std::unique_ptr fallback_encoder_; EncodedImageCallback* callback_; bool forced_fallback_possible_; diff --git a/media/engine/videoencodersoftwarefallbackwrapper_unittest.cc b/media/engine/videoencodersoftwarefallbackwrapper_unittest.cc index 1ec325d844..e39b02f71c 100644 --- a/media/engine/videoencodersoftwarefallbackwrapper_unittest.cc +++ b/media/engine/videoencodersoftwarefallbackwrapper_unittest.cc @@ -13,6 +13,7 @@ #include #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/temporal_layers.h" #include "modules/video_coding/include/video_codec_interface.h" @@ -42,7 +43,7 @@ class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test { const std::string& field_trials) : override_field_trials_(field_trials), fake_encoder_(new CountingFakeEncoder()), - fallback_wrapper_(cricket::VideoCodec("VP8"), + fallback_wrapper_(std::unique_ptr(VP8Encoder::Create()), std::unique_ptr(fake_encoder_)) {} class CountingFakeEncoder : public VideoEncoder { diff --git a/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc b/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc index 34ec2a1d43..dc77605201 100644 --- a/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc +++ b/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc @@ -382,7 +382,9 @@ void VideoProcessorIntegrationTest::CreateEncoderAndDecoder() { if (config_.sw_fallback_encoder) { encoder_ = rtc::MakeUnique( - codec, std::move(encoder_)); + std::unique_ptr( + cricket::InternalEncoderFactory().CreateVideoEncoder(codec)), + std::move(encoder_)); } if (config_.sw_fallback_decoder) { decoder_ = rtc::MakeUnique(