Revert "Move FakeCodec to separate target and behave like real encoder."
This reverts commit 223eba5f72b5228847eeebaaef1c4305a29e8b3d. Reason for revert: Breaks perf tests and downstream projects. Original change's description: > Move FakeCodec to separate target and behave like real encoder. > > Add FakeVp8Encoder, change FakeEncoder to use BitrateAllocator for simulcast. > Change call_test to use VP8 payload name for simulcast tests. > > Bug: none > Change-Id: I5a34c52e66bbd6c05859729ed14ae87ac26b5969 > Reviewed-on: https://webrtc-review.googlesource.com/91861 > Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org> > Reviewed-by: Sebastian Jansson <srte@webrtc.org> > Reviewed-by: Erik Språng <sprang@webrtc.org> > Reviewed-by: Per Kjellander <perkj@webrtc.org> > Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> > Cr-Commit-Position: refs/heads/master@{#24359} TBR=mbonadei@webrtc.org,ilnik@webrtc.org,sprang@webrtc.org,srte@webrtc.org,perkj@webrtc.org Change-Id: I602acecb3f340cc8d737ca074bf52496593419c8 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: none Reviewed-on: https://webrtc-review.googlesource.com/95181 Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24365}
This commit is contained in:

committed by
Commit Bot

parent
ac50c6a204
commit
7d13a6e5b9
@ -347,13 +347,11 @@ if (rtc_include_tests) {
|
|||||||
"../system_wrappers",
|
"../system_wrappers",
|
||||||
"../test:audio_codec_mocks",
|
"../test:audio_codec_mocks",
|
||||||
"../test:direct_transport",
|
"../test:direct_transport",
|
||||||
"../test:fake_video_codecs",
|
|
||||||
"../test:field_trial",
|
"../test:field_trial",
|
||||||
"../test:test_common",
|
"../test:test_common",
|
||||||
"../test:test_support",
|
"../test:test_support",
|
||||||
"../test:video_test_common",
|
"../test:video_test_common",
|
||||||
"../video:video",
|
"../video:video",
|
||||||
"//testing/gmock",
|
|
||||||
"//testing/gtest",
|
"//testing/gtest",
|
||||||
"//third_party/abseil-cpp/absl/memory",
|
"//third_party/abseil-cpp/absl/memory",
|
||||||
]
|
]
|
||||||
@ -392,7 +390,6 @@ if (rtc_include_tests) {
|
|||||||
"../system_wrappers:metrics_default",
|
"../system_wrappers:metrics_default",
|
||||||
"../system_wrappers:runtime_enabled_features_default",
|
"../system_wrappers:runtime_enabled_features_default",
|
||||||
"../test:direct_transport",
|
"../test:direct_transport",
|
||||||
"../test:fake_video_codecs",
|
|
||||||
"../test:field_trial",
|
"../test:field_trial",
|
||||||
"../test:fileutils",
|
"../test:fileutils",
|
||||||
"../test:perf_test",
|
"../test:perf_test",
|
||||||
|
@ -357,9 +357,6 @@ void RtpVideoSender::OnBitrateAllocationUpdated(
|
|||||||
// inactive.
|
// inactive.
|
||||||
if (layer_bitrates[i]) {
|
if (layer_bitrates[i]) {
|
||||||
rtp_modules_[i]->SetVideoBitrateAllocation(*layer_bitrates[i]);
|
rtp_modules_[i]->SetVideoBitrateAllocation(*layer_bitrates[i]);
|
||||||
} else {
|
|
||||||
// Signal a 0 bitrate on a simulcast stream.
|
|
||||||
rtp_modules_[i]->SetVideoBitrateAllocation(VideoBitrateAllocation());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
DefaultVideoBitrateAllocator::DefaultVideoBitrateAllocator(
|
DefaultVideoBitrateAllocator::DefaultVideoBitrateAllocator(
|
||||||
@ -29,23 +27,14 @@ VideoBitrateAllocation DefaultVideoBitrateAllocator::GetAllocation(
|
|||||||
if (total_bitrate_bps == 0 || !codec_.active)
|
if (total_bitrate_bps == 0 || !codec_.active)
|
||||||
return allocation;
|
return allocation;
|
||||||
|
|
||||||
uint32_t allocated_bitrate_bps = total_bitrate_bps;
|
if (total_bitrate_bps < codec_.minBitrate * 1000) {
|
||||||
allocated_bitrate_bps =
|
allocation.SetBitrate(0, 0, codec_.minBitrate * 1000);
|
||||||
std::max(allocated_bitrate_bps, codec_.minBitrate * 1000);
|
} else if (codec_.maxBitrate > 0 &&
|
||||||
if (codec_.maxBitrate > 0) {
|
total_bitrate_bps > codec_.maxBitrate * 1000) {
|
||||||
allocated_bitrate_bps =
|
allocation.SetBitrate(0, 0, codec_.maxBitrate * 1000);
|
||||||
std::min(allocated_bitrate_bps, codec_.maxBitrate * 1000);
|
} else {
|
||||||
|
allocation.SetBitrate(0, 0, total_bitrate_bps);
|
||||||
}
|
}
|
||||||
size_t num_simulcast_streams =
|
|
||||||
std::max<size_t>(1, codec_.numberOfSimulcastStreams);
|
|
||||||
// The bitrate is split between all the streams in proportion of powers of 2
|
|
||||||
// e.g. 1:2, 1:2:4, etc.
|
|
||||||
for (size_t i = 0; i < num_simulcast_streams; i++) {
|
|
||||||
allocation.SetBitrate(
|
|
||||||
i, 0,
|
|
||||||
allocated_bitrate_bps * (1 << i) / ((1 << num_simulcast_streams) - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return allocation;
|
return allocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,32 +299,23 @@ if (rtc_include_tests) {
|
|||||||
rtc_test("test_support_unittests") {
|
rtc_test("test_support_unittests") {
|
||||||
deps = [
|
deps = [
|
||||||
":direct_transport",
|
":direct_transport",
|
||||||
":fake_video_codecs",
|
|
||||||
":fileutils",
|
":fileutils",
|
||||||
":fileutils_unittests",
|
|
||||||
":perf_test",
|
":perf_test",
|
||||||
":rtp_test_utils",
|
":rtp_test_utils",
|
||||||
":test_common",
|
|
||||||
":test_main",
|
":test_main",
|
||||||
":test_support",
|
":test_support",
|
||||||
":test_support_test_artifacts",
|
":test_support_test_artifacts",
|
||||||
":video_test_common",
|
":video_test_common",
|
||||||
":video_test_support",
|
":video_test_support",
|
||||||
"../api:create_simulcast_test_fixture_api",
|
|
||||||
"../api:simulcast_test_fixture_api",
|
|
||||||
"../api/video:video_frame_i420",
|
"../api/video:video_frame_i420",
|
||||||
"../modules/rtp_rtcp:rtp_rtcp",
|
"../modules/rtp_rtcp:rtp_rtcp",
|
||||||
"../modules/video_capture",
|
|
||||||
"../modules/video_coding:simulcast_test_fixture_impl",
|
|
||||||
"../rtc_base:rtc_base_approved",
|
"../rtc_base:rtc_base_approved",
|
||||||
"../test:single_threaded_task_queue",
|
"../test:single_threaded_task_queue",
|
||||||
"//testing/gmock",
|
|
||||||
"//testing/gtest",
|
"//testing/gtest",
|
||||||
"//third_party/abseil-cpp/absl/memory",
|
"//third_party/abseil-cpp/absl/memory",
|
||||||
]
|
]
|
||||||
sources = [
|
sources = [
|
||||||
"direct_transport_unittest.cc",
|
"direct_transport_unittest.cc",
|
||||||
"fake_vp8_encoder_unittest.cc",
|
|
||||||
"frame_generator_unittest.cc",
|
"frame_generator_unittest.cc",
|
||||||
"rtp_file_reader_unittest.cc",
|
"rtp_file_reader_unittest.cc",
|
||||||
"rtp_file_writer_unittest.cc",
|
"rtp_file_writer_unittest.cc",
|
||||||
@ -351,7 +342,6 @@ if (rtc_include_tests) {
|
|||||||
if (is_ios) {
|
if (is_ios) {
|
||||||
deps += [ ":test_support_unittests_bundle_data" ]
|
deps += [ ":test_support_unittests_bundle_data" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_android && !build_with_chromium) {
|
if (!is_android && !build_with_chromium) {
|
||||||
# This is needed in order to avoid:
|
# This is needed in order to avoid:
|
||||||
# undefined symbol: webrtc::videocapturemodule::VideoCaptureImpl::Create
|
# undefined symbol: webrtc::videocapturemodule::VideoCaptureImpl::Create
|
||||||
@ -498,46 +488,13 @@ rtc_source_set("single_threaded_task_queue") {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc_source_set("fake_video_codecs") {
|
|
||||||
testonly = true
|
|
||||||
visibility = [ "*" ]
|
|
||||||
sources = [
|
|
||||||
"configurable_frame_size_encoder.cc",
|
|
||||||
"configurable_frame_size_encoder.h",
|
|
||||||
"fake_decoder.cc",
|
|
||||||
"fake_decoder.h",
|
|
||||||
"fake_encoder.cc",
|
|
||||||
"fake_encoder.h",
|
|
||||||
"fake_vp8_encoder.cc",
|
|
||||||
"fake_vp8_encoder.h",
|
|
||||||
]
|
|
||||||
if (!build_with_chromium && is_clang) {
|
|
||||||
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
|
|
||||||
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
|
|
||||||
}
|
|
||||||
deps = [
|
|
||||||
"..:webrtc_common",
|
|
||||||
"../api/video:video_frame_i420",
|
|
||||||
"../api/video_codecs:video_codecs_api",
|
|
||||||
"../common_video:common_video",
|
|
||||||
"../modules/video_coding:video_codec_interface",
|
|
||||||
"../modules/video_coding:video_coding_utility",
|
|
||||||
"../modules/video_coding:webrtc_h264",
|
|
||||||
"../modules/video_coding:webrtc_vp8",
|
|
||||||
"../modules/video_coding:webrtc_vp9",
|
|
||||||
"../rtc_base:checks",
|
|
||||||
"../rtc_base:rtc_base_approved",
|
|
||||||
"../rtc_base:rtc_task_queue",
|
|
||||||
"../rtc_base:sequenced_task_checker",
|
|
||||||
"../system_wrappers",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc_source_set("test_common") {
|
rtc_source_set("test_common") {
|
||||||
testonly = true
|
testonly = true
|
||||||
sources = [
|
sources = [
|
||||||
"call_test.cc",
|
"call_test.cc",
|
||||||
"call_test.h",
|
"call_test.h",
|
||||||
|
"configurable_frame_size_encoder.cc",
|
||||||
|
"configurable_frame_size_encoder.h",
|
||||||
"constants.cc",
|
"constants.cc",
|
||||||
"constants.h",
|
"constants.h",
|
||||||
"drifting_clock.cc",
|
"drifting_clock.cc",
|
||||||
@ -545,6 +502,10 @@ rtc_source_set("test_common") {
|
|||||||
"encoder_proxy_factory.h",
|
"encoder_proxy_factory.h",
|
||||||
"encoder_settings.cc",
|
"encoder_settings.cc",
|
||||||
"encoder_settings.h",
|
"encoder_settings.h",
|
||||||
|
"fake_decoder.cc",
|
||||||
|
"fake_decoder.h",
|
||||||
|
"fake_encoder.cc",
|
||||||
|
"fake_encoder.h",
|
||||||
"fake_videorenderer.h",
|
"fake_videorenderer.h",
|
||||||
"function_video_decoder_factory.h",
|
"function_video_decoder_factory.h",
|
||||||
"function_video_encoder_factory.h",
|
"function_video_encoder_factory.h",
|
||||||
@ -573,17 +534,18 @@ rtc_source_set("test_common") {
|
|||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
":direct_transport",
|
":direct_transport",
|
||||||
":fake_video_codecs",
|
|
||||||
":fileutils",
|
":fileutils",
|
||||||
":rtp_test_utils",
|
":rtp_test_utils",
|
||||||
":test_support",
|
":test_support",
|
||||||
":video_test_common",
|
":video_test_common",
|
||||||
|
"..:webrtc_common",
|
||||||
"../api:libjingle_peerconnection_api",
|
"../api:libjingle_peerconnection_api",
|
||||||
"../api:simulated_network_api",
|
"../api:simulated_network_api",
|
||||||
"../api:transport_api",
|
"../api:transport_api",
|
||||||
"../api/audio_codecs:builtin_audio_decoder_factory",
|
"../api/audio_codecs:builtin_audio_decoder_factory",
|
||||||
"../api/audio_codecs:builtin_audio_encoder_factory",
|
"../api/audio_codecs:builtin_audio_encoder_factory",
|
||||||
"../api/video:video_frame",
|
"../api/video:video_frame",
|
||||||
|
"../api/video:video_frame_i420",
|
||||||
"../api/video_codecs:video_codecs_api",
|
"../api/video_codecs:video_codecs_api",
|
||||||
"../audio",
|
"../audio",
|
||||||
"../call",
|
"../call",
|
||||||
@ -593,6 +555,7 @@ rtc_source_set("test_common") {
|
|||||||
"../call:simulated_network",
|
"../call:simulated_network",
|
||||||
"../call:simulated_packet_receiver",
|
"../call:simulated_packet_receiver",
|
||||||
"../call:video_stream_api",
|
"../call:video_stream_api",
|
||||||
|
"../common_video",
|
||||||
"../logging:rtc_event_log_api",
|
"../logging:rtc_event_log_api",
|
||||||
"../logging:rtc_event_log_impl_base",
|
"../logging:rtc_event_log_impl_base",
|
||||||
"../media:rtc_internal_video_codecs",
|
"../media:rtc_internal_video_codecs",
|
||||||
@ -606,6 +569,7 @@ rtc_source_set("test_common") {
|
|||||||
"../modules/rtp_rtcp",
|
"../modules/rtp_rtcp",
|
||||||
"../modules/rtp_rtcp:mock_rtp_rtcp",
|
"../modules/rtp_rtcp:mock_rtp_rtcp",
|
||||||
"../modules/rtp_rtcp:rtp_rtcp_format",
|
"../modules/rtp_rtcp:rtp_rtcp_format",
|
||||||
|
"../modules/video_coding:video_codec_interface",
|
||||||
"../modules/video_coding:video_coding_utility",
|
"../modules/video_coding:video_coding_utility",
|
||||||
"../modules/video_coding:webrtc_h264",
|
"../modules/video_coding:webrtc_h264",
|
||||||
"../modules/video_coding:webrtc_multiplex",
|
"../modules/video_coding:webrtc_multiplex",
|
||||||
@ -613,6 +577,8 @@ rtc_source_set("test_common") {
|
|||||||
"../modules/video_coding:webrtc_vp9",
|
"../modules/video_coding:webrtc_vp9",
|
||||||
"../rtc_base:checks",
|
"../rtc_base:checks",
|
||||||
"../rtc_base:rtc_base_approved",
|
"../rtc_base:rtc_base_approved",
|
||||||
|
"../rtc_base:rtc_task_queue",
|
||||||
|
"../rtc_base:sequenced_task_checker",
|
||||||
"../rtc_base/experiments:congestion_controller_experiment",
|
"../rtc_base/experiments:congestion_controller_experiment",
|
||||||
"../system_wrappers",
|
"../system_wrappers",
|
||||||
"../system_wrappers:field_trial_api",
|
"../system_wrappers:field_trial_api",
|
||||||
|
@ -43,14 +43,9 @@ CallTest::CallTest()
|
|||||||
audio_send_stream_(nullptr),
|
audio_send_stream_(nullptr),
|
||||||
bbr_network_controller_factory_(new BbrNetworkControllerFactory()),
|
bbr_network_controller_factory_(new BbrNetworkControllerFactory()),
|
||||||
fake_encoder_factory_([this]() {
|
fake_encoder_factory_([this]() {
|
||||||
std::unique_ptr<FakeEncoder> fake_encoder;
|
auto encoder = absl::make_unique<test::FakeEncoder>(clock_);
|
||||||
if (video_encoder_configs_[0].codec_type == kVideoCodecVP8) {
|
encoder->SetMaxBitrate(fake_encoder_max_bitrate_);
|
||||||
fake_encoder = absl::make_unique<FakeVP8Encoder>(clock_);
|
return encoder;
|
||||||
} else {
|
|
||||||
fake_encoder = absl::make_unique<FakeEncoder>(clock_);
|
|
||||||
}
|
|
||||||
fake_encoder->SetMaxBitrate(fake_encoder_max_bitrate_);
|
|
||||||
return fake_encoder;
|
|
||||||
}),
|
}),
|
||||||
num_video_streams_(1),
|
num_video_streams_(1),
|
||||||
num_audio_streams_(0),
|
num_audio_streams_(0),
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include "test/encoder_settings.h"
|
#include "test/encoder_settings.h"
|
||||||
#include "test/fake_decoder.h"
|
#include "test/fake_decoder.h"
|
||||||
#include "test/fake_videorenderer.h"
|
#include "test/fake_videorenderer.h"
|
||||||
#include "test/fake_vp8_encoder.h"
|
|
||||||
#include "test/frame_generator_capturer.h"
|
#include "test/frame_generator_capturer.h"
|
||||||
#include "test/function_video_encoder_factory.h"
|
#include "test/function_video_encoder_factory.h"
|
||||||
#include "test/rtp_rtcp_observer.h"
|
#include "test/rtp_rtcp_observer.h"
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "common_video/include/video_frame.h"
|
#include "common_video/include/video_frame.h"
|
||||||
#include "modules/video_coding/include/video_codec_interface.h"
|
#include "modules/video_coding/include/video_codec_interface.h"
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
|
#include "test/gtest.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
@ -22,7 +22,7 @@ namespace test {
|
|||||||
class ConfigurableFrameSizeEncoder : public VideoEncoder {
|
class ConfigurableFrameSizeEncoder : public VideoEncoder {
|
||||||
public:
|
public:
|
||||||
explicit ConfigurableFrameSizeEncoder(size_t max_frame_size);
|
explicit ConfigurableFrameSizeEncoder(size_t max_frame_size);
|
||||||
~ConfigurableFrameSizeEncoder() override;
|
virtual ~ConfigurableFrameSizeEncoder();
|
||||||
|
|
||||||
int32_t InitEncode(const VideoCodec* codec_settings,
|
int32_t InitEncode(const VideoCodec* codec_settings,
|
||||||
int32_t number_of_cores,
|
int32_t number_of_cores,
|
||||||
|
@ -12,17 +12,16 @@
|
|||||||
|
|
||||||
#include "api/video/i420_buffer.h"
|
#include "api/video/i420_buffer.h"
|
||||||
#include "rtc_base/timeutils.h"
|
#include "rtc_base/timeutils.h"
|
||||||
|
#include "test/call_test.h"
|
||||||
|
#include "test/gtest.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
namespace {
|
|
||||||
const int kDefaultWidth = 320;
|
|
||||||
const int kDefaultHeight = 180;
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
FakeDecoder::FakeDecoder()
|
FakeDecoder::FakeDecoder()
|
||||||
: callback_(NULL), width_(kDefaultWidth), height_(kDefaultHeight) {}
|
: callback_(NULL),
|
||||||
|
width_(CallTest::kDefaultWidth),
|
||||||
|
height_(CallTest::kDefaultHeight) {}
|
||||||
|
|
||||||
int32_t FakeDecoder::InitDecode(const VideoCodec* config,
|
int32_t FakeDecoder::InitDecode(const VideoCodec* config,
|
||||||
int32_t number_of_cores) {
|
int32_t number_of_cores) {
|
||||||
@ -76,7 +75,7 @@ int32_t FakeH264Decoder::Decode(const EncodedImage& input,
|
|||||||
i += sizeof(kStartCode) + 1; // Skip start code and NAL header.
|
i += sizeof(kStartCode) + 1; // Skip start code and NAL header.
|
||||||
}
|
}
|
||||||
if (input._buffer[i] != value) {
|
if (input._buffer[i] != value) {
|
||||||
RTC_CHECK_EQ(value, input._buffer[i])
|
EXPECT_EQ(value, input._buffer[i])
|
||||||
<< "Bitstream mismatch between sender and receiver.";
|
<< "Bitstream mismatch between sender and receiver.";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "common_types.h" // NOLINT(build/include)
|
#include "common_types.h" // NOLINT(build/include)
|
||||||
#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"
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "system_wrappers/include/sleep.h"
|
#include "system_wrappers/include/sleep.h"
|
||||||
|
#include "test/gtest.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace test {
|
namespace test {
|
||||||
@ -37,9 +37,6 @@ FakeEncoder::FakeEncoder(Clock* clock)
|
|||||||
for (size_t i = 0; i < sizeof(encoded_buffer_); ++i) {
|
for (size_t i = 0; i < sizeof(encoded_buffer_); ++i) {
|
||||||
encoded_buffer_[i] = static_cast<uint8_t>(i);
|
encoded_buffer_[i] = static_cast<uint8_t>(i);
|
||||||
}
|
}
|
||||||
for (bool& used : used_layers_) {
|
|
||||||
used = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeEncoder::SetMaxBitrate(int max_kbps) {
|
void FakeEncoder::SetMaxBitrate(int max_kbps) {
|
||||||
@ -56,7 +53,6 @@ int32_t FakeEncoder::InitEncode(const VideoCodec* config,
|
|||||||
target_bitrate_.SetBitrate(0, 0, config_.startBitrate * 1000);
|
target_bitrate_.SetBitrate(0, 0, config_.startBitrate * 1000);
|
||||||
configured_input_framerate_ = config_.maxFramerate;
|
configured_input_framerate_ = config_.maxFramerate;
|
||||||
pending_keyframe_ = true;
|
pending_keyframe_ = true;
|
||||||
last_frame_info_ = FrameInfo();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +63,9 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
|
|||||||
unsigned char num_simulcast_streams;
|
unsigned char num_simulcast_streams;
|
||||||
SimulcastStream simulcast_streams[kMaxSimulcastStreams];
|
SimulcastStream simulcast_streams[kMaxSimulcastStreams];
|
||||||
EncodedImageCallback* callback;
|
EncodedImageCallback* callback;
|
||||||
VideoBitrateAllocation target_bitrate;
|
uint32_t target_bitrate_sum_kbps;
|
||||||
|
int max_target_bitrate_kbps;
|
||||||
|
size_t num_encoded_bytes;
|
||||||
int framerate;
|
int framerate;
|
||||||
VideoCodecMode mode;
|
VideoCodecMode mode;
|
||||||
bool keyframe;
|
bool keyframe;
|
||||||
@ -79,7 +77,9 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
|
|||||||
simulcast_streams[i] = config_.simulcastStream[i];
|
simulcast_streams[i] = config_.simulcastStream[i];
|
||||||
}
|
}
|
||||||
callback = callback_;
|
callback = callback_;
|
||||||
target_bitrate = target_bitrate_;
|
target_bitrate_sum_kbps = target_bitrate_.get_sum_kbps();
|
||||||
|
max_target_bitrate_kbps = max_target_bitrate_kbps_;
|
||||||
|
num_encoded_bytes = sizeof(encoded_buffer_);
|
||||||
mode = config_.mode;
|
mode = config_.mode;
|
||||||
if (configured_input_framerate_ > 0) {
|
if (configured_input_framerate_ > 0) {
|
||||||
framerate = configured_input_framerate_;
|
framerate = configured_input_framerate_;
|
||||||
@ -90,28 +90,63 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
|
|||||||
pending_keyframe_ = false;
|
pending_keyframe_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameInfo frame_info =
|
for (FrameType frame_type : *frame_types) {
|
||||||
NextFrame(frame_types, keyframe, num_simulcast_streams, target_bitrate,
|
if (frame_type == kVideoFrameKey) {
|
||||||
simulcast_streams, framerate);
|
keyframe = true;
|
||||||
for (uint8_t i = 0; i < frame_info.layers.size(); ++i) {
|
break;
|
||||||
if (frame_info.layers[i].size == 0) {
|
|
||||||
// Drop this temporal layer.
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RTC_DCHECK_GT(max_framerate, 0);
|
||||||
|
|
||||||
|
size_t bitrate =
|
||||||
|
std::max(target_bitrate_sum_kbps, simulcast_streams[0].minBitrate);
|
||||||
|
if (max_target_bitrate_kbps > 0)
|
||||||
|
bitrate = std::min(bitrate, static_cast<size_t>(max_target_bitrate_kbps));
|
||||||
|
|
||||||
|
size_t bits_available = bitrate * 1000 / framerate;
|
||||||
|
|
||||||
|
RTC_DCHECK_GT(num_simulcast_streams, 0);
|
||||||
|
for (unsigned char i = 0; i < num_simulcast_streams; ++i) {
|
||||||
CodecSpecificInfo specifics;
|
CodecSpecificInfo specifics;
|
||||||
memset(&specifics, 0, sizeof(specifics));
|
memset(&specifics, 0, sizeof(specifics));
|
||||||
specifics.codecType = kVideoCodecGeneric;
|
specifics.codecType = kVideoCodecGeneric;
|
||||||
specifics.codecSpecific.generic.simulcast_idx = i;
|
specifics.codecSpecific.generic.simulcast_idx = i;
|
||||||
std::unique_ptr<uint8_t[]> encoded_buffer(
|
size_t min_stream_bits = static_cast<size_t>(
|
||||||
new uint8_t[frame_info.layers[i].size]);
|
(simulcast_streams[i].minBitrate * 1000) / framerate);
|
||||||
memcpy(encoded_buffer.get(), encoded_buffer_, frame_info.layers[i].size);
|
size_t max_stream_bits = static_cast<size_t>(
|
||||||
EncodedImage encoded(encoded_buffer.get(), frame_info.layers[i].size,
|
(simulcast_streams[i].maxBitrate * 1000) / framerate);
|
||||||
sizeof(encoded_buffer_));
|
size_t stream_bits =
|
||||||
encoded._timeStamp = input_image.timestamp();
|
(bits_available > max_stream_bits) ? max_stream_bits : bits_available;
|
||||||
|
size_t stream_bytes = (stream_bits + 7) / 8;
|
||||||
|
if (keyframe) {
|
||||||
|
// The first frame is a key frame and should be larger.
|
||||||
|
// Store the overshoot bytes and distribute them over the coming frames,
|
||||||
|
// so that we on average meet the bitrate target.
|
||||||
|
debt_bytes_ += (kKeyframeSizeFactor - 1) * stream_bytes;
|
||||||
|
stream_bytes *= kKeyframeSizeFactor;
|
||||||
|
} else {
|
||||||
|
if (debt_bytes_ > 0) {
|
||||||
|
// Pay at most half of the frame size for old debts.
|
||||||
|
size_t payment_size = std::min(stream_bytes / 2, debt_bytes_);
|
||||||
|
debt_bytes_ -= payment_size;
|
||||||
|
stream_bytes -= payment_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream_bytes > num_encoded_bytes)
|
||||||
|
stream_bytes = num_encoded_bytes;
|
||||||
|
|
||||||
|
// Always encode something on the first frame.
|
||||||
|
if (min_stream_bits > bits_available && i > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::unique_ptr<uint8_t[]> encoded_buffer(new uint8_t[num_encoded_bytes]);
|
||||||
|
memcpy(encoded_buffer.get(), encoded_buffer_, num_encoded_bytes);
|
||||||
|
EncodedImage encoded(encoded_buffer.get(), stream_bytes, num_encoded_bytes);
|
||||||
|
encoded.SetTimestamp(input_image.timestamp());
|
||||||
encoded.capture_time_ms_ = input_image.render_time_ms();
|
encoded.capture_time_ms_ = input_image.render_time_ms();
|
||||||
encoded._frameType =
|
encoded._frameType = (*frame_types)[i];
|
||||||
frame_info.keyframe ? kVideoFrameKey : kVideoFrameDelta;
|
|
||||||
encoded._encodedWidth = simulcast_streams[i].width;
|
encoded._encodedWidth = simulcast_streams[i].width;
|
||||||
encoded._encodedHeight = simulcast_streams[i].height;
|
encoded._encodedHeight = simulcast_streams[i].height;
|
||||||
encoded.rotation_ = input_image.rotation();
|
encoded.rotation_ = input_image.rotation();
|
||||||
@ -119,77 +154,17 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
|
|||||||
? VideoContentType::SCREENSHARE
|
? VideoContentType::SCREENSHARE
|
||||||
: VideoContentType::UNSPECIFIED;
|
: VideoContentType::UNSPECIFIED;
|
||||||
specifics.codec_name = ImplementationName();
|
specifics.codec_name = ImplementationName();
|
||||||
|
specifics.codecSpecific.generic.simulcast_idx = i;
|
||||||
|
RTC_DCHECK(callback);
|
||||||
if (callback->OnEncodedImage(encoded, &specifics, nullptr).error !=
|
if (callback->OnEncodedImage(encoded, &specifics, nullptr).error !=
|
||||||
EncodedImageCallback::Result::OK) {
|
EncodedImageCallback::Result::OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
bits_available -= std::min(encoded._length * 8, bits_available);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FakeEncoder::FrameInfo FakeEncoder::NextFrame(
|
|
||||||
const std::vector<FrameType>* frame_types,
|
|
||||||
bool keyframe,
|
|
||||||
uint8_t num_simulcast_streams,
|
|
||||||
const VideoBitrateAllocation& target_bitrate,
|
|
||||||
SimulcastStream simulcast_streams[kMaxSimulcastStreams],
|
|
||||||
int framerate) {
|
|
||||||
FrameInfo frame_info;
|
|
||||||
frame_info.keyframe = keyframe;
|
|
||||||
|
|
||||||
if (frame_types) {
|
|
||||||
for (FrameType frame_type : *frame_types) {
|
|
||||||
if (frame_type == kVideoFrameKey) {
|
|
||||||
frame_info.keyframe = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < num_simulcast_streams; ++i) {
|
|
||||||
if (target_bitrate.GetBitrate(i, 0) > 0) {
|
|
||||||
int temporal_id = last_frame_info_.layers.size() > i
|
|
||||||
? ++last_frame_info_.layers[i].temporal_id %
|
|
||||||
simulcast_streams[i].numberOfTemporalLayers
|
|
||||||
: 0;
|
|
||||||
frame_info.layers.emplace_back(0, temporal_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last_frame_info_.layers.size() < frame_info.layers.size()) {
|
|
||||||
// A new keyframe is needed since a new layer will be added.
|
|
||||||
frame_info.keyframe = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < frame_info.layers.size(); ++i) {
|
|
||||||
FrameInfo::SpatialLayer& layer_info = frame_info.layers[i];
|
|
||||||
if (frame_info.keyframe) {
|
|
||||||
layer_info.temporal_id = 0;
|
|
||||||
size_t avg_frame_size =
|
|
||||||
(target_bitrate.GetBitrate(i, 0) + 7) / (8 * framerate);
|
|
||||||
|
|
||||||
// The first frame is a key frame and should be larger.
|
|
||||||
// Store the overshoot bytes and distribute them over the coming frames,
|
|
||||||
// so that we on average meet the bitrate target.
|
|
||||||
debt_bytes_ += (kKeyframeSizeFactor - 1) * avg_frame_size;
|
|
||||||
layer_info.size = kKeyframeSizeFactor * avg_frame_size;
|
|
||||||
} else {
|
|
||||||
size_t avg_frame_size =
|
|
||||||
(target_bitrate.GetBitrate(i, layer_info.temporal_id) + 7) /
|
|
||||||
(8 * framerate);
|
|
||||||
layer_info.size = avg_frame_size;
|
|
||||||
if (debt_bytes_ > 0) {
|
|
||||||
// Pay at most half of the frame size for old debts.
|
|
||||||
size_t payment_size = std::min(avg_frame_size / 2, debt_bytes_);
|
|
||||||
debt_bytes_ -= payment_size;
|
|
||||||
layer_info.size -= payment_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
last_frame_info_ = frame_info;
|
|
||||||
return frame_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t FakeEncoder::RegisterEncodeCompleteCallback(
|
int32_t FakeEncoder::RegisterEncodeCompleteCallback(
|
||||||
EncodedImageCallback* callback) {
|
EncodedImageCallback* callback) {
|
||||||
rtc::CritScope cs(&crit_sect_);
|
rtc::CritScope cs(&crit_sect_);
|
||||||
|
@ -50,30 +50,7 @@ class FakeEncoder : public VideoEncoder {
|
|||||||
static const char* kImplementationName;
|
static const char* kImplementationName;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct FrameInfo {
|
|
||||||
bool keyframe;
|
|
||||||
struct SpatialLayer {
|
|
||||||
SpatialLayer() = default;
|
|
||||||
SpatialLayer(int size, int temporal_id)
|
|
||||||
: size(size), temporal_id(temporal_id) {}
|
|
||||||
// Size of a current frame in the layer.
|
|
||||||
int size = 0;
|
|
||||||
// Temporal index of a current frame in the layer.
|
|
||||||
int temporal_id = 0;
|
|
||||||
};
|
|
||||||
std::vector<SpatialLayer> layers;
|
|
||||||
};
|
|
||||||
|
|
||||||
FrameInfo NextFrame(const std::vector<FrameType>* frame_types,
|
|
||||||
bool keyframe,
|
|
||||||
uint8_t num_simulcast_streams,
|
|
||||||
const VideoBitrateAllocation& target_bitrate,
|
|
||||||
SimulcastStream simulcast_streams[kMaxSimulcastStreams],
|
|
||||||
int framerate);
|
|
||||||
|
|
||||||
FrameInfo last_frame_info_;
|
|
||||||
Clock* const clock_;
|
Clock* const clock_;
|
||||||
|
|
||||||
VideoCodec config_ RTC_GUARDED_BY(crit_sect_);
|
VideoCodec config_ RTC_GUARDED_BY(crit_sect_);
|
||||||
EncodedImageCallback* callback_ RTC_GUARDED_BY(crit_sect_);
|
EncodedImageCallback* callback_ RTC_GUARDED_BY(crit_sect_);
|
||||||
VideoBitrateAllocation target_bitrate_ RTC_GUARDED_BY(crit_sect_);
|
VideoBitrateAllocation target_bitrate_ RTC_GUARDED_BY(crit_sect_);
|
||||||
@ -83,7 +60,6 @@ class FakeEncoder : public VideoEncoder {
|
|||||||
rtc::CriticalSection crit_sect_;
|
rtc::CriticalSection crit_sect_;
|
||||||
|
|
||||||
uint8_t encoded_buffer_[100000];
|
uint8_t encoded_buffer_[100000];
|
||||||
bool used_layers_[kMaxSimulcastStreams];
|
|
||||||
|
|
||||||
// Current byte debt to be payed over a number of frames.
|
// Current byte debt to be payed over a number of frames.
|
||||||
// The debt is acquired by keyframes overshooting the bitrate target.
|
// The debt is acquired by keyframes overshooting the bitrate target.
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 "test/fake_vp8_encoder.h"
|
|
||||||
|
|
||||||
#include "common_types.h" // NOLINT(build/include)
|
|
||||||
#include "modules/video_coding/codecs/vp8/temporal_layers.h"
|
|
||||||
#include "modules/video_coding/include/video_codec_interface.h"
|
|
||||||
#include "modules/video_coding/include/video_error_codes.h"
|
|
||||||
#include "modules/video_coding/utility/simulcast_utility.h"
|
|
||||||
#include "rtc_base/checks.h"
|
|
||||||
#include "rtc_base/logging.h"
|
|
||||||
#include "rtc_base/random.h"
|
|
||||||
#include "rtc_base/timeutils.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
FakeVP8Encoder::FakeVP8Encoder(Clock* clock)
|
|
||||||
: FakeEncoder(clock), callback_(nullptr) {
|
|
||||||
FakeEncoder::RegisterEncodeCompleteCallback(this);
|
|
||||||
sequence_checker_.Detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t FakeVP8Encoder::RegisterEncodeCompleteCallback(
|
|
||||||
EncodedImageCallback* callback) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
|
||||||
callback_ = callback;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t FakeVP8Encoder::InitEncode(const VideoCodec* config,
|
|
||||||
int32_t number_of_cores,
|
|
||||||
size_t max_payload_size) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
|
||||||
auto result =
|
|
||||||
FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
|
|
||||||
if (result != WEBRTC_VIDEO_CODEC_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int number_of_streams = SimulcastUtility::NumberOfSimulcastStreams(*config);
|
|
||||||
bool doing_simulcast = number_of_streams > 1;
|
|
||||||
|
|
||||||
int num_temporal_layers =
|
|
||||||
doing_simulcast ? config->simulcastStream[0].numberOfTemporalLayers
|
|
||||||
: config->VP8().numberOfTemporalLayers;
|
|
||||||
RTC_DCHECK_GT(num_temporal_layers, 0);
|
|
||||||
|
|
||||||
SetupTemporalLayers(number_of_streams, num_temporal_layers, *config);
|
|
||||||
|
|
||||||
return WEBRTC_VIDEO_CODEC_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t FakeVP8Encoder::Release() {
|
|
||||||
auto result = FakeEncoder::Release();
|
|
||||||
sequence_checker_.Detach();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FakeVP8Encoder::SetupTemporalLayers(int num_streams,
|
|
||||||
int num_temporal_layers,
|
|
||||||
const VideoCodec& codec) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
|
||||||
|
|
||||||
temporal_layers_.clear();
|
|
||||||
for (int i = 0; i < num_streams; ++i) {
|
|
||||||
temporal_layers_.emplace_back(
|
|
||||||
TemporalLayers::CreateTemporalLayers(codec, i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FakeVP8Encoder::PopulateCodecSpecific(
|
|
||||||
CodecSpecificInfo* codec_specific,
|
|
||||||
const TemporalLayers::FrameConfig& tl_config,
|
|
||||||
FrameType frame_type,
|
|
||||||
int stream_idx,
|
|
||||||
uint32_t timestamp) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
|
||||||
codec_specific->codecType = kVideoCodecVP8;
|
|
||||||
codec_specific->codec_name = ImplementationName();
|
|
||||||
CodecSpecificInfoVP8* vp8Info = &(codec_specific->codecSpecific.VP8);
|
|
||||||
vp8Info->simulcastIdx = stream_idx;
|
|
||||||
vp8Info->keyIdx = kNoKeyIdx;
|
|
||||||
vp8Info->nonReference = false;
|
|
||||||
temporal_layers_[stream_idx]->PopulateCodecSpecific(
|
|
||||||
frame_type == kVideoFrameKey, tl_config, vp8Info, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
EncodedImageCallback::Result FakeVP8Encoder::OnEncodedImage(
|
|
||||||
const EncodedImage& encoded_image,
|
|
||||||
const CodecSpecificInfo* codec_specific_info,
|
|
||||||
const RTPFragmentationHeader* fragments) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
|
||||||
uint8_t stream_idx = codec_specific_info->codecSpecific.generic.simulcast_idx;
|
|
||||||
CodecSpecificInfo overrided_specific_info;
|
|
||||||
TemporalLayers::FrameConfig tl_config =
|
|
||||||
temporal_layers_[stream_idx]->UpdateLayerConfig(encoded_image._timeStamp);
|
|
||||||
PopulateCodecSpecific(&overrided_specific_info, tl_config,
|
|
||||||
encoded_image._frameType, stream_idx,
|
|
||||||
encoded_image._timeStamp);
|
|
||||||
temporal_layers_[stream_idx]->FrameEncoded(encoded_image._timeStamp,
|
|
||||||
encoded_image._length, -1);
|
|
||||||
|
|
||||||
return callback_->OnEncodedImage(encoded_image, &overrided_specific_info,
|
|
||||||
fragments);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace webrtc
|
|
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 TEST_FAKE_VP8_ENCODER_H_
|
|
||||||
#define TEST_FAKE_VP8_ENCODER_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "modules/video_coding/codecs/vp8/temporal_layers.h"
|
|
||||||
#include "test/fake_encoder.h"
|
|
||||||
|
|
||||||
#include "rtc_base/criticalsection.h"
|
|
||||||
#include "rtc_base/sequenced_task_checker.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
class FakeVP8Encoder : public FakeEncoder, public EncodedImageCallback {
|
|
||||||
public:
|
|
||||||
explicit FakeVP8Encoder(Clock* clock);
|
|
||||||
virtual ~FakeVP8Encoder() = default;
|
|
||||||
|
|
||||||
int32_t RegisterEncodeCompleteCallback(
|
|
||||||
EncodedImageCallback* callback) override;
|
|
||||||
|
|
||||||
int32_t InitEncode(const VideoCodec* config,
|
|
||||||
int32_t number_of_cores,
|
|
||||||
size_t max_payload_size) override;
|
|
||||||
|
|
||||||
int32_t Release() override;
|
|
||||||
|
|
||||||
const char* ImplementationName() const override { return "FakeVp8Encoder"; }
|
|
||||||
|
|
||||||
Result OnEncodedImage(const EncodedImage& encodedImage,
|
|
||||||
const CodecSpecificInfo* codecSpecificInfo,
|
|
||||||
const RTPFragmentationHeader* fragments) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void SetupTemporalLayers(int num_streams,
|
|
||||||
int num_temporal_layers,
|
|
||||||
const VideoCodec& codec);
|
|
||||||
void PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
|
|
||||||
const TemporalLayers::FrameConfig& tl_config,
|
|
||||||
FrameType frame_type,
|
|
||||||
int stream_idx,
|
|
||||||
uint32_t timestamp);
|
|
||||||
|
|
||||||
rtc::SequencedTaskChecker sequence_checker_;
|
|
||||||
EncodedImageCallback* callback_ RTC_GUARDED_BY(sequence_checker_);
|
|
||||||
|
|
||||||
std::vector<std::unique_ptr<TemporalLayers>> temporal_layers_
|
|
||||||
RTC_GUARDED_BY(sequence_checker_);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace webrtc
|
|
||||||
|
|
||||||
#endif // TEST_FAKE_VP8_ENCODER_H_
|
|
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <memory>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "absl/memory/memory.h"
|
|
||||||
#include "api/test/create_simulcast_test_fixture.h"
|
|
||||||
#include "api/test/simulcast_test_fixture.h"
|
|
||||||
#include "modules/video_coding/utility/simulcast_test_fixture_impl.h"
|
|
||||||
#include "test/fake_decoder.h"
|
|
||||||
#include "test/fake_vp8_encoder.h"
|
|
||||||
#include "test/function_video_decoder_factory.h"
|
|
||||||
#include "test/function_video_encoder_factory.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
namespace test {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
std::unique_ptr<SimulcastTestFixture> CreateSpecificSimulcastTestFixture() {
|
|
||||||
std::unique_ptr<VideoEncoderFactory> encoder_factory =
|
|
||||||
absl::make_unique<FunctionVideoEncoderFactory>([]() {
|
|
||||||
return absl::make_unique<FakeVP8Encoder>(Clock::GetRealTimeClock());
|
|
||||||
});
|
|
||||||
std::unique_ptr<VideoDecoderFactory> decoder_factory =
|
|
||||||
absl::make_unique<FunctionVideoDecoderFactory>(
|
|
||||||
[]() { return absl::make_unique<FakeDecoder>(); });
|
|
||||||
return CreateSimulcastTestFixture(std::move(encoder_factory),
|
|
||||||
std::move(decoder_factory),
|
|
||||||
SdpVideoFormat("VP8"));
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
TEST(TestFakeVp8Codec, TestKeyFrameRequestsOnAllStreams) {
|
|
||||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
|
||||||
fixture->TestKeyFrameRequestsOnAllStreams();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestFakeVp8Codec, TestPaddingAllStreams) {
|
|
||||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
|
||||||
fixture->TestPaddingAllStreams();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestFakeVp8Codec, TestPaddingTwoStreams) {
|
|
||||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
|
||||||
fixture->TestPaddingTwoStreams();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestFakeVp8Codec, TestPaddingTwoStreamsOneMaxedOut) {
|
|
||||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
|
||||||
fixture->TestPaddingTwoStreamsOneMaxedOut();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestFakeVp8Codec, TestPaddingOneStream) {
|
|
||||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
|
||||||
fixture->TestPaddingOneStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestFakeVp8Codec, TestPaddingOneStreamTwoMaxedOut) {
|
|
||||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
|
||||||
fixture->TestPaddingOneStreamTwoMaxedOut();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestFakeVp8Codec, TestSendAllStreams) {
|
|
||||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
|
||||||
fixture->TestSendAllStreams();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestFakeVp8Codec, TestDisablingStreams) {
|
|
||||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
|
||||||
fixture->TestDisablingStreams();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestFakeVp8Codec, TestSwitchingToOneStream) {
|
|
||||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
|
||||||
fixture->TestSwitchingToOneStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestFakeVp8Codec, TestSwitchingToOneOddStream) {
|
|
||||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
|
||||||
fixture->TestSwitchingToOneOddStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestFakeVp8Codec, TestSwitchingToOneSmallStream) {
|
|
||||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
|
||||||
fixture->TestSwitchingToOneSmallStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TestFakeVp8Codec, TestSpatioTemporalLayers333PatternEncoder) {
|
|
||||||
auto fixture = CreateSpecificSimulcastTestFixture();
|
|
||||||
fixture->TestSpatioTemporalLayers333PatternEncoder();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace test
|
|
||||||
} // namespace webrtc
|
|
@ -361,7 +361,6 @@ if (rtc_include_tests) {
|
|||||||
"../system_wrappers",
|
"../system_wrappers",
|
||||||
"../system_wrappers:metrics_default",
|
"../system_wrappers:metrics_default",
|
||||||
"../system_wrappers:runtime_enabled_features_default",
|
"../system_wrappers:runtime_enabled_features_default",
|
||||||
"../test:fake_video_codecs",
|
|
||||||
"../test:field_trial",
|
"../test:field_trial",
|
||||||
"../test:rtp_test_utils",
|
"../test:rtp_test_utils",
|
||||||
"../test:run_test",
|
"../test:run_test",
|
||||||
@ -473,7 +472,6 @@ if (rtc_include_tests) {
|
|||||||
"../system_wrappers:metrics_api",
|
"../system_wrappers:metrics_api",
|
||||||
"../system_wrappers:metrics_default",
|
"../system_wrappers:metrics_default",
|
||||||
"../test:direct_transport",
|
"../test:direct_transport",
|
||||||
"../test:fake_video_codecs",
|
|
||||||
"../test:field_trial",
|
"../test:field_trial",
|
||||||
"../test:fileutils",
|
"../test:fileutils",
|
||||||
"../test:perf_test",
|
"../test:perf_test",
|
||||||
|
@ -30,12 +30,7 @@ class RtcpXrObserver : public test::EndToEndTest {
|
|||||||
sent_rtcp_rrtr_(0),
|
sent_rtcp_rrtr_(0),
|
||||||
sent_rtcp_target_bitrate_(false),
|
sent_rtcp_target_bitrate_(false),
|
||||||
sent_zero_rtcp_target_bitrate_(false),
|
sent_zero_rtcp_target_bitrate_(false),
|
||||||
sent_rtcp_dlrr_(0),
|
sent_rtcp_dlrr_(0) {}
|
||||||
send_transport_(nullptr) {
|
|
||||||
forward_transport_config_.link_capacity_kbps = 500;
|
|
||||||
forward_transport_config_.queue_delay_ms = 0;
|
|
||||||
forward_transport_config_.loss_percent = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Receive stream should send RR packets (and RRTR packets if enabled).
|
// Receive stream should send RR packets (and RRTR packets if enabled).
|
||||||
@ -61,14 +56,6 @@ class RtcpXrObserver : public test::EndToEndTest {
|
|||||||
test::RtcpPacketParser parser;
|
test::RtcpPacketParser parser;
|
||||||
EXPECT_TRUE(parser.Parse(packet, length));
|
EXPECT_TRUE(parser.Parse(packet, length));
|
||||||
|
|
||||||
if (parser.sender_ssrc() == test::CallTest::kVideoSendSsrcs[1] &&
|
|
||||||
enable_zero_target_bitrate_) {
|
|
||||||
// Reduce bandwidth restriction to disable second stream after it was
|
|
||||||
// enabled for some time.
|
|
||||||
forward_transport_config_.link_capacity_kbps = 200;
|
|
||||||
send_transport_->SetConfig(forward_transport_config_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sent_rtcp_sr_ += parser.sender_report()->num_packets();
|
sent_rtcp_sr_ += parser.sender_report()->num_packets();
|
||||||
EXPECT_LE(parser.xr()->num_packets(), 1);
|
EXPECT_LE(parser.xr()->num_packets(), 1);
|
||||||
if (parser.xr()->num_packets() > 0) {
|
if (parser.xr()->num_packets() > 0) {
|
||||||
@ -77,12 +64,8 @@ class RtcpXrObserver : public test::EndToEndTest {
|
|||||||
++sent_rtcp_dlrr_;
|
++sent_rtcp_dlrr_;
|
||||||
if (parser.xr()->target_bitrate()) {
|
if (parser.xr()->target_bitrate()) {
|
||||||
sent_rtcp_target_bitrate_ = true;
|
sent_rtcp_target_bitrate_ = true;
|
||||||
auto target_bitrates =
|
for (const rtcp::TargetBitrate::BitrateItem& item :
|
||||||
parser.xr()->target_bitrate()->GetTargetBitrates();
|
parser.xr()->target_bitrate()->GetTargetBitrates()) {
|
||||||
if (target_bitrates.empty()) {
|
|
||||||
sent_zero_rtcp_target_bitrate_ = true;
|
|
||||||
}
|
|
||||||
for (const rtcp::TargetBitrate::BitrateItem& item : target_bitrates) {
|
|
||||||
if (item.target_bitrate_kbps == 0) {
|
if (item.target_bitrate_kbps == 0) {
|
||||||
sent_zero_rtcp_target_bitrate_ = true;
|
sent_zero_rtcp_target_bitrate_ = true;
|
||||||
break;
|
break;
|
||||||
@ -115,20 +98,39 @@ class RtcpXrObserver : public test::EndToEndTest {
|
|||||||
return enable_zero_target_bitrate_ ? 2 : 1;
|
return enable_zero_target_bitrate_ ? 2 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
test::PacketTransport* CreateSendTransport(
|
// This test uses VideoStream settings different from the the default one
|
||||||
test::SingleThreadedTaskQueueForTesting* task_queue,
|
// implemented in DefaultVideoStreamFactory, so it implements its own
|
||||||
Call* sender_call) {
|
// VideoEncoderConfig::VideoStreamFactoryInterface which is created
|
||||||
send_transport_ = new test::PacketTransport(
|
// in ModifyVideoConfigs.
|
||||||
task_queue, sender_call, this, test::PacketTransport::kSender,
|
class ZeroTargetVideoStreamFactory
|
||||||
test::CallTest::payload_type_map_, forward_transport_config_);
|
: public VideoEncoderConfig::VideoStreamFactoryInterface {
|
||||||
return send_transport_;
|
public:
|
||||||
}
|
ZeroTargetVideoStreamFactory() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<VideoStream> CreateEncoderStreams(
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
const VideoEncoderConfig& encoder_config) override {
|
||||||
|
std::vector<VideoStream> streams =
|
||||||
|
test::CreateVideoStreams(width, height, encoder_config);
|
||||||
|
// Set one of the streams' target bitrates to zero to test that a
|
||||||
|
// bitrate of 0 can be signalled.
|
||||||
|
streams[encoder_config.number_of_streams - 1].min_bitrate_bps = 0;
|
||||||
|
streams[encoder_config.number_of_streams - 1].target_bitrate_bps = 0;
|
||||||
|
streams[encoder_config.number_of_streams - 1].max_bitrate_bps = 0;
|
||||||
|
return streams;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void ModifyVideoConfigs(
|
void ModifyVideoConfigs(
|
||||||
VideoSendStream::Config* send_config,
|
VideoSendStream::Config* send_config,
|
||||||
std::vector<VideoReceiveStream::Config>* receive_configs,
|
std::vector<VideoReceiveStream::Config>* receive_configs,
|
||||||
VideoEncoderConfig* encoder_config) override {
|
VideoEncoderConfig* encoder_config) override {
|
||||||
if (enable_zero_target_bitrate_) {
|
if (enable_zero_target_bitrate_) {
|
||||||
|
encoder_config->video_stream_factory =
|
||||||
|
new rtc::RefCountedObject<ZeroTargetVideoStreamFactory>();
|
||||||
|
|
||||||
// Configure VP8 to be able to use simulcast.
|
// Configure VP8 to be able to use simulcast.
|
||||||
send_config->rtp.payload_name = "VP8";
|
send_config->rtp.payload_name = "VP8";
|
||||||
encoder_config->codec_type = kVideoCodecVP8;
|
encoder_config->codec_type = kVideoCodecVP8;
|
||||||
@ -164,8 +166,6 @@ class RtcpXrObserver : public test::EndToEndTest {
|
|||||||
bool sent_rtcp_target_bitrate_ RTC_GUARDED_BY(&crit_);
|
bool sent_rtcp_target_bitrate_ RTC_GUARDED_BY(&crit_);
|
||||||
bool sent_zero_rtcp_target_bitrate_ RTC_GUARDED_BY(&crit_);
|
bool sent_zero_rtcp_target_bitrate_ RTC_GUARDED_BY(&crit_);
|
||||||
int sent_rtcp_dlrr_;
|
int sent_rtcp_dlrr_;
|
||||||
DefaultNetworkSimulationConfig forward_transport_config_;
|
|
||||||
test::PacketTransport* send_transport_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(ExtendedReportsEndToEndTest,
|
TEST_F(ExtendedReportsEndToEndTest,
|
||||||
|
Reference in New Issue
Block a user