aboutsummaryrefslogtreecommitdiff
path: root/cast/streaming/resolution.cc
diff options
context:
space:
mode:
Diffstat (limited to 'cast/streaming/resolution.cc')
-rw-r--r--cast/streaming/resolution.cc122
1 files changed, 122 insertions, 0 deletions
diff --git a/cast/streaming/resolution.cc b/cast/streaming/resolution.cc
new file mode 100644
index 00000000..9c763cfe
--- /dev/null
+++ b/cast/streaming/resolution.cc
@@ -0,0 +1,122 @@
+// 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 "cast/streaming/resolution.h"
+
+#include <utility>
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+#include "cast/streaming/message_fields.h"
+#include "platform/base/error.h"
+#include "util/json/json_helpers.h"
+#include "util/osp_logging.h"
+
+namespace openscreen {
+namespace cast {
+
+namespace {
+
+/// Dimension properties.
+// Width in pixels.
+static constexpr char kWidth[] = "width";
+
+// Height in pixels.
+static constexpr char kHeight[] = "height";
+
+// Frame rate as a rational decimal number or fraction.
+// E.g. 30 and "3000/1001" are both valid representations.
+static constexpr char kFrameRate[] = "frameRate";
+
+// Choice of epsilon for double comparison allows for proper comparison
+// for both aspect ratios and frame rates. For frame rates, it is based on the
+// broadcast rate of 29.97fps, which is actually 29.976. For aspect ratios, it
+// allows for a one-pixel difference at a 4K resolution, we want it to be
+// relatively high to avoid false negative comparison results.
+bool FrameRateEquals(double a, double b) {
+ const double kEpsilonForFrameRateComparisons = .0001;
+ return std::abs(a - b) < kEpsilonForFrameRateComparisons;
+}
+
+} // namespace
+
+bool Resolution::TryParse(const Json::Value& root, Resolution* out) {
+ if (!json::TryParseInt(root[kWidth], &(out->width)) ||
+ !json::TryParseInt(root[kHeight], &(out->height))) {
+ return false;
+ }
+ return out->IsValid();
+}
+
+bool Resolution::IsValid() const {
+ return width > 0 && height > 0;
+}
+
+Json::Value Resolution::ToJson() const {
+ OSP_DCHECK(IsValid());
+ Json::Value root;
+ root[kWidth] = width;
+ root[kHeight] = height;
+
+ return root;
+}
+
+bool Resolution::operator==(const Resolution& other) const {
+ return std::tie(width, height) == std::tie(other.width, other.height);
+}
+
+bool Resolution::operator!=(const Resolution& other) const {
+ return !(*this == other);
+}
+
+bool Resolution::IsSupersetOf(const Resolution& other) const {
+ return width >= other.width && height >= other.height;
+}
+
+bool Dimensions::TryParse(const Json::Value& root, Dimensions* out) {
+ if (!json::TryParseInt(root[kWidth], &(out->width)) ||
+ !json::TryParseInt(root[kHeight], &(out->height)) ||
+ !(root[kFrameRate].isNull() ||
+ json::TryParseSimpleFraction(root[kFrameRate], &(out->frame_rate)))) {
+ return false;
+ }
+ return out->IsValid();
+}
+
+bool Dimensions::IsValid() const {
+ return width > 0 && height > 0 && frame_rate.is_positive();
+}
+
+Json::Value Dimensions::ToJson() const {
+ OSP_DCHECK(IsValid());
+ Json::Value root;
+ root[kWidth] = width;
+ root[kHeight] = height;
+ root[kFrameRate] = frame_rate.ToString();
+
+ return root;
+}
+
+bool Dimensions::operator==(const Dimensions& other) const {
+ return (std::tie(width, height) == std::tie(other.width, other.height) &&
+ FrameRateEquals(static_cast<double>(frame_rate),
+ static_cast<double>(other.frame_rate)));
+}
+
+bool Dimensions::operator!=(const Dimensions& other) const {
+ return !(*this == other);
+}
+
+bool Dimensions::IsSupersetOf(const Dimensions& other) const {
+ if (static_cast<double>(frame_rate) !=
+ static_cast<double>(other.frame_rate)) {
+ return static_cast<double>(frame_rate) >=
+ static_cast<double>(other.frame_rate);
+ }
+
+ return ToResolution().IsSupersetOf(other.ToResolution());
+}
+
+} // namespace cast
+} // namespace openscreen