blob: ce11d5abe6fe271a828fc8bafc69042d81195f88 [file] [log] [blame]
/*
* Copyright (c) 2023 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 "modules/video_coding/codecs/test/video_codec_stats_impl.h"
#include <tuple>
#include "absl/types/optional.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
namespace test {
namespace {
using ::testing::Return;
using ::testing::Values;
using Filter = VideoCodecStats::Filter;
using Frame = VideoCodecStatsImpl::Frame;
using Stream = VideoCodecStats::Stream;
} // namespace
TEST(VideoCodecStatsImpl, AddAndGetFrame) {
VideoCodecStatsImpl stats;
stats.AddFrame({.timestamp_rtp = 0, .spatial_idx = 0});
stats.AddFrame({.timestamp_rtp = 0, .spatial_idx = 1});
stats.AddFrame({.timestamp_rtp = 1, .spatial_idx = 0});
Frame* fs = stats.GetFrame(/*timestamp_rtp=*/0, /*spatial_idx=*/0);
ASSERT_NE(fs, nullptr);
EXPECT_EQ(fs->timestamp_rtp, 0u);
EXPECT_EQ(fs->spatial_idx, 0);
fs = stats.GetFrame(/*timestamp_rtp=*/0, /*spatial_idx=*/1);
ASSERT_NE(fs, nullptr);
EXPECT_EQ(fs->timestamp_rtp, 0u);
EXPECT_EQ(fs->spatial_idx, 1);
fs = stats.GetFrame(/*timestamp_rtp=*/1, /*spatial_idx=*/0);
ASSERT_NE(fs, nullptr);
EXPECT_EQ(fs->timestamp_rtp, 1u);
EXPECT_EQ(fs->spatial_idx, 0);
fs = stats.GetFrame(/*timestamp_rtp=*/1, /*spatial_idx=*/1);
EXPECT_EQ(fs, nullptr);
}
class VideoCodecStatsImplSlicingTest
: public ::testing::TestWithParam<std::tuple<Filter, std::vector<int>>> {};
TEST_P(VideoCodecStatsImplSlicingTest, Slice) {
Filter filter = std::get<0>(GetParam());
std::vector<int> expected_frames = std::get<1>(GetParam());
std::vector<VideoCodecStats::Frame> frames = {
{.frame_num = 0, .timestamp_rtp = 0, .spatial_idx = 0, .temporal_idx = 0},
{.frame_num = 0, .timestamp_rtp = 0, .spatial_idx = 1, .temporal_idx = 0},
{.frame_num = 1, .timestamp_rtp = 1, .spatial_idx = 0, .temporal_idx = 1},
{.frame_num = 1,
.timestamp_rtp = 1,
.spatial_idx = 1,
.temporal_idx = 1}};
VideoCodecStatsImpl stats;
stats.AddFrame(frames[0]);
stats.AddFrame(frames[1]);
stats.AddFrame(frames[2]);
stats.AddFrame(frames[3]);
std::vector<VideoCodecStats::Frame> slice = stats.Slice(filter);
ASSERT_EQ(slice.size(), expected_frames.size());
for (size_t i = 0; i < expected_frames.size(); ++i) {
Frame& expected = frames[expected_frames[i]];
EXPECT_EQ(slice[i].frame_num, expected.frame_num);
EXPECT_EQ(slice[i].timestamp_rtp, expected.timestamp_rtp);
EXPECT_EQ(slice[i].spatial_idx, expected.spatial_idx);
EXPECT_EQ(slice[i].temporal_idx, expected.temporal_idx);
}
}
INSTANTIATE_TEST_SUITE_P(
All,
VideoCodecStatsImplSlicingTest,
::testing::Values(
std::make_tuple(Filter{}, std::vector<int>{0, 1, 2, 3}),
std::make_tuple(Filter{.first_frame = 1}, std::vector<int>{2, 3}),
std::make_tuple(Filter{.last_frame = 0}, std::vector<int>{0, 1}),
std::make_tuple(Filter{.spatial_idx = 0}, std::vector<int>{0, 2}),
std::make_tuple(Filter{.temporal_idx = 1},
std::vector<int>{0, 1, 2, 3})));
TEST(VideoCodecStatsImpl, AggregateBitrate) {
std::vector<VideoCodecStats::Frame> frames = {
{.frame_num = 0,
.timestamp_rtp = 0,
.frame_size = DataSize::Bytes(1000),
.target_bitrate = DataRate::BytesPerSec(1000)},
{.frame_num = 1,
.timestamp_rtp = 90000,
.frame_size = DataSize::Bytes(2000),
.target_bitrate = DataRate::BytesPerSec(1000)}};
Stream stream = VideoCodecStatsImpl().Aggregate(frames);
EXPECT_EQ(stream.encoded_bitrate_kbps.GetAverage(), 12.0);
EXPECT_EQ(stream.bitrate_mismatch_pct.GetAverage(), 50.0);
}
TEST(VideoCodecStatsImpl, AggregateFramerate) {
std::vector<VideoCodecStats::Frame> frames = {
{.frame_num = 0,
.timestamp_rtp = 0,
.frame_size = DataSize::Bytes(1),
.target_framerate = Frequency::Hertz(1)},
{.frame_num = 1,
.timestamp_rtp = 90000,
.frame_size = DataSize::Zero(),
.target_framerate = Frequency::Hertz(1)}};
Stream stream = VideoCodecStatsImpl().Aggregate(frames);
EXPECT_EQ(stream.encoded_framerate_fps.GetAverage(), 0.5);
EXPECT_EQ(stream.framerate_mismatch_pct.GetAverage(), -50.0);
}
TEST(VideoCodecStatsImpl, AggregateTransmissionTime) {
std::vector<VideoCodecStats::Frame> frames = {
{.frame_num = 0,
.timestamp_rtp = 0,
.frame_size = DataSize::Bytes(2),
.target_bitrate = DataRate::BytesPerSec(1)},
{.frame_num = 1,
.timestamp_rtp = 90000,
.frame_size = DataSize::Bytes(3),
.target_bitrate = DataRate::BytesPerSec(1)}};
Stream stream = VideoCodecStatsImpl().Aggregate(frames);
ASSERT_EQ(stream.transmission_time_ms.NumSamples(), 2);
ASSERT_EQ(stream.transmission_time_ms.GetSamples()[0], 2000);
ASSERT_EQ(stream.transmission_time_ms.GetSamples()[1], 4000);
}
} // namespace test
} // namespace webrtc