blob: 0de872d46625ba0bea8e864ac63449a5a1296cfa [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/video_transformation.h"
#include <math.h>
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
namespace {
enum class Flip { kNone, kVertical, kHorizontal, kBoth };
// Rotation by angle Θ is represented in the matrix as:
// [ cos(Θ), -sin(Θ)]
// [ sin(Θ), cos(Θ)]
// a vertical flip is represented by the cosine's having opposite signs
// and a horizontal flip is represented by the sine's having the same sign.
constexpr void FromAngle(double angle_degrees, int32_t* matrix, Flip flip) {
double f_matrix[4] = {0, 0, 0, 0};
f_matrix[0] = f_matrix[3] = cos(angle_degrees * 3.1415926535 / 180.0);
f_matrix[1] = f_matrix[2] = sin(angle_degrees * 3.1415926535 / 180.0);
if (flip == Flip::kVertical || flip == Flip::kBoth)
f_matrix[3] *= -1;
if (flip == Flip::kVertical || flip == Flip::kNone)
f_matrix[2] *= -1;
matrix[0] = static_cast<int32_t>(round(f_matrix[0] * (1 << 16)));
matrix[1] = static_cast<int32_t>(round(f_matrix[1] * (1 << 16)));
matrix[3] = static_cast<int32_t>(round(f_matrix[2] * (1 << 16)));
matrix[4] = static_cast<int32_t>(round(f_matrix[3] * (1 << 16)));
}
} // namespace
class VideoTransformationTest : public testing::Test {
public:
VideoTransformationTest() = default;
VideoTransformationTest(const VideoTransformationTest&) = delete;
VideoTransformationTest& operator=(const VideoTransformationTest&) = delete;
~VideoTransformationTest() override = default;
};
TEST_F(VideoTransformationTest, ComputeRotationAngles) {
int32_t matrix[9];
// Standard 90 degree increments with no rotation all end up rotated normally
FromAngle(0.0, matrix, Flip::kNone);
ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix),
VideoTransformation(VIDEO_ROTATION_0, false));
FromAngle(90.0, matrix, Flip::kNone);
ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix),
VideoTransformation(VIDEO_ROTATION_90, false));
FromAngle(180.0, matrix, Flip::kNone);
ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix),
VideoTransformation(VIDEO_ROTATION_180, false));
FromAngle(270.0, matrix, Flip::kNone);
ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix),
VideoTransformation(VIDEO_ROTATION_270, false));
// Non-right-angle rotations all get set to 0, since we can't render those
// properly anyway.
FromAngle(60.0, matrix, Flip::kNone);
ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix),
VideoTransformation(VIDEO_ROTATION_0, false));
FromAngle(45.0, matrix, Flip::kNone);
ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix),
VideoTransformation(VIDEO_ROTATION_0, false));
// Flips can cause weird things - ie a vertical flip + 180 rotation
// is the same thing as a horizontal flip + no rotation!
FromAngle(180.0, matrix, Flip::kVertical);
ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix),
VideoTransformation(VIDEO_ROTATION_0, true));
// Vertical and horizontal flipping is the same as a 180 degree rotation
FromAngle(0.0, matrix, Flip::kBoth);
ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix),
VideoTransformation(VIDEO_ROTATION_180, true));
// An invalid matrix is always going to give no rotation or mirroring.
for (int i = 0; i < 9; i++)
matrix[i] = 78123;
ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix),
VideoTransformation(VIDEO_ROTATION_0, false));
}
} // namespace media