1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "rtc_tools/frame_analyzer/video_temporal_aligner.h"
12
13 #include <cstddef>
14
15 #include "rtc_tools/frame_analyzer/video_quality_analysis.h"
16 #include "rtc_tools/video_file_reader.h"
17 #include "test/gtest.h"
18 #include "test/testsupport/file_utils.h"
19
20 namespace webrtc {
21 namespace test {
22
23 class VideoTemporalAlignerTest : public ::testing::Test {
24 protected:
SetUp()25 void SetUp() {
26 reference_video =
27 OpenYuvFile(ResourcePath("foreman_128x96", "yuv"), 128, 96);
28 ASSERT_TRUE(reference_video);
29 }
30
31 rtc::scoped_refptr<Video> reference_video;
32 };
33
TEST_F(VideoTemporalAlignerTest,FindMatchingFrameIndicesEmpty)34 TEST_F(VideoTemporalAlignerTest, FindMatchingFrameIndicesEmpty) {
35 rtc::scoped_refptr<Video> empty_test_video =
36 ReorderVideo(reference_video, std::vector<size_t>());
37
38 const std::vector<size_t> matched_indices =
39 FindMatchingFrameIndices(reference_video, empty_test_video);
40
41 EXPECT_TRUE(matched_indices.empty());
42 }
43
TEST_F(VideoTemporalAlignerTest,FindMatchingFrameIndicesIdentity)44 TEST_F(VideoTemporalAlignerTest, FindMatchingFrameIndicesIdentity) {
45 const std::vector<size_t> indices =
46 FindMatchingFrameIndices(reference_video, reference_video);
47
48 EXPECT_EQ(indices.size(), reference_video->number_of_frames());
49 for (size_t i = 0; i < indices.size(); ++i)
50 EXPECT_EQ(i, indices[i]);
51 }
52
TEST_F(VideoTemporalAlignerTest,FindMatchingFrameIndicesDuplicateFrames)53 TEST_F(VideoTemporalAlignerTest, FindMatchingFrameIndicesDuplicateFrames) {
54 const std::vector<size_t> indices = {2, 2, 2, 2};
55
56 // Generate a test video based on this sequence.
57 rtc::scoped_refptr<Video> test_video = ReorderVideo(reference_video, indices);
58
59 const std::vector<size_t> matched_indices =
60 FindMatchingFrameIndices(reference_video, test_video);
61
62 EXPECT_EQ(indices, matched_indices);
63 }
64
TEST_F(VideoTemporalAlignerTest,FindMatchingFrameIndicesLoopAround)65 TEST_F(VideoTemporalAlignerTest, FindMatchingFrameIndicesLoopAround) {
66 std::vector<size_t> indices;
67 for (size_t i = 0; i < reference_video->number_of_frames() * 2; ++i)
68 indices.push_back(i % reference_video->number_of_frames());
69
70 // Generate a test video based on this sequence.
71 rtc::scoped_refptr<Video> test_video = ReorderVideo(reference_video, indices);
72
73 const std::vector<size_t> matched_indices =
74 FindMatchingFrameIndices(reference_video, test_video);
75
76 for (size_t i = 0; i < matched_indices.size(); ++i)
77 EXPECT_EQ(i, matched_indices[i]);
78 }
79
TEST_F(VideoTemporalAlignerTest,FindMatchingFrameIndicesStressTest)80 TEST_F(VideoTemporalAlignerTest, FindMatchingFrameIndicesStressTest) {
81 std::vector<size_t> indices;
82 // Arbitrary start index.
83 const size_t start_index = 12345;
84 // Generate some generic sequence of frames.
85 indices.push_back(start_index % reference_video->number_of_frames());
86 indices.push_back((start_index + 1) % reference_video->number_of_frames());
87 indices.push_back((start_index + 2) % reference_video->number_of_frames());
88 indices.push_back((start_index + 5) % reference_video->number_of_frames());
89 indices.push_back((start_index + 10) % reference_video->number_of_frames());
90 indices.push_back((start_index + 20) % reference_video->number_of_frames());
91 indices.push_back((start_index + 20) % reference_video->number_of_frames());
92 indices.push_back((start_index + 22) % reference_video->number_of_frames());
93 indices.push_back((start_index + 32) % reference_video->number_of_frames());
94
95 // Generate a test video based on this sequence.
96 rtc::scoped_refptr<Video> test_video = ReorderVideo(reference_video, indices);
97
98 const std::vector<size_t> matched_indices =
99 FindMatchingFrameIndices(reference_video, test_video);
100
101 EXPECT_EQ(indices, matched_indices);
102 }
103
TEST_F(VideoTemporalAlignerTest,GenerateAlignedReferenceVideo)104 TEST_F(VideoTemporalAlignerTest, GenerateAlignedReferenceVideo) {
105 // Arbitrary start index.
106 const size_t start_index = 12345;
107 std::vector<size_t> indices;
108 const size_t frame_step = 10;
109 for (size_t i = 0; i < reference_video->number_of_frames() / frame_step;
110 ++i) {
111 indices.push_back((start_index + i * frame_step) %
112 reference_video->number_of_frames());
113 }
114
115 // Generate a test video based on this sequence.
116 rtc::scoped_refptr<Video> test_video = ReorderVideo(reference_video, indices);
117
118 rtc::scoped_refptr<Video> aligned_reference_video =
119 GenerateAlignedReferenceVideo(reference_video, test_video);
120
121 // Assume perfect match, i.e. ssim == 1, for all frames.
122 for (size_t i = 0; i < test_video->number_of_frames(); ++i) {
123 EXPECT_EQ(1.0, Ssim(test_video->GetFrame(i),
124 aligned_reference_video->GetFrame(i)));
125 }
126 }
127
128 } // namespace test
129 } // namespace webrtc
130