diff --git a/media/BUILD.gn b/media/BUILD.gn index 515496b318..cc89bd098a 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn @@ -234,6 +234,8 @@ rtc_static_library("rtc_internal_video_codecs") { sources = [ "engine/convert_legacy_video_factory.cc", "engine/convert_legacy_video_factory.h", + "engine/fake_video_codec_factory.cc", + "engine/fake_video_codec_factory.h", "engine/internaldecoderfactory.cc", "engine/internaldecoderfactory.h", "engine/internalencoderfactory.cc", @@ -269,6 +271,7 @@ rtc_static_library("rtc_internal_video_codecs") { "../api/video_codecs:video_codecs_api", "../call:call_interfaces", "../call:video_stream_api", + "../modules:module_api", "../modules/video_coding:webrtc_h264", "../modules/video_coding:webrtc_multiplex", "../modules/video_coding:webrtc_vp8", @@ -277,6 +280,7 @@ rtc_static_library("rtc_internal_video_codecs") { "../rtc_base:deprecation", "../rtc_base:rtc_base_approved", "../rtc_base/system:rtc_export", + "../test:fake_video_codecs", "//third_party/abseil-cpp/absl/strings", ] } diff --git a/media/engine/fake_video_codec_factory.cc b/media/engine/fake_video_codec_factory.cc new file mode 100644 index 0000000000..aec351041e --- /dev/null +++ b/media/engine/fake_video_codec_factory.cc @@ -0,0 +1,76 @@ +/* + * 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 "media/engine/fake_video_codec_factory.h" + +#include "absl/memory/memory.h" +#include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_decoder.h" +#include "api/video_codecs/video_encoder.h" +#include "modules/include/module_common_types.h" +#include "modules/video_coding/include/video_codec_interface.h" +#include "modules/video_coding/include/video_error_codes.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" +#include "test/fake_decoder.h" +#include "test/fake_encoder.h" + +namespace { + +static const char kFakeCodecFactoryCodecName[] = "FakeCodec"; + +} // anonymous namespace + +namespace webrtc { + +FakeVideoEncoderFactory::FakeVideoEncoderFactory() = default; + +// static +std::unique_ptr FakeVideoEncoderFactory::CreateVideoEncoder() { + return absl::make_unique(Clock::GetRealTimeClock(), + 10000000); +} + +std::vector FakeVideoEncoderFactory::GetSupportedFormats() + const { + return std::vector( + 1, SdpVideoFormat(kFakeCodecFactoryCodecName)); +} + +VideoEncoderFactory::CodecInfo FakeVideoEncoderFactory::QueryVideoEncoder( + const SdpVideoFormat& format) const { + return VideoEncoderFactory::CodecInfo{false, false}; +} + +std::unique_ptr FakeVideoEncoderFactory::CreateVideoEncoder( + const SdpVideoFormat& format) { + return absl::make_unique(Clock::GetRealTimeClock(), + 10000000); +} + +FakeVideoDecoderFactory::FakeVideoDecoderFactory() = default; + +// static +std::unique_ptr FakeVideoDecoderFactory::CreateVideoDecoder() { + return absl::make_unique(); +} + +std::vector FakeVideoDecoderFactory::GetSupportedFormats() + const { + return std::vector( + 1, SdpVideoFormat(kFakeCodecFactoryCodecName)); +} + +std::unique_ptr FakeVideoDecoderFactory::CreateVideoDecoder( + const SdpVideoFormat& format) { + return absl::make_unique(); +} + +} // namespace webrtc diff --git a/media/engine/fake_video_codec_factory.h b/media/engine/fake_video_codec_factory.h new file mode 100644 index 0000000000..8e00418123 --- /dev/null +++ b/media/engine/fake_video_codec_factory.h @@ -0,0 +1,54 @@ +/* + * 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 MEDIA_ENGINE_FAKE_VIDEO_CODEC_FACTORY_H_ +#define MEDIA_ENGINE_FAKE_VIDEO_CODEC_FACTORY_H_ + +#include +#include + +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder_factory.h" + +namespace webrtc { + +// Provides a fake video encoder instance that produces frames large enough for +// the given bitrate constraints. +class FakeVideoEncoderFactory : public VideoEncoderFactory { + public: + FakeVideoEncoderFactory(); + + static std::unique_ptr CreateVideoEncoder(); + + // VideoEncoderFactory implementation + std::vector GetSupportedFormats() const override; + VideoEncoderFactory::CodecInfo QueryVideoEncoder( + const SdpVideoFormat& format) const override; + std::unique_ptr CreateVideoEncoder( + const SdpVideoFormat& format) override; +}; + +// Provides a fake video decoder instance that ignores the given bitstream and +// produces frames. +class FakeVideoDecoderFactory : public VideoDecoderFactory { + public: + FakeVideoDecoderFactory(); + + static std::unique_ptr CreateVideoDecoder(); + + // VideoDecoderFactory implementation + std::vector GetSupportedFormats() const override; + std::unique_ptr CreateVideoDecoder( + const SdpVideoFormat& format) override; +}; + +} // namespace webrtc + +#endif // MEDIA_ENGINE_FAKE_VIDEO_CODEC_FACTORY_H_ diff --git a/test/BUILD.gn b/test/BUILD.gn index ffa6d01ddb..a35abc8f54 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -589,7 +589,7 @@ rtc_source_set("single_threaded_task_queue") { } rtc_source_set("fake_video_codecs") { - testonly = true + allow_poison = [ "software_video_codecs" ] visibility = [ "*" ] sources = [ "configurable_frame_size_encoder.cc", diff --git a/test/fake_encoder.cc b/test/fake_encoder.cc index 06329c680a..e110d815b4 100644 --- a/test/fake_encoder.cc +++ b/test/fake_encoder.cc @@ -47,7 +47,9 @@ void WriteCounter(unsigned char* payload, uint32_t counter) { }; // namespace -FakeEncoder::FakeEncoder(Clock* clock) +FakeEncoder::FakeEncoder(Clock* clock) : FakeEncoder(clock, 100000) {} + +FakeEncoder::FakeEncoder(Clock* clock, size_t buffer_size) : clock_(clock), callback_(nullptr), configured_input_framerate_(-1), @@ -56,7 +58,8 @@ FakeEncoder::FakeEncoder(Clock* clock) counter_(0), debt_bytes_(0) { // Generate some arbitrary not-all-zero data - for (size_t i = 0; i < sizeof(encoded_buffer_); ++i) { + encoded_buffer_.resize(buffer_size); + for (size_t i = 0; i < encoded_buffer_.size(); ++i) { encoded_buffer_[i] = static_cast(i); } for (bool& used : used_layers_) { @@ -130,12 +133,12 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image, specifics.codecType = kVideoCodecGeneric; std::unique_ptr encoded_buffer( new uint8_t[frame_info.layers[i].size]); - memcpy(encoded_buffer.get(), encoded_buffer_, + memcpy(encoded_buffer.get(), encoded_buffer_.data(), frame_info.layers[i].size - 4); // Write a counter to the image to make each frame unique. WriteCounter(encoded_buffer.get() + frame_info.layers[i].size - 4, counter); EncodedImage encoded(encoded_buffer.get(), frame_info.layers[i].size, - sizeof(encoded_buffer_)); + encoded_buffer_.size()); encoded.SetTimestamp(input_image.timestamp()); encoded.capture_time_ms_ = input_image.render_time_ms(); encoded._frameType = diff --git a/test/fake_encoder.h b/test/fake_encoder.h index 753b1eaf7b..10cbc52e61 100644 --- a/test/fake_encoder.h +++ b/test/fake_encoder.h @@ -36,6 +36,7 @@ namespace test { class FakeEncoder : public VideoEncoder { public: explicit FakeEncoder(Clock* clock); + FakeEncoder(Clock* clock, size_t buffer_size); virtual ~FakeEncoder() = default; // Sets max bitrate. Not thread-safe, call before registering the encoder. @@ -91,7 +92,7 @@ class FakeEncoder : public VideoEncoder { uint32_t counter_ RTC_GUARDED_BY(crit_sect_); rtc::CriticalSection crit_sect_; - uint8_t encoded_buffer_[100000]; + std::vector encoded_buffer_; bool used_layers_[kMaxSimulcastStreams]; // Current byte debt to be payed over a number of frames. diff --git a/video/BUILD.gn b/video/BUILD.gn index 6b040c905b..1366b3aa5a 100644 --- a/video/BUILD.gn +++ b/video/BUILD.gn @@ -264,6 +264,7 @@ if (rtc_include_tests) { "../rtc_base:rtc_base_approved", "../rtc_base:rtc_base_tests_utils", "../system_wrappers", + "../test:fake_video_codecs", "../test:fileutils", "../test:perf_test", "../test:rtp_test_utils", diff --git a/video/full_stack_tests.cc b/video/full_stack_tests.cc index bceafe41c5..1e7f75f96e 100644 --- a/video/full_stack_tests.cc +++ b/video/full_stack_tests.cc @@ -1094,6 +1094,37 @@ TEST(FullStackTest, SimulcastVP8_3SL_Low) { fixture->RunWithAnalyzer(simulcast); } +// This test assumes ideal network conditions with target bandwidth being +// available and exercises WebRTC calls with a high target bitrate(100 Mbps). +TEST(FullStackTest, HighBitrateWithFakeCodec) { + auto fixture = CreateVideoQualityTestFixture(); + const int target_bitrate = 100000000; + ParamsWithLogging generator; + generator.call.send_side_bwe = true; + generator.call.call_bitrate_config.min_bitrate_bps = target_bitrate; + generator.call.call_bitrate_config.start_bitrate_bps = target_bitrate; + generator.call.call_bitrate_config.max_bitrate_bps = target_bitrate; + generator.video[0] = {true, + 360, + 240, + 30, + target_bitrate / 2, + target_bitrate, + target_bitrate * 2, + false, + "FakeCodec", + 1, + 0, + 0, + false, + false, + false, + "Generator"}; + generator.analyzer = {"high_bitrate_with_fake_codec", 0.0, 0.0, + kFullStackTestDurationSecs}; + fixture->RunWithAnalyzer(generator); +} + TEST(FullStackTest, LargeRoomVP8_5thumb) { auto fixture = CreateVideoQualityTestFixture(); ParamsWithLogging large_room; diff --git a/video/video_quality_test.cc b/video/video_quality_test.cc index 28b5f2a403..25cae31c00 100644 --- a/video/video_quality_test.cc +++ b/video/video_quality_test.cc @@ -23,6 +23,7 @@ #include "logging/rtc_event_log/output/rtc_event_log_output_file.h" #include "media/engine/adm_helpers.h" #include "media/engine/encoder_simulcast_proxy.h" +#include "media/engine/fake_video_codec_factory.h" #include "media/engine/internalencoderfactory.h" #include "media/engine/webrtcvideoengine.h" #include "modules/audio_device/include/audio_device.h" @@ -170,6 +171,8 @@ std::unique_ptr VideoQualityTest::CreateVideoDecoder( if (format.name == "multiplex") { decoder = absl::make_unique( &internal_decoder_factory_, SdpVideoFormat(cricket::kVp9CodecName)); + } else if (format.name == "FakeCodec") { + decoder = webrtc::FakeVideoDecoderFactory::CreateVideoDecoder(); } else { decoder = internal_decoder_factory_.CreateVideoDecoder(format); } @@ -194,6 +197,8 @@ std::unique_ptr VideoQualityTest::CreateVideoEncoder( } else if (format.name == "multiplex") { encoder = absl::make_unique( &internal_encoder_factory_, SdpVideoFormat(cricket::kVp9CodecName)); + } else if (format.name == "FakeCodec") { + encoder = webrtc::FakeVideoEncoderFactory::CreateVideoEncoder(); } else { encoder = internal_encoder_factory_.CreateVideoEncoder(format); } @@ -556,6 +561,8 @@ void VideoQualityTest::SetupVideo(Transport* send_transport, payload_type = kPayloadTypeVP9; } else if (params_.video[video_idx].codec == "multiplex") { payload_type = kPayloadTypeVP9; + } else if (params_.video[video_idx].codec == "FakeCodec") { + payload_type = kFakeVideoSendPayloadType; } else { RTC_NOTREACHED() << "Codec not supported!"; return;