blob: 0191465aec23094466f787b9577ed970e6eb6e63 [file] [log] [blame]
/*
* Copyright (c) 2025 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 "video/timing/simulator/rendering_simulator.h"
#include <memory>
#include "absl/strings/string_view.h"
#include "api/units/data_size.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "logging/rtc_event_log/rtc_event_log_parser.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "video/timing/simulator/test/parsed_rtc_event_log_from_resources.h"
namespace webrtc::video_timing_simulator {
namespace {
using ::testing::AllOf;
using ::testing::Eq;
using ::testing::Field;
using ::testing::Matcher;
using ::testing::SizeIs;
using Frame = RenderingSimulator::Frame;
using Stream = RenderingSimulator::Stream;
Matcher<const Frame&> EqualsFrame(const Frame& expected) {
return AllOf(
Field("num_packets", &Frame::num_packets, Eq(expected.num_packets)),
Field("size", &Frame::size, Eq(expected.size)),
Field("payload_type", &Frame::payload_type, Eq(expected.payload_type)),
Field("rtp_timestamp", &Frame::rtp_timestamp, Eq(expected.rtp_timestamp)),
Field("unwrapped_rtp_timestamp", &Frame::unwrapped_rtp_timestamp,
Eq(expected.unwrapped_rtp_timestamp)),
Field("frame_id", &Frame::frame_id, Eq(expected.frame_id)),
Field("spatial_id", &Frame::spatial_id, Eq(expected.spatial_id)),
Field("temporal_id", &Frame::temporal_id, Eq(expected.temporal_id)),
Field("num_references", &Frame::num_references,
Eq(expected.num_references)),
Field("first_packet_arrival_timestamp",
&Frame::first_packet_arrival_timestamp,
Eq(expected.first_packet_arrival_timestamp)),
Field("last_packet_arrival_timestamp",
&Frame::last_packet_arrival_timestamp,
Eq(expected.last_packet_arrival_timestamp)),
Field("assembled_timestamp", &Frame::assembled_timestamp,
Eq(expected.assembled_timestamp)),
Field("render_timestamp", &Frame::render_timestamp,
Eq(expected.render_timestamp)),
Field("decoded_timestamp", &Frame::decoded_timestamp,
Eq(expected.decoded_timestamp)),
Field("rendered_timestamp", &Frame::rendered_timestamp,
Eq(expected.rendered_timestamp)),
Field("frames_dropped", &Frame::frames_dropped,
Eq(expected.frames_dropped)),
Field("jitter_buffer_minimum_delay", &Frame::jitter_buffer_minimum_delay,
Eq(expected.jitter_buffer_minimum_delay)),
Field("jitter_buffer_target_delay", &Frame::jitter_buffer_target_delay,
Eq(expected.jitter_buffer_target_delay)),
Field("jitter_buffer_delay", &Frame::jitter_buffer_delay,
Eq(expected.jitter_buffer_delay)));
}
// TODO: b/423646186 - Add tests for logs with losses.
TEST(RenderingSimulatorTest, VideoRecvVp8) {
std::unique_ptr<ParsedRtcEventLog> parsed_log =
ParsedRtcEventLogFromResources("video_recv_vp8_pt96");
RenderingSimulator::Config config{.name = "vp8"};
RenderingSimulator simulator(config);
RenderingSimulator::Results results = simulator.Simulate(*parsed_log);
EXPECT_THAT(results.config_name, Eq("vp8"));
ASSERT_THAT(results.streams, SizeIs(1));
const auto& stream = results.streams.front();
EXPECT_THAT(stream.creation_timestamp, Eq(Timestamp::Millis(100942625)));
EXPECT_THAT(stream.ssrc, Eq(3965119250));
EXPECT_THAT(stream.frames, SizeIs(650));
// Spot check the second to last frame.
// (The last frame is actually non-decodable due to a VideoReceiveStream2
// recreation in the log.)
const auto& last_frame = stream.frames[stream.frames.size() - 2];
EXPECT_THAT(
last_frame,
EqualsFrame(
{// Frame information.
.num_packets = 7,
.size = DataSize::Bytes(7669),
// RTP header information.
.payload_type = 96,
.rtp_timestamp = 2498233591,
.unwrapped_rtp_timestamp = 2498233591,
// Dependency descriptor information.
.frame_id = 648,
.spatial_id = 0,
.temporal_id = 0,
.num_references = 1,
// Packet timestamps.
.first_packet_arrival_timestamp = Timestamp::Millis(100964151),
.last_packet_arrival_timestamp = Timestamp::Millis(100964166),
// Frame timestamps.
.assembled_timestamp = Timestamp::Millis(100964166),
.render_timestamp = Timestamp::Millis(100964193),
.decoded_timestamp = Timestamp::Micros(100964182726),
.rendered_timestamp = Timestamp::Micros(100964182726),
// Jitter buffer information.
.frames_dropped = 0,
.jitter_buffer_minimum_delay = TimeDelta::Micros(18861),
.jitter_buffer_target_delay = TimeDelta::Micros(18861),
.jitter_buffer_delay = TimeDelta::Micros(31726)}));
}
TEST(RenderingSimulatorTest, VideoRecvVp9) {
std::unique_ptr<ParsedRtcEventLog> parsed_log =
ParsedRtcEventLogFromResources("video_recv_vp9_pt98");
RenderingSimulator::Config config{.name = "vp9"};
RenderingSimulator simulator(config);
RenderingSimulator::Results results = simulator.Simulate(*parsed_log);
EXPECT_THAT(results.config_name, Eq("vp9"));
ASSERT_THAT(results.streams, SizeIs(1));
const auto& stream = results.streams.front();
EXPECT_THAT(stream.ssrc, Eq(2849747025));
EXPECT_THAT(stream.frames, SizeIs(1493));
// Spot check the last frame.
const auto& last_frame = stream.frames.back();
EXPECT_THAT(
last_frame,
EqualsFrame(
{// Frame information.
.num_packets = 6,
.size = DataSize::Bytes(6265),
// RTP header information.
.payload_type = 98,
.rtp_timestamp = 2236817278,
.unwrapped_rtp_timestamp = 2236817278,
// Dependency descriptor information.
.frame_id = 1493,
.spatial_id = 0,
.temporal_id = 1,
.num_references = 1,
// Packet timestamps.
.first_packet_arrival_timestamp = Timestamp::Millis(98768274),
.last_packet_arrival_timestamp = Timestamp::Millis(98768284),
// Frame timestamps.
.assembled_timestamp = Timestamp::Millis(98768284),
.render_timestamp = Timestamp::Millis(98768325),
.decoded_timestamp = Timestamp::Micros(98768315261),
.rendered_timestamp = Timestamp::Micros(98768315261),
// Jitter buffer state.
.frames_dropped = 0,
.jitter_buffer_minimum_delay = TimeDelta::Micros(26611),
.jitter_buffer_target_delay = TimeDelta::Micros(26611),
.jitter_buffer_delay = TimeDelta::Micros(41261)}));
}
TEST(RenderingSimulatorTest, VideoRecvAv1) {
std::unique_ptr<ParsedRtcEventLog> parsed_log =
ParsedRtcEventLogFromResources("video_recv_av1_pt45");
RenderingSimulator::Config config{.name = "av1"};
RenderingSimulator simulator(config);
RenderingSimulator::Results results = simulator.Simulate(*parsed_log);
EXPECT_THAT(results.config_name, Eq("av1"));
ASSERT_THAT(results.streams, SizeIs(1));
const auto& stream = results.streams.front();
EXPECT_THAT(stream.ssrc, Eq(2805827407));
EXPECT_THAT(stream.frames, SizeIs(1412));
// Spot check the second to last frame.
// (The last frame is actually non-decodable due to a VideoReceiveStream2
// recreation in the log.)
const auto& last_frame = stream.frames[stream.frames.size() - 2];
EXPECT_THAT(
last_frame,
EqualsFrame(
{// Frame information.
.num_packets = 11,
.size = DataSize::Bytes(12705),
// RTP header information.
.payload_type = 45,
.rtp_timestamp = 2213213027,
.unwrapped_rtp_timestamp = 2213213027,
// Dependency descriptor information.
.frame_id = 1410,
.spatial_id = 0,
.temporal_id = 0,
.num_references = 1,
// Packet timestamps.
.first_packet_arrival_timestamp = Timestamp::Millis(98868775),
.last_packet_arrival_timestamp = Timestamp::Millis(98868790),
// Frame timestamps.
.assembled_timestamp = Timestamp::Millis(98868790),
.render_timestamp = Timestamp::Millis(98868822),
.decoded_timestamp = Timestamp::Micros(98868811531),
.rendered_timestamp = Timestamp::Micros(98868811531),
// Jitter buffer state.
.frames_dropped = 0,
.jitter_buffer_minimum_delay = TimeDelta::Micros(23864),
.jitter_buffer_target_delay = TimeDelta::Micros(23864),
.jitter_buffer_delay = TimeDelta::Micros(36531)}));
}
TEST(RenderingSimulatorTest, VideoRecvSequentialJoinVp8Vp9Av1) {
std::unique_ptr<ParsedRtcEventLog> parsed_log =
ParsedRtcEventLogFromResources("video_recv_sequential_join_vp8_vp9_av1");
RenderingSimulator::Config config;
RenderingSimulator simulator(config);
RenderingSimulator::Results results = simulator.Simulate(*parsed_log);
EXPECT_THAT(results.streams,
ElementsAre(AllOf(Field(&Stream::ssrc, Eq(2827012235)),
Field(&Stream::frames, SizeIs(1746))),
AllOf(Field(&Stream::ssrc, Eq(1651489786)),
Field(&Stream::frames, SizeIs(1157))),
AllOf(Field(&Stream::ssrc, Eq(1934275846)),
Field(&Stream::frames, SizeIs(361)))));
}
} // namespace
} // namespace webrtc::video_timing_simulator