| /* |
| * Copyright (C) 2024 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| //#define LOG_NDEBUG 0 |
| #define LOG_TAG "CodecCapabilitiesUtils" |
| |
| #include <android-base/properties.h> |
| #include <utils/Log.h> |
| |
| #include <algorithm> |
| #include <cmath> |
| #include <cstdlib> |
| #include <string> |
| #include <vector> |
| |
| #include <media/CodecCapabilitiesUtils.h> |
| #include <media/stagefright/foundation/ADebug.h> |
| #include <media/stagefright/foundation/AUtils.h> |
| |
| namespace android { |
| |
| // VideoSize |
| |
| VideoSize::VideoSize(int32_t width, int32_t height) : mWidth(width), mHeight(height) {} |
| |
| VideoSize::VideoSize() : mWidth(0), mHeight(0) {} |
| |
| int32_t VideoSize::getWidth() const { return mWidth; } |
| |
| int32_t VideoSize::getHeight() const { return mHeight; } |
| |
| bool VideoSize::equals(VideoSize other) const { |
| return mWidth == other.mWidth && mHeight == other.mHeight; |
| } |
| |
| bool VideoSize::empty() const { |
| return mWidth <= 0 || mHeight <= 0; |
| } |
| |
| std::string VideoSize::toString() const { |
| return std::to_string(mWidth) + "x" + std::to_string(mHeight); |
| } |
| |
| std::optional<VideoSize> VideoSize::ParseSize(std::string str) { |
| if (str.empty()) { |
| return std::nullopt; |
| } |
| |
| std::regex regex("([0-9]+)([*x])([0-9]+)"); |
| std::smatch match; |
| if (std::regex_match(str, match, regex)) { |
| long int w = strtol(match[1].str().c_str(), NULL, 10); |
| long int h = strtol(match[3].str().c_str(), NULL, 10); |
| return std::make_optional(VideoSize(w, h)); |
| } else { |
| ALOGW("could not parse size %s", str.c_str()); |
| return std::nullopt; |
| } |
| } |
| |
| std::optional<std::pair<VideoSize, VideoSize>> VideoSize::ParseSizeRange(const std::string str) { |
| size_t ix = str.find_first_of('-'); |
| if (ix != std::string::npos) { |
| std::optional<VideoSize> lowerOpt = VideoSize::ParseSize(str.substr(0, ix)); |
| std::optional<VideoSize> upperOpt = VideoSize::ParseSize(str.substr(ix + 1)); |
| if (!lowerOpt || !upperOpt) { |
| return std::nullopt; |
| } |
| return std::make_optional( |
| std::pair<VideoSize, VideoSize>(lowerOpt.value(), upperOpt.value())); |
| } else { |
| std::optional<VideoSize> opt = VideoSize::ParseSize(str); |
| if (!opt) { |
| return std::nullopt; |
| } |
| return std::make_optional(std::pair<VideoSize, VideoSize>(opt.value(), opt.value())); |
| } |
| } |
| |
| Range<int32_t> VideoSize::GetAllowedDimensionRange() { |
| #ifdef __LP64__ |
| return Range<int32_t>(1, 32768); |
| #else |
| int32_t value = base::GetIntProperty("media.resolution.limit.32bit", (int32_t)4096); |
| return Range<int32_t>(1, value); |
| #endif |
| } |
| |
| // Rational |
| |
| std::optional<Rational> Rational::Parse(std::string str) { |
| if (str.compare("NaN") == 0) { |
| return std::make_optional(NaN); |
| } else if (str.compare("Infinity") == 0) { |
| return std::make_optional(POSITIVE_INFINITY); |
| } else if (str.compare("-Infinity") == 0) { |
| return std::make_optional(NEGATIVE_INFINITY); |
| } |
| |
| std::regex regex("([0-9]+)([:/])([0-9]+)"); |
| std::smatch match; |
| if (std::regex_match(str, match, regex)) { |
| long int numerator = strtol(match[1].str().c_str(), NULL, 10); |
| long int denominator = strtol(match[3].str().c_str(), NULL, 10); |
| return std::make_optional(Rational(numerator, denominator)); |
| } else { |
| ALOGW("could not parse string: %s to Rational", str.c_str()); |
| return std::nullopt; |
| } |
| } |
| |
| Rational Rational::scale(int32_t num, int32_t den) { |
| int32_t common = std::gcd(num, den); |
| num /= common; |
| den /= common; |
| return Rational( |
| (int32_t)(mNumerator * (double)num), // saturate to int |
| (int32_t)(mDenominator * (double)den)); // saturate to int |
| } |
| |
| Range<Rational> Rational::ScaleRange(Range<Rational> range, int32_t num, int32_t den) { |
| if (num == den) { |
| return range; |
| } |
| return Range( |
| range.lower().scale(num, den), |
| range.upper().scale(num, den)); |
| } |
| |
| std::optional<Range<Rational>> Rational::ParseRange(const std::string str) { |
| size_t ix = str.find_first_of('-'); |
| if (ix != std::string::npos) { |
| std::optional<Rational> lower = Parse(str.substr(0, ix)); |
| std::optional<Rational> upper = Parse(str.substr(ix + 1)); |
| if (!lower || !upper) { |
| return std::nullopt; |
| } |
| return std::make_optional<Range<Rational>>(lower.value(), upper.value()); |
| } else { |
| std::optional<Rational> value = Parse(str); |
| if (!value) { |
| return std::nullopt; |
| } |
| return std::make_optional<Range<Rational>>(value.value(), value.value()); |
| } |
| } |
| |
| } // namespace android |