summaryrefslogtreecommitdiff
path: root/chromium/media/base/video_transformation.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/base/video_transformation.cc')
-rw-r--r--chromium/media/base/video_transformation.cc95
1 files changed, 95 insertions, 0 deletions
diff --git a/chromium/media/base/video_transformation.cc b/chromium/media/base/video_transformation.cc
new file mode 100644
index 00000000000..4ba3658ffae
--- /dev/null
+++ b/chromium/media/base/video_transformation.cc
@@ -0,0 +1,95 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// 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 <stddef.h>
+
+#include "base/logging.h"
+
+namespace media {
+namespace {
+
+double FixedToFloatingPoint(int32_t i) {
+ return static_cast<double>(i >> 16);
+}
+
+} // namespace
+
+std::string VideoRotationToString(VideoRotation rotation) {
+ switch (rotation) {
+ case VIDEO_ROTATION_0:
+ return "0°";
+ case VIDEO_ROTATION_90:
+ return "90°";
+ case VIDEO_ROTATION_180:
+ return "180°";
+ case VIDEO_ROTATION_270:
+ return "270°";
+ }
+ NOTREACHED();
+ return "";
+}
+
+bool operator==(const struct VideoTransformation& first,
+ const struct VideoTransformation& second) {
+ return first.rotation == second.rotation && first.mirrored == second.mirrored;
+}
+
+VideoTransformation::VideoTransformation(int32_t matrix[4]) {
+ // 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.
+
+ // Check the matrix for validity
+ if (abs(matrix[0]) != abs(matrix[3]) || abs(matrix[1]) != abs(matrix[2])) {
+ rotation = VIDEO_ROTATION_0;
+ mirrored = false;
+ return;
+ }
+
+ double angle = acos(FixedToFloatingPoint(matrix[0])) * 180 / base::kPiDouble;
+
+ // Calculate angle offsets for rotation - rotating about the X axis
+ // can be expressed as a 180 degree rotation and a Y axis rotation
+ mirrored = false;
+ if (matrix[0] != matrix[3] && matrix[0] != 0) {
+ mirrored = !mirrored;
+ angle += 180;
+ }
+
+ if (matrix[1] == matrix[3] && matrix[1] != 0) {
+ mirrored = !mirrored;
+ }
+
+ // Normalize the angle
+ while (angle < 0)
+ angle += 360;
+
+ while (angle >= 360)
+ angle -= 360;
+
+ // 16 bits of fixed point decimal is enough to give 6 decimals of precision
+ // to cos(Θ). A delta of ±0.000001 causes acos(cos(Θ)) to differ by a minimum
+ // of 0.0002, which is why we only need to check that the angle is only
+ // accurate to within four decimal places. This is preferred to checking for
+ // a more precise accuracy, as the 'double' type is architecture dependent and
+ // there may be variance in floating point errors.
+ if (abs(angle - 0) < 1e-4) {
+ rotation = VIDEO_ROTATION_0;
+ } else if (abs(angle - 180) < 1e-4) {
+ rotation = VIDEO_ROTATION_180;
+ } else if (abs(angle - 90) < 1e-4) {
+ bool quadrant = asin(FixedToFloatingPoint(matrix[2])) < 0;
+ rotation = quadrant ? VIDEO_ROTATION_90 : VIDEO_ROTATION_270;
+ } else {
+ rotation = VIDEO_ROTATION_0;
+ mirrored = false;
+ }
+}
+
+} // namespace media