CodecCapabilities: Port VideoCapabilities from Java to Native.
Test: atest VideoCapsHevcTest
Bug: b/306023029
Change-Id: If849e4bb6ded7c70af294c4b8fe8e3f79d378394
diff --git a/media/libmedia/CodecCapabilitiesUtils.cpp b/media/libmedia/CodecCapabilitiesUtils.cpp
index ef28fcb..01bb24e 100644
--- a/media/libmedia/CodecCapabilitiesUtils.cpp
+++ b/media/libmedia/CodecCapabilitiesUtils.cpp
@@ -16,19 +16,146 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "CodecCapabilitiesUtils"
+
+#include <android-base/properties.h>
#include <utils/Log.h>
#include <algorithm>
#include <cmath>
-#include <regex>
+#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
\ No newline at end of file