• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "CodecCapabilitiesUtils"
19 
20 #include <android-base/properties.h>
21 #include <utils/Log.h>
22 
23 #include <algorithm>
24 #include <cmath>
25 #include <cstdlib>
26 #include <string>
27 #include <vector>
28 
29 #include <media/CodecCapabilitiesUtils.h>
30 #include <media/stagefright/foundation/ADebug.h>
31 #include <media/stagefright/foundation/AUtils.h>
32 
33 namespace android {
34 
SaturateDoubleToInt32(double d)35 static int32_t SaturateDoubleToInt32(double d) {
36     if (d >= static_cast<double>(std::numeric_limits<int32_t>::max())) {
37         return std::numeric_limits<int32_t>::max();
38     } else if (d <= static_cast<double>(std::numeric_limits<int32_t>::min())) {
39         return std::numeric_limits<int32_t>::min();
40     } else {
41         return static_cast<int32_t>(d);
42     }
43 }
44 
45 // VideoSize
46 
VideoSize(int32_t width,int32_t height)47 VideoSize::VideoSize(int32_t width, int32_t height) : mWidth(width), mHeight(height) {}
48 
VideoSize()49 VideoSize::VideoSize() : mWidth(0), mHeight(0) {}
50 
getWidth() const51 int32_t VideoSize::getWidth() const { return mWidth; }
52 
getHeight() const53 int32_t VideoSize::getHeight() const { return mHeight; }
54 
equals(VideoSize other) const55 bool VideoSize::equals(VideoSize other) const {
56     return mWidth == other.mWidth && mHeight == other.mHeight;
57 }
58 
empty() const59 bool VideoSize::empty() const {
60     return mWidth <= 0 || mHeight <= 0;
61 }
62 
toString() const63 std::string VideoSize::toString() const {
64     return std::to_string(mWidth) + "x" + std::to_string(mHeight);
65 }
66 
ParseSize(std::string str)67 std::optional<VideoSize> VideoSize::ParseSize(std::string str) {
68     if (str.empty()) {
69         return std::nullopt;
70     }
71 
72     std::regex regex("([0-9]+)([*x])([0-9]+)");
73     std::smatch match;
74     if (std::regex_match(str, match, regex)) {
75         long int w = strtol(match[1].str().c_str(), NULL, 10);
76         long int h = strtol(match[3].str().c_str(), NULL, 10);
77         return std::make_optional(VideoSize(w, h));
78     } else {
79         ALOGW("could not parse size %s", str.c_str());
80         return std::nullopt;
81     }
82 }
83 
ParseSizeRange(const std::string str)84 std::optional<std::pair<VideoSize, VideoSize>> VideoSize::ParseSizeRange(const std::string str) {
85     size_t ix = str.find_first_of('-');
86     if (ix != std::string::npos) {
87         std::optional<VideoSize> lowerOpt = VideoSize::ParseSize(str.substr(0, ix));
88         std::optional<VideoSize> upperOpt = VideoSize::ParseSize(str.substr(ix + 1));
89         if (!lowerOpt || !upperOpt) {
90             return std::nullopt;
91         }
92         return std::make_optional(
93                 std::pair<VideoSize, VideoSize>(lowerOpt.value(), upperOpt.value()));
94     } else {
95         std::optional<VideoSize> opt = VideoSize::ParseSize(str);
96         if (!opt) {
97             return std::nullopt;
98         }
99         return std::make_optional(std::pair<VideoSize, VideoSize>(opt.value(), opt.value()));
100     }
101 }
102 
GetAllowedDimensionRange()103 Range<int32_t> VideoSize::GetAllowedDimensionRange() {
104 #ifdef __LP64__
105     return Range<int32_t>(1, 32768);
106 #else
107     int32_t value = base::GetIntProperty("media.resolution.limit.32bit", (int32_t)4096);
108     return Range<int32_t>(1, value);
109 #endif
110 }
111 
112 // Rational
113 
Parse(std::string str)114 std::optional<Rational> Rational::Parse(std::string str) {
115     if (str.compare("NaN") == 0) {
116         return std::make_optional(NaN);
117     } else if (str.compare("Infinity") == 0) {
118         return std::make_optional(POSITIVE_INFINITY);
119     } else if (str.compare("-Infinity") == 0) {
120         return std::make_optional(NEGATIVE_INFINITY);
121     }
122 
123     std::regex regex("([0-9]+)([:/])([0-9]+)");
124     std::smatch match;
125     if (std::regex_match(str, match, regex)) {
126         long int numerator = strtol(match[1].str().c_str(), NULL, 10);
127         long int denominator = strtol(match[3].str().c_str(), NULL, 10);
128         return std::make_optional(Rational(numerator, denominator));
129     } else {
130         ALOGW("could not parse string: %s to Rational", str.c_str());
131         return std::nullopt;
132     }
133 }
134 
scale(int32_t num,int32_t den)135 Rational Rational::scale(int32_t num, int32_t den) {
136     int32_t common = std::gcd(num, den);
137     num /= common;
138     den /= common;
139     // ToDo: Reevaluate how to satureate double to int without drastically changing it.
140     return Rational(
141             SaturateDoubleToInt32(mNumerator * (double)num),
142             SaturateDoubleToInt32(mDenominator * (double)den));
143 }
144 
ScaleRange(Range<Rational> range,int32_t num,int32_t den)145 Range<Rational> Rational::ScaleRange(Range<Rational> range, int32_t num, int32_t den) {
146     if (num == den) {
147         return range;
148     }
149     return Range(
150             range.lower().scale(num, den),
151             range.upper().scale(num, den));
152 }
153 
ParseRange(const std::string str)154 std::optional<Range<Rational>> Rational::ParseRange(const std::string str) {
155     size_t ix = str.find_first_of('-');
156     if (ix != std::string::npos) {
157         std::optional<Rational> lower = Parse(str.substr(0, ix));
158         std::optional<Rational> upper = Parse(str.substr(ix + 1));
159         if (!lower || !upper) {
160             return std::nullopt;
161         }
162         return std::make_optional<Range<Rational>>(lower.value(), upper.value());
163     } else {
164         std::optional<Rational> value = Parse(str);
165         if (!value) {
166             return std::nullopt;
167         }
168         return std::make_optional<Range<Rational>>(value.value(), value.value());
169     }
170 }
171 
172 }  // namespace android