Skip to content

Commit c98aebb

Browse files
Ilya NikolaevskiyWebRTC LUCI CQ
authored andcommitted
Change how alignment requirements are processed
Software fallback wrapper now reports least common multiple of requirements for two encoders. SimulcastEncoderAdapter queries actual encoder before InitEncode call and requests alignment for all layers if simulcast is not supported by any of the encoders. Bug: chromium:1084702 Change-Id: Iaed8190737125d447036b6c664b863be72556a5d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/225881 Reviewed-by: Niels Moller <[email protected]> Commit-Queue: Ilya Nikolaevskiy <[email protected]> Cr-Commit-Position: refs/heads/master@{#34466}
1 parent 2c38c9c commit c98aebb

File tree

4 files changed

+81
-17
lines changed

4 files changed

+81
-17
lines changed

api/video_codecs/video_encoder_software_fallback_wrapper.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "api/video/video_frame.h"
2626
#include "api/video_codecs/video_codec.h"
2727
#include "api/video_codecs/video_encoder.h"
28+
#include "media/base/video_common.h"
2829
#include "modules/video_coding/include/video_error_codes.h"
2930
#include "modules/video_coding/utility/simulcast_utility.h"
3031
#include "rtc_base/checks.h"
@@ -417,6 +418,13 @@ VideoEncoder::EncoderInfo VideoEncoderSoftwareFallbackWrapper::GetEncoderInfo()
417418
EncoderInfo info =
418419
IsFallbackActive() ? fallback_encoder_info : default_encoder_info;
419420

421+
info.requested_resolution_alignment = cricket::LeastCommonMultiple(
422+
fallback_encoder_info.requested_resolution_alignment,
423+
default_encoder_info.requested_resolution_alignment);
424+
info.apply_alignment_to_all_simulcast_layers =
425+
fallback_encoder_info.apply_alignment_to_all_simulcast_layers ||
426+
default_encoder_info.apply_alignment_to_all_simulcast_layers;
427+
420428
if (fallback_params_.has_value()) {
421429
const auto settings = (encoder_state_ == EncoderState::kForcedFallback)
422430
? fallback_encoder_info.scaling_settings

media/engine/simulcast_encoder_adapter.cc

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,13 @@ namespace webrtc {
149149

150150
SimulcastEncoderAdapter::EncoderContext::EncoderContext(
151151
std::unique_ptr<VideoEncoder> encoder,
152-
bool prefer_temporal_support)
152+
bool prefer_temporal_support,
153+
VideoEncoder::EncoderInfo primary_info,
154+
VideoEncoder::EncoderInfo fallback_info)
153155
: encoder_(std::move(encoder)),
154-
prefer_temporal_support_(prefer_temporal_support) {}
156+
prefer_temporal_support_(prefer_temporal_support),
157+
primary_info_(std::move(primary_info)),
158+
fallback_info_(std::move(fallback_info)) {}
155159

156160
void SimulcastEncoderAdapter::EncoderContext::Release() {
157161
if (encoder_) {
@@ -690,7 +694,7 @@ void SimulcastEncoderAdapter::DestroyStoredEncoders() {
690694

691695
std::unique_ptr<SimulcastEncoderAdapter::EncoderContext>
692696
SimulcastEncoderAdapter::FetchOrCreateEncoderContext(
693-
bool is_lowest_quality_stream) {
697+
bool is_lowest_quality_stream) const {
694698
bool prefer_temporal_support = fallback_encoder_factory_ != nullptr &&
695699
is_lowest_quality_stream &&
696700
prefer_temporal_support_on_base_layer_;
@@ -712,14 +716,20 @@ SimulcastEncoderAdapter::FetchOrCreateEncoderContext(
712716
} else {
713717
std::unique_ptr<VideoEncoder> encoder =
714718
primary_encoder_factory_->CreateVideoEncoder(video_format_);
719+
VideoEncoder::EncoderInfo primary_info = encoder->GetEncoderInfo();
720+
VideoEncoder::EncoderInfo fallback_info = primary_info;
715721
if (fallback_encoder_factory_ != nullptr) {
722+
std::unique_ptr<VideoEncoder> fallback_encoder =
723+
fallback_encoder_factory_->CreateVideoEncoder(video_format_);
724+
fallback_info = fallback_encoder->GetEncoderInfo();
716725
encoder = CreateVideoEncoderSoftwareFallbackWrapper(
717-
fallback_encoder_factory_->CreateVideoEncoder(video_format_),
718-
std::move(encoder), prefer_temporal_support);
726+
std::move(fallback_encoder), std::move(encoder),
727+
prefer_temporal_support);
719728
}
720729

721730
encoder_context = std::make_unique<SimulcastEncoderAdapter::EncoderContext>(
722-
std::move(encoder), prefer_temporal_support);
731+
std::move(encoder), prefer_temporal_support, primary_info,
732+
fallback_info);
723733
}
724734

725735
encoder_context->encoder().RegisterEncodeCompleteCallback(
@@ -789,9 +799,11 @@ webrtc::VideoCodec SimulcastEncoderAdapter::MakeStreamCodec(
789799
void SimulcastEncoderAdapter::OverrideFromFieldTrial(
790800
VideoEncoder::EncoderInfo* info) const {
791801
if (encoder_info_override_.requested_resolution_alignment()) {
792-
info->requested_resolution_alignment =
793-
*encoder_info_override_.requested_resolution_alignment();
802+
info->requested_resolution_alignment = cricket::LeastCommonMultiple(
803+
info->requested_resolution_alignment,
804+
*encoder_info_override_.requested_resolution_alignment());
794805
info->apply_alignment_to_all_simulcast_layers =
806+
info->apply_alignment_to_all_simulcast_layers ||
795807
encoder_info_override_.apply_alignment_to_all_simulcast_layers();
796808
}
797809
if (!encoder_info_override_.resolution_bitrate_limits().empty()) {
@@ -815,7 +827,34 @@ VideoEncoder::EncoderInfo SimulcastEncoderAdapter::GetEncoderInfo() const {
815827
encoder_info.apply_alignment_to_all_simulcast_layers = false;
816828
encoder_info.supports_native_handle = true;
817829
encoder_info.scaling_settings.thresholds = absl::nullopt;
830+
818831
if (stream_contexts_.empty()) {
832+
// GetEncoderInfo queried before InitEncode. Only alignment info is needed
833+
// to be filled.
834+
// Create one encoder and query it.
835+
836+
std::unique_ptr<SimulcastEncoderAdapter::EncoderContext> encoder_context =
837+
FetchOrCreateEncoderContext(true);
838+
839+
const VideoEncoder::EncoderInfo& primary_info =
840+
encoder_context->PrimaryInfo();
841+
const VideoEncoder::EncoderInfo& fallback_info =
842+
encoder_context->FallbackInfo();
843+
844+
encoder_info.requested_resolution_alignment = cricket::LeastCommonMultiple(
845+
primary_info.requested_resolution_alignment,
846+
fallback_info.requested_resolution_alignment);
847+
848+
encoder_info.apply_alignment_to_all_simulcast_layers =
849+
primary_info.apply_alignment_to_all_simulcast_layers ||
850+
fallback_info.apply_alignment_to_all_simulcast_layers;
851+
852+
if (!primary_info.supports_simulcast || !fallback_info.supports_simulcast) {
853+
encoder_info.apply_alignment_to_all_simulcast_layers = true;
854+
}
855+
856+
cached_encoder_contexts_.emplace_back(std::move(encoder_context));
857+
819858
OverrideFromFieldTrial(&encoder_info);
820859
return encoder_info;
821860
}
@@ -825,7 +864,6 @@ VideoEncoder::EncoderInfo SimulcastEncoderAdapter::GetEncoderInfo() const {
825864
for (size_t i = 0; i < stream_contexts_.size(); ++i) {
826865
VideoEncoder::EncoderInfo encoder_impl_info =
827866
stream_contexts_[i].encoder().GetEncoderInfo();
828-
829867
if (i == 0) {
830868
// Encoder name indicates names of all sub-encoders.
831869
encoder_info.implementation_name += " (";
@@ -864,7 +902,12 @@ VideoEncoder::EncoderInfo SimulcastEncoderAdapter::GetEncoderInfo() const {
864902
encoder_info.requested_resolution_alignment = cricket::LeastCommonMultiple(
865903
encoder_info.requested_resolution_alignment,
866904
encoder_impl_info.requested_resolution_alignment);
867-
if (encoder_impl_info.apply_alignment_to_all_simulcast_layers) {
905+
// request alignment on all layers if any of the encoders may need it, or
906+
// if any non-top layer encoder requests a non-trivial alignment.
907+
if (encoder_impl_info.apply_alignment_to_all_simulcast_layers ||
908+
(encoder_impl_info.requested_resolution_alignment > 1 &&
909+
(codec_.simulcastStream[i].height < codec_.height ||
910+
codec_.simulcastStream[i].width < codec_.width))) {
868911
encoder_info.apply_alignment_to_all_simulcast_layers = true;
869912
}
870913
}

media/engine/simulcast_encoder_adapter.h

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,24 @@ class RTC_EXPORT SimulcastEncoderAdapter : public VideoEncoder {
7171
class EncoderContext {
7272
public:
7373
EncoderContext(std::unique_ptr<VideoEncoder> encoder,
74-
bool prefer_temporal_support);
74+
bool prefer_temporal_support,
75+
VideoEncoder::EncoderInfo primary_info,
76+
VideoEncoder::EncoderInfo fallback_info);
7577
EncoderContext& operator=(EncoderContext&&) = delete;
7678

7779
VideoEncoder& encoder() { return *encoder_; }
7880
bool prefer_temporal_support() { return prefer_temporal_support_; }
7981
void Release();
8082

83+
const VideoEncoder::EncoderInfo& PrimaryInfo() { return primary_info_; }
84+
85+
const VideoEncoder::EncoderInfo& FallbackInfo() { return fallback_info_; }
86+
8187
private:
8288
std::unique_ptr<VideoEncoder> encoder_;
8389
bool prefer_temporal_support_;
90+
const VideoEncoder::EncoderInfo primary_info_;
91+
const VideoEncoder::EncoderInfo fallback_info_;
8492
};
8593

8694
class StreamContext : public EncodedImageCallback {
@@ -138,8 +146,11 @@ class RTC_EXPORT SimulcastEncoderAdapter : public VideoEncoder {
138146

139147
void DestroyStoredEncoders();
140148

149+
// This method creates encoder. May reuse previously created encoders from
150+
// |cached_encoder_contexts_|. It's const because it's used from
151+
// const GetEncoderInfo().
141152
std::unique_ptr<EncoderContext> FetchOrCreateEncoderContext(
142-
bool is_lowest_quality_stream);
153+
bool is_lowest_quality_stream) const;
143154

144155
webrtc::VideoCodec MakeStreamCodec(const webrtc::VideoCodec& codec,
145156
int stream_idx,
@@ -169,9 +180,11 @@ class RTC_EXPORT SimulcastEncoderAdapter : public VideoEncoder {
169180
// Used for checking the single-threaded access of the encoder interface.
170181
RTC_NO_UNIQUE_ADDRESS SequenceChecker encoder_queue_;
171182

172-
// Store encoders in between calls to Release and InitEncode, so they don't
173-
// have to be recreated. Remaining encoders are destroyed by the destructor.
174-
std::list<std::unique_ptr<EncoderContext>> cached_encoder_contexts_;
183+
// Store previously created and released encoders , so they don't have to be
184+
// recreated. Remaining encoders are destroyed by the destructor.
185+
// Marked as |mutable| becuase we may need to temporarily create encoder in
186+
// GetEncoderInfo(), which is const.
187+
mutable std::list<std::unique_ptr<EncoderContext>> cached_encoder_contexts_;
175188

176189
const absl::optional<unsigned int> experimental_boosted_screenshare_qp_;
177190
const bool boost_base_layer_quality_;

media/engine/simulcast_encoder_adapter_unittest.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -900,8 +900,6 @@ TEST_F(TestSimulcastEncoderAdapterFake, SetRatesUnderMinBitrate) {
900900
}
901901

902902
TEST_F(TestSimulcastEncoderAdapterFake, SupportsImplementationName) {
903-
EXPECT_EQ("SimulcastEncoderAdapter",
904-
adapter_->GetEncoderInfo().implementation_name);
905903
SimulcastTestFixtureImpl::DefaultSettings(
906904
&codec_, static_cast<const int*>(kTestTemporalLayerProfile),
907905
kVideoCodecVP8);
@@ -910,6 +908,8 @@ TEST_F(TestSimulcastEncoderAdapterFake, SupportsImplementationName) {
910908
encoder_names.push_back("codec2");
911909
encoder_names.push_back("codec3");
912910
helper_->factory()->SetEncoderNames(encoder_names);
911+
EXPECT_EQ("SimulcastEncoderAdapter",
912+
adapter_->GetEncoderInfo().implementation_name);
913913
EXPECT_EQ(0, adapter_->InitEncode(&codec_, kSettings));
914914
EXPECT_EQ("SimulcastEncoderAdapter (codec1, codec2, codec3)",
915915
adapter_->GetEncoderInfo().implementation_name);

0 commit comments

Comments
 (0)