blob: 01bb24e4bcb5eb32579ea1c1107f84ab7815183c [file] [log] [blame] [edit]
/*
* 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