Loading media/libstagefright/codec2/include/C2.h +239 −0 Original line number Diff line number Diff line Loading @@ -210,6 +210,219 @@ enum c2_blocking_t : int32_t { } \ DEFINE_OTHER_COMPARISON_OPERATORS(type) template<typename T, typename B> class C2_HIDE c2_cntr_t; /// \cond INTERNAL /// \defgroup utils_internal /// @{ template<typename T> struct C2_HIDE _c2_cntr_compat_helper { template<typename U, typename E=typename std::enable_if<std::is_integral<U>::value>::type> __attribute__((no_sanitize("integer"))) inline static constexpr T get(const U &value) { return T(value); } template<typename U, typename E=typename std::enable_if<(sizeof(U) >= sizeof(T))>::type> __attribute__((no_sanitize("integer"))) inline static constexpr T get(const c2_cntr_t<U, void> &value) { return T(value.mValue); } }; /// @} /// \endcond /** * Integral counter type. * * This is basically an unsigned integral type that is NEVER checked for overflow/underflow - and * comparison operators are redefined. * * \note Comparison of counter types is not fully transitive, e.g. * it could be that a > b > c but a !> c. * std::less<>, greater<>, less_equal<> and greater_equal<> specializations yield total ordering, * but may not match semantic ordering of the values. * * Technically: counter types represent integer values: A * 2^N + value, where A can be arbitrary. * This makes addition, subtraction, multiplication (as well as bitwise operations) well defined. * However, division is in general not well defined, as the result may depend on A. This is also * true for logical operators and boolean conversion. * * Even though well defined, bitwise operators are not implemented for counter types as they are not * meaningful. */ template<typename T, typename B=typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value>::type> class C2_HIDE c2_cntr_t { using compat = _c2_cntr_compat_helper<T>; T mValue; constexpr static T HALF_RANGE = T(~0) ^ (T(~0) >> 1); template<typename U> friend struct _c2_cntr_compat_helper; public: /** * Default constructor. Initialized counter to 0. */ inline constexpr c2_cntr_t() : mValue(T(0)) {} /** * Construct from a compatible type. */ template<typename U> inline constexpr c2_cntr_t(const U &value) : mValue(compat::get(value)) {} /** * Peek as underlying signed type. */ __attribute__((no_sanitize("integer"))) inline constexpr typename std::make_signed<T>::type peek() const { return static_cast<typename std::make_signed<T>::type>(mValue); } /** * Peek as underlying unsigned type. */ inline constexpr T peeku() const { return mValue; } /** * Peek as long long - e.g. for printing. */ __attribute__((no_sanitize("integer"))) inline constexpr long long peekll() const { return (long long)mValue; } /** * Peek as unsigned long long - e.g. for printing. */ __attribute__((no_sanitize("integer"))) inline constexpr unsigned long long peekull() const { return (unsigned long long)mValue; } /** * Convert to a smaller counter type. This is always safe. */ template<typename U, typename E=typename std::enable_if<sizeof(U) < sizeof(T)>::type> inline operator c2_cntr_t<U>() { return c2_cntr_t<U>(mValue); } /** * Arithmetic operators */ #define DEFINE_C2_CNTR_BINARY_OP(attrib, op, op_assign) \ template<typename U> \ attrib inline c2_cntr_t<T>& operator op_assign(const U &value) { \ mValue op_assign compat::get(value); \ return *this; \ } \ \ template<typename U, typename E=decltype(compat::get(U(0)))> \ attrib inline constexpr c2_cntr_t<T> operator op(const U &value) const { \ return c2_cntr_t<T>(mValue op compat::get(value)); \ } \ \ template<typename U, typename E=typename std::enable_if<sizeof(U) < sizeof(T)>::type> \ attrib inline constexpr c2_cntr_t<U> operator op(const c2_cntr_t<U> &value) const { \ return c2_cntr_t<U>(U(mValue) op value.peeku()); \ } #define DEFINE_C2_CNTR_UNARY_OP(attrib, op) \ attrib inline constexpr c2_cntr_t<T> operator op() const { \ return c2_cntr_t<T>(op mValue); \ } #define DEFINE_C2_CNTR_CREMENT_OP(attrib, op) \ attrib inline c2_cntr_t<T> &operator op() { \ op mValue; \ return *this; \ } \ attrib inline c2_cntr_t<T> operator op(int) { \ return c2_cntr_t<T, void>(mValue op); \ } DEFINE_C2_CNTR_BINARY_OP(__attribute__((no_sanitize("integer"))), +, +=) DEFINE_C2_CNTR_BINARY_OP(__attribute__((no_sanitize("integer"))), -, -=) DEFINE_C2_CNTR_BINARY_OP(__attribute__((no_sanitize("integer"))), *, *=) DEFINE_C2_CNTR_UNARY_OP(__attribute__((no_sanitize("integer"))), -) DEFINE_C2_CNTR_UNARY_OP(__attribute__((no_sanitize("integer"))), +) DEFINE_C2_CNTR_CREMENT_OP(__attribute__((no_sanitize("integer"))), ++) DEFINE_C2_CNTR_CREMENT_OP(__attribute__((no_sanitize("integer"))), --) template<typename U, typename E=typename std::enable_if<std::is_unsigned<U>::value>::type> __attribute__((no_sanitize("integer"))) inline constexpr c2_cntr_t<T> operator<<(const U &value) const { return c2_cntr_t<T>(mValue << value); } template<typename U, typename E=typename std::enable_if<std::is_unsigned<U>::value>::type> __attribute__((no_sanitize("integer"))) inline c2_cntr_t<T> &operator<<=(const U &value) { mValue <<= value; return *this; } /** * Comparison operators */ __attribute__((no_sanitize("integer"))) inline constexpr bool operator<=(const c2_cntr_t<T> &other) const { return T(other.mValue - mValue) < HALF_RANGE; } __attribute__((no_sanitize("integer"))) inline constexpr bool operator>=(const c2_cntr_t<T> &other) const { return T(mValue - other.mValue) < HALF_RANGE; } inline constexpr bool operator==(const c2_cntr_t<T> &other) const { return mValue == other.mValue; } inline constexpr bool operator!=(const c2_cntr_t<T> &other) const { return !(*this == other); } inline constexpr bool operator<(const c2_cntr_t<T> &other) const { return *this <= other && *this != other; } inline constexpr bool operator>(const c2_cntr_t<T> &other) const { return *this >= other && *this != other; } }; template<typename U, typename T, typename E=typename std::enable_if<std::is_integral<U>::value>::type> inline constexpr c2_cntr_t<T> operator+(const U &a, const c2_cntr_t<T> &b) { return b + a; } template<typename U, typename T, typename E=typename std::enable_if<std::is_integral<U>::value>::type> inline constexpr c2_cntr_t<T> operator-(const U &a, const c2_cntr_t<T> &b) { return c2_cntr_t<T>(a) - b; } template<typename U, typename T, typename E=typename std::enable_if<std::is_integral<U>::value>::type> inline constexpr c2_cntr_t<T> operator*(const U &a, const c2_cntr_t<T> &b) { return b * a; } typedef c2_cntr_t<uint32_t> c2_cntr32_t; /** 32-bit counter type */ typedef c2_cntr_t<uint64_t> c2_cntr64_t; /** 64-bit counter type */ /// \cond INTERNAL /// \defgroup utils_internal Loading Loading @@ -326,4 +539,30 @@ constexpr typename c2_types<T, U, V...>::min_type c2_min(const T a, const U b, c } // namespace android #endif #include <functional> template<typename T> struct std::less<::android::c2_cntr_t<T>> { constexpr bool operator()(const ::android::c2_cntr_t<T> &lh, const ::android::c2_cntr_t<T> &rh) const { return lh.peeku() < rh.peeku(); } }; template<typename T> struct std::less_equal<::android::c2_cntr_t<T>> { constexpr bool operator()(const ::android::c2_cntr_t<T> &lh, const ::android::c2_cntr_t<T> &rh) const { return lh.peeku() <= rh.peeku(); } }; template<typename T> struct std::greater<::android::c2_cntr_t<T>> { constexpr bool operator()(const ::android::c2_cntr_t<T> &lh, const ::android::c2_cntr_t<T> &rh) const { return lh.peeku() > rh.peeku(); } }; template<typename T> struct std::greater_equal<::android::c2_cntr_t<T>> { constexpr bool operator()(const ::android::c2_cntr_t<T> &lh, const ::android::c2_cntr_t<T> &rh) const { return lh.peeku() >= rh.peeku(); } }; #endif // C2_H_ media/libstagefright/codec2/include/C2Param.h +33 −17 Original line number Diff line number Diff line Loading @@ -737,15 +737,19 @@ public: union Primitive { int32_t i32; ///< int32_t value uint32_t u32; ///< uint32_t value c2_cntr32_t c32; ///< c2_cntr32_t value int64_t i64; ///< int64_t value uint64_t u64; ///< uint64_t value c2_cntr64_t c64; ///< c2_cntr64_t value float fp; ///< float value // constructors - implicit Primitive(int32_t value) : i32(value) { } Primitive(uint32_t value) : u32(value) { } Primitive(c2_cntr32_t value) : c32(value) { } Primitive(int64_t value) : i64(value) { } Primitive(uint64_t value) : u64(value) { } Primitive(c2_cntr64_t value) : c64(value) { } Primitive(float value) : fp(value) { } Primitive() : u64(0) { } Loading @@ -759,8 +763,10 @@ public: NO_INIT, INT32, UINT32, CNTR32, INT64, UINT64, CNTR64, FLOAT, }; Loading Loading @@ -792,12 +798,16 @@ template<> inline const int32_t &C2Value::Primitive::ref<int32_t>() const { retu template<> inline const int64_t &C2Value::Primitive::ref<int64_t>() const { return i64; } template<> inline const uint32_t &C2Value::Primitive::ref<uint32_t>() const { return u32; } template<> inline const uint64_t &C2Value::Primitive::ref<uint64_t>() const { return u64; } template<> inline const c2_cntr32_t &C2Value::Primitive::ref<c2_cntr32_t>() const { return c32; } template<> inline const c2_cntr64_t &C2Value::Primitive::ref<c2_cntr64_t>() const { return c64; } template<> inline const float &C2Value::Primitive::ref<float>() const { return fp; } template<> constexpr C2Value::type_t C2Value::typeFor<int32_t>() { return INT32; } template<> constexpr C2Value::type_t C2Value::typeFor<int64_t>() { return INT64; } template<> constexpr C2Value::type_t C2Value::typeFor<uint32_t>() { return UINT32; } template<> constexpr C2Value::type_t C2Value::typeFor<uint64_t>() { return UINT64; } template<> constexpr C2Value::type_t C2Value::typeFor<c2_cntr32_t>() { return CNTR32; } template<> constexpr C2Value::type_t C2Value::typeFor<c2_cntr64_t>() { return CNTR64; } template<> constexpr C2Value::type_t C2Value::typeFor<float>() { return FLOAT; } /** Loading @@ -817,8 +827,10 @@ struct C2FieldDescriptor { // primitive types INT32 = C2Value::INT32, ///< 32-bit signed integer UINT32 = C2Value::UINT32, ///< 32-bit unsigned integer CNTR32 = C2Value::CNTR32, ///< 32-bit counter INT64 = C2Value::INT64, ///< 64-bit signed integer UINT64 = C2Value::UINT64, ///< 64-bit signed integer CNTR64 = C2Value::CNTR64, ///< 64-bit counter FLOAT = C2Value::FLOAT, ///< 32-bit floating point // array types Loading Loading @@ -905,8 +917,10 @@ private: // type resolution inline static type_t getType(int32_t*) { return INT32; } inline static type_t getType(uint32_t*) { return UINT32; } inline static type_t getType(c2_cntr32_t*) { return CNTR32; } inline static type_t getType(int64_t*) { return INT64; } inline static type_t getType(uint64_t*) { return UINT64; } inline static type_t getType(c2_cntr64_t*) { return CNTR64; } inline static type_t getType(float*) { return FLOAT; } inline static type_t getType(char*) { return STRING; } inline static type_t getType(uint8_t*) { return BLOB; } Loading Loading @@ -936,8 +950,10 @@ template<> inline C2FieldDescriptor::named_values_type C2FieldDescriptor::namedV // non-enumerated integral types. DEFINE_NO_NAMED_VALUES_FOR(int32_t) DEFINE_NO_NAMED_VALUES_FOR(uint32_t) DEFINE_NO_NAMED_VALUES_FOR(c2_cntr32_t) DEFINE_NO_NAMED_VALUES_FOR(int64_t) DEFINE_NO_NAMED_VALUES_FOR(uint64_t) DEFINE_NO_NAMED_VALUES_FOR(c2_cntr64_t) DEFINE_NO_NAMED_VALUES_FOR(uint8_t) DEFINE_NO_NAMED_VALUES_FOR(char) DEFINE_NO_NAMED_VALUES_FOR(float) Loading media/libstagefright/codec2/tests/C2_test.cpp +84 −0 Original line number Diff line number Diff line Loading @@ -75,4 +75,88 @@ static_assert(c2_const_checker<max_u32_u32>::num() == 2, "should be 2"); static_assert(c2_const_checker<max_u32_u64>::num() == 3, "should be 3"); static_assert(c2_const_checker<max_u32_u8>::num() == 0x7fffffff, "should be 0x7fffffff"); /* ======================================= COUNTER TESTS ======================================= */ void c2_cntr_static_test() { // sanity checks for construction/assignment constexpr c2_cntr32_t c32_a(123); constexpr c2_cntr64_t c64_a(-456); c2_cntr32_t c32_b __unused = c64_a; // c32_b = 64.; // DISALLOWED // c2_cntr64_t c64_b = c32_a; // DISALLOWED // sanity checks for some constexpr operators static_assert(std::is_same<decltype(c32_a + c64_a), decltype(c64_a + c32_a)>::value, "+ should result same type"); static_assert(c32_a + c64_a == c2_cntr32_t(-333), "123 + -456 = -333"); static_assert(c32_a + c32_a == c2_cntr32_t(246), "123 + 123 = 246"); static_assert(c64_a + c32_a == c2_cntr32_t(-333), "-456 + 123 = 579"); static_assert(std::is_same<decltype(c32_a + 1), decltype(1 + c32_a)>::value, "+ should result same type"); static_assert(c32_a + 456 == c2_cntr32_t(579), "123 + 456 = 579"); static_assert(456 + c64_a == c2_cntr64_t(0), "456 + -456 = 0"); static_assert(std::is_same<decltype(c32_a - c64_a), decltype(c64_a - c32_a)>::value, "- should result same type"); static_assert(c32_a - c64_a == c2_cntr32_t(579), "123 - -456 = 579"); static_assert(c32_a - c32_a == c2_cntr32_t(0), "123 - 123 = 0"); static_assert(c64_a - c32_a == c2_cntr32_t(-579), "-456 - 123 = -579"); static_assert(std::is_same<decltype(c32_a - 1), decltype(1 - c32_a)>::value, "- should result same type"); static_assert(c32_a - 456 == c2_cntr32_t(-333), "123 - 456 = -333"); static_assert(456 - c64_a == c2_cntr64_t(912), "456 - -456 = 912"); static_assert(std::is_same<decltype(c32_a * c64_a), decltype(c64_a * c32_a)>::value, "* should result same type"); static_assert(c32_a * c64_a == c2_cntr32_t(-56088), "123 * -456 = -56088"); static_assert(c32_a * c32_a == c2_cntr32_t(15129), "123 * 123 = 15129"); static_assert(c64_a * c32_a == c2_cntr32_t(-56088), "-456 * 123 = -56088"); static_assert(std::is_same<decltype(c32_a * 1), decltype(1 * c32_a)>::value, "* should result same type"); static_assert(c32_a * 456 == c2_cntr32_t(56088), "123 * 456 = 56088"); static_assert(456 * c64_a == c2_cntr64_t(-207936), "456 * -456 = -207936"); static_assert((c32_a << 26u) == c2_cntr32_t(0xEC000000), "123 << 26 = 0xEC000000"); // sanity checks for unary operators static_assert(c2_cntr32_t(1) == +c2_cntr32_t(1), "1 == +1"); static_assert(c2_cntr32_t(1) == -c2_cntr32_t(-1), "1 == --1"); // sanity checks for comparison using c8_t = c2_cntr_t<uint8_t>; static_assert(c8_t(-0x80) > c8_t(0x7f), "80 > 7F"); static_assert(c8_t(-0x80) >= c8_t(0x7f), "80 >= 7F"); static_assert(c8_t(0x7f) > c8_t(0x7e), "7F > 7E"); static_assert(c8_t(0x7f) >= c8_t(0x7e), "7F >= 7E"); static_assert(!(c8_t(-0x80) > c8_t(0)), "80 !> 00"); static_assert(!(c8_t(-0x80) >= c8_t(0)), "80 !>= 00"); static_assert(!(c8_t(-0x80) > c8_t(-0x80)), "80 !> 80"); static_assert(c8_t(-0x80) >= c8_t(-0x80), "80 >= 80"); static_assert(c8_t(-0x80) == c8_t(0x80), "80 == 80"); static_assert(!(c8_t(-0x80) == c8_t(0)), "80 != 0"); static_assert(c8_t(-0x80) != c8_t(0x7f), "80 != 7F"); static_assert(!(c8_t(0x7f) != c8_t(0x7f)), "80 != 7F"); static_assert(c8_t(0x7f) < c8_t(-0x80), "7F < 80"); static_assert(c8_t(0x7f) <= c8_t(-0x80), "7F < 80"); static_assert(c8_t(0x7e) < c8_t(0x7f), "7E < 7F"); static_assert(c8_t(0x7e) <= c8_t(0x7f), "7E < 7F"); static_assert(!(c8_t(-0x40) < c8_t(0x40)), "-40 !< 40"); static_assert(!(c8_t(-0x40) <= c8_t(0x40)), "-40 !<= 40"); static_assert(!(c8_t(-0x40) < c8_t(-0x40)), "-40 !< -40"); static_assert(c8_t(-0x40) <= c8_t(-0x40), "-40 <= -40"); static_assert(c2_cntr32_t(-0x7fffffff - 1) > c2_cntr32_t(0x7fffffff), "80 > 7F"); static_assert(!(c2_cntr32_t(-0x7fffffff - 1) > c2_cntr32_t(0)), "80 !> 00"); static_assert(c2_cntr32_t(1) == c2_cntr32_t(c2_cntr64_t(0x100000001ul)), "1 == 1"); } class C2Test : public ::testing::Test { }; TEST_F(C2Test, CounterTest) { c2_cntr32_t c32_a(123); c2_cntr64_t c64_a(-456); EXPECT_EQ(c32_a += 3, c2_cntr32_t(126)); EXPECT_EQ(c32_a += c64_a, c2_cntr32_t(-330)); EXPECT_EQ(c32_a <<= 2u, c2_cntr32_t(-1320)); EXPECT_EQ(c64_a *= 3, c2_cntr64_t(-1368)); EXPECT_EQ(c32_a -= c64_a, c2_cntr32_t(48)); EXPECT_EQ(c32_a -= 40, c2_cntr32_t(8)); EXPECT_EQ(c32_a *= c32_a, c2_cntr32_t(64)); } } // namespace android Loading
media/libstagefright/codec2/include/C2.h +239 −0 Original line number Diff line number Diff line Loading @@ -210,6 +210,219 @@ enum c2_blocking_t : int32_t { } \ DEFINE_OTHER_COMPARISON_OPERATORS(type) template<typename T, typename B> class C2_HIDE c2_cntr_t; /// \cond INTERNAL /// \defgroup utils_internal /// @{ template<typename T> struct C2_HIDE _c2_cntr_compat_helper { template<typename U, typename E=typename std::enable_if<std::is_integral<U>::value>::type> __attribute__((no_sanitize("integer"))) inline static constexpr T get(const U &value) { return T(value); } template<typename U, typename E=typename std::enable_if<(sizeof(U) >= sizeof(T))>::type> __attribute__((no_sanitize("integer"))) inline static constexpr T get(const c2_cntr_t<U, void> &value) { return T(value.mValue); } }; /// @} /// \endcond /** * Integral counter type. * * This is basically an unsigned integral type that is NEVER checked for overflow/underflow - and * comparison operators are redefined. * * \note Comparison of counter types is not fully transitive, e.g. * it could be that a > b > c but a !> c. * std::less<>, greater<>, less_equal<> and greater_equal<> specializations yield total ordering, * but may not match semantic ordering of the values. * * Technically: counter types represent integer values: A * 2^N + value, where A can be arbitrary. * This makes addition, subtraction, multiplication (as well as bitwise operations) well defined. * However, division is in general not well defined, as the result may depend on A. This is also * true for logical operators and boolean conversion. * * Even though well defined, bitwise operators are not implemented for counter types as they are not * meaningful. */ template<typename T, typename B=typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value>::type> class C2_HIDE c2_cntr_t { using compat = _c2_cntr_compat_helper<T>; T mValue; constexpr static T HALF_RANGE = T(~0) ^ (T(~0) >> 1); template<typename U> friend struct _c2_cntr_compat_helper; public: /** * Default constructor. Initialized counter to 0. */ inline constexpr c2_cntr_t() : mValue(T(0)) {} /** * Construct from a compatible type. */ template<typename U> inline constexpr c2_cntr_t(const U &value) : mValue(compat::get(value)) {} /** * Peek as underlying signed type. */ __attribute__((no_sanitize("integer"))) inline constexpr typename std::make_signed<T>::type peek() const { return static_cast<typename std::make_signed<T>::type>(mValue); } /** * Peek as underlying unsigned type. */ inline constexpr T peeku() const { return mValue; } /** * Peek as long long - e.g. for printing. */ __attribute__((no_sanitize("integer"))) inline constexpr long long peekll() const { return (long long)mValue; } /** * Peek as unsigned long long - e.g. for printing. */ __attribute__((no_sanitize("integer"))) inline constexpr unsigned long long peekull() const { return (unsigned long long)mValue; } /** * Convert to a smaller counter type. This is always safe. */ template<typename U, typename E=typename std::enable_if<sizeof(U) < sizeof(T)>::type> inline operator c2_cntr_t<U>() { return c2_cntr_t<U>(mValue); } /** * Arithmetic operators */ #define DEFINE_C2_CNTR_BINARY_OP(attrib, op, op_assign) \ template<typename U> \ attrib inline c2_cntr_t<T>& operator op_assign(const U &value) { \ mValue op_assign compat::get(value); \ return *this; \ } \ \ template<typename U, typename E=decltype(compat::get(U(0)))> \ attrib inline constexpr c2_cntr_t<T> operator op(const U &value) const { \ return c2_cntr_t<T>(mValue op compat::get(value)); \ } \ \ template<typename U, typename E=typename std::enable_if<sizeof(U) < sizeof(T)>::type> \ attrib inline constexpr c2_cntr_t<U> operator op(const c2_cntr_t<U> &value) const { \ return c2_cntr_t<U>(U(mValue) op value.peeku()); \ } #define DEFINE_C2_CNTR_UNARY_OP(attrib, op) \ attrib inline constexpr c2_cntr_t<T> operator op() const { \ return c2_cntr_t<T>(op mValue); \ } #define DEFINE_C2_CNTR_CREMENT_OP(attrib, op) \ attrib inline c2_cntr_t<T> &operator op() { \ op mValue; \ return *this; \ } \ attrib inline c2_cntr_t<T> operator op(int) { \ return c2_cntr_t<T, void>(mValue op); \ } DEFINE_C2_CNTR_BINARY_OP(__attribute__((no_sanitize("integer"))), +, +=) DEFINE_C2_CNTR_BINARY_OP(__attribute__((no_sanitize("integer"))), -, -=) DEFINE_C2_CNTR_BINARY_OP(__attribute__((no_sanitize("integer"))), *, *=) DEFINE_C2_CNTR_UNARY_OP(__attribute__((no_sanitize("integer"))), -) DEFINE_C2_CNTR_UNARY_OP(__attribute__((no_sanitize("integer"))), +) DEFINE_C2_CNTR_CREMENT_OP(__attribute__((no_sanitize("integer"))), ++) DEFINE_C2_CNTR_CREMENT_OP(__attribute__((no_sanitize("integer"))), --) template<typename U, typename E=typename std::enable_if<std::is_unsigned<U>::value>::type> __attribute__((no_sanitize("integer"))) inline constexpr c2_cntr_t<T> operator<<(const U &value) const { return c2_cntr_t<T>(mValue << value); } template<typename U, typename E=typename std::enable_if<std::is_unsigned<U>::value>::type> __attribute__((no_sanitize("integer"))) inline c2_cntr_t<T> &operator<<=(const U &value) { mValue <<= value; return *this; } /** * Comparison operators */ __attribute__((no_sanitize("integer"))) inline constexpr bool operator<=(const c2_cntr_t<T> &other) const { return T(other.mValue - mValue) < HALF_RANGE; } __attribute__((no_sanitize("integer"))) inline constexpr bool operator>=(const c2_cntr_t<T> &other) const { return T(mValue - other.mValue) < HALF_RANGE; } inline constexpr bool operator==(const c2_cntr_t<T> &other) const { return mValue == other.mValue; } inline constexpr bool operator!=(const c2_cntr_t<T> &other) const { return !(*this == other); } inline constexpr bool operator<(const c2_cntr_t<T> &other) const { return *this <= other && *this != other; } inline constexpr bool operator>(const c2_cntr_t<T> &other) const { return *this >= other && *this != other; } }; template<typename U, typename T, typename E=typename std::enable_if<std::is_integral<U>::value>::type> inline constexpr c2_cntr_t<T> operator+(const U &a, const c2_cntr_t<T> &b) { return b + a; } template<typename U, typename T, typename E=typename std::enable_if<std::is_integral<U>::value>::type> inline constexpr c2_cntr_t<T> operator-(const U &a, const c2_cntr_t<T> &b) { return c2_cntr_t<T>(a) - b; } template<typename U, typename T, typename E=typename std::enable_if<std::is_integral<U>::value>::type> inline constexpr c2_cntr_t<T> operator*(const U &a, const c2_cntr_t<T> &b) { return b * a; } typedef c2_cntr_t<uint32_t> c2_cntr32_t; /** 32-bit counter type */ typedef c2_cntr_t<uint64_t> c2_cntr64_t; /** 64-bit counter type */ /// \cond INTERNAL /// \defgroup utils_internal Loading Loading @@ -326,4 +539,30 @@ constexpr typename c2_types<T, U, V...>::min_type c2_min(const T a, const U b, c } // namespace android #endif #include <functional> template<typename T> struct std::less<::android::c2_cntr_t<T>> { constexpr bool operator()(const ::android::c2_cntr_t<T> &lh, const ::android::c2_cntr_t<T> &rh) const { return lh.peeku() < rh.peeku(); } }; template<typename T> struct std::less_equal<::android::c2_cntr_t<T>> { constexpr bool operator()(const ::android::c2_cntr_t<T> &lh, const ::android::c2_cntr_t<T> &rh) const { return lh.peeku() <= rh.peeku(); } }; template<typename T> struct std::greater<::android::c2_cntr_t<T>> { constexpr bool operator()(const ::android::c2_cntr_t<T> &lh, const ::android::c2_cntr_t<T> &rh) const { return lh.peeku() > rh.peeku(); } }; template<typename T> struct std::greater_equal<::android::c2_cntr_t<T>> { constexpr bool operator()(const ::android::c2_cntr_t<T> &lh, const ::android::c2_cntr_t<T> &rh) const { return lh.peeku() >= rh.peeku(); } }; #endif // C2_H_
media/libstagefright/codec2/include/C2Param.h +33 −17 Original line number Diff line number Diff line Loading @@ -737,15 +737,19 @@ public: union Primitive { int32_t i32; ///< int32_t value uint32_t u32; ///< uint32_t value c2_cntr32_t c32; ///< c2_cntr32_t value int64_t i64; ///< int64_t value uint64_t u64; ///< uint64_t value c2_cntr64_t c64; ///< c2_cntr64_t value float fp; ///< float value // constructors - implicit Primitive(int32_t value) : i32(value) { } Primitive(uint32_t value) : u32(value) { } Primitive(c2_cntr32_t value) : c32(value) { } Primitive(int64_t value) : i64(value) { } Primitive(uint64_t value) : u64(value) { } Primitive(c2_cntr64_t value) : c64(value) { } Primitive(float value) : fp(value) { } Primitive() : u64(0) { } Loading @@ -759,8 +763,10 @@ public: NO_INIT, INT32, UINT32, CNTR32, INT64, UINT64, CNTR64, FLOAT, }; Loading Loading @@ -792,12 +798,16 @@ template<> inline const int32_t &C2Value::Primitive::ref<int32_t>() const { retu template<> inline const int64_t &C2Value::Primitive::ref<int64_t>() const { return i64; } template<> inline const uint32_t &C2Value::Primitive::ref<uint32_t>() const { return u32; } template<> inline const uint64_t &C2Value::Primitive::ref<uint64_t>() const { return u64; } template<> inline const c2_cntr32_t &C2Value::Primitive::ref<c2_cntr32_t>() const { return c32; } template<> inline const c2_cntr64_t &C2Value::Primitive::ref<c2_cntr64_t>() const { return c64; } template<> inline const float &C2Value::Primitive::ref<float>() const { return fp; } template<> constexpr C2Value::type_t C2Value::typeFor<int32_t>() { return INT32; } template<> constexpr C2Value::type_t C2Value::typeFor<int64_t>() { return INT64; } template<> constexpr C2Value::type_t C2Value::typeFor<uint32_t>() { return UINT32; } template<> constexpr C2Value::type_t C2Value::typeFor<uint64_t>() { return UINT64; } template<> constexpr C2Value::type_t C2Value::typeFor<c2_cntr32_t>() { return CNTR32; } template<> constexpr C2Value::type_t C2Value::typeFor<c2_cntr64_t>() { return CNTR64; } template<> constexpr C2Value::type_t C2Value::typeFor<float>() { return FLOAT; } /** Loading @@ -817,8 +827,10 @@ struct C2FieldDescriptor { // primitive types INT32 = C2Value::INT32, ///< 32-bit signed integer UINT32 = C2Value::UINT32, ///< 32-bit unsigned integer CNTR32 = C2Value::CNTR32, ///< 32-bit counter INT64 = C2Value::INT64, ///< 64-bit signed integer UINT64 = C2Value::UINT64, ///< 64-bit signed integer CNTR64 = C2Value::CNTR64, ///< 64-bit counter FLOAT = C2Value::FLOAT, ///< 32-bit floating point // array types Loading Loading @@ -905,8 +917,10 @@ private: // type resolution inline static type_t getType(int32_t*) { return INT32; } inline static type_t getType(uint32_t*) { return UINT32; } inline static type_t getType(c2_cntr32_t*) { return CNTR32; } inline static type_t getType(int64_t*) { return INT64; } inline static type_t getType(uint64_t*) { return UINT64; } inline static type_t getType(c2_cntr64_t*) { return CNTR64; } inline static type_t getType(float*) { return FLOAT; } inline static type_t getType(char*) { return STRING; } inline static type_t getType(uint8_t*) { return BLOB; } Loading Loading @@ -936,8 +950,10 @@ template<> inline C2FieldDescriptor::named_values_type C2FieldDescriptor::namedV // non-enumerated integral types. DEFINE_NO_NAMED_VALUES_FOR(int32_t) DEFINE_NO_NAMED_VALUES_FOR(uint32_t) DEFINE_NO_NAMED_VALUES_FOR(c2_cntr32_t) DEFINE_NO_NAMED_VALUES_FOR(int64_t) DEFINE_NO_NAMED_VALUES_FOR(uint64_t) DEFINE_NO_NAMED_VALUES_FOR(c2_cntr64_t) DEFINE_NO_NAMED_VALUES_FOR(uint8_t) DEFINE_NO_NAMED_VALUES_FOR(char) DEFINE_NO_NAMED_VALUES_FOR(float) Loading
media/libstagefright/codec2/tests/C2_test.cpp +84 −0 Original line number Diff line number Diff line Loading @@ -75,4 +75,88 @@ static_assert(c2_const_checker<max_u32_u32>::num() == 2, "should be 2"); static_assert(c2_const_checker<max_u32_u64>::num() == 3, "should be 3"); static_assert(c2_const_checker<max_u32_u8>::num() == 0x7fffffff, "should be 0x7fffffff"); /* ======================================= COUNTER TESTS ======================================= */ void c2_cntr_static_test() { // sanity checks for construction/assignment constexpr c2_cntr32_t c32_a(123); constexpr c2_cntr64_t c64_a(-456); c2_cntr32_t c32_b __unused = c64_a; // c32_b = 64.; // DISALLOWED // c2_cntr64_t c64_b = c32_a; // DISALLOWED // sanity checks for some constexpr operators static_assert(std::is_same<decltype(c32_a + c64_a), decltype(c64_a + c32_a)>::value, "+ should result same type"); static_assert(c32_a + c64_a == c2_cntr32_t(-333), "123 + -456 = -333"); static_assert(c32_a + c32_a == c2_cntr32_t(246), "123 + 123 = 246"); static_assert(c64_a + c32_a == c2_cntr32_t(-333), "-456 + 123 = 579"); static_assert(std::is_same<decltype(c32_a + 1), decltype(1 + c32_a)>::value, "+ should result same type"); static_assert(c32_a + 456 == c2_cntr32_t(579), "123 + 456 = 579"); static_assert(456 + c64_a == c2_cntr64_t(0), "456 + -456 = 0"); static_assert(std::is_same<decltype(c32_a - c64_a), decltype(c64_a - c32_a)>::value, "- should result same type"); static_assert(c32_a - c64_a == c2_cntr32_t(579), "123 - -456 = 579"); static_assert(c32_a - c32_a == c2_cntr32_t(0), "123 - 123 = 0"); static_assert(c64_a - c32_a == c2_cntr32_t(-579), "-456 - 123 = -579"); static_assert(std::is_same<decltype(c32_a - 1), decltype(1 - c32_a)>::value, "- should result same type"); static_assert(c32_a - 456 == c2_cntr32_t(-333), "123 - 456 = -333"); static_assert(456 - c64_a == c2_cntr64_t(912), "456 - -456 = 912"); static_assert(std::is_same<decltype(c32_a * c64_a), decltype(c64_a * c32_a)>::value, "* should result same type"); static_assert(c32_a * c64_a == c2_cntr32_t(-56088), "123 * -456 = -56088"); static_assert(c32_a * c32_a == c2_cntr32_t(15129), "123 * 123 = 15129"); static_assert(c64_a * c32_a == c2_cntr32_t(-56088), "-456 * 123 = -56088"); static_assert(std::is_same<decltype(c32_a * 1), decltype(1 * c32_a)>::value, "* should result same type"); static_assert(c32_a * 456 == c2_cntr32_t(56088), "123 * 456 = 56088"); static_assert(456 * c64_a == c2_cntr64_t(-207936), "456 * -456 = -207936"); static_assert((c32_a << 26u) == c2_cntr32_t(0xEC000000), "123 << 26 = 0xEC000000"); // sanity checks for unary operators static_assert(c2_cntr32_t(1) == +c2_cntr32_t(1), "1 == +1"); static_assert(c2_cntr32_t(1) == -c2_cntr32_t(-1), "1 == --1"); // sanity checks for comparison using c8_t = c2_cntr_t<uint8_t>; static_assert(c8_t(-0x80) > c8_t(0x7f), "80 > 7F"); static_assert(c8_t(-0x80) >= c8_t(0x7f), "80 >= 7F"); static_assert(c8_t(0x7f) > c8_t(0x7e), "7F > 7E"); static_assert(c8_t(0x7f) >= c8_t(0x7e), "7F >= 7E"); static_assert(!(c8_t(-0x80) > c8_t(0)), "80 !> 00"); static_assert(!(c8_t(-0x80) >= c8_t(0)), "80 !>= 00"); static_assert(!(c8_t(-0x80) > c8_t(-0x80)), "80 !> 80"); static_assert(c8_t(-0x80) >= c8_t(-0x80), "80 >= 80"); static_assert(c8_t(-0x80) == c8_t(0x80), "80 == 80"); static_assert(!(c8_t(-0x80) == c8_t(0)), "80 != 0"); static_assert(c8_t(-0x80) != c8_t(0x7f), "80 != 7F"); static_assert(!(c8_t(0x7f) != c8_t(0x7f)), "80 != 7F"); static_assert(c8_t(0x7f) < c8_t(-0x80), "7F < 80"); static_assert(c8_t(0x7f) <= c8_t(-0x80), "7F < 80"); static_assert(c8_t(0x7e) < c8_t(0x7f), "7E < 7F"); static_assert(c8_t(0x7e) <= c8_t(0x7f), "7E < 7F"); static_assert(!(c8_t(-0x40) < c8_t(0x40)), "-40 !< 40"); static_assert(!(c8_t(-0x40) <= c8_t(0x40)), "-40 !<= 40"); static_assert(!(c8_t(-0x40) < c8_t(-0x40)), "-40 !< -40"); static_assert(c8_t(-0x40) <= c8_t(-0x40), "-40 <= -40"); static_assert(c2_cntr32_t(-0x7fffffff - 1) > c2_cntr32_t(0x7fffffff), "80 > 7F"); static_assert(!(c2_cntr32_t(-0x7fffffff - 1) > c2_cntr32_t(0)), "80 !> 00"); static_assert(c2_cntr32_t(1) == c2_cntr32_t(c2_cntr64_t(0x100000001ul)), "1 == 1"); } class C2Test : public ::testing::Test { }; TEST_F(C2Test, CounterTest) { c2_cntr32_t c32_a(123); c2_cntr64_t c64_a(-456); EXPECT_EQ(c32_a += 3, c2_cntr32_t(126)); EXPECT_EQ(c32_a += c64_a, c2_cntr32_t(-330)); EXPECT_EQ(c32_a <<= 2u, c2_cntr32_t(-1320)); EXPECT_EQ(c64_a *= 3, c2_cntr64_t(-1368)); EXPECT_EQ(c32_a -= c64_a, c2_cntr32_t(48)); EXPECT_EQ(c32_a -= 40, c2_cntr32_t(8)); EXPECT_EQ(c32_a *= c32_a, c2_cntr32_t(64)); } } // namespace android