summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/test
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/libwebrtc/test/BUILD.gn11
-rw-r--r--third_party/libwebrtc/test/OWNERS1
-rw-r--r--third_party/libwebrtc/test/call_test.cc2
-rw-r--r--third_party/libwebrtc/test/fake_decoder.cc2
-rw-r--r--third_party/libwebrtc/test/frame_generator_capturer.cc10
-rw-r--r--third_party/libwebrtc/test/frame_generator_capturer.h6
-rw-r--r--third_party/libwebrtc/test/fuzzers/BUILD.gn38
-rw-r--r--third_party/libwebrtc/test/fuzzers/audio_processing_configs_fuzzer.cc17
-rw-r--r--third_party/libwebrtc/test/fuzzers/corpora/receive-side-cc/testcase-5414098152390656bin0 -> 87 bytes
-rw-r--r--third_party/libwebrtc/test/fuzzers/rtp_format_h264_fuzzer.cc75
-rw-r--r--third_party/libwebrtc/test/fuzzers/rtp_format_vp8_fuzzer.cc73
-rw-r--r--third_party/libwebrtc/test/fuzzers/rtp_format_vp9_fuzzer.cc73
-rw-r--r--third_party/libwebrtc/test/network/BUILD.gn4
-rw-r--r--third_party/libwebrtc/test/network/cross_traffic_unittest.cc2
-rw-r--r--third_party/libwebrtc/test/network/network_emulation.cc17
-rw-r--r--third_party/libwebrtc/test/network/network_emulation.h16
-rw-r--r--third_party/libwebrtc/test/network/network_emulation_manager.cc19
-rw-r--r--third_party/libwebrtc/test/network/network_emulation_manager.h4
-rw-r--r--third_party/libwebrtc/test/network/network_emulation_pc_unittest.cc3
-rw-r--r--third_party/libwebrtc/test/pc/e2e/BUILD.gn3
-rw-r--r--third_party/libwebrtc/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc24
-rw-r--r--third_party/libwebrtc/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc16
-rw-r--r--third_party/libwebrtc/test/pc/e2e/cross_media_metrics_reporter.cc12
-rw-r--r--third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.cc9
-rw-r--r--third_party/libwebrtc/test/pc/e2e/peer_connection_quality_test.cc2
-rw-r--r--third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.cc18
-rw-r--r--third_party/libwebrtc/test/pc/e2e/test_peer_factory.cc9
-rw-r--r--third_party/libwebrtc/test/pc/e2e/test_peer_factory.h6
-rw-r--r--third_party/libwebrtc/test/peer_scenario/peer_scenario_client.cc3
-rw-r--r--third_party/libwebrtc/test/run_loop_unittest.cc2
-rw-r--r--third_party/libwebrtc/test/scenario/audio_stream.cc2
-rw-r--r--third_party/libwebrtc/test/scenario/video_stream.cc3
-rw-r--r--third_party/libwebrtc/test/time_controller/BUILD.gn3
-rw-r--r--third_party/libwebrtc/test/time_controller/external_time_controller_unittest.cc42
-rw-r--r--third_party/libwebrtc/test/time_controller/real_time_controller.cc5
-rw-r--r--third_party/libwebrtc/test/time_controller/real_time_controller.h3
-rw-r--r--third_party/libwebrtc/test/time_controller/simulated_time_controller.cc3
-rw-r--r--third_party/libwebrtc/test/time_controller/simulated_time_controller.h1
-rw-r--r--third_party/libwebrtc/test/time_controller/simulated_time_controller_unittest.cc38
-rw-r--r--third_party/libwebrtc/test/video_codec_tester.cc338
-rw-r--r--third_party/libwebrtc/test/video_codec_tester_unittest.cc513
41 files changed, 1054 insertions, 374 deletions
diff --git a/third_party/libwebrtc/test/BUILD.gn b/third_party/libwebrtc/test/BUILD.gn
index 854530c01e..75d8d9f3a8 100644
--- a/third_party/libwebrtc/test/BUILD.gn
+++ b/third_party/libwebrtc/test/BUILD.gn
@@ -167,7 +167,6 @@ rtc_library("frame_generator_capturer") {
"../rtc_base:checks",
"../rtc_base:logging",
"../rtc_base:macromagic",
- "../rtc_base:rtc_task_queue",
"../rtc_base/synchronization:mutex",
"../rtc_base/task_utils:repeating_task",
"../system_wrappers",
@@ -215,7 +214,6 @@ rtc_library("video_test_common") {
"../rtc_base:criticalsection",
"../rtc_base:logging",
"../rtc_base:refcount",
- "../rtc_base:rtc_task_queue",
"../rtc_base:timeutils",
"../rtc_base/synchronization:mutex",
"../rtc_base/task_utils:repeating_task",
@@ -737,13 +735,17 @@ if (rtc_include_tests) {
"../api:mock_video_encoder",
"../api:scoped_refptr",
"../api:simulcast_test_fixture_api",
+ "../api/task_queue",
"../api/task_queue:task_queue_test",
"../api/test/video:function_video_factory",
"../api/test/video:video_frame_writer",
"../api/units:data_rate",
+ "../api/units:data_size",
+ "../api/units:frequency",
"../api/units:time_delta",
"../api/video:encoded_image",
"../api/video:video_frame",
+ "../api/video_codecs:scalability_mode",
"../api/video_codecs:video_codecs_api",
"../call:video_stream_api",
"../common_video",
@@ -760,7 +762,6 @@ if (rtc_include_tests) {
"../modules/video_coding/svc:scalability_mode_util",
"../rtc_base:criticalsection",
"../rtc_base:rtc_event",
- "../rtc_base:rtc_task_queue",
"../rtc_base/synchronization:mutex",
"../rtc_base/system:file_wrapper",
"jitter:jitter_unittests",
@@ -1022,7 +1023,6 @@ rtc_library("fake_video_codecs") {
"../rtc_base:checks",
"../rtc_base:criticalsection",
"../rtc_base:macromagic",
- "../rtc_base:rtc_task_queue",
"../rtc_base:timeutils",
"../rtc_base/synchronization:mutex",
"../system_wrappers",
@@ -1395,6 +1395,7 @@ rtc_library("video_codec_tester") {
"video_codec_tester.h",
]
deps = [
+ ":scoped_key_value_config",
"../api:array_view",
"../api/numerics:numerics",
"../api/test/metrics:metric",
@@ -1413,6 +1414,7 @@ rtc_library("video_codec_tester") {
"../media:media_constants",
"../modules/video_coding:video_codec_interface",
"../modules/video_coding:video_coding_utility",
+ "../modules/video_coding:webrtc_h264",
"../modules/video_coding:webrtc_vp9_helpers",
"../modules/video_coding/codecs/av1:av1_svc_config",
"../modules/video_coding/svc:scalability_mode_util",
@@ -1426,6 +1428,7 @@ rtc_library("video_codec_tester") {
"../system_wrappers",
"../test:fileutils",
"../test:video_test_support",
+ "../video/config:streams_config",
"//third_party/libyuv",
]
diff --git a/third_party/libwebrtc/test/OWNERS b/third_party/libwebrtc/test/OWNERS
index a1bd812244..f747873741 100644
--- a/third_party/libwebrtc/test/OWNERS
+++ b/third_party/libwebrtc/test/OWNERS
@@ -2,6 +2,5 @@ sprang@webrtc.org
srte@webrtc.org
stefan@webrtc.org
titovartem@webrtc.org
-landrey@webrtc.org
mbonadei@webrtc.org
jleconte@webrtc.org
diff --git a/third_party/libwebrtc/test/call_test.cc b/third_party/libwebrtc/test/call_test.cc
index 09099cccd6..6cdd8da133 100644
--- a/third_party/libwebrtc/test/call_test.cc
+++ b/third_party/libwebrtc/test/call_test.cc
@@ -572,7 +572,7 @@ void CallTest::CreateVideoSendStreams() {
if (fec_controller_factory_.get()) {
video_send_streams_[i] = sender_call_->CreateVideoSendStream(
video_send_configs_[i].Copy(), video_encoder_configs_[i].Copy(),
- fec_controller_factory_->CreateFecController());
+ fec_controller_factory_->CreateFecController(send_env_));
} else {
video_send_streams_[i] = sender_call_->CreateVideoSendStream(
video_send_configs_[i].Copy(), video_encoder_configs_[i].Copy());
diff --git a/third_party/libwebrtc/test/fake_decoder.cc b/third_party/libwebrtc/test/fake_decoder.cc
index 01d95bfeb4..12bff8d36c 100644
--- a/third_party/libwebrtc/test/fake_decoder.cc
+++ b/third_party/libwebrtc/test/fake_decoder.cc
@@ -15,13 +15,13 @@
#include <memory>
#include "api/scoped_refptr.h"
+#include "api/task_queue/task_queue_factory.h"
#include "api/video/i420_buffer.h"
#include "api/video/video_frame.h"
#include "api/video/video_frame_buffer.h"
#include "api/video/video_rotation.h"
#include "modules/video_coding/include/video_error_codes.h"
#include "rtc_base/checks.h"
-#include "rtc_base/task_queue.h"
#include "rtc_base/time_utils.h"
namespace webrtc {
diff --git a/third_party/libwebrtc/test/frame_generator_capturer.cc b/third_party/libwebrtc/test/frame_generator_capturer.cc
index 6ba0807a74..7cdfec2cc2 100644
--- a/third_party/libwebrtc/test/frame_generator_capturer.cc
+++ b/third_party/libwebrtc/test/frame_generator_capturer.cc
@@ -29,7 +29,6 @@
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/synchronization/mutex.h"
-#include "rtc_base/task_queue.h"
#include "rtc_base/task_utils/repeating_task.h"
#include "system_wrappers/include/clock.h"
#include "test/test_video_capturer.h"
@@ -58,6 +57,9 @@ FrameGeneratorCapturer::FrameGeneratorCapturer(
FrameGeneratorCapturer::~FrameGeneratorCapturer() {
Stop();
+ // Deconstruct first as tasks in the TaskQueue access other fields of the
+ // instance of this class.
+ task_queue_ = nullptr;
}
void FrameGeneratorCapturer::SetFakeRotation(VideoRotation rotation) {
@@ -78,7 +80,7 @@ bool FrameGeneratorCapturer::Init() {
return false;
frame_task_ = RepeatingTaskHandle::DelayedStart(
- task_queue_.Get(),
+ task_queue_.get(),
TimeDelta::Seconds(1) / GetCurrentConfiguredFramerate(),
[this] {
InsertFrame();
@@ -131,7 +133,7 @@ void FrameGeneratorCapturer::Start() {
}
if (!frame_task_.Running()) {
frame_task_ = RepeatingTaskHandle::Start(
- task_queue_.Get(),
+ task_queue_.get(),
[this] {
InsertFrame();
return TimeDelta::Seconds(1) / GetCurrentConfiguredFramerate();
@@ -219,7 +221,7 @@ void FrameGeneratorCapturer::UpdateFps(int max_fps) {
void FrameGeneratorCapturer::ForceFrame() {
// One-time non-repeating task,
- task_queue_.PostTask([this] { InsertFrame(); });
+ task_queue_->PostTask([this] { InsertFrame(); });
}
int FrameGeneratorCapturer::GetCurrentConfiguredFramerate() {
diff --git a/third_party/libwebrtc/test/frame_generator_capturer.h b/third_party/libwebrtc/test/frame_generator_capturer.h
index 6824ba681e..bb0c445c53 100644
--- a/third_party/libwebrtc/test/frame_generator_capturer.h
+++ b/third_party/libwebrtc/test/frame_generator_capturer.h
@@ -15,6 +15,7 @@
#include <memory>
#include "absl/types/optional.h"
+#include "api/task_queue/task_queue_base.h"
#include "api/task_queue/task_queue_factory.h"
#include "api/test/frame_generator_interface.h"
#include "api/video/color_space.h"
@@ -23,7 +24,6 @@
#include "api/video/video_sink_interface.h"
#include "api/video/video_source_interface.h"
#include "rtc_base/synchronization/mutex.h"
-#include "rtc_base/task_queue.h"
#include "rtc_base/task_utils/repeating_task.h"
#include "rtc_base/thread_annotations.h"
#include "system_wrappers/include/clock.h"
@@ -106,9 +106,7 @@ class FrameGeneratorCapturer : public TestVideoCapturer {
int64_t first_frame_capture_time_;
- // Must be the last field, so it will be deconstructed first as tasks
- // in the TaskQueue access other fields of the instance of this class.
- rtc::TaskQueue task_queue_;
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue_;
};
} // namespace test
} // namespace webrtc
diff --git a/third_party/libwebrtc/test/fuzzers/BUILD.gn b/third_party/libwebrtc/test/fuzzers/BUILD.gn
index 43e9a5e922..083c20c6f4 100644
--- a/third_party/libwebrtc/test/fuzzers/BUILD.gn
+++ b/third_party/libwebrtc/test/fuzzers/BUILD.gn
@@ -238,6 +238,36 @@ webrtc_fuzzer_test("rtp_packetizer_av1_fuzzer") {
]
}
+webrtc_fuzzer_test("rtp_format_h264_fuzzer") {
+ sources = [ "rtp_format_h264_fuzzer.cc" ]
+ deps = [
+ "../../api/video:video_frame_type",
+ "../../modules/rtp_rtcp:rtp_rtcp",
+ "../../modules/rtp_rtcp:rtp_rtcp_format",
+ "../../rtc_base:checks",
+ ]
+}
+
+webrtc_fuzzer_test("rtp_format_vp8_fuzzer") {
+ sources = [ "rtp_format_vp8_fuzzer.cc" ]
+ deps = [
+ "../../api/video:video_frame_type",
+ "../../modules/rtp_rtcp:rtp_rtcp",
+ "../../modules/rtp_rtcp:rtp_rtcp_format",
+ "../../rtc_base:checks",
+ ]
+}
+
+webrtc_fuzzer_test("rtp_format_vp9_fuzzer") {
+ sources = [ "rtp_format_vp9_fuzzer.cc" ]
+ deps = [
+ "../../api/video:video_frame_type",
+ "../../modules/rtp_rtcp:rtp_rtcp",
+ "../../modules/rtp_rtcp:rtp_rtcp_format",
+ "../../rtc_base:checks",
+ ]
+}
+
webrtc_fuzzer_test("receive_side_congestion_controller_fuzzer") {
sources = [ "receive_side_congestion_controller_fuzzer.cc" ]
deps = [
@@ -248,6 +278,7 @@ webrtc_fuzzer_test("receive_side_congestion_controller_fuzzer") {
"../../modules/rtp_rtcp:rtp_rtcp_format",
"../../system_wrappers",
]
+ seed_corpus = "corpora/receive-side-cc"
}
rtc_library("audio_decoder_fuzzer") {
@@ -469,6 +500,7 @@ webrtc_fuzzer_test("audio_processing_fuzzer") {
"../../api:scoped_refptr",
"../../api/audio:aec3_factory",
"../../api/audio:echo_detector_creator",
+ "../../api/task_queue",
"../../api/task_queue:default_task_queue_factory",
"../../modules/audio_processing",
"../../modules/audio_processing:api",
@@ -478,11 +510,13 @@ webrtc_fuzzer_test("audio_processing_fuzzer") {
"../../modules/audio_processing/aec_dump",
"../../modules/audio_processing/aec_dump:aec_dump_impl",
"../../rtc_base:macromagic",
- "../../rtc_base:rtc_task_queue",
"../../rtc_base:safe_minmax",
"../../system_wrappers:field_trial",
]
- absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/base:nullability",
+ "//third_party/abseil-cpp/absl/memory",
+ ]
seed_corpus = "corpora/audio_processing-corpus"
}
diff --git a/third_party/libwebrtc/test/fuzzers/audio_processing_configs_fuzzer.cc b/third_party/libwebrtc/test/fuzzers/audio_processing_configs_fuzzer.cc
index 331a373f4e..93bce2f2e7 100644
--- a/third_party/libwebrtc/test/fuzzers/audio_processing_configs_fuzzer.cc
+++ b/third_party/libwebrtc/test/fuzzers/audio_processing_configs_fuzzer.cc
@@ -11,16 +11,17 @@
#include <bitset>
#include <string>
+#include "absl/base/nullability.h"
#include "absl/memory/memory.h"
#include "api/audio/echo_canceller3_factory.h"
#include "api/audio/echo_detector_creator.h"
#include "api/task_queue/default_task_queue_factory.h"
+#include "api/task_queue/task_queue_base.h"
#include "modules/audio_processing/aec_dump/aec_dump_factory.h"
#include "modules/audio_processing/include/audio_processing.h"
#include "modules/audio_processing/test/audio_processing_builder_for_testing.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/numerics/safe_minmax.h"
-#include "rtc_base/task_queue.h"
#include "system_wrappers/include/field_trial.h"
#include "test/fuzzers/audio_processing_fuzzer_helper.h"
#include "test/fuzzers/fuzz_data_helper.h"
@@ -33,9 +34,10 @@ const std::string kFieldTrialNames[] = {
"WebRTC-Aec3ShortHeadroomKillSwitch",
};
-rtc::scoped_refptr<AudioProcessing> CreateApm(test::FuzzDataHelper* fuzz_data,
- std::string* field_trial_string,
- rtc::TaskQueue* worker_queue) {
+rtc::scoped_refptr<AudioProcessing> CreateApm(
+ test::FuzzDataHelper* fuzz_data,
+ std::string* field_trial_string,
+ absl::Nonnull<TaskQueueBase*> worker_queue) {
// Parse boolean values for optionally enabling different
// configurable public components of APM.
bool use_ts = fuzz_data->ReadOrDefaultValue(true);
@@ -134,9 +136,10 @@ void FuzzOneInput(const uint8_t* data, size_t size) {
// for field_trial.h. Hence it's created here and not in CreateApm.
std::string field_trial_string = "";
- rtc::TaskQueue worker_queue(GetTaskQueueFactory()->CreateTaskQueue(
- "rtc-low-prio", rtc::TaskQueue::Priority::LOW));
- auto apm = CreateApm(&fuzz_data, &field_trial_string, &worker_queue);
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> worker_queue =
+ GetTaskQueueFactory()->CreateTaskQueue("rtc-low-prio",
+ TaskQueueFactory::Priority::LOW);
+ auto apm = CreateApm(&fuzz_data, &field_trial_string, worker_queue.get());
if (apm) {
FuzzAudioProcessing(&fuzz_data, std::move(apm));
diff --git a/third_party/libwebrtc/test/fuzzers/corpora/receive-side-cc/testcase-5414098152390656 b/third_party/libwebrtc/test/fuzzers/corpora/receive-side-cc/testcase-5414098152390656
new file mode 100644
index 0000000000..98c423cdc2
--- /dev/null
+++ b/third_party/libwebrtc/test/fuzzers/corpora/receive-side-cc/testcase-5414098152390656
Binary files differ
diff --git a/third_party/libwebrtc/test/fuzzers/rtp_format_h264_fuzzer.cc b/third_party/libwebrtc/test/fuzzers/rtp_format_h264_fuzzer.cc
new file mode 100644
index 0000000000..ddf2ca9d3d
--- /dev/null
+++ b/third_party/libwebrtc/test/fuzzers/rtp_format_h264_fuzzer.cc
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2024 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 <stddef.h>
+#include <stdint.h>
+
+#include "api/video/video_frame_type.h"
+#include "modules/rtp_rtcp/source/rtp_format.h"
+#include "modules/rtp_rtcp/source/rtp_format_h264.h"
+#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
+#include "rtc_base/checks.h"
+#include "test/fuzzers/fuzz_data_helper.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ test::FuzzDataHelper fuzz_input(rtc::MakeArrayView(data, size));
+
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 1200;
+ // Read uint8_t to be sure reduction_lens are much smaller than
+ // max_payload_len and thus limits structure is valid.
+ limits.first_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ limits.last_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ limits.single_packet_reduction_len =
+ fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ const H264PacketizationMode kPacketizationModes[] = {
+ H264PacketizationMode::NonInterleaved,
+ H264PacketizationMode::SingleNalUnit};
+
+ H264PacketizationMode packetization_mode =
+ fuzz_input.SelectOneOf(kPacketizationModes);
+
+ // Main function under test: RtpPacketizerH264's constructor.
+ RtpPacketizerH264 packetizer(fuzz_input.ReadByteArray(fuzz_input.BytesLeft()),
+ limits, packetization_mode);
+
+ size_t num_packets = packetizer.NumPackets();
+ if (num_packets == 0) {
+ return;
+ }
+ // When packetization was successful, validate NextPacket function too.
+ // While at it, check that packets respect the payload size limits.
+ RtpPacketToSend rtp_packet(nullptr);
+ // Single packet.
+ if (num_packets == 1) {
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.single_packet_reduction_len);
+ return;
+ }
+ // First packet.
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.first_packet_reduction_len);
+ // Middle packets.
+ for (size_t i = 1; i < num_packets - 1; ++i) {
+ rtp_packet.Clear();
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet))
+ << "Failed to get packet#" << i;
+ RTC_CHECK_LE(rtp_packet.payload_size(), limits.max_payload_len)
+ << "Packet #" << i << " exceeds it's limit";
+ }
+ // Last packet.
+ rtp_packet.Clear();
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.last_packet_reduction_len);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/test/fuzzers/rtp_format_vp8_fuzzer.cc b/third_party/libwebrtc/test/fuzzers/rtp_format_vp8_fuzzer.cc
new file mode 100644
index 0000000000..c3c055de0f
--- /dev/null
+++ b/third_party/libwebrtc/test/fuzzers/rtp_format_vp8_fuzzer.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024 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 <stddef.h>
+#include <stdint.h>
+
+#include "api/video/video_frame_type.h"
+#include "modules/rtp_rtcp/source/rtp_format.h"
+#include "modules/rtp_rtcp/source/rtp_format_vp8.h"
+#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
+#include "rtc_base/checks.h"
+#include "test/fuzzers/fuzz_data_helper.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ test::FuzzDataHelper fuzz_input(rtc::MakeArrayView(data, size));
+
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 1200;
+ // Read uint8_t to be sure reduction_lens are much smaller than
+ // max_payload_len and thus limits structure is valid.
+ limits.first_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ limits.last_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ limits.single_packet_reduction_len =
+ fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+
+ RTPVideoHeaderVP8 hdr_info;
+ hdr_info.InitRTPVideoHeaderVP8();
+ uint16_t picture_id = fuzz_input.ReadOrDefaultValue<uint16_t>(0);
+ hdr_info.pictureId =
+ picture_id >= 0x8000 ? kNoPictureId : picture_id & 0x7fff;
+
+ // Main function under test: RtpPacketizerVp8's constructor.
+ RtpPacketizerVp8 packetizer(fuzz_input.ReadByteArray(fuzz_input.BytesLeft()),
+ limits, hdr_info);
+
+ size_t num_packets = packetizer.NumPackets();
+ if (num_packets == 0) {
+ return;
+ }
+ // When packetization was successful, validate NextPacket function too.
+ // While at it, check that packets respect the payload size limits.
+ RtpPacketToSend rtp_packet(nullptr);
+ // Single packet.
+ if (num_packets == 1) {
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.single_packet_reduction_len);
+ return;
+ }
+ // First packet.
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.first_packet_reduction_len);
+ // Middle packets.
+ for (size_t i = 1; i < num_packets - 1; ++i) {
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet))
+ << "Failed to get packet#" << i;
+ RTC_CHECK_LE(rtp_packet.payload_size(), limits.max_payload_len)
+ << "Packet #" << i << " exceeds it's limit";
+ }
+ // Last packet.
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.last_packet_reduction_len);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/test/fuzzers/rtp_format_vp9_fuzzer.cc b/third_party/libwebrtc/test/fuzzers/rtp_format_vp9_fuzzer.cc
new file mode 100644
index 0000000000..3b5e67f697
--- /dev/null
+++ b/third_party/libwebrtc/test/fuzzers/rtp_format_vp9_fuzzer.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024 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 <stddef.h>
+#include <stdint.h>
+
+#include "api/video/video_frame_type.h"
+#include "modules/rtp_rtcp/source/rtp_format.h"
+#include "modules/rtp_rtcp/source/rtp_format_vp9.h"
+#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
+#include "rtc_base/checks.h"
+#include "test/fuzzers/fuzz_data_helper.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ test::FuzzDataHelper fuzz_input(rtc::MakeArrayView(data, size));
+
+ RtpPacketizer::PayloadSizeLimits limits;
+ limits.max_payload_len = 1200;
+ // Read uint8_t to be sure reduction_lens are much smaller than
+ // max_payload_len and thus limits structure is valid.
+ limits.first_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ limits.last_packet_reduction_len = fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+ limits.single_packet_reduction_len =
+ fuzz_input.ReadOrDefaultValue<uint8_t>(0);
+
+ RTPVideoHeaderVP9 hdr_info;
+ hdr_info.InitRTPVideoHeaderVP9();
+ uint16_t picture_id = fuzz_input.ReadOrDefaultValue<uint16_t>(0);
+ hdr_info.picture_id =
+ picture_id >= 0x8000 ? kNoPictureId : picture_id & 0x7fff;
+
+ // Main function under test: RtpPacketizerVp9's constructor.
+ RtpPacketizerVp9 packetizer(fuzz_input.ReadByteArray(fuzz_input.BytesLeft()),
+ limits, hdr_info);
+
+ size_t num_packets = packetizer.NumPackets();
+ if (num_packets == 0) {
+ return;
+ }
+ // When packetization was successful, validate NextPacket function too.
+ // While at it, check that packets respect the payload size limits.
+ RtpPacketToSend rtp_packet(nullptr);
+ // Single packet.
+ if (num_packets == 1) {
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.single_packet_reduction_len);
+ return;
+ }
+ // First packet.
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.first_packet_reduction_len);
+ // Middle packets.
+ for (size_t i = 1; i < num_packets - 1; ++i) {
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet))
+ << "Failed to get packet#" << i;
+ RTC_CHECK_LE(rtp_packet.payload_size(), limits.max_payload_len)
+ << "Packet #" << i << " exceeds it's limit";
+ }
+ // Last packet.
+ RTC_CHECK(packetizer.NextPacket(&rtp_packet));
+ RTC_CHECK_LE(rtp_packet.payload_size(),
+ limits.max_payload_len - limits.last_packet_reduction_len);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/test/network/BUILD.gn b/third_party/libwebrtc/test/network/BUILD.gn
index b8255d35fd..6df563d31d 100644
--- a/third_party/libwebrtc/test/network/BUILD.gn
+++ b/third_party/libwebrtc/test/network/BUILD.gn
@@ -47,6 +47,7 @@ rtc_library("emulated_network") {
"../../api:simulated_network_api",
"../../api:time_controller",
"../../api/numerics",
+ "../../api/task_queue",
"../../api/task_queue:pending_task_safety_flag",
"../../api/test/network_emulation",
"../../api/transport:stun_types",
@@ -67,7 +68,6 @@ rtc_library("emulated_network") {
"../../rtc_base:random",
"../../rtc_base:rtc_base_tests_utils",
"../../rtc_base:rtc_event",
- "../../rtc_base:rtc_task_queue",
"../../rtc_base:safe_minmax",
"../../rtc_base:socket",
"../../rtc_base:socket_address",
@@ -87,6 +87,7 @@ rtc_library("emulated_network") {
]
absl_deps = [
"//third_party/abseil-cpp/absl/algorithm:container",
+ "//third_party/abseil-cpp/absl/base:nullability",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
@@ -117,7 +118,6 @@ if (rtc_include_tests && !build_with_chromium) {
deps = [
":emulated_network",
"../:test_support",
- "../../api:callfactory_api",
"../../api:enable_media_with_defaults",
"../../api:libjingle_peerconnection_api",
"../../api:scoped_refptr",
diff --git a/third_party/libwebrtc/test/network/cross_traffic_unittest.cc b/third_party/libwebrtc/test/network/cross_traffic_unittest.cc
index 36aff67bb2..0f98fc9e72 100644
--- a/third_party/libwebrtc/test/network/cross_traffic_unittest.cc
+++ b/third_party/libwebrtc/test/network/cross_traffic_unittest.cc
@@ -55,7 +55,7 @@ struct TrafficCounterFixture {
EmulatedEndpointConfig(),
EmulatedNetworkStatsGatheringMode::kDefault,
},
- /*is_enabled=*/true, &task_queue_, &clock};
+ /*is_enabled=*/true, task_queue_.Get(), &clock};
};
} // namespace
diff --git a/third_party/libwebrtc/test/network/network_emulation.cc b/third_party/libwebrtc/test/network/network_emulation.cc
index f1c9ca80dd..642bf6fc7a 100644
--- a/third_party/libwebrtc/test/network/network_emulation.cc
+++ b/third_party/libwebrtc/test/network/network_emulation.cc
@@ -15,9 +15,11 @@
#include <memory>
#include <utility>
+#include "absl/base/nullability.h"
#include "absl/types/optional.h"
#include "api/numerics/samples_stats_counter.h"
#include "api/sequence_checker.h"
+#include "api/task_queue/task_queue_base.h"
#include "api/test/network_emulation/network_emulation_interfaces.h"
#include "api/test/network_emulation_manager.h"
#include "api/units/data_size.h"
@@ -330,7 +332,7 @@ void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) {
return;
Timestamp current_time = clock_->CurrentTime();
process_task_ = RepeatingTaskHandle::DelayedStart(
- task_queue_->Get(),
+ task_queue_,
std::max(TimeDelta::Zero(),
Timestamp::Micros(*next_time_us) - current_time),
[this]() {
@@ -383,7 +385,7 @@ void LinkEmulation::Process(Timestamp at_time) {
}
}
-NetworkRouterNode::NetworkRouterNode(rtc::TaskQueue* task_queue)
+NetworkRouterNode::NetworkRouterNode(absl::Nonnull<TaskQueueBase*> task_queue)
: task_queue_(task_queue) {}
void NetworkRouterNode::OnPacketReceived(EmulatedIpPacket packet) {
@@ -459,7 +461,7 @@ void NetworkRouterNode::SetFilter(
EmulatedNetworkNode::EmulatedNetworkNode(
Clock* clock,
- rtc::TaskQueue* task_queue,
+ absl::Nonnull<TaskQueueBase*> task_queue,
std::unique_ptr<NetworkBehaviorInterface> network_behavior,
EmulatedNetworkStatsGatheringMode stats_gathering_mode)
: router_(task_queue),
@@ -510,10 +512,11 @@ EmulatedEndpointImpl::Options::Options(
config.allow_receive_packets_with_different_dest_ip),
log_name(ip.ToString() + " (" + config.name.value_or("") + ")") {}
-EmulatedEndpointImpl::EmulatedEndpointImpl(const Options& options,
- bool is_enabled,
- rtc::TaskQueue* task_queue,
- Clock* clock)
+EmulatedEndpointImpl::EmulatedEndpointImpl(
+ const Options& options,
+ bool is_enabled,
+ absl::Nonnull<TaskQueueBase*> task_queue,
+ Clock* clock)
: options_(options),
is_enabled_(is_enabled),
clock_(clock),
diff --git a/third_party/libwebrtc/test/network/network_emulation.h b/third_party/libwebrtc/test/network/network_emulation.h
index dffabafa7c..20705197be 100644
--- a/third_party/libwebrtc/test/network/network_emulation.h
+++ b/third_party/libwebrtc/test/network/network_emulation.h
@@ -19,10 +19,12 @@
#include <utility>
#include <vector>
+#include "absl/base/nullability.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "api/numerics/samples_stats_counter.h"
#include "api/sequence_checker.h"
+#include "api/task_queue/task_queue_base.h"
#include "api/test/network_emulation/network_emulation_interfaces.h"
#include "api/test/network_emulation_manager.h"
#include "api/test/simulated_network.h"
@@ -145,7 +147,7 @@ class EmulatedNetworkNodeStatsBuilder {
class LinkEmulation : public EmulatedNetworkReceiverInterface {
public:
LinkEmulation(Clock* clock,
- rtc::TaskQueue* task_queue,
+ absl::Nonnull<TaskQueueBase*> task_queue,
std::unique_ptr<NetworkBehaviorInterface> network_behavior,
EmulatedNetworkReceiverInterface* receiver,
EmulatedNetworkStatsGatheringMode stats_gathering_mode)
@@ -168,7 +170,7 @@ class LinkEmulation : public EmulatedNetworkReceiverInterface {
void Process(Timestamp at_time) RTC_RUN_ON(task_queue_);
Clock* const clock_;
- rtc::TaskQueue* const task_queue_;
+ const absl::Nonnull<TaskQueueBase*> task_queue_;
const std::unique_ptr<NetworkBehaviorInterface> network_behavior_
RTC_GUARDED_BY(task_queue_);
EmulatedNetworkReceiverInterface* const receiver_;
@@ -186,7 +188,7 @@ class LinkEmulation : public EmulatedNetworkReceiverInterface {
// the packet will be silently dropped.
class NetworkRouterNode : public EmulatedNetworkReceiverInterface {
public:
- explicit NetworkRouterNode(rtc::TaskQueue* task_queue);
+ explicit NetworkRouterNode(absl::Nonnull<TaskQueueBase*> task_queue);
void OnPacketReceived(EmulatedIpPacket packet) override;
void SetReceiver(const rtc::IPAddress& dest_ip,
@@ -200,7 +202,7 @@ class NetworkRouterNode : public EmulatedNetworkReceiverInterface {
void SetFilter(std::function<bool(const EmulatedIpPacket&)> filter);
private:
- rtc::TaskQueue* const task_queue_;
+ const absl::Nonnull<TaskQueueBase*> task_queue_;
absl::optional<EmulatedNetworkReceiverInterface*> default_receiver_
RTC_GUARDED_BY(task_queue_);
std::map<rtc::IPAddress, EmulatedNetworkReceiverInterface*> routing_
@@ -224,7 +226,7 @@ class EmulatedNetworkNode : public EmulatedNetworkReceiverInterface {
// they are ready.
EmulatedNetworkNode(
Clock* clock,
- rtc::TaskQueue* task_queue,
+ absl::Nonnull<TaskQueueBase*> task_queue,
std::unique_ptr<NetworkBehaviorInterface> network_behavior,
EmulatedNetworkStatsGatheringMode stats_gathering_mode);
~EmulatedNetworkNode() override;
@@ -283,7 +285,7 @@ class EmulatedEndpointImpl : public EmulatedEndpoint {
EmulatedEndpointImpl(const Options& options,
bool is_enabled,
- rtc::TaskQueue* task_queue,
+ absl::Nonnull<TaskQueueBase*> task_queue,
Clock* clock);
~EmulatedEndpointImpl() override;
@@ -341,7 +343,7 @@ class EmulatedEndpointImpl : public EmulatedEndpoint {
const Options options_;
bool is_enabled_ RTC_GUARDED_BY(enabled_state_checker_);
Clock* const clock_;
- rtc::TaskQueue* const task_queue_;
+ const absl::Nonnull<TaskQueueBase*> task_queue_;
std::unique_ptr<rtc::Network> network_;
NetworkRouterNode router_;
diff --git a/third_party/libwebrtc/test/network/network_emulation_manager.cc b/third_party/libwebrtc/test/network/network_emulation_manager.cc
index 97c0bc1ba8..dd0e93d8ee 100644
--- a/third_party/libwebrtc/test/network/network_emulation_manager.cc
+++ b/third_party/libwebrtc/test/network/network_emulation_manager.cc
@@ -13,6 +13,7 @@
#include <algorithm>
#include <memory>
+#include "api/field_trials_view.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "call/simulated_network.h"
@@ -30,10 +31,12 @@ constexpr uint32_t kMinIPv4Address = 0xC0A80000;
// uint32_t representation of 192.168.255.255 address
constexpr uint32_t kMaxIPv4Address = 0xC0A8FFFF;
-std::unique_ptr<TimeController> CreateTimeController(TimeMode mode) {
+std::unique_ptr<TimeController> CreateTimeController(
+ TimeMode mode,
+ const FieldTrialsView* field_trials) {
switch (mode) {
case TimeMode::kRealTime:
- return std::make_unique<RealTimeController>();
+ return std::make_unique<RealTimeController>(field_trials);
case TimeMode::kSimulated:
// Using an offset of 100000 to get nice fixed width and readable
// timestamps in typical test scenarios.
@@ -46,10 +49,11 @@ std::unique_ptr<TimeController> CreateTimeController(TimeMode mode) {
NetworkEmulationManagerImpl::NetworkEmulationManagerImpl(
TimeMode mode,
- EmulatedNetworkStatsGatheringMode stats_gathering_mode)
+ EmulatedNetworkStatsGatheringMode stats_gathering_mode,
+ const FieldTrialsView* field_trials)
: time_mode_(mode),
stats_gathering_mode_(stats_gathering_mode),
- time_controller_(CreateTimeController(mode)),
+ time_controller_(CreateTimeController(mode, field_trials)),
clock_(time_controller_->GetClock()),
next_node_id_(1),
next_ip4_address_(kMinIPv4Address),
@@ -75,8 +79,9 @@ EmulatedNetworkNode* NetworkEmulationManagerImpl::CreateEmulatedNode(
EmulatedNetworkNode* NetworkEmulationManagerImpl::CreateEmulatedNode(
std::unique_ptr<NetworkBehaviorInterface> network_behavior) {
- auto node = std::make_unique<EmulatedNetworkNode>(
- clock_, &task_queue_, std::move(network_behavior), stats_gathering_mode_);
+ auto node = std::make_unique<EmulatedNetworkNode>(clock_, task_queue_.Get(),
+ std::move(network_behavior),
+ stats_gathering_mode_);
EmulatedNetworkNode* out = node.get();
task_queue_.PostTask([this, node = std::move(node)]() mutable {
network_nodes_.push_back(std::move(node));
@@ -111,7 +116,7 @@ EmulatedEndpointImpl* NetworkEmulationManagerImpl::CreateEndpoint(
auto node = std::make_unique<EmulatedEndpointImpl>(
EmulatedEndpointImpl::Options(next_node_id_++, *ip, config,
stats_gathering_mode_),
- config.start_as_enabled, &task_queue_, clock_);
+ config.start_as_enabled, task_queue_.Get(), clock_);
EmulatedEndpointImpl* out = node.get();
endpoints_.push_back(std::move(node));
return out;
diff --git a/third_party/libwebrtc/test/network/network_emulation_manager.h b/third_party/libwebrtc/test/network/network_emulation_manager.h
index 29debca693..4b0a76494f 100644
--- a/third_party/libwebrtc/test/network/network_emulation_manager.h
+++ b/third_party/libwebrtc/test/network/network_emulation_manager.h
@@ -18,6 +18,7 @@
#include <vector>
#include "api/array_view.h"
+#include "api/field_trials_view.h"
#include "api/test/network_emulation_manager.h"
#include "api/test/simulated_network.h"
#include "api/test/time_controller.h"
@@ -38,7 +39,8 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager {
public:
NetworkEmulationManagerImpl(
TimeMode mode,
- EmulatedNetworkStatsGatheringMode stats_gathering_mode);
+ EmulatedNetworkStatsGatheringMode stats_gathering_mode,
+ const FieldTrialsView* field_trials = nullptr);
~NetworkEmulationManagerImpl();
EmulatedNetworkNode* CreateEmulatedNode(BuiltInNetworkBehaviorConfig config,
diff --git a/third_party/libwebrtc/test/network/network_emulation_pc_unittest.cc b/third_party/libwebrtc/test/network/network_emulation_pc_unittest.cc
index 09d3946747..73ac54e7ef 100644
--- a/third_party/libwebrtc/test/network/network_emulation_pc_unittest.cc
+++ b/third_party/libwebrtc/test/network/network_emulation_pc_unittest.cc
@@ -56,8 +56,7 @@ rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
rtc::Thread* network_thread) {
PeerConnectionFactoryDependencies pcf_deps;
pcf_deps.task_queue_factory = CreateDefaultTaskQueueFactory();
- pcf_deps.event_log_factory =
- std::make_unique<RtcEventLogFactory>(pcf_deps.task_queue_factory.get());
+ pcf_deps.event_log_factory = std::make_unique<RtcEventLogFactory>();
pcf_deps.network_thread = network_thread;
pcf_deps.signaling_thread = signaling_thread;
pcf_deps.trials = std::make_unique<FieldTrialBasedConfig>();
diff --git a/third_party/libwebrtc/test/pc/e2e/BUILD.gn b/third_party/libwebrtc/test/pc/e2e/BUILD.gn
index 9d1c1d437f..0eb7aa2c68 100644
--- a/third_party/libwebrtc/test/pc/e2e/BUILD.gn
+++ b/third_party/libwebrtc/test/pc/e2e/BUILD.gn
@@ -99,6 +99,7 @@ if (!build_with_chromium) {
"../../../api:enable_media_with_defaults",
"../../../api:time_controller",
"../../../api/rtc_event_log:rtc_event_log_factory",
+ "../../../api/task_queue",
"../../../api/task_queue:default_task_queue_factory",
"../../../api/test/pclf:media_configuration",
"../../../api/test/pclf:media_quality_test_params",
@@ -109,7 +110,6 @@ if (!build_with_chromium) {
"../../../modules/audio_device:test_audio_device_module",
"../../../modules/audio_processing/aec_dump",
"../../../p2p:rtc_p2p",
- "../../../rtc_base:rtc_task_queue",
"../../../rtc_base:threading",
"analyzer/video:quality_analyzing_video_encoder",
"analyzer/video:video_quality_analyzer_injection_helper",
@@ -286,7 +286,6 @@ if (!build_with_chromium) {
":default_audio_quality_analyzer",
":network_quality_metrics_reporter",
":stats_based_network_quality_metrics_reporter",
- "../../../api:callfactory_api",
"../../../api:create_network_emulation_manager",
"../../../api:create_peer_connection_quality_test_frame_generator",
"../../../api:create_peerconnection_quality_test_fixture",
diff --git a/third_party/libwebrtc/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc b/third_party/libwebrtc/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc
index bca52d9bfc..93d8906d6a 100644
--- a/third_party/libwebrtc/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc
+++ b/third_party/libwebrtc/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc
@@ -42,29 +42,27 @@ void DefaultAudioQualityAnalyzer::OnStatsReports(
auto stats = report->GetStatsOfType<RTCInboundRtpStreamStats>();
for (auto& stat : stats) {
- if (!stat->kind.is_defined() || !(*stat->kind == "audio")) {
+ if (!stat->kind.has_value() || !(*stat->kind == "audio")) {
continue;
}
StatsSample sample;
- sample.total_samples_received =
- stat->total_samples_received.ValueOrDefault(0ul);
- sample.concealed_samples = stat->concealed_samples.ValueOrDefault(0ul);
+ sample.total_samples_received = stat->total_samples_received.value_or(0ul);
+ sample.concealed_samples = stat->concealed_samples.value_or(0ul);
sample.removed_samples_for_acceleration =
- stat->removed_samples_for_acceleration.ValueOrDefault(0ul);
+ stat->removed_samples_for_acceleration.value_or(0ul);
sample.inserted_samples_for_deceleration =
- stat->inserted_samples_for_deceleration.ValueOrDefault(0ul);
+ stat->inserted_samples_for_deceleration.value_or(0ul);
sample.silent_concealed_samples =
- stat->silent_concealed_samples.ValueOrDefault(0ul);
+ stat->silent_concealed_samples.value_or(0ul);
sample.jitter_buffer_delay =
- TimeDelta::Seconds(stat->jitter_buffer_delay.ValueOrDefault(0.));
+ TimeDelta::Seconds(stat->jitter_buffer_delay.value_or(0.));
sample.jitter_buffer_target_delay =
- TimeDelta::Seconds(stat->jitter_buffer_target_delay.ValueOrDefault(0.));
+ TimeDelta::Seconds(stat->jitter_buffer_target_delay.value_or(0.));
sample.jitter_buffer_emitted_count =
- stat->jitter_buffer_emitted_count.ValueOrDefault(0ul);
- sample.total_samples_duration =
- stat->total_samples_duration.ValueOrDefault(0.);
- sample.total_audio_energy = stat->total_audio_energy.ValueOrDefault(0.);
+ stat->jitter_buffer_emitted_count.value_or(0ul);
+ sample.total_samples_duration = stat->total_samples_duration.value_or(0.);
+ sample.total_audio_energy = stat->total_audio_energy.value_or(0.);
TrackIdStreamInfoMap::StreamInfo stream_info =
analyzer_helper_->GetStreamInfoFromTrackId(*stat->track_identifier);
diff --git a/third_party/libwebrtc/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc b/third_party/libwebrtc/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc
index 817b3caad0..87f1590cb0 100644
--- a/third_party/libwebrtc/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc
+++ b/third_party/libwebrtc/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc
@@ -58,12 +58,14 @@ void VideoQualityMetricsReporter::OnStatsReports(
auto transport_stats = report->GetStatsOfType<RTCTransportStats>();
if (transport_stats.size() == 0u ||
- !transport_stats[0]->selected_candidate_pair_id.is_defined()) {
+ !transport_stats[0]->selected_candidate_pair_id.has_value()) {
return;
}
RTC_DCHECK_EQ(transport_stats.size(), 1);
std::string selected_ice_id =
- transport_stats[0]->selected_candidate_pair_id.ValueToString();
+ transport_stats[0]
+ ->GetAttribute(transport_stats[0]->selected_candidate_pair_id)
+ .ToString();
// Use the selected ICE candidate pair ID to get the appropriate ICE stats.
const RTCIceCandidatePairStats ice_candidate_pair_stats =
report->Get(selected_ice_id)->cast_to<const RTCIceCandidatePairStats>();
@@ -71,7 +73,7 @@ void VideoQualityMetricsReporter::OnStatsReports(
auto outbound_rtp_stats = report->GetStatsOfType<RTCOutboundRtpStreamStats>();
StatsSample sample;
for (auto& s : outbound_rtp_stats) {
- if (!s->kind.is_defined()) {
+ if (!s->kind.has_value()) {
continue;
}
if (!(*s->kind == "video")) {
@@ -81,15 +83,15 @@ void VideoQualityMetricsReporter::OnStatsReports(
sample.sample_time = s->timestamp();
}
sample.retransmitted_bytes_sent +=
- DataSize::Bytes(s->retransmitted_bytes_sent.ValueOrDefault(0ul));
- sample.bytes_sent += DataSize::Bytes(s->bytes_sent.ValueOrDefault(0ul));
+ DataSize::Bytes(s->retransmitted_bytes_sent.value_or(0ul));
+ sample.bytes_sent += DataSize::Bytes(s->bytes_sent.value_or(0ul));
sample.header_bytes_sent +=
- DataSize::Bytes(s->header_bytes_sent.ValueOrDefault(0ul));
+ DataSize::Bytes(s->header_bytes_sent.value_or(0ul));
}
MutexLock lock(&video_bwe_stats_lock_);
VideoBweStats& video_bwe_stats = video_bwe_stats_[std::string(pc_label)];
- if (ice_candidate_pair_stats.available_outgoing_bitrate.is_defined()) {
+ if (ice_candidate_pair_stats.available_outgoing_bitrate.has_value()) {
video_bwe_stats.available_send_bandwidth.AddSample(
DataRate::BitsPerSec(
*ice_candidate_pair_stats.available_outgoing_bitrate)
diff --git a/third_party/libwebrtc/test/pc/e2e/cross_media_metrics_reporter.cc b/third_party/libwebrtc/test/pc/e2e/cross_media_metrics_reporter.cc
index aad5946c9f..c1536018d2 100644
--- a/third_party/libwebrtc/test/pc/e2e/cross_media_metrics_reporter.cc
+++ b/third_party/libwebrtc/test/pc/e2e/cross_media_metrics_reporter.cc
@@ -47,8 +47,8 @@ void CrossMediaMetricsReporter::OnStatsReports(
std::map<std::string, std::vector<const RTCInboundRtpStreamStats*>>
sync_group_stats;
for (const auto& stat : inbound_stats) {
- if (stat->estimated_playout_timestamp.ValueOrDefault(0.) > 0 &&
- stat->track_identifier.is_defined()) {
+ if (stat->estimated_playout_timestamp.value_or(0.) > 0 &&
+ stat->track_identifier.has_value()) {
sync_group_stats[reporter_helper_
->GetStreamInfoFromTrackId(*stat->track_identifier)
.sync_group]
@@ -66,8 +66,8 @@ void CrossMediaMetricsReporter::OnStatsReports(
const RTCInboundRtpStreamStats* audio_stat = pair.second[0];
const RTCInboundRtpStreamStats* video_stat = pair.second[1];
- RTC_CHECK(pair.second.size() == 2 && audio_stat->kind.is_defined() &&
- video_stat->kind.is_defined() &&
+ RTC_CHECK(pair.second.size() == 2 && audio_stat->kind.has_value() &&
+ video_stat->kind.has_value() &&
*audio_stat->kind != *video_stat->kind)
<< "Sync group should consist of one audio and one video stream.";
@@ -77,8 +77,8 @@ void CrossMediaMetricsReporter::OnStatsReports(
// Stream labels of a sync group are same for all polls, so we need it add
// it only once.
if (stats_info_.find(sync_group) == stats_info_.end()) {
- RTC_CHECK(audio_stat->track_identifier.is_defined());
- RTC_CHECK(video_stat->track_identifier.is_defined());
+ RTC_CHECK(audio_stat->track_identifier.has_value());
+ RTC_CHECK(video_stat->track_identifier.has_value());
stats_info_[sync_group].audio_stream_info =
reporter_helper_->GetStreamInfoFromTrackId(
*audio_stat->track_identifier);
diff --git a/third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.cc b/third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.cc
index 2d6aa597ce..257fecf309 100644
--- a/third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.cc
+++ b/third_party/libwebrtc/test/pc/e2e/network_quality_metrics_reporter.cc
@@ -79,15 +79,14 @@ void NetworkQualityMetricsReporter::OnStatsReports(
auto inbound_stats = report->GetStatsOfType<RTCInboundRtpStreamStats>();
for (const auto& stat : inbound_stats) {
payload_received +=
- DataSize::Bytes(stat->bytes_received.ValueOrDefault(0ul) +
- stat->header_bytes_received.ValueOrDefault(0ul));
+ DataSize::Bytes(stat->bytes_received.value_or(0ul) +
+ stat->header_bytes_received.value_or(0ul));
}
auto outbound_stats = report->GetStatsOfType<RTCOutboundRtpStreamStats>();
for (const auto& stat : outbound_stats) {
- payload_sent +=
- DataSize::Bytes(stat->bytes_sent.ValueOrDefault(0ul) +
- stat->header_bytes_sent.ValueOrDefault(0ul));
+ payload_sent += DataSize::Bytes(stat->bytes_sent.value_or(0ul) +
+ stat->header_bytes_sent.value_or(0ul));
}
MutexLock lock(&lock_);
diff --git a/third_party/libwebrtc/test/pc/e2e/peer_connection_quality_test.cc b/third_party/libwebrtc/test/pc/e2e/peer_connection_quality_test.cc
index 5eb47b4682..90f201facd 100644
--- a/third_party/libwebrtc/test/pc/e2e/peer_connection_quality_test.cc
+++ b/third_party/libwebrtc/test/pc/e2e/peer_connection_quality_test.cc
@@ -277,7 +277,7 @@ void PeerConnectionE2EQualityTest::Run(RunParams run_params) {
TestPeerFactory test_peer_factory(
signaling_thread.get(), time_controller_,
- video_quality_analyzer_injection_helper_.get(), task_queue_.get());
+ video_quality_analyzer_injection_helper_.get(), task_queue_->Get());
alice_ = test_peer_factory.CreateTestPeer(
std::move(alice_configurer),
std::make_unique<FixturePeerConnectionObserver>(
diff --git a/third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.cc b/third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.cc
index eb5f29287e..b965a7acd8 100644
--- a/third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.cc
+++ b/third_party/libwebrtc/test/pc/e2e/stats_based_network_quality_metrics_reporter.cc
@@ -299,25 +299,23 @@ void StatsBasedNetworkQualityMetricsReporter::OnStatsReports(
auto inbound_stats = report->GetStatsOfType<RTCInboundRtpStreamStats>();
for (const auto& stat : inbound_stats) {
cur_stats.payload_received +=
- DataSize::Bytes(stat->bytes_received.ValueOrDefault(0ul) +
- stat->header_bytes_received.ValueOrDefault(0ul));
+ DataSize::Bytes(stat->bytes_received.value_or(0ul) +
+ stat->header_bytes_received.value_or(0ul));
}
auto outbound_stats = report->GetStatsOfType<RTCOutboundRtpStreamStats>();
for (const auto& stat : outbound_stats) {
- cur_stats.payload_sent +=
- DataSize::Bytes(stat->bytes_sent.ValueOrDefault(0ul) +
- stat->header_bytes_sent.ValueOrDefault(0ul));
+ cur_stats.payload_sent += DataSize::Bytes(
+ stat->bytes_sent.value_or(0ul) + stat->header_bytes_sent.value_or(0ul));
}
auto candidate_pairs_stats = report->GetStatsOfType<RTCTransportStats>();
for (const auto& stat : candidate_pairs_stats) {
cur_stats.total_received +=
- DataSize::Bytes(stat->bytes_received.ValueOrDefault(0ul));
- cur_stats.total_sent +=
- DataSize::Bytes(stat->bytes_sent.ValueOrDefault(0ul));
- cur_stats.packets_received += stat->packets_received.ValueOrDefault(0ul);
- cur_stats.packets_sent += stat->packets_sent.ValueOrDefault(0ul);
+ DataSize::Bytes(stat->bytes_received.value_or(0ul));
+ cur_stats.total_sent += DataSize::Bytes(stat->bytes_sent.value_or(0ul));
+ cur_stats.packets_received += stat->packets_received.value_or(0ul);
+ cur_stats.packets_sent += stat->packets_sent.value_or(0ul);
}
MutexLock lock(&mutex_);
diff --git a/third_party/libwebrtc/test/pc/e2e/test_peer_factory.cc b/third_party/libwebrtc/test/pc/e2e/test_peer_factory.cc
index dd900027ee..a184c5db3c 100644
--- a/third_party/libwebrtc/test/pc/e2e/test_peer_factory.cc
+++ b/third_party/libwebrtc/test/pc/e2e/test_peer_factory.cc
@@ -43,16 +43,14 @@ constexpr int kDefaultSamplingFrequencyInHz = 48000;
// and `pc_dependencies` if they are omitted. Also setup required
// dependencies, that won't be specially provided by factory and will be just
// transferred to peer connection creation code.
-void SetMandatoryEntities(InjectableComponents* components,
- TimeController& time_controller) {
+void SetMandatoryEntities(InjectableComponents* components) {
RTC_DCHECK(components->pcf_dependencies);
RTC_DCHECK(components->pc_dependencies);
// Setup required peer connection factory dependencies.
if (components->pcf_dependencies->event_log_factory == nullptr) {
components->pcf_dependencies->event_log_factory =
- std::make_unique<RtcEventLogFactory>(
- time_controller.GetTaskQueueFactory());
+ std::make_unique<RtcEventLogFactory>();
}
if (!components->pcf_dependencies->trials) {
components->pcf_dependencies->trials =
@@ -286,7 +284,7 @@ std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
RTC_DCHECK(configurable_params);
RTC_DCHECK_EQ(configurable_params->video_configs.size(),
video_sources.size());
- SetMandatoryEntities(components.get(), time_controller_);
+ SetMandatoryEntities(components.get());
params->rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;
// Create peer connection factory.
@@ -329,6 +327,7 @@ std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
components->worker_thread, components->network_thread);
rtc::scoped_refptr<PeerConnectionFactoryInterface> peer_connection_factory =
CreateModularPeerConnectionFactory(std::move(pcf_deps));
+ peer_connection_factory->SetOptions(params->peer_connection_factory_options);
// Create peer connection.
PeerConnectionDependencies pc_deps =
diff --git a/third_party/libwebrtc/test/pc/e2e/test_peer_factory.h b/third_party/libwebrtc/test/pc/e2e/test_peer_factory.h
index f2698e2a15..cc61b04ae1 100644
--- a/third_party/libwebrtc/test/pc/e2e/test_peer_factory.h
+++ b/third_party/libwebrtc/test/pc/e2e/test_peer_factory.h
@@ -18,12 +18,12 @@
#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event_log_factory.h"
+#include "api/task_queue/task_queue_base.h"
#include "api/test/pclf/media_configuration.h"
#include "api/test/pclf/media_quality_test_params.h"
#include "api/test/pclf/peer_configurer.h"
#include "api/test/time_controller.h"
#include "modules/audio_device/include/test_audio_device.h"
-#include "rtc_base/task_queue.h"
#include "test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h"
#include "test/pc/e2e/test_peer.h"
@@ -55,7 +55,7 @@ class TestPeerFactory {
TestPeerFactory(rtc::Thread* signaling_thread,
TimeController& time_controller,
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper,
- rtc::TaskQueue* task_queue)
+ TaskQueueBase* task_queue)
: signaling_thread_(signaling_thread),
time_controller_(time_controller),
video_analyzer_helper_(video_analyzer_helper),
@@ -75,7 +75,7 @@ class TestPeerFactory {
rtc::Thread* signaling_thread_;
TimeController& time_controller_;
VideoQualityAnalyzerInjectionHelper* video_analyzer_helper_;
- rtc::TaskQueue* task_queue_;
+ TaskQueueBase* const task_queue_;
};
} // namespace webrtc_pc_e2e
diff --git a/third_party/libwebrtc/test/peer_scenario/peer_scenario_client.cc b/third_party/libwebrtc/test/peer_scenario/peer_scenario_client.cc
index 60f2ea7f2e..1397b32fe3 100644
--- a/third_party/libwebrtc/test/peer_scenario/peer_scenario_client.cc
+++ b/third_party/libwebrtc/test/peer_scenario/peer_scenario_client.cc
@@ -248,8 +248,7 @@ PeerScenarioClient::PeerScenarioClient(
pcf_deps.worker_thread = worker_thread_.get();
pcf_deps.task_queue_factory =
net->time_controller()->CreateTaskQueueFactory();
- pcf_deps.event_log_factory =
- std::make_unique<RtcEventLogFactory>(task_queue_factory_);
+ pcf_deps.event_log_factory = std::make_unique<RtcEventLogFactory>();
pcf_deps.trials = std::make_unique<FieldTrialBasedConfig>();
pcf_deps.adm = TestAudioDeviceModule::Create(
diff --git a/third_party/libwebrtc/test/run_loop_unittest.cc b/third_party/libwebrtc/test/run_loop_unittest.cc
index 80f0bcbdcc..e6c747ac4f 100644
--- a/third_party/libwebrtc/test/run_loop_unittest.cc
+++ b/third_party/libwebrtc/test/run_loop_unittest.cc
@@ -10,8 +10,8 @@
#include "test/run_loop.h"
+#include "api/task_queue/task_queue_base.h"
#include "api/units/time_delta.h"
-#include "rtc_base/task_queue.h"
#include "test/gtest.h"
namespace webrtc {
diff --git a/third_party/libwebrtc/test/scenario/audio_stream.cc b/third_party/libwebrtc/test/scenario/audio_stream.cc
index 5f7db7acdf..232f7382bd 100644
--- a/third_party/libwebrtc/test/scenario/audio_stream.cc
+++ b/third_party/libwebrtc/test/scenario/audio_stream.cc
@@ -89,7 +89,7 @@ SendAudioStream::SendAudioStream(
AudioSendStream::Config send_config(send_transport);
ssrc_ = sender->GetNextAudioSsrc();
send_config.rtp.ssrc = ssrc_;
- SdpAudioFormat::Parameters sdp_params;
+ CodecParameterMap sdp_params;
if (config.source.channels == 2)
sdp_params["stereo"] = "1";
if (config.encoder.initial_frame_length != TimeDelta::Millis(20))
diff --git a/third_party/libwebrtc/test/scenario/video_stream.cc b/third_party/libwebrtc/test/scenario/video_stream.cc
index eb20f8dbc7..654aed7c6c 100644
--- a/third_party/libwebrtc/test/scenario/video_stream.cc
+++ b/third_party/libwebrtc/test/scenario/video_stream.cc
@@ -430,7 +430,8 @@ SendVideoStream::SendVideoStream(CallClient* sender,
if (config.stream.fec_controller_factory) {
send_stream_ = sender_->call_->CreateVideoSendStream(
std::move(send_config), std::move(encoder_config),
- config.stream.fec_controller_factory->CreateFecController());
+ config.stream.fec_controller_factory->CreateFecController(
+ sender_->env_));
} else {
send_stream_ = sender_->call_->CreateVideoSendStream(
std::move(send_config), std::move(encoder_config));
diff --git a/third_party/libwebrtc/test/time_controller/BUILD.gn b/third_party/libwebrtc/test/time_controller/BUILD.gn
index b4b368a42a..6686528345 100644
--- a/third_party/libwebrtc/test/time_controller/BUILD.gn
+++ b/third_party/libwebrtc/test/time_controller/BUILD.gn
@@ -24,6 +24,7 @@ rtc_library("time_controller") {
]
deps = [
+ "../../api:field_trials_view",
"../../api:sequence_checker",
"../../api:time_controller",
"../../api/task_queue",
@@ -57,10 +58,10 @@ if (rtc_include_tests) {
":time_controller",
"../:test_support",
"../../api:time_controller",
+ "../../api/task_queue",
"../../api/units:time_delta",
"../../rtc_base:macromagic",
"../../rtc_base:rtc_event",
- "../../rtc_base:rtc_task_queue",
"../../rtc_base:task_queue_for_test",
"../../rtc_base:threading",
"../../rtc_base/synchronization:mutex",
diff --git a/third_party/libwebrtc/test/time_controller/external_time_controller_unittest.cc b/third_party/libwebrtc/test/time_controller/external_time_controller_unittest.cc
index 13d63fe8ed..302055999a 100644
--- a/third_party/libwebrtc/test/time_controller/external_time_controller_unittest.cc
+++ b/third_party/libwebrtc/test/time_controller/external_time_controller_unittest.cc
@@ -14,8 +14,8 @@
#include <memory>
#include <utility>
+#include "api/task_queue/task_queue_base.h"
#include "rtc_base/event.h"
-#include "rtc_base/task_queue.h"
#include "rtc_base/task_utils/repeating_task.h"
#include "test/gmock.h"
#include "test/gtest.h"
@@ -88,11 +88,11 @@ TEST(ExternalTimeControllerTest, TaskIsStoppedOnStop) {
const int kMargin = 1;
FakeAlarm alarm(kStartTime);
ExternalTimeController time_simulation(&alarm);
- rtc::TaskQueue task_queue(
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
- "TestQueue", TaskQueueFactory::Priority::NORMAL));
+ "TestQueue", TaskQueueFactory::Priority::NORMAL);
std::atomic_int counter(0);
- auto handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
+ auto handle = RepeatingTaskHandle::Start(task_queue.get(), [&] {
if (++counter >= kShortIntervalCount)
return kLongInterval;
return kShortInterval;
@@ -101,7 +101,7 @@ TEST(ExternalTimeControllerTest, TaskIsStoppedOnStop) {
time_simulation.AdvanceTime(kShortInterval * (kShortIntervalCount + kMargin));
EXPECT_EQ(counter.load(), kShortIntervalCount);
- task_queue.PostTask(
+ task_queue->PostTask(
[handle = std::move(handle)]() mutable { handle.Stop(); });
// Sleep long enough that the task would run at least once more if not
@@ -114,13 +114,13 @@ TEST(ExternalTimeControllerTest, TaskCanStopItself) {
std::atomic_int counter(0);
FakeAlarm alarm(kStartTime);
ExternalTimeController time_simulation(&alarm);
- rtc::TaskQueue task_queue(
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
- "TestQueue", TaskQueueFactory::Priority::NORMAL));
+ "TestQueue", TaskQueueFactory::Priority::NORMAL);
RepeatingTaskHandle handle;
- task_queue.PostTask([&] {
- handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
+ task_queue->PostTask([&] {
+ handle = RepeatingTaskHandle::Start(task_queue.get(), [&] {
++counter;
handle.Stop();
return TimeDelta::Millis(2);
@@ -134,12 +134,12 @@ TEST(ExternalTimeControllerTest, YieldForTask) {
FakeAlarm alarm(kStartTime);
ExternalTimeController time_simulation(&alarm);
- rtc::TaskQueue task_queue(
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
- "TestQueue", TaskQueueFactory::Priority::NORMAL));
+ "TestQueue", TaskQueueFactory::Priority::NORMAL);
rtc::Event event;
- task_queue.PostTask([&] { event.Set(); });
+ task_queue->PostTask([&] { event.Set(); });
EXPECT_TRUE(event.Wait(TimeDelta::Millis(200)));
}
@@ -147,16 +147,16 @@ TEST(ExternalTimeControllerTest, TasksYieldToEachOther) {
FakeAlarm alarm(kStartTime);
ExternalTimeController time_simulation(&alarm);
- rtc::TaskQueue task_queue(
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
- "TestQueue", TaskQueueFactory::Priority::NORMAL));
- rtc::TaskQueue other_queue(
+ "TestQueue", TaskQueueFactory::Priority::NORMAL);
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> other_queue =
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
- "OtherQueue", TaskQueueFactory::Priority::NORMAL));
+ "OtherQueue", TaskQueueFactory::Priority::NORMAL);
- task_queue.PostTask([&] {
+ task_queue->PostTask([&] {
rtc::Event event;
- other_queue.PostTask([&] { event.Set(); });
+ other_queue->PostTask([&] { event.Set(); });
EXPECT_TRUE(event.Wait(TimeDelta::Millis(200)));
});
@@ -167,11 +167,11 @@ TEST(ExternalTimeControllerTest, CurrentTaskQueue) {
FakeAlarm alarm(kStartTime);
ExternalTimeController time_simulation(&alarm);
- rtc::TaskQueue task_queue(
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
- "TestQueue", TaskQueueFactory::Priority::NORMAL));
+ "TestQueue", TaskQueueFactory::Priority::NORMAL);
- task_queue.PostTask([&] { EXPECT_TRUE(task_queue.IsCurrent()); });
+ task_queue->PostTask([&] { EXPECT_TRUE(task_queue->IsCurrent()); });
time_simulation.AdvanceTime(TimeDelta::Millis(10));
}
diff --git a/third_party/libwebrtc/test/time_controller/real_time_controller.cc b/third_party/libwebrtc/test/time_controller/real_time_controller.cc
index 7cc750d6d4..537532d20f 100644
--- a/third_party/libwebrtc/test/time_controller/real_time_controller.cc
+++ b/third_party/libwebrtc/test/time_controller/real_time_controller.cc
@@ -9,6 +9,7 @@
*/
#include "test/time_controller/real_time_controller.h"
+#include "api/field_trials_view.h"
#include "api/task_queue/default_task_queue_factory.h"
#include "rtc_base/null_socket_server.h"
@@ -30,8 +31,8 @@ class MainThread : public rtc::Thread {
CurrentThreadSetter current_setter_;
};
} // namespace
-RealTimeController::RealTimeController()
- : task_queue_factory_(CreateDefaultTaskQueueFactory()),
+RealTimeController::RealTimeController(const FieldTrialsView* field_trials)
+ : task_queue_factory_(CreateDefaultTaskQueueFactory(field_trials)),
main_thread_(std::make_unique<MainThread>()) {
main_thread_->SetName("Main", this);
}
diff --git a/third_party/libwebrtc/test/time_controller/real_time_controller.h b/third_party/libwebrtc/test/time_controller/real_time_controller.h
index 5f02eaf85f..0085732e63 100644
--- a/third_party/libwebrtc/test/time_controller/real_time_controller.h
+++ b/third_party/libwebrtc/test/time_controller/real_time_controller.h
@@ -13,6 +13,7 @@
#include <functional>
#include <memory>
+#include "api/field_trials_view.h"
#include "api/task_queue/task_queue_factory.h"
#include "api/test/time_controller.h"
#include "api/units/time_delta.h"
@@ -21,7 +22,7 @@
namespace webrtc {
class RealTimeController : public TimeController {
public:
- RealTimeController();
+ RealTimeController(const FieldTrialsView* field_trials = nullptr);
Clock* GetClock() override;
TaskQueueFactory* GetTaskQueueFactory() override;
diff --git a/third_party/libwebrtc/test/time_controller/simulated_time_controller.cc b/third_party/libwebrtc/test/time_controller/simulated_time_controller.cc
index dbb36fdfcc..ce666c4bf5 100644
--- a/third_party/libwebrtc/test/time_controller/simulated_time_controller.cc
+++ b/third_party/libwebrtc/test/time_controller/simulated_time_controller.cc
@@ -218,9 +218,6 @@ void GlobalSimulatedTimeController::SkipForwardBy(TimeDelta duration) {
impl_.AdvanceTime(target_time);
sim_clock_.AdvanceTimeMicroseconds(duration.us());
global_clock_.AdvanceTime(duration);
-
- // Run tasks that were pending during the skip.
- impl_.RunReadyRunners();
}
void GlobalSimulatedTimeController::Register(
diff --git a/third_party/libwebrtc/test/time_controller/simulated_time_controller.h b/third_party/libwebrtc/test/time_controller/simulated_time_controller.h
index f3f0da9274..df7f866b14 100644
--- a/third_party/libwebrtc/test/time_controller/simulated_time_controller.h
+++ b/third_party/libwebrtc/test/time_controller/simulated_time_controller.h
@@ -139,7 +139,6 @@ class GlobalSimulatedTimeController : public TimeController {
void AdvanceTime(TimeDelta duration) override;
// Advances time by `duration`and do not run delayed tasks in the meantime.
- // Runs any pending tasks at the end.
// Useful for simulating contention on destination queues.
void SkipForwardBy(TimeDelta duration);
diff --git a/third_party/libwebrtc/test/time_controller/simulated_time_controller_unittest.cc b/third_party/libwebrtc/test/time_controller/simulated_time_controller_unittest.cc
index f223ffe85d..c1c0ac2c0e 100644
--- a/third_party/libwebrtc/test/time_controller/simulated_time_controller_unittest.cc
+++ b/third_party/libwebrtc/test/time_controller/simulated_time_controller_unittest.cc
@@ -13,9 +13,9 @@
#include <atomic>
#include <memory>
+#include "api/task_queue/task_queue_base.h"
#include "api/units/time_delta.h"
#include "rtc_base/event.h"
-#include "rtc_base/task_queue.h"
#include "rtc_base/task_queue_for_test.h"
#include "rtc_base/task_utils/repeating_task.h"
#include "test/gmock.h"
@@ -39,11 +39,11 @@ TEST(SimulatedTimeControllerTest, TaskIsStoppedOnStop) {
const int kShortIntervalCount = 4;
const int kMargin = 1;
GlobalSimulatedTimeController time_simulation(kStartTime);
- rtc::TaskQueue task_queue(
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
- "TestQueue", TaskQueueFactory::Priority::NORMAL));
+ "TestQueue", TaskQueueFactory::Priority::NORMAL);
std::atomic_int counter(0);
- auto handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
+ auto handle = RepeatingTaskHandle::Start(task_queue.get(), [&] {
if (++counter >= kShortIntervalCount)
return kLongInterval;
return kShortInterval;
@@ -52,7 +52,7 @@ TEST(SimulatedTimeControllerTest, TaskIsStoppedOnStop) {
time_simulation.AdvanceTime(kShortInterval * (kShortIntervalCount + kMargin));
EXPECT_EQ(counter.load(), kShortIntervalCount);
- task_queue.PostTask(
+ task_queue->PostTask(
[handle = std::move(handle)]() mutable { handle.Stop(); });
// Sleep long enough that the task would run at least once more if not
@@ -64,13 +64,13 @@ TEST(SimulatedTimeControllerTest, TaskIsStoppedOnStop) {
TEST(SimulatedTimeControllerTest, TaskCanStopItself) {
std::atomic_int counter(0);
GlobalSimulatedTimeController time_simulation(kStartTime);
- rtc::TaskQueue task_queue(
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
- "TestQueue", TaskQueueFactory::Priority::NORMAL));
+ "TestQueue", TaskQueueFactory::Priority::NORMAL);
RepeatingTaskHandle handle;
- task_queue.PostTask([&] {
- handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
+ task_queue->PostTask([&] {
+ handle = RepeatingTaskHandle::Start(task_queue.get(), [&] {
++counter;
handle.Stop();
return TimeDelta::Millis(2);
@@ -86,29 +86,29 @@ TEST(SimulatedTimeControllerTest, Example) {
void DoPeriodicTask() {}
TimeDelta TimeUntilNextRun() { return TimeDelta::Millis(100); }
void StartPeriodicTask(RepeatingTaskHandle* handle,
- rtc::TaskQueue* task_queue) {
- *handle = RepeatingTaskHandle::Start(task_queue->Get(), [this] {
+ TaskQueueBase* task_queue) {
+ *handle = RepeatingTaskHandle::Start(task_queue, [this] {
DoPeriodicTask();
return TimeUntilNextRun();
});
}
};
GlobalSimulatedTimeController time_simulation(kStartTime);
- rtc::TaskQueue task_queue(
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
- "TestQueue", TaskQueueFactory::Priority::NORMAL));
+ "TestQueue", TaskQueueFactory::Priority::NORMAL);
auto object = std::make_unique<ObjectOnTaskQueue>();
// Create and start the periodic task.
RepeatingTaskHandle handle;
- object->StartPeriodicTask(&handle, &task_queue);
+ object->StartPeriodicTask(&handle, task_queue.get());
// Restart the task
- task_queue.PostTask(
+ task_queue->PostTask(
[handle = std::move(handle)]() mutable { handle.Stop(); });
- object->StartPeriodicTask(&handle, &task_queue);
- task_queue.PostTask(
+ object->StartPeriodicTask(&handle, task_queue.get());
+ task_queue->PostTask(
[handle = std::move(handle)]() mutable { handle.Stop(); });
- task_queue.PostTask([object = std::move(object)] {});
+ task_queue->PostTask([object = std::move(object)] {});
}
TEST(SimulatedTimeControllerTest, DelayTaskRunOnTime) {
@@ -159,6 +159,8 @@ TEST(SimulatedTimeControllerTest, SkipsDelayedTaskForward) {
}));
main_thread->PostDelayedTask(fun.AsStdFunction(), shorter_duration);
sim.SkipForwardBy(duration_during_which_nothing_runs);
+ // Run tasks that were pending during the skip.
+ sim.AdvanceTime(TimeDelta::Zero());
}
} // namespace webrtc
diff --git a/third_party/libwebrtc/test/video_codec_tester.cc b/third_party/libwebrtc/test/video_codec_tester.cc
index 9453c3a7ef..f5fdc07a6b 100644
--- a/third_party/libwebrtc/test/video_codec_tester.cc
+++ b/third_party/libwebrtc/test/video_codec_tester.cc
@@ -23,10 +23,13 @@
#include "api/video/video_bitrate_allocator.h"
#include "api/video/video_codec_type.h"
#include "api/video/video_frame.h"
+#include "api/video_codecs/h264_profile_level_id.h"
+#include "api/video_codecs/simulcast_stream.h"
#include "api/video_codecs/video_decoder.h"
#include "api/video_codecs/video_encoder.h"
#include "media/base/media_constants.h"
#include "modules/video_coding/codecs/av1/av1_svc_config.h"
+#include "modules/video_coding/codecs/h264/include/h264.h"
#include "modules/video_coding/codecs/vp9/svc_config.h"
#include "modules/video_coding/include/video_codec_interface.h"
#include "modules/video_coding/include/video_error_codes.h"
@@ -39,10 +42,12 @@
#include "rtc_base/task_queue_for_test.h"
#include "rtc_base/time_utils.h"
#include "system_wrappers/include/sleep.h"
+#include "test/scoped_key_value_config.h"
#include "test/testsupport/file_utils.h"
#include "test/testsupport/frame_reader.h"
#include "test/testsupport/video_frame_writer.h"
#include "third_party/libyuv/include/libyuv/compare.h"
+#include "video/config/simulcast.h"
namespace webrtc {
namespace test {
@@ -260,9 +265,10 @@ class TesterIvfWriter {
task_queue_.SendTask([] {});
}
- void Write(const EncodedImage& encoded_frame) {
- task_queue_.PostTask([this, encoded_frame] {
- int spatial_idx = encoded_frame.SimulcastIndex().value_or(0);
+ void Write(const EncodedImage& encoded_frame, VideoCodecType codec_type) {
+ task_queue_.PostTask([this, encoded_frame, codec_type] {
+ int spatial_idx = encoded_frame.SpatialIndex().value_or(
+ encoded_frame.SimulcastIndex().value_or(0));
if (ivf_file_writers_.find(spatial_idx) == ivf_file_writers_.end()) {
std::string ivf_path =
base_path_ + "-s" + std::to_string(spatial_idx) + ".ivf";
@@ -277,8 +283,7 @@ class TesterIvfWriter {
}
// To play: ffplay -vcodec vp8|vp9|av1|hevc|h264 filename
- ivf_file_writers_.at(spatial_idx)
- ->WriteFrame(encoded_frame, VideoCodecType::kVideoCodecGeneric);
+ ivf_file_writers_.at(spatial_idx)->WriteFrame(encoded_frame, codec_type);
});
}
@@ -344,7 +349,8 @@ class VideoCodecAnalyzer : public VideoCodecTester::VideoCodecStats {
int64_t encode_finished_us = rtc::TimeMicros();
task_queue_.PostTask(
[this, timestamp_rtp = encoded_frame.RtpTimestamp(),
- spatial_idx = encoded_frame.SpatialIndex().value_or(0),
+ spatial_idx = encoded_frame.SpatialIndex().value_or(
+ encoded_frame.SimulcastIndex().value_or(0)),
temporal_idx = encoded_frame.TemporalIndex().value_or(0),
width = encoded_frame._encodedWidth,
height = encoded_frame._encodedHeight,
@@ -378,17 +384,30 @@ class VideoCodecAnalyzer : public VideoCodecTester::VideoCodecStats {
int64_t decode_start_us = rtc::TimeMicros();
task_queue_.PostTask(
[this, timestamp_rtp = encoded_frame.RtpTimestamp(),
- spatial_idx = encoded_frame.SpatialIndex().value_or(0),
+ spatial_idx = encoded_frame.SpatialIndex().value_or(
+ encoded_frame.SimulcastIndex().value_or(0)),
+ temporal_idx = encoded_frame.TemporalIndex().value_or(0),
+ width = encoded_frame._encodedWidth,
+ height = encoded_frame._encodedHeight,
+ frame_type = encoded_frame._frameType, qp = encoded_frame.qp_,
frame_size_bytes = encoded_frame.size(), decode_start_us]() {
- if (frames_.find(timestamp_rtp) == frames_.end() ||
- frames_.at(timestamp_rtp).find(spatial_idx) ==
- frames_.at(timestamp_rtp).end()) {
+ bool decode_only = frames_.find(timestamp_rtp) == frames_.end();
+ if (decode_only || frames_.at(timestamp_rtp).find(spatial_idx) ==
+ frames_.at(timestamp_rtp).end()) {
Frame frame;
frame.timestamp_rtp = timestamp_rtp;
- frame.layer_id = {.spatial_idx = spatial_idx};
- frame.frame_size = DataSize::Bytes(frame_size_bytes);
- frames_.emplace(timestamp_rtp,
- std::map<int, Frame>{{spatial_idx, frame}});
+ frame.layer_id = {.spatial_idx = spatial_idx,
+ .temporal_idx = temporal_idx};
+ frame.width = width;
+ frame.height = height;
+ frame.keyframe = frame_type == VideoFrameType::kVideoFrameKey;
+ frame.qp = qp;
+ if (decode_only) {
+ frame.frame_size = DataSize::Bytes(frame_size_bytes);
+ frames_[timestamp_rtp] = {{spatial_idx, frame}};
+ } else {
+ frames_[timestamp_rtp][spatial_idx] = frame;
+ }
}
Frame& frame = frames_.at(timestamp_rtp).at(spatial_idx);
@@ -485,6 +504,8 @@ class VideoCodecAnalyzer : public VideoCodecTester::VideoCodecStats {
Frame superframe = subframes.back();
for (const Frame& frame :
rtc::ArrayView<Frame>(subframes).subview(0, subframes.size() - 1)) {
+ superframe.decoded |= frame.decoded;
+ superframe.encoded |= frame.encoded;
superframe.frame_size += frame.frame_size;
superframe.keyframe |= frame.keyframe;
superframe.encode_time =
@@ -775,11 +796,13 @@ class Decoder : public DecodedImageCallback {
RTC_CHECK(decoder_) << "Could not create decoder for video format "
<< sdp_video_format.ToString();
- task_queue_.PostTaskAndWait([this, &sdp_video_format] {
+ codec_type_ = PayloadStringToCodecType(sdp_video_format.name);
+
+ task_queue_.PostTaskAndWait([this] {
decoder_->RegisterDecodeCompleteCallback(this);
VideoDecoder::Settings ds;
- ds.set_codec_type(PayloadStringToCodecType(sdp_video_format.name));
+ ds.set_codec_type(*codec_type_);
ds.set_number_of_cores(1);
ds.set_max_render_resolution({1280, 720});
bool result = decoder_->Configure(ds);
@@ -788,6 +811,16 @@ class Decoder : public DecodedImageCallback {
}
void Decode(const EncodedImage& encoded_frame) {
+ int spatial_idx = encoded_frame.SpatialIndex().value_or(
+ encoded_frame.SimulcastIndex().value_or(0));
+ {
+ MutexLock lock(&mutex_);
+ RTC_CHECK_EQ(spatial_idx_.value_or(spatial_idx), spatial_idx)
+ << "Spatial index changed from " << *spatial_idx_ << " to "
+ << spatial_idx;
+ spatial_idx_ = spatial_idx;
+ }
+
Timestamp pts =
Timestamp::Micros((encoded_frame.RtpTimestamp() / k90kHz).us());
@@ -804,7 +837,7 @@ class Decoder : public DecodedImageCallback {
pacer_.Schedule(pts));
if (ivf_writer_) {
- ivf_writer_->Write(encoded_frame);
+ ivf_writer_->Write(encoded_frame, *codec_type_);
}
}
@@ -815,10 +848,16 @@ class Decoder : public DecodedImageCallback {
private:
int Decoded(VideoFrame& decoded_frame) override {
- analyzer_->FinishDecode(decoded_frame, /*spatial_idx=*/0);
+ int spatial_idx;
+ {
+ MutexLock lock(&mutex_);
+ spatial_idx = *spatial_idx_;
+ }
+
+ analyzer_->FinishDecode(decoded_frame, spatial_idx);
if (y4m_writer_) {
- y4m_writer_->Write(decoded_frame, /*spatial_idx=*/0);
+ y4m_writer_->Write(decoded_frame, spatial_idx);
}
return WEBRTC_VIDEO_CODEC_OK;
@@ -831,6 +870,9 @@ class Decoder : public DecodedImageCallback {
LimitedTaskQueue task_queue_;
std::unique_ptr<TesterIvfWriter> ivf_writer_;
std::unique_ptr<TesterY4mWriter> y4m_writer_;
+ absl::optional<VideoCodecType> codec_type_;
+ absl::optional<int> spatial_idx_ RTC_GUARDED_BY(mutex_);
+ Mutex mutex_;
};
class Encoder : public EncodedImageCallback {
@@ -863,6 +905,9 @@ class Encoder : public EncodedImageCallback {
RTC_CHECK(encoder_) << "Could not create encoder for video format "
<< encoding_settings.sdp_video_format.ToString();
+ codec_type_ =
+ PayloadStringToCodecType(encoding_settings.sdp_video_format.name);
+
task_queue_.PostTaskAndWait([this, encoding_settings] {
encoder_->RegisterEncodeCompleteCallback(this);
Configure(encoding_settings);
@@ -888,14 +933,13 @@ class Encoder : public EncodedImageCallback {
!IsSameRate(encoding_settings, *last_encoding_settings_)) {
SetRates(encoding_settings);
}
+ last_encoding_settings_ = encoding_settings;
int error = encoder_->Encode(input_frame, /*frame_types=*/nullptr);
if (error != 0) {
RTC_LOG(LS_WARNING) << "Encode failed with error code " << error
<< " RTP timestamp " << input_frame.timestamp();
}
-
- last_encoding_settings_ = encoding_settings;
},
pacer_.Schedule(pts));
@@ -906,13 +950,54 @@ class Encoder : public EncodedImageCallback {
void Flush() {
task_queue_.PostTaskAndWait([this] { encoder_->Release(); });
+ if (last_superframe_) {
+ int num_spatial_layers =
+ ScalabilityModeToNumSpatialLayers(last_superframe_->scalability_mode);
+ for (int sidx = *last_superframe_->encoded_frame.SpatialIndex() + 1;
+ sidx < num_spatial_layers; ++sidx) {
+ last_superframe_->encoded_frame.SetSpatialIndex(sidx);
+ DeliverEncodedFrame(last_superframe_->encoded_frame);
+ }
+ last_superframe_.reset();
+ }
}
private:
+ struct Superframe {
+ EncodedImage encoded_frame;
+ rtc::scoped_refptr<EncodedImageBuffer> encoded_data;
+ ScalabilityMode scalability_mode;
+ };
+
Result OnEncodedImage(const EncodedImage& encoded_frame,
const CodecSpecificInfo* codec_specific_info) override {
analyzer_->FinishEncode(encoded_frame);
+ if (last_superframe_ && last_superframe_->encoded_frame.RtpTimestamp() !=
+ encoded_frame.RtpTimestamp()) {
+ // New temporal unit. We have frame of previous temporal unit (TU) stored
+ // which means that the previous TU used spatial prediction. If encoder
+ // dropped a frame of layer X in the previous TU, mark the stored frame
+ // as a frame belonging to layer >X and deliver it such that decoders of
+ // layer >X receive encoded lower layers.
+ int num_spatial_layers =
+ ScalabilityModeToNumSpatialLayers(last_superframe_->scalability_mode);
+ for (int sidx = *last_superframe_->encoded_frame.SpatialIndex() + 1;
+ sidx < num_spatial_layers; ++sidx) {
+ last_superframe_->encoded_frame.SetSpatialIndex(sidx);
+ DeliverEncodedFrame(last_superframe_->encoded_frame);
+ }
+ last_superframe_.reset();
+ }
+
+ const EncodedImage& superframe =
+ MakeSuperFrame(encoded_frame, codec_specific_info);
+ DeliverEncodedFrame(superframe);
+
+ return Result(Result::Error::OK);
+ }
+
+ void DeliverEncodedFrame(const EncodedImage& encoded_frame) {
{
MutexLock lock(&mutex_);
auto it = callbacks_.find(encoded_frame.RtpTimestamp());
@@ -922,23 +1007,30 @@ class Encoder : public EncodedImageCallback {
}
if (ivf_writer_ != nullptr) {
- ivf_writer_->Write(encoded_frame);
+ ivf_writer_->Write(encoded_frame, codec_type_);
}
-
- return Result(Result::Error::OK);
}
void Configure(const EncodingSettings& es) {
- const LayerSettings& layer_settings = es.layers_settings.rbegin()->second;
- const DataRate& bitrate = layer_settings.bitrate;
+ const LayerSettings& top_layer_settings =
+ es.layers_settings.rbegin()->second;
+ const int num_spatial_layers =
+ ScalabilityModeToNumSpatialLayers(es.scalability_mode);
+ const int num_temporal_layers =
+ ScalabilityModeToNumTemporalLayers(es.scalability_mode);
+ DataRate total_bitrate = std::accumulate(
+ es.layers_settings.begin(), es.layers_settings.end(), DataRate::Zero(),
+ [](DataRate acc, const std::pair<const LayerId, LayerSettings> layer) {
+ return acc + layer.second.bitrate;
+ });
VideoCodec vc;
- vc.width = layer_settings.resolution.width;
- vc.height = layer_settings.resolution.height;
- vc.startBitrate = bitrate.kbps();
- vc.maxBitrate = bitrate.kbps();
+ vc.width = top_layer_settings.resolution.width;
+ vc.height = top_layer_settings.resolution.height;
+ vc.startBitrate = total_bitrate.kbps();
+ vc.maxBitrate = total_bitrate.kbps();
vc.minBitrate = 0;
- vc.maxFramerate = layer_settings.framerate.hertz<uint32_t>();
+ vc.maxFramerate = top_layer_settings.framerate.hertz<uint32_t>();
vc.active = true;
vc.numberOfSimulcastStreams = 0;
vc.mode = webrtc::VideoCodecMode::kRealtimeVideo;
@@ -950,10 +1042,11 @@ class Encoder : public EncodedImageCallback {
switch (vc.codecType) {
case kVideoCodecVP8:
*(vc.VP8()) = VideoEncoder::GetDefaultVp8Settings();
- vc.VP8()->SetNumberOfTemporalLayers(
- ScalabilityModeToNumTemporalLayers(es.scalability_mode));
+ vc.VP8()->SetNumberOfTemporalLayers(num_temporal_layers);
+ vc.SetScalabilityMode(std::vector<ScalabilityMode>{
+ ScalabilityMode::kL1T1, ScalabilityMode::kL1T2,
+ ScalabilityMode::kL1T3}[num_temporal_layers - 1]);
vc.qpMax = cricket::kDefaultVideoMaxQpVpx;
- // TODO(webrtc:14852): Configure simulcast.
break;
case kVideoCodecVP9:
*(vc.VP9()) = VideoEncoder::GetDefaultVp9Settings();
@@ -966,6 +1059,7 @@ class Encoder : public EncodedImageCallback {
break;
case kVideoCodecH264:
*(vc.H264()) = VideoEncoder::GetDefaultH264Settings();
+ vc.H264()->SetNumberOfTemporalLayers(num_temporal_layers);
vc.qpMax = cricket::kDefaultVideoMaxQpH26x;
break;
case kVideoCodecH265:
@@ -977,6 +1071,36 @@ class Encoder : public EncodedImageCallback {
break;
}
+ bool is_simulcast =
+ num_spatial_layers > 1 &&
+ (vc.codecType == kVideoCodecVP8 || vc.codecType == kVideoCodecH264 ||
+ vc.codecType == kVideoCodecH265);
+ if (is_simulcast) {
+ vc.numberOfSimulcastStreams = num_spatial_layers;
+ for (int sidx = 0; sidx < num_spatial_layers; ++sidx) {
+ auto tl0_settings = es.layers_settings.find(
+ LayerId{.spatial_idx = sidx, .temporal_idx = 0});
+ auto tlx_settings = es.layers_settings.find(LayerId{
+ .spatial_idx = sidx, .temporal_idx = num_temporal_layers - 1});
+ DataRate total_bitrate = std::accumulate(
+ tl0_settings, tlx_settings, DataRate::Zero(),
+ [](DataRate acc,
+ const std::pair<const LayerId, LayerSettings> layer) {
+ return acc + layer.second.bitrate;
+ });
+ SimulcastStream& ss = vc.simulcastStream[sidx];
+ ss.width = tl0_settings->second.resolution.width;
+ ss.height = tl0_settings->second.resolution.height;
+ ss.numberOfTemporalLayers = num_temporal_layers;
+ ss.maxBitrate = total_bitrate.kbps();
+ ss.targetBitrate = total_bitrate.kbps();
+ ss.minBitrate = 0;
+ ss.maxFramerate = vc.maxFramerate;
+ ss.qpMax = vc.qpMax;
+ ss.active = true;
+ }
+ }
+
VideoEncoder::Settings ves(
VideoEncoder::Capabilities(/*loss_notification=*/false),
/*number_of_cores=*/1,
@@ -1021,6 +1145,52 @@ class Encoder : public EncodedImageCallback {
return true;
}
+ static bool IsSvc(const EncodedImage& encoded_frame,
+ const CodecSpecificInfo& codec_specific_info) {
+ if (!codec_specific_info.scalability_mode) {
+ return false;
+ }
+ ScalabilityMode scalability_mode = *codec_specific_info.scalability_mode;
+ return (kFullSvcScalabilityModes.count(scalability_mode) ||
+ (kKeySvcScalabilityModes.count(scalability_mode) &&
+ encoded_frame.FrameType() == VideoFrameType::kVideoFrameKey));
+ }
+
+ const EncodedImage& MakeSuperFrame(
+ const EncodedImage& encoded_frame,
+ const CodecSpecificInfo* codec_specific_info) {
+ if (last_superframe_) {
+ // Append to base spatial layer frame(s).
+ RTC_CHECK_EQ(*encoded_frame.SpatialIndex(),
+ *last_superframe_->encoded_frame.SpatialIndex() + 1)
+ << "Inter-layer frame drops are not supported.";
+ size_t current_size = last_superframe_->encoded_data->size();
+ last_superframe_->encoded_data->Realloc(current_size +
+ encoded_frame.size());
+ memcpy(last_superframe_->encoded_data->data() + current_size,
+ encoded_frame.data(), encoded_frame.size());
+ last_superframe_->encoded_frame.SetEncodedData(
+ last_superframe_->encoded_data);
+ last_superframe_->encoded_frame.SetSpatialIndex(
+ encoded_frame.SpatialIndex());
+ return last_superframe_->encoded_frame;
+ }
+
+ RTC_CHECK(codec_specific_info != nullptr);
+ if (IsSvc(encoded_frame, *codec_specific_info)) {
+ last_superframe_ = Superframe{
+ .encoded_frame = EncodedImage(encoded_frame),
+ .encoded_data = EncodedImageBuffer::Create(encoded_frame.data(),
+ encoded_frame.size()),
+ .scalability_mode = *codec_specific_info->scalability_mode};
+ last_superframe_->encoded_frame.SetEncodedData(
+ last_superframe_->encoded_data);
+ return last_superframe_->encoded_frame;
+ }
+
+ return encoded_frame;
+ }
+
VideoEncoderFactory* const encoder_factory_;
std::unique_ptr<VideoEncoder> encoder_;
VideoCodecAnalyzer* const analyzer_;
@@ -1032,9 +1202,62 @@ class Encoder : public EncodedImageCallback {
std::unique_ptr<TesterIvfWriter> ivf_writer_;
std::map<uint32_t, int> sidx_ RTC_GUARDED_BY(mutex_);
std::map<uint32_t, EncodeCallback> callbacks_ RTC_GUARDED_BY(mutex_);
+ VideoCodecType codec_type_;
+ absl::optional<Superframe> last_superframe_;
Mutex mutex_;
};
+void ConfigureSimulcast(VideoCodec* vc) {
+ int num_spatial_layers =
+ ScalabilityModeToNumSpatialLayers(*vc->GetScalabilityMode());
+ int num_temporal_layers =
+ ScalabilityModeToNumTemporalLayers(*vc->GetScalabilityMode());
+
+ if (num_spatial_layers == 1) {
+ SimulcastStream* ss = &vc->simulcastStream[0];
+ ss->width = vc->width;
+ ss->height = vc->height;
+ ss->numberOfTemporalLayers = num_temporal_layers;
+ ss->maxBitrate = vc->maxBitrate;
+ ss->targetBitrate = vc->maxBitrate;
+ ss->minBitrate = vc->minBitrate;
+ ss->qpMax = vc->qpMax;
+ ss->active = true;
+ return;
+ }
+
+ ScopedKeyValueConfig field_trials((rtc::StringBuilder()
+ << "WebRTC-VP8ConferenceTemporalLayers/"
+ << num_temporal_layers << "/")
+ .str());
+
+ const std::vector<webrtc::VideoStream> streams = cricket::GetSimulcastConfig(
+ /*min_layer=*/1, num_spatial_layers, vc->width, vc->height,
+ /*bitrate_priority=*/1.0, cricket::kDefaultVideoMaxQpVpx,
+ /*is_screenshare=*/false, /*temporal_layers_supported=*/true,
+ field_trials);
+
+ vc->numberOfSimulcastStreams = streams.size();
+ RTC_CHECK_LE(vc->numberOfSimulcastStreams, num_spatial_layers);
+ if (vc->numberOfSimulcastStreams < num_spatial_layers) {
+ vc->SetScalabilityMode(LimitNumSpatialLayers(*vc->GetScalabilityMode(),
+ vc->numberOfSimulcastStreams));
+ }
+
+ for (int i = 0; i < vc->numberOfSimulcastStreams; ++i) {
+ SimulcastStream* ss = &vc->simulcastStream[i];
+ ss->width = streams[i].width;
+ ss->height = streams[i].height;
+ RTC_CHECK_EQ(*streams[i].num_temporal_layers, num_temporal_layers);
+ ss->numberOfTemporalLayers = *streams[i].num_temporal_layers;
+ ss->maxBitrate = streams[i].max_bitrate_bps / 1000;
+ ss->targetBitrate = streams[i].target_bitrate_bps / 1000;
+ ss->minBitrate = streams[i].min_bitrate_bps / 1000;
+ ss->qpMax = streams[i].max_qp;
+ ss->active = true;
+ }
+}
+
std::tuple<std::vector<DataRate>, ScalabilityMode>
SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
ScalabilityMode scalability_mode,
@@ -1075,8 +1298,7 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
// TODO(webrtc:14852): Configure simulcast.
*(vc.VP8()) = VideoEncoder::GetDefaultVp8Settings();
vc.VP8()->SetNumberOfTemporalLayers(num_temporal_layers);
- vc.simulcastStream[0].width = vc.width;
- vc.simulcastStream[0].height = vc.height;
+ ConfigureSimulcast(&vc);
break;
case kVideoCodecVP9: {
*(vc.VP9()) = VideoEncoder::GetDefaultVp9Settings();
@@ -1095,6 +1317,7 @@ SplitBitrateAndUpdateScalabilityMode(std::string codec_type,
case kVideoCodecH264: {
*(vc.H264()) = VideoEncoder::GetDefaultH264Settings();
vc.H264()->SetNumberOfTemporalLayers(num_temporal_layers);
+ ConfigureSimulcast(&vc);
} break;
case kVideoCodecH265:
break;
@@ -1227,14 +1450,24 @@ std::map<uint32_t, EncodingSettings> VideoCodecTester::CreateEncodingSettings(
}
}
+ SdpVideoFormat sdp_video_format = SdpVideoFormat(codec_type);
+ if (codec_type == "H264") {
+ const std::string packetization_mode =
+ "1"; // H264PacketizationMode::SingleNalUnit
+ sdp_video_format.parameters =
+ CreateH264Format(H264Profile::kProfileConstrainedBaseline,
+ H264Level::kLevel3_1, packetization_mode,
+ /*add_scalability_modes=*/false)
+ .parameters;
+ }
+
std::map<uint32_t, EncodingSettings> frames_settings;
uint32_t timestamp_rtp = first_timestamp_rtp;
for (int frame_num = 0; frame_num < num_frames; ++frame_num) {
frames_settings.emplace(
- timestamp_rtp,
- EncodingSettings{.sdp_video_format = SdpVideoFormat(codec_type),
- .scalability_mode = scalability_mode,
- .layers_settings = layers_settings});
+ timestamp_rtp, EncodingSettings{.sdp_video_format = sdp_video_format,
+ .scalability_mode = scalability_mode,
+ .layers_settings = layers_settings});
timestamp_rtp += k90kHz / Frequency::MilliHertz(1000 * framerate_fps);
}
@@ -1298,10 +1531,19 @@ VideoCodecTester::RunEncodeDecodeTest(
VideoSource video_source(source_settings);
std::unique_ptr<VideoCodecAnalyzer> analyzer =
std::make_unique<VideoCodecAnalyzer>(&video_source);
- Decoder decoder(decoder_factory, decoder_settings, analyzer.get());
+ const EncodingSettings& frame_settings = encoding_settings.begin()->second;
Encoder encoder(encoder_factory, encoder_settings, analyzer.get());
- encoder.Initialize(encoding_settings.begin()->second);
- decoder.Initialize(encoding_settings.begin()->second.sdp_video_format);
+ encoder.Initialize(frame_settings);
+
+ int num_spatial_layers =
+ ScalabilityModeToNumSpatialLayers(frame_settings.scalability_mode);
+ std::vector<std::unique_ptr<Decoder>> decoders;
+ for (int sidx = 0; sidx < num_spatial_layers; ++sidx) {
+ auto decoder = std::make_unique<Decoder>(decoder_factory, decoder_settings,
+ analyzer.get());
+ decoder->Initialize(frame_settings.sdp_video_format);
+ decoders.push_back(std::move(decoder));
+ }
for (const auto& [timestamp_rtp, frame_settings] : encoding_settings) {
const EncodingSettings::LayerSettings& top_layer =
@@ -1309,13 +1551,17 @@ VideoCodecTester::RunEncodeDecodeTest(
VideoFrame source_frame = video_source.PullFrame(
timestamp_rtp, top_layer.resolution, top_layer.framerate);
encoder.Encode(source_frame, frame_settings,
- [&decoder](const EncodedImage& encoded_frame) {
- decoder.Decode(encoded_frame);
+ [&decoders](const EncodedImage& encoded_frame) {
+ int sidx = encoded_frame.SpatialIndex().value_or(
+ encoded_frame.SimulcastIndex().value_or(0));
+ decoders.at(sidx)->Decode(encoded_frame);
});
}
encoder.Flush();
- decoder.Flush();
+ for (auto& decoder : decoders) {
+ decoder->Flush();
+ }
analyzer->Flush();
return std::move(analyzer);
}
diff --git a/third_party/libwebrtc/test/video_codec_tester_unittest.cc b/third_party/libwebrtc/test/video_codec_tester_unittest.cc
index af31fe2c13..df5dca90a2 100644
--- a/third_party/libwebrtc/test/video_codec_tester_unittest.cc
+++ b/third_party/libwebrtc/test/video_codec_tester_unittest.cc
@@ -22,9 +22,14 @@
#include "api/test/mock_video_encoder.h"
#include "api/test/mock_video_encoder_factory.h"
#include "api/units/data_rate.h"
+#include "api/units/data_size.h"
+#include "api/units/frequency.h"
#include "api/units/time_delta.h"
#include "api/video/i420_buffer.h"
#include "api/video/video_frame.h"
+#include "api/video_codecs/scalability_mode.h"
+#include "api/video_codecs/video_decoder.h"
+#include "api/video_codecs/video_encoder.h"
#include "modules/video_coding/include/video_codec_interface.h"
#include "modules/video_coding/svc/scalability_mode_util.h"
#include "test/gmock.h"
@@ -44,6 +49,8 @@ using ::testing::InvokeWithoutArgs;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SizeIs;
+using ::testing::UnorderedElementsAreArray;
+using ::testing::Values;
using VideoCodecStats = VideoCodecTester::VideoCodecStats;
using VideoSourceSettings = VideoCodecTester::VideoSourceSettings;
@@ -77,14 +84,19 @@ rtc::scoped_refptr<I420Buffer> CreateYuvBuffer(uint8_t y = 0,
return buffer;
}
+// TODO(ssilkin): Wrap this into a class that removes file in dtor.
std::string CreateYuvFile(int width, int height, int num_frames) {
std::string path = webrtc::test::TempFilename(webrtc::test::OutputPath(),
"video_codec_tester_unittest");
FILE* file = fopen(path.c_str(), "wb");
for (int frame_num = 0; frame_num < num_frames; ++frame_num) {
- uint8_t y = (frame_num + 0) & 255;
- uint8_t u = (frame_num + 1) & 255;
- uint8_t v = (frame_num + 2) & 255;
+ // For purposes of testing quality estimation, we need Y, U, V values in
+ // source and decoded video to be unique and deterministic. In source video
+ // we make them functions of frame number. The test decoder makes them
+ // functions of encoded frame size in decoded video.
+ uint8_t y = (frame_num * 3 + 0) & 255;
+ uint8_t u = (frame_num * 3 + 1) & 255;
+ uint8_t v = (frame_num * 3 + 2) & 255;
rtc::scoped_refptr<I420Buffer> buffer = CreateYuvBuffer(y, u, v);
fwrite(buffer->DataY(), 1, width * height, file);
int chroma_size_bytes = (width + 1) / 2 * (height + 1) / 2;
@@ -95,115 +107,161 @@ std::string CreateYuvFile(int width, int height, int num_frames) {
return path;
}
-std::unique_ptr<VideoCodecStats> RunTest(std::vector<std::vector<Frame>> frames,
- ScalabilityMode scalability_mode) {
- int num_frames = static_cast<int>(frames.size());
- std::string source_yuv_path = CreateYuvFile(kWidth, kHeight, num_frames);
- VideoSourceSettings source_settings{
- .file_path = source_yuv_path,
- .resolution = {.width = kWidth, .height = kHeight},
- .framerate = kTargetFramerate};
+class TestVideoEncoder : public MockVideoEncoder {
+ public:
+ TestVideoEncoder(ScalabilityMode scalability_mode,
+ std::vector<std::vector<Frame>> encoded_frames)
+ : scalability_mode_(scalability_mode), encoded_frames_(encoded_frames) {}
+ int32_t Encode(const VideoFrame& input_frame,
+ const std::vector<VideoFrameType>*) override {
+ for (const Frame& frame : encoded_frames_[num_encoded_frames_]) {
+ if (frame.frame_size.IsZero()) {
+ continue; // Frame drop.
+ }
+ EncodedImage encoded_frame;
+ encoded_frame._encodedWidth = frame.width;
+ encoded_frame._encodedHeight = frame.height;
+ encoded_frame.SetFrameType(frame.keyframe
+ ? VideoFrameType::kVideoFrameKey
+ : VideoFrameType::kVideoFrameDelta);
+ encoded_frame.SetRtpTimestamp(input_frame.timestamp());
+ encoded_frame.SetSpatialIndex(frame.layer_id.spatial_idx);
+ encoded_frame.SetTemporalIndex(frame.layer_id.temporal_idx);
+ encoded_frame.SetEncodedData(
+ EncodedImageBuffer::Create(frame.frame_size.bytes()));
+ CodecSpecificInfo codec_specific_info;
+ codec_specific_info.scalability_mode = scalability_mode_;
+ callback_->OnEncodedImage(encoded_frame, &codec_specific_info);
+ }
+ ++num_encoded_frames_;
+ return WEBRTC_VIDEO_CODEC_OK;
+ }
- int num_encoded_frames = 0;
- EncodedImageCallback* encoded_frame_callback;
- NiceMock<MockVideoEncoderFactory> encoder_factory;
- ON_CALL(encoder_factory, CreateVideoEncoder)
- .WillByDefault([&](const SdpVideoFormat&) {
- auto encoder = std::make_unique<NiceMock<MockVideoEncoder>>();
- ON_CALL(*encoder, RegisterEncodeCompleteCallback)
- .WillByDefault([&](EncodedImageCallback* callback) {
- encoded_frame_callback = callback;
- return WEBRTC_VIDEO_CODEC_OK;
- });
- ON_CALL(*encoder, Encode)
- .WillByDefault([&](const VideoFrame& input_frame,
- const std::vector<VideoFrameType>*) {
- for (const Frame& frame : frames[num_encoded_frames]) {
- EncodedImage encoded_frame;
- encoded_frame._encodedWidth = frame.width;
- encoded_frame._encodedHeight = frame.height;
- encoded_frame.SetFrameType(
- frame.keyframe ? VideoFrameType::kVideoFrameKey
- : VideoFrameType::kVideoFrameDelta);
- encoded_frame.SetRtpTimestamp(input_frame.timestamp());
- encoded_frame.SetSpatialIndex(frame.layer_id.spatial_idx);
- encoded_frame.SetTemporalIndex(frame.layer_id.temporal_idx);
- encoded_frame.SetEncodedData(
- EncodedImageBuffer::Create(frame.frame_size.bytes()));
- encoded_frame_callback->OnEncodedImage(
- encoded_frame,
- /*codec_specific_info=*/nullptr);
- }
- ++num_encoded_frames;
- return WEBRTC_VIDEO_CODEC_OK;
- });
- return encoder;
- });
+ int32_t RegisterEncodeCompleteCallback(
+ EncodedImageCallback* callback) override {
+ callback_ = callback;
+ return WEBRTC_VIDEO_CODEC_OK;
+ }
- int num_decoded_frames = 0;
- DecodedImageCallback* decode_callback;
- NiceMock<MockVideoDecoderFactory> decoder_factory;
- ON_CALL(decoder_factory, CreateVideoDecoder)
- .WillByDefault([&](const SdpVideoFormat&) {
- auto decoder = std::make_unique<NiceMock<MockVideoDecoder>>();
- ON_CALL(*decoder, RegisterDecodeCompleteCallback)
- .WillByDefault([&](DecodedImageCallback* callback) {
- decode_callback = callback;
- return WEBRTC_VIDEO_CODEC_OK;
- });
- ON_CALL(*decoder, Decode(_, _))
- .WillByDefault([&](const EncodedImage& encoded_frame, int64_t) {
- // Make values to be different from source YUV generated in
- // `CreateYuvFile`.
- uint8_t y = ((num_decoded_frames + 1) * 2) & 255;
- uint8_t u = ((num_decoded_frames + 2) * 2) & 255;
- uint8_t v = ((num_decoded_frames + 3) * 2) & 255;
- rtc::scoped_refptr<I420Buffer> frame_buffer =
- CreateYuvBuffer(y, u, v);
- VideoFrame decoded_frame =
- VideoFrame::Builder()
- .set_video_frame_buffer(frame_buffer)
- .set_timestamp_rtp(encoded_frame.RtpTimestamp())
- .build();
- decode_callback->Decoded(decoded_frame);
- ++num_decoded_frames;
- return WEBRTC_VIDEO_CODEC_OK;
- });
- return decoder;
- });
+ private:
+ ScalabilityMode scalability_mode_;
+ std::vector<std::vector<Frame>> encoded_frames_;
+ int num_encoded_frames_ = 0;
+ EncodedImageCallback* callback_;
+};
+
+class TestVideoDecoder : public MockVideoDecoder {
+ public:
+ int32_t Decode(const EncodedImage& encoded_frame, int64_t) {
+ uint8_t y = (encoded_frame.size() + 0) & 255;
+ uint8_t u = (encoded_frame.size() + 2) & 255;
+ uint8_t v = (encoded_frame.size() + 4) & 255;
+ rtc::scoped_refptr<I420Buffer> frame_buffer = CreateYuvBuffer(y, u, v);
+ VideoFrame decoded_frame =
+ VideoFrame::Builder()
+ .set_video_frame_buffer(frame_buffer)
+ .set_timestamp_rtp(encoded_frame.RtpTimestamp())
+ .build();
+ callback_->Decoded(decoded_frame);
+ frame_sizes_.push_back(DataSize::Bytes(encoded_frame.size()));
+ return WEBRTC_VIDEO_CODEC_OK;
+ }
- int num_spatial_layers = ScalabilityModeToNumSpatialLayers(scalability_mode);
- int num_temporal_layers =
- ScalabilityModeToNumTemporalLayers(scalability_mode);
+ int32_t RegisterDecodeCompleteCallback(DecodedImageCallback* callback) {
+ callback_ = callback;
+ return WEBRTC_VIDEO_CODEC_OK;
+ }
- std::map<uint32_t, EncodingSettings> encoding_settings;
- for (int frame_num = 0; frame_num < num_frames; ++frame_num) {
- std::map<LayerId, LayerSettings> layers_settings;
- for (int sidx = 0; sidx < num_spatial_layers; ++sidx) {
- for (int tidx = 0; tidx < num_temporal_layers; ++tidx) {
- layers_settings.emplace(
- LayerId{.spatial_idx = sidx, .temporal_idx = tidx},
- LayerSettings{.resolution = {.width = kWidth, .height = kHeight},
- .framerate = kTargetFramerate /
- (1 << (num_temporal_layers - 1 - tidx)),
- .bitrate = kTargetLayerBitrate});
+ const std::vector<DataSize>& frame_sizes() const { return frame_sizes_; }
+
+ private:
+ DecodedImageCallback* callback_;
+ std::vector<DataSize> frame_sizes_;
+};
+
+class VideoCodecTesterTest : public ::testing::Test {
+ public:
+ std::unique_ptr<VideoCodecStats> RunEncodeDecodeTest(
+ std::string codec_type,
+ ScalabilityMode scalability_mode,
+ std::vector<std::vector<Frame>> encoded_frames) {
+ int num_frames = encoded_frames.size();
+ std::string yuv_path = CreateYuvFile(kWidth, kHeight, num_frames);
+ VideoSourceSettings video_source_settings{
+ .file_path = yuv_path,
+ .resolution = {.width = kWidth, .height = kHeight},
+ .framerate = kTargetFramerate};
+
+ NiceMock<MockVideoEncoderFactory> encoder_factory;
+ ON_CALL(encoder_factory, CreateVideoEncoder)
+ .WillByDefault([&](const SdpVideoFormat&) {
+ return std::make_unique<NiceMock<TestVideoEncoder>>(scalability_mode,
+ encoded_frames);
+ });
+
+ NiceMock<MockVideoDecoderFactory> decoder_factory;
+ ON_CALL(decoder_factory, CreateVideoDecoder)
+ .WillByDefault([&](const SdpVideoFormat&) {
+ // Video codec tester destroyes decoder at the end of test. Test
+ // decoder collects stats which we need to access after test. To keep
+ // the decode alive we wrap it into a wrapper and pass the wrapper to
+ // the tester.
+ class DecoderWrapper : public TestVideoDecoder {
+ public:
+ explicit DecoderWrapper(TestVideoDecoder* decoder)
+ : decoder_(decoder) {}
+ int32_t Decode(const EncodedImage& encoded_frame,
+ int64_t render_time_ms) {
+ return decoder_->Decode(encoded_frame, render_time_ms);
+ }
+ int32_t RegisterDecodeCompleteCallback(
+ DecodedImageCallback* callback) {
+ return decoder_->RegisterDecodeCompleteCallback(callback);
+ }
+ TestVideoDecoder* decoder_;
+ };
+ decoders_.push_back(std::make_unique<NiceMock<TestVideoDecoder>>());
+ return std::make_unique<NiceMock<DecoderWrapper>>(
+ decoders_.back().get());
+ });
+
+ int num_spatial_layers =
+ ScalabilityModeToNumSpatialLayers(scalability_mode);
+ int num_temporal_layers =
+ ScalabilityModeToNumTemporalLayers(scalability_mode);
+ std::map<uint32_t, EncodingSettings> encoding_settings;
+ for (int frame_num = 0; frame_num < num_frames; ++frame_num) {
+ std::map<LayerId, LayerSettings> layers_settings;
+ for (int sidx = 0; sidx < num_spatial_layers; ++sidx) {
+ for (int tidx = 0; tidx < num_temporal_layers; ++tidx) {
+ layers_settings.emplace(
+ LayerId{.spatial_idx = sidx, .temporal_idx = tidx},
+ LayerSettings{
+ .resolution = {.width = kWidth, .height = kHeight},
+ .framerate = kTargetFramerate /
+ (1 << (num_temporal_layers - 1 - tidx)),
+ .bitrate = kTargetLayerBitrate});
+ }
}
+ encoding_settings.emplace(
+ encoded_frames[frame_num].front().timestamp_rtp,
+ EncodingSettings{.sdp_video_format = SdpVideoFormat(codec_type),
+ .scalability_mode = scalability_mode,
+ .layers_settings = layers_settings});
}
- encoding_settings.emplace(
- frames[frame_num][0].timestamp_rtp,
- EncodingSettings{.scalability_mode = scalability_mode,
- .layers_settings = layers_settings});
+
+ std::unique_ptr<VideoCodecStats> stats =
+ VideoCodecTester::RunEncodeDecodeTest(
+ video_source_settings, &encoder_factory, &decoder_factory,
+ EncoderSettings{}, DecoderSettings{}, encoding_settings);
+
+ remove(yuv_path.c_str());
+ return stats;
}
- EncoderSettings encoder_settings;
- DecoderSettings decoder_settings;
- std::unique_ptr<VideoCodecStats> stats =
- VideoCodecTester::RunEncodeDecodeTest(
- source_settings, &encoder_factory, &decoder_factory, encoder_settings,
- decoder_settings, encoding_settings);
- remove(source_yuv_path.c_str());
- return stats;
-}
+ protected:
+ std::vector<std::unique_ptr<TestVideoDecoder>> decoders_;
+};
EncodedImage CreateEncodedImage(uint32_t timestamp_rtp) {
EncodedImage encoded_image;
@@ -233,52 +291,63 @@ class MockCodedVideoSource : public CodedVideoSource {
} // namespace
-TEST(VideoCodecTester, Slice) {
- std::unique_ptr<VideoCodecStats> stats = RunTest(
- {{{.timestamp_rtp = 0, .layer_id = {.spatial_idx = 0, .temporal_idx = 0}},
- {.timestamp_rtp = 0,
- .layer_id = {.spatial_idx = 1, .temporal_idx = 0}}},
- {{.timestamp_rtp = 1,
- .layer_id = {.spatial_idx = 0, .temporal_idx = 1}}}},
- ScalabilityMode::kL2T2);
+TEST_F(VideoCodecTesterTest, Slice) {
+ std::unique_ptr<VideoCodecStats> stats =
+ RunEncodeDecodeTest("VP9", ScalabilityMode::kL2T2,
+ {{{.timestamp_rtp = 0,
+ .layer_id = {.spatial_idx = 0, .temporal_idx = 0},
+ .frame_size = DataSize::Bytes(1)},
+ {.timestamp_rtp = 0,
+ .layer_id = {.spatial_idx = 1, .temporal_idx = 0},
+ .frame_size = DataSize::Bytes(2)}},
+ {{.timestamp_rtp = 1,
+ .layer_id = {.spatial_idx = 0, .temporal_idx = 1},
+ .frame_size = DataSize::Bytes(3)}}});
std::vector<Frame> slice = stats->Slice(Filter{}, /*merge=*/false);
- EXPECT_THAT(slice, ElementsAre(Field(&Frame::timestamp_rtp, 0),
- Field(&Frame::timestamp_rtp, 0),
- Field(&Frame::timestamp_rtp, 1)));
+ EXPECT_THAT(slice,
+ ElementsAre(Field(&Frame::frame_size, DataSize::Bytes(1)),
+ Field(&Frame::frame_size, DataSize::Bytes(2)),
+ Field(&Frame::frame_size, DataSize::Bytes(3)),
+ Field(&Frame::frame_size, DataSize::Bytes(0))));
slice = stats->Slice({.min_timestamp_rtp = 1}, /*merge=*/false);
- EXPECT_THAT(slice, ElementsAre(Field(&Frame::timestamp_rtp, 1)));
+ EXPECT_THAT(slice,
+ ElementsAre(Field(&Frame::frame_size, DataSize::Bytes(3)),
+ Field(&Frame::frame_size, DataSize::Bytes(0))));
slice = stats->Slice({.max_timestamp_rtp = 0}, /*merge=*/false);
- EXPECT_THAT(slice, ElementsAre(Field(&Frame::timestamp_rtp, 0),
- Field(&Frame::timestamp_rtp, 0)));
+ EXPECT_THAT(slice,
+ ElementsAre(Field(&Frame::frame_size, DataSize::Bytes(1)),
+ Field(&Frame::frame_size, DataSize::Bytes(2))));
slice = stats->Slice({.layer_id = {{.spatial_idx = 0, .temporal_idx = 0}}},
/*merge=*/false);
- EXPECT_THAT(slice, ElementsAre(Field(&Frame::timestamp_rtp, 0)));
+ EXPECT_THAT(slice,
+ ElementsAre(Field(&Frame::frame_size, DataSize::Bytes(1))));
slice = stats->Slice({.layer_id = {{.spatial_idx = 0, .temporal_idx = 1}}},
/*merge=*/false);
- EXPECT_THAT(slice, ElementsAre(Field(&Frame::timestamp_rtp, 0),
- Field(&Frame::timestamp_rtp, 1)));
+ EXPECT_THAT(slice,
+ ElementsAre(Field(&Frame::frame_size, DataSize::Bytes(1)),
+ Field(&Frame::frame_size, DataSize::Bytes(3))));
}
-TEST(VideoCodecTester, Merge) {
+TEST_F(VideoCodecTesterTest, Merge) {
std::unique_ptr<VideoCodecStats> stats =
- RunTest({{{.timestamp_rtp = 0,
- .layer_id = {.spatial_idx = 0, .temporal_idx = 0},
- .frame_size = DataSize::Bytes(1),
- .keyframe = true},
- {.timestamp_rtp = 0,
- .layer_id = {.spatial_idx = 1, .temporal_idx = 0},
- .frame_size = DataSize::Bytes(2)}},
- {{.timestamp_rtp = 1,
- .layer_id = {.spatial_idx = 0, .temporal_idx = 1},
- .frame_size = DataSize::Bytes(4)},
- {.timestamp_rtp = 1,
- .layer_id = {.spatial_idx = 1, .temporal_idx = 1},
- .frame_size = DataSize::Bytes(8)}}},
- ScalabilityMode::kL2T2_KEY);
+ RunEncodeDecodeTest("VP8", ScalabilityMode::kL2T2_KEY,
+ {{{.timestamp_rtp = 0,
+ .layer_id = {.spatial_idx = 0, .temporal_idx = 0},
+ .frame_size = DataSize::Bytes(1),
+ .keyframe = true},
+ {.timestamp_rtp = 0,
+ .layer_id = {.spatial_idx = 1, .temporal_idx = 0},
+ .frame_size = DataSize::Bytes(2)}},
+ {{.timestamp_rtp = 1,
+ .layer_id = {.spatial_idx = 0, .temporal_idx = 1},
+ .frame_size = DataSize::Bytes(4)},
+ {.timestamp_rtp = 1,
+ .layer_id = {.spatial_idx = 1, .temporal_idx = 1},
+ .frame_size = DataSize::Bytes(8)}}});
std::vector<Frame> slice = stats->Slice(Filter{}, /*merge=*/true);
EXPECT_THAT(
@@ -300,33 +369,34 @@ struct AggregationTestParameters {
};
class VideoCodecTesterTestAggregation
- : public ::testing::TestWithParam<AggregationTestParameters> {};
+ : public VideoCodecTesterTest,
+ public ::testing::WithParamInterface<AggregationTestParameters> {};
TEST_P(VideoCodecTesterTestAggregation, Aggregate) {
AggregationTestParameters test_params = GetParam();
std::unique_ptr<VideoCodecStats> stats =
- RunTest({{// L0T0
- {.timestamp_rtp = 0,
- .layer_id = {.spatial_idx = 0, .temporal_idx = 0},
- .frame_size = DataSize::Bytes(1),
- .keyframe = true},
- // L1T0
- {.timestamp_rtp = 0,
- .layer_id = {.spatial_idx = 1, .temporal_idx = 0},
- .frame_size = DataSize::Bytes(2)}},
- // Emulate frame drop (frame_size = 0).
- {{.timestamp_rtp = 3000,
- .layer_id = {.spatial_idx = 0, .temporal_idx = 0},
- .frame_size = DataSize::Zero()}},
- {// L0T1
- {.timestamp_rtp = 87000,
- .layer_id = {.spatial_idx = 0, .temporal_idx = 1},
- .frame_size = DataSize::Bytes(4)},
- // L1T1
- {.timestamp_rtp = 87000,
- .layer_id = {.spatial_idx = 1, .temporal_idx = 1},
- .frame_size = DataSize::Bytes(8)}}},
- ScalabilityMode::kL2T2_KEY);
+ RunEncodeDecodeTest("VP8", ScalabilityMode::kL2T2_KEY,
+ {{// L0T0
+ {.timestamp_rtp = 0,
+ .layer_id = {.spatial_idx = 0, .temporal_idx = 0},
+ .frame_size = DataSize::Bytes(1),
+ .keyframe = true},
+ // L1T0
+ {.timestamp_rtp = 0,
+ .layer_id = {.spatial_idx = 1, .temporal_idx = 0},
+ .frame_size = DataSize::Bytes(2)}},
+ // Emulate frame drop (frame_size = 0).
+ {{.timestamp_rtp = 3000,
+ .layer_id = {.spatial_idx = 0, .temporal_idx = 0},
+ .frame_size = DataSize::Zero()}},
+ {// L0T1
+ {.timestamp_rtp = 87000,
+ .layer_id = {.spatial_idx = 0, .temporal_idx = 1},
+ .frame_size = DataSize::Bytes(4)},
+ // L1T1
+ {.timestamp_rtp = 87000,
+ .layer_id = {.spatial_idx = 1, .temporal_idx = 1},
+ .frame_size = DataSize::Bytes(8)}}});
Stream stream = stats->Aggregate(test_params.filter);
EXPECT_EQ(stream.keyframe.GetSum(), test_params.expected_keyframe_sum);
@@ -343,7 +413,7 @@ TEST_P(VideoCodecTesterTestAggregation, Aggregate) {
INSTANTIATE_TEST_SUITE_P(
All,
VideoCodecTesterTestAggregation,
- ::testing::Values(
+ Values(
// No filtering.
AggregationTestParameters{
.filter = {},
@@ -400,11 +470,11 @@ INSTANTIATE_TEST_SUITE_P(
.expected_framerate_mismatch_pct =
100 * (2.0 / kTargetFramerate.hertz() - 1)}));
-TEST(VideoCodecTester, Psnr) {
- std::unique_ptr<VideoCodecStats> stats =
- RunTest({{{.timestamp_rtp = 0, .frame_size = DataSize::Bytes(1)}},
- {{.timestamp_rtp = 3000, .frame_size = DataSize::Bytes(1)}}},
- ScalabilityMode::kL1T1);
+TEST_F(VideoCodecTesterTest, Psnr) {
+ std::unique_ptr<VideoCodecStats> stats = RunEncodeDecodeTest(
+ "VP8", ScalabilityMode::kL1T1,
+ {{{.timestamp_rtp = 0, .frame_size = DataSize::Bytes(2)}},
+ {{.timestamp_rtp = 3000, .frame_size = DataSize::Bytes(6)}}});
std::vector<Frame> slice = stats->Slice(Filter{}, /*merge=*/false);
ASSERT_THAT(slice, SizeIs(2));
@@ -418,6 +488,107 @@ TEST(VideoCodecTester, Psnr) {
EXPECT_NEAR(slice[1].psnr->v, 34, 1);
}
+struct ScalabilityTestParameters {
+ std::string codec_type;
+ ScalabilityMode scalability_mode;
+ // Temporal unit -> spatial layer -> frame size.
+ std::vector<std::map<int, DataSize>> encoded_frame_sizes;
+ std::vector<DataSize> expected_decode_frame_sizes;
+};
+
+class VideoCodecTesterTestScalability
+ : public VideoCodecTesterTest,
+ public ::testing::WithParamInterface<ScalabilityTestParameters> {};
+
+TEST_P(VideoCodecTesterTestScalability, EncodeDecode) {
+ ScalabilityTestParameters test_params = GetParam();
+ std::vector<std::vector<Frame>> frames;
+ for (size_t frame_num = 0; frame_num < test_params.encoded_frame_sizes.size();
+ ++frame_num) {
+ std::vector<Frame> temporal_unit;
+ for (auto [sidx, frame_size] : test_params.encoded_frame_sizes[frame_num]) {
+ temporal_unit.push_back(
+ Frame{.timestamp_rtp = static_cast<uint32_t>(3000 * frame_num),
+ .layer_id = {.spatial_idx = sidx, .temporal_idx = 0},
+ .frame_size = frame_size,
+ .keyframe = (frame_num == 0 && sidx == 0)});
+ }
+ frames.push_back(temporal_unit);
+ }
+ RunEncodeDecodeTest(test_params.codec_type, test_params.scalability_mode,
+ frames);
+
+ size_t num_spatial_layers =
+ ScalabilityModeToNumSpatialLayers(test_params.scalability_mode);
+ EXPECT_EQ(num_spatial_layers, decoders_.size());
+
+ // Collect input frame sizes from all decoders.
+ std::vector<DataSize> decode_frame_sizes;
+ for (const auto& decoder : decoders_) {
+ const auto& frame_sizes = decoder->frame_sizes();
+ decode_frame_sizes.insert(decode_frame_sizes.end(), frame_sizes.begin(),
+ frame_sizes.end());
+ }
+ EXPECT_THAT(decode_frame_sizes, UnorderedElementsAreArray(
+ test_params.expected_decode_frame_sizes));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ All,
+ VideoCodecTesterTestScalability,
+ Values(
+ ScalabilityTestParameters{
+ .codec_type = "VP8",
+ .scalability_mode = ScalabilityMode::kS2T1,
+ .encoded_frame_sizes = {{{0, DataSize::Bytes(1)},
+ {1, DataSize::Bytes(2)}},
+ {{0, DataSize::Bytes(4)},
+ // Emulate frame drop.
+ {1, DataSize::Bytes(0)}}},
+ .expected_decode_frame_sizes = {DataSize::Bytes(1),
+ DataSize::Bytes(2),
+ DataSize::Bytes(4)},
+ },
+ ScalabilityTestParameters{
+ .codec_type = "VP9",
+ .scalability_mode = ScalabilityMode::kL2T1,
+ .encoded_frame_sizes =
+ {{{0, DataSize::Bytes(1)}, {1, DataSize::Bytes(2)}},
+ {{0, DataSize::Bytes(4)}, {1, DataSize::Bytes(8)}},
+ {{0, DataSize::Bytes(16)},
+ // Emulate frame drop.
+ {1, DataSize::Bytes(0)}}},
+ .expected_decode_frame_sizes =
+ {DataSize::Bytes(1), DataSize::Bytes(3), DataSize::Bytes(4),
+ DataSize::Bytes(12), DataSize::Bytes(16), DataSize::Bytes(16)},
+ },
+ ScalabilityTestParameters{
+ .codec_type = "VP9",
+ .scalability_mode = ScalabilityMode::kL2T1_KEY,
+ .encoded_frame_sizes =
+ {{{0, DataSize::Bytes(1)}, {1, DataSize::Bytes(2)}},
+ {{0, DataSize::Bytes(4)}, {1, DataSize::Bytes(8)}},
+ {{0, DataSize::Bytes(16)},
+ // Emulate frame drop.
+ {1, DataSize::Bytes(0)}}},
+ .expected_decode_frame_sizes =
+ {DataSize::Bytes(1), DataSize::Bytes(3), DataSize::Bytes(4),
+ DataSize::Bytes(8), DataSize::Bytes(16)},
+ },
+ ScalabilityTestParameters{
+ .codec_type = "VP9",
+ .scalability_mode = ScalabilityMode::kS2T1,
+ .encoded_frame_sizes =
+ {{{0, DataSize::Bytes(1)}, {1, DataSize::Bytes(2)}},
+ {{0, DataSize::Bytes(4)}, {1, DataSize::Bytes(8)}},
+ {{0, DataSize::Bytes(16)},
+ // Emulate frame drop.
+ {1, DataSize::Bytes(0)}}},
+ .expected_decode_frame_sizes =
+ {DataSize::Bytes(1), DataSize::Bytes(2), DataSize::Bytes(4),
+ DataSize::Bytes(8), DataSize::Bytes(16)},
+ }));
+
class VideoCodecTesterTestPacing
: public ::testing::TestWithParam<std::tuple<PacingSettings, int>> {
public:
@@ -428,15 +599,11 @@ class VideoCodecTesterTestPacing
const Frequency kTargetFramerate = Frequency::Hertz(10);
void SetUp() override {
- source_yuv_file_path_ = webrtc::test::TempFilename(
- webrtc::test::OutputPath(), "video_codec_tester_impl_unittest");
- FILE* file = fopen(source_yuv_file_path_.c_str(), "wb");
- for (int i = 0; i < 3 * kSourceWidth * kSourceHeight / 2; ++i) {
- fwrite("x", 1, 1, file);
- }
- fclose(file);
+ source_yuv_file_path_ = CreateYuvFile(kSourceWidth, kSourceHeight, 1);
}
+ void TearDown() override { remove(source_yuv_file_path_.c_str()); }
+
protected:
std::string source_yuv_file_path_;
};
@@ -498,7 +665,7 @@ TEST_P(VideoCodecTesterTestPacing, PaceDecode) {
INSTANTIATE_TEST_SUITE_P(
DISABLED_All,
VideoCodecTesterTestPacing,
- ::testing::Values(
+ Values(
// No pacing.
std::make_tuple(PacingSettings{.mode = PacingMode::kNoPacing},
/*expected_delta_ms=*/0),