xref: /aosp_15_r20/external/openscreen/cast/streaming/resolution.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "cast/streaming/resolution.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <utility>
8*3f982cf4SFabien Sanglard 
9*3f982cf4SFabien Sanglard #include "absl/strings/str_cat.h"
10*3f982cf4SFabien Sanglard #include "absl/strings/str_split.h"
11*3f982cf4SFabien Sanglard #include "cast/streaming/message_fields.h"
12*3f982cf4SFabien Sanglard #include "platform/base/error.h"
13*3f982cf4SFabien Sanglard #include "util/json/json_helpers.h"
14*3f982cf4SFabien Sanglard #include "util/osp_logging.h"
15*3f982cf4SFabien Sanglard 
16*3f982cf4SFabien Sanglard namespace openscreen {
17*3f982cf4SFabien Sanglard namespace cast {
18*3f982cf4SFabien Sanglard 
19*3f982cf4SFabien Sanglard namespace {
20*3f982cf4SFabien Sanglard 
21*3f982cf4SFabien Sanglard /// Dimension properties.
22*3f982cf4SFabien Sanglard // Width in pixels.
23*3f982cf4SFabien Sanglard static constexpr char kWidth[] = "width";
24*3f982cf4SFabien Sanglard 
25*3f982cf4SFabien Sanglard // Height in pixels.
26*3f982cf4SFabien Sanglard static constexpr char kHeight[] = "height";
27*3f982cf4SFabien Sanglard 
28*3f982cf4SFabien Sanglard // Frame rate as a rational decimal number or fraction.
29*3f982cf4SFabien Sanglard // E.g. 30 and "3000/1001" are both valid representations.
30*3f982cf4SFabien Sanglard static constexpr char kFrameRate[] = "frameRate";
31*3f982cf4SFabien Sanglard 
32*3f982cf4SFabien Sanglard // Choice of epsilon for double comparison allows for proper comparison
33*3f982cf4SFabien Sanglard // for both aspect ratios and frame rates. For frame rates, it is based on the
34*3f982cf4SFabien Sanglard // broadcast rate of 29.97fps, which is actually 29.976. For aspect ratios, it
35*3f982cf4SFabien Sanglard // allows for a one-pixel difference at a 4K resolution, we want it to be
36*3f982cf4SFabien Sanglard // relatively high to avoid false negative comparison results.
FrameRateEquals(double a,double b)37*3f982cf4SFabien Sanglard bool FrameRateEquals(double a, double b) {
38*3f982cf4SFabien Sanglard   const double kEpsilonForFrameRateComparisons = .0001;
39*3f982cf4SFabien Sanglard   return std::abs(a - b) < kEpsilonForFrameRateComparisons;
40*3f982cf4SFabien Sanglard }
41*3f982cf4SFabien Sanglard 
42*3f982cf4SFabien Sanglard }  // namespace
43*3f982cf4SFabien Sanglard 
TryParse(const Json::Value & root,Resolution * out)44*3f982cf4SFabien Sanglard bool Resolution::TryParse(const Json::Value& root, Resolution* out) {
45*3f982cf4SFabien Sanglard   if (!json::TryParseInt(root[kWidth], &(out->width)) ||
46*3f982cf4SFabien Sanglard       !json::TryParseInt(root[kHeight], &(out->height))) {
47*3f982cf4SFabien Sanglard     return false;
48*3f982cf4SFabien Sanglard   }
49*3f982cf4SFabien Sanglard   return out->IsValid();
50*3f982cf4SFabien Sanglard }
51*3f982cf4SFabien Sanglard 
IsValid() const52*3f982cf4SFabien Sanglard bool Resolution::IsValid() const {
53*3f982cf4SFabien Sanglard   return width > 0 && height > 0;
54*3f982cf4SFabien Sanglard }
55*3f982cf4SFabien Sanglard 
ToJson() const56*3f982cf4SFabien Sanglard Json::Value Resolution::ToJson() const {
57*3f982cf4SFabien Sanglard   OSP_DCHECK(IsValid());
58*3f982cf4SFabien Sanglard   Json::Value root;
59*3f982cf4SFabien Sanglard   root[kWidth] = width;
60*3f982cf4SFabien Sanglard   root[kHeight] = height;
61*3f982cf4SFabien Sanglard 
62*3f982cf4SFabien Sanglard   return root;
63*3f982cf4SFabien Sanglard }
64*3f982cf4SFabien Sanglard 
operator ==(const Resolution & other) const65*3f982cf4SFabien Sanglard bool Resolution::operator==(const Resolution& other) const {
66*3f982cf4SFabien Sanglard   return std::tie(width, height) == std::tie(other.width, other.height);
67*3f982cf4SFabien Sanglard }
68*3f982cf4SFabien Sanglard 
operator !=(const Resolution & other) const69*3f982cf4SFabien Sanglard bool Resolution::operator!=(const Resolution& other) const {
70*3f982cf4SFabien Sanglard   return !(*this == other);
71*3f982cf4SFabien Sanglard }
72*3f982cf4SFabien Sanglard 
IsSupersetOf(const Resolution & other) const73*3f982cf4SFabien Sanglard bool Resolution::IsSupersetOf(const Resolution& other) const {
74*3f982cf4SFabien Sanglard   return width >= other.width && height >= other.height;
75*3f982cf4SFabien Sanglard }
76*3f982cf4SFabien Sanglard 
TryParse(const Json::Value & root,Dimensions * out)77*3f982cf4SFabien Sanglard bool Dimensions::TryParse(const Json::Value& root, Dimensions* out) {
78*3f982cf4SFabien Sanglard   if (!json::TryParseInt(root[kWidth], &(out->width)) ||
79*3f982cf4SFabien Sanglard       !json::TryParseInt(root[kHeight], &(out->height)) ||
80*3f982cf4SFabien Sanglard       !(root[kFrameRate].isNull() ||
81*3f982cf4SFabien Sanglard         json::TryParseSimpleFraction(root[kFrameRate], &(out->frame_rate)))) {
82*3f982cf4SFabien Sanglard     return false;
83*3f982cf4SFabien Sanglard   }
84*3f982cf4SFabien Sanglard   return out->IsValid();
85*3f982cf4SFabien Sanglard }
86*3f982cf4SFabien Sanglard 
IsValid() const87*3f982cf4SFabien Sanglard bool Dimensions::IsValid() const {
88*3f982cf4SFabien Sanglard   return width > 0 && height > 0 && frame_rate.is_positive();
89*3f982cf4SFabien Sanglard }
90*3f982cf4SFabien Sanglard 
ToJson() const91*3f982cf4SFabien Sanglard Json::Value Dimensions::ToJson() const {
92*3f982cf4SFabien Sanglard   OSP_DCHECK(IsValid());
93*3f982cf4SFabien Sanglard   Json::Value root;
94*3f982cf4SFabien Sanglard   root[kWidth] = width;
95*3f982cf4SFabien Sanglard   root[kHeight] = height;
96*3f982cf4SFabien Sanglard   root[kFrameRate] = frame_rate.ToString();
97*3f982cf4SFabien Sanglard 
98*3f982cf4SFabien Sanglard   return root;
99*3f982cf4SFabien Sanglard }
100*3f982cf4SFabien Sanglard 
operator ==(const Dimensions & other) const101*3f982cf4SFabien Sanglard bool Dimensions::operator==(const Dimensions& other) const {
102*3f982cf4SFabien Sanglard   return (std::tie(width, height) == std::tie(other.width, other.height) &&
103*3f982cf4SFabien Sanglard           FrameRateEquals(static_cast<double>(frame_rate),
104*3f982cf4SFabien Sanglard                           static_cast<double>(other.frame_rate)));
105*3f982cf4SFabien Sanglard }
106*3f982cf4SFabien Sanglard 
operator !=(const Dimensions & other) const107*3f982cf4SFabien Sanglard bool Dimensions::operator!=(const Dimensions& other) const {
108*3f982cf4SFabien Sanglard   return !(*this == other);
109*3f982cf4SFabien Sanglard }
110*3f982cf4SFabien Sanglard 
IsSupersetOf(const Dimensions & other) const111*3f982cf4SFabien Sanglard bool Dimensions::IsSupersetOf(const Dimensions& other) const {
112*3f982cf4SFabien Sanglard   if (static_cast<double>(frame_rate) !=
113*3f982cf4SFabien Sanglard       static_cast<double>(other.frame_rate)) {
114*3f982cf4SFabien Sanglard     return static_cast<double>(frame_rate) >=
115*3f982cf4SFabien Sanglard            static_cast<double>(other.frame_rate);
116*3f982cf4SFabien Sanglard   }
117*3f982cf4SFabien Sanglard 
118*3f982cf4SFabien Sanglard   return ToResolution().IsSupersetOf(other.ToResolution());
119*3f982cf4SFabien Sanglard }
120*3f982cf4SFabien Sanglard 
121*3f982cf4SFabien Sanglard }  // namespace cast
122*3f982cf4SFabien Sanglard }  // namespace openscreen
123