Move Codec2-related code from hardware/google/av
Test: None
Bug: 112362730
Change-Id: Ie2f8ff431d65c40333f267ab9877d47089adeea4
diff --git a/media/codec2/include/C2.h b/media/codec2/include/C2.h
new file mode 100644
index 0000000..8a55f8d
--- /dev/null
+++ b/media/codec2/include/C2.h
@@ -0,0 +1,552 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef C2_H_
+#define C2_H_
+
+#include <errno.h>
+
+#include <string>
+
+/** nanoseconds with arbitrary origin. */
+typedef int64_t c2_nsecs_t;
+
+/** \mainpage Codec2
+ *
+ * Codec2 is a generic frame-based data processing API.
+ *
+ * The media subsystem accesses components via the \ref API.
+ */
+
+/** \ingroup API
+ *
+ * The Codec2 API defines the operation of data processing components and their interaction with
+ * the rest of the system.
+ *
+ * Coding Conventions
+ *
+ * Mitigating Binary Compatibility.
+ *
+ * While full binary compatibility is not a goal of the API (due to our use of STL), we try to
+ * mitigate binary breaks by adhering to the following conventions:
+ *
+ * - at most one vtable with placeholder virtual methods
+ * - all optional/placeholder virtual methods returning a c2_status_t, with C2_OMITTED not requiring
+ * any update to input/output arguments.
+ * - limiting symbol export of inline methods
+ * - use of pimpl (or shared-pimpl)
+ *
+ * Naming
+ *
+ * - all classes and types prefix with C2
+ * - classes for internal use prefix with _C2
+ * - enum values in global namespace prefix with C2_ all caps
+ * - enum values inside classes have no C2_ prefix as class already has it
+ * - supporting two kinds of enum naming: all-caps and kCamelCase
+ * \todo revisit kCamelCase for param-type
+ *
+ * Aspects
+ *
+ * Aspects define certain common behavior across a group of objects.
+ * - classes whose name matches _C2.*Aspect
+ * - only protected constructors
+ * - no desctructor and copiable
+ * - all methods are inline or static (this is opposite of the interface paradigm where all methods
+ * are virtual, which would not work due to the at most one vtable rule.)
+ * - only private variables (this prevents subclasses interfering with the aspects.)
+ */
+
+/// \defgroup types Common Types
+/// @{
+
+/**
+ * C2String: basic string implementation
+ */
+typedef std::string C2String;
+
+/**
+ * C2StringLiteral: basic string literal implementation.
+ * \note these are never owned by any object, and can only refer to C string literals.
+ */
+typedef const char *C2StringLiteral;
+
+/**
+ * c2_status_t: status codes used.
+ */
+enum c2_status_t : int32_t {
+/*
+ * Use POSIX errno constants.
+ */
+ C2_OK = 0, ///< operation completed successfully
+
+ // bad input
+ C2_BAD_VALUE = EINVAL, ///< argument has invalid value (user error)
+ C2_BAD_INDEX = ENXIO, ///< argument uses invalid index (user error)
+ C2_CANNOT_DO = ENOTSUP, ///< argument/index is valid but not possible
+
+ // bad sequencing of events
+ C2_DUPLICATE = EEXIST, ///< object already exists
+ C2_NOT_FOUND = ENOENT, ///< object not found
+ C2_BAD_STATE = EPERM, ///< operation is not permitted in the current state
+ C2_BLOCKING = EWOULDBLOCK, ///< operation would block but blocking is not permitted
+ C2_CANCELED = EINTR, ///< operation interrupted/canceled
+
+ // bad environment
+ C2_NO_MEMORY = ENOMEM, ///< not enough memory to complete operation
+ C2_REFUSED = EACCES, ///< missing permission to complete operation
+
+ C2_TIMED_OUT = ETIMEDOUT, ///< operation did not complete within timeout
+
+ // bad versioning
+ C2_OMITTED = ENOSYS, ///< operation is not implemented/supported (optional only)
+
+ // unknown fatal
+ C2_CORRUPTED = EFAULT, ///< some unexpected error prevented the operation
+ C2_NO_INIT = ENODEV, ///< status has not been initialized
+};
+
+/**
+ * Type that describes the desired blocking behavior for variable blocking calls. Blocking in this
+ * API is used in a somewhat modified meaning such that operations that merely update variables
+ * protected by mutexes are still considered "non-blocking" (always used in quotes).
+ */
+enum c2_blocking_t : int32_t {
+ /**
+ * The operation SHALL be "non-blocking". This means that it shall not perform any file
+ * operations, or call/wait on other processes. It may use a protected region as long as the
+ * mutex is never used to protect code that is otherwise "may block".
+ */
+ C2_DONT_BLOCK = false,
+ /**
+ * The operation MAY be temporarily blocking.
+ */
+ C2_MAY_BLOCK = true,
+};
+
+/// @}
+
+/// \defgroup utils Utilities
+/// @{
+
+#define C2_DO_NOT_COPY(type) \
+ type& operator=(const type &) = delete; \
+ type(const type &) = delete; \
+
+#define C2_DEFAULT_MOVE(type) \
+ type& operator=(type &&) = default; \
+ type(type &&) = default; \
+
+#define C2_ALLOW_OVERFLOW __attribute__((no_sanitize("integer")))
+#define C2_CONST __attribute__((const))
+#define C2_HIDE __attribute__((visibility("hidden")))
+#define C2_INLINE inline C2_HIDE
+#define C2_INTERNAL __attribute__((internal_linkage))
+#define C2_PACK __attribute__((aligned(4)))
+#define C2_PURE __attribute__((pure))
+
+#define DEFINE_OTHER_COMPARISON_OPERATORS(type) \
+ inline bool operator!=(const type &other) const { return !(*this == other); } \
+ inline bool operator<=(const type &other) const { return (*this == other) || (*this < other); } \
+ inline bool operator>=(const type &other) const { return !(*this < other); } \
+ inline bool operator>(const type &other) const { return !(*this < other) && !(*this == other); }
+
+#define DEFINE_FIELD_BASED_COMPARISON_OPERATORS(type, field) \
+ inline bool operator<(const type &other) const { return field < other.field; } \
+ inline bool operator==(const type &other) const { return field == other.field; } \
+ DEFINE_OTHER_COMPARISON_OPERATORS(type)
+
+#define DEFINE_FIELD_AND_MASK_BASED_COMPARISON_OPERATORS(type, field, mask) \
+ inline bool operator<(const type &other) const { \
+ return (field & mask) < (other.field & (mask)); \
+ } \
+ inline bool operator==(const type &other) const { \
+ return (field & mask) == (other.field & (mask)); \
+ } \
+ DEFINE_OTHER_COMPARISON_OPERATORS(type)
+
+#define DEFINE_ENUM_OPERATORS(etype) \
+ inline constexpr etype operator|(etype a, etype b) { return (etype)(std::underlying_type<etype>::type(a) | std::underlying_type<etype>::type(b)); } \
+ inline constexpr etype &operator|=(etype &a, etype b) { a = (etype)(std::underlying_type<etype>::type(a) | std::underlying_type<etype>::type(b)); return a; } \
+ inline constexpr etype operator&(etype a, etype b) { return (etype)(std::underlying_type<etype>::type(a) & std::underlying_type<etype>::type(b)); } \
+ inline constexpr etype &operator&=(etype &a, etype b) { a = (etype)(std::underlying_type<etype>::type(a) & std::underlying_type<etype>::type(b)); return a; } \
+ inline constexpr etype operator^(etype a, etype b) { return (etype)(std::underlying_type<etype>::type(a) ^ std::underlying_type<etype>::type(b)); } \
+ inline constexpr etype &operator^=(etype &a, etype b) { a = (etype)(std::underlying_type<etype>::type(a) ^ std::underlying_type<etype>::type(b)); return a; } \
+ inline constexpr etype operator~(etype a) { return (etype)(~std::underlying_type<etype>::type(a)); }
+
+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>
+ C2_ALLOW_OVERFLOW
+ 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>
+ C2_ALLOW_OVERFLOW
+ 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.
+ */
+ C2_ALLOW_OVERFLOW
+ 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.
+ */
+ C2_ALLOW_OVERFLOW
+ inline constexpr long long peekll() const {
+ return (long long)mValue;
+ }
+
+ /**
+ * Peek as unsigned long long - e.g. for printing.
+ */
+ C2_ALLOW_OVERFLOW
+ 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(C2_ALLOW_OVERFLOW, +, +=)
+ DEFINE_C2_CNTR_BINARY_OP(C2_ALLOW_OVERFLOW, -, -=)
+ DEFINE_C2_CNTR_BINARY_OP(C2_ALLOW_OVERFLOW, *, *=)
+
+ DEFINE_C2_CNTR_UNARY_OP(C2_ALLOW_OVERFLOW, -)
+ DEFINE_C2_CNTR_UNARY_OP(C2_ALLOW_OVERFLOW, +)
+
+ DEFINE_C2_CNTR_CREMENT_OP(C2_ALLOW_OVERFLOW, ++)
+ DEFINE_C2_CNTR_CREMENT_OP(C2_ALLOW_OVERFLOW, --)
+
+ template<typename U, typename E=typename std::enable_if<std::is_unsigned<U>::value>::type>
+ C2_ALLOW_OVERFLOW
+ 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>
+ C2_ALLOW_OVERFLOW
+ inline c2_cntr_t<T> &operator<<=(const U &value) {
+ mValue <<= value;
+ return *this;
+ }
+
+ /**
+ * Comparison operators
+ */
+ C2_ALLOW_OVERFLOW
+ inline constexpr bool operator<=(const c2_cntr_t<T> &other) const {
+ return T(other.mValue - mValue) < HALF_RANGE;
+ }
+
+ C2_ALLOW_OVERFLOW
+ 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
+/// @{
+
+template<typename... T> struct c2_types;
+
+/** specialization for a single type */
+template<typename T>
+struct c2_types<T> {
+ typedef typename std::decay<T>::type wide_type;
+ typedef wide_type narrow_type;
+ typedef wide_type min_type; // type for min(T...)
+};
+
+/** specialization for two types */
+template<typename T, typename U>
+struct c2_types<T, U> {
+ static_assert(std::is_floating_point<T>::value == std::is_floating_point<U>::value,
+ "mixing floating point and non-floating point types is disallowed");
+ static_assert(std::is_signed<T>::value == std::is_signed<U>::value,
+ "mixing signed and unsigned types is disallowed");
+
+ typedef typename std::decay<
+ decltype(true ? std::declval<T>() : std::declval<U>())>::type wide_type;
+ typedef typename std::decay<
+ typename std::conditional<sizeof(T) < sizeof(U), T, U>::type>::type narrow_type;
+ typedef typename std::conditional<
+ std::is_signed<T>::value, wide_type, narrow_type>::type min_type;
+};
+
+/// @}
+
+/// \endcond
+
+/**
+ * Type support utility class. Only supports similar classes, such as:
+ * - all floating point
+ * - all unsigned/all signed
+ * - all pointer
+ */
+template<typename T, typename U, typename... V>
+struct c2_types<T, U, V...> {
+ /** Common type that accommodates all template parameter types. */
+ typedef typename c2_types<typename c2_types<T, U>::wide_type, V...>::wide_type wide_type;
+ /** Narrowest type of the template parameter types. */
+ typedef typename c2_types<typename c2_types<T, U>::narrow_type, V...>::narrow_type narrow_type;
+ /** Type that accommodates the minimum value for any input for the template parameter types. */
+ typedef typename c2_types<typename c2_types<T, U>::min_type, V...>::min_type min_type;
+};
+
+/**
+ * \ingroup utils_internal
+ * specialization for two values */
+template<typename T, typename U>
+inline constexpr typename c2_types<T, U>::wide_type c2_max(const T a, const U b) {
+ typedef typename c2_types<T, U>::wide_type wide_type;
+ return ({ wide_type a_(a), b_(b); a_ > b_ ? a_ : b_; });
+}
+
+/**
+ * Finds the maximum value of a list of "similarly typed" values.
+ *
+ * This is an extension to std::max where the types do not have to be identical, and the smallest
+ * resulting type is used that accommodates the argument types.
+ *
+ * \note Value types must be similar, e.g. all floating point, all pointers, all signed, or all
+ * unsigned.
+ *
+ * @return the largest of the input arguments.
+ */
+template<typename T, typename U, typename... V>
+constexpr typename c2_types<T, U, V...>::wide_type c2_max(const T a, const U b, const V ... c) {
+ typedef typename c2_types<T, U, V...>::wide_type wide_type;
+ return ({ wide_type a_(a), b_(c2_max(b, c...)); a_ > b_ ? a_ : b_; });
+}
+
+/**
+ * \ingroup utils_internal
+ * specialization for two values */
+template<typename T, typename U>
+inline constexpr typename c2_types<T, U>::min_type c2_min(const T a, const U b) {
+ typedef typename c2_types<T, U>::wide_type wide_type;
+ return ({
+ wide_type a_(a), b_(b);
+ static_cast<typename c2_types<T, U>::min_type>(a_ < b_ ? a_ : b_);
+ });
+}
+
+/**
+ * Finds the minimum value of a list of "similarly typed" values.
+ *
+ * This is an extension to std::min where the types do not have to be identical, and the smallest
+ * resulting type is used that accommodates the argument types.
+ *
+ * \note Value types must be similar, e.g. all floating point, all pointers, all signed, or all
+ * unsigned.
+ *
+ * @return the smallest of the input arguments.
+ */
+template<typename T, typename U, typename... V>
+constexpr typename c2_types<T, U, V...>::min_type c2_min(const T a, const U b, const V ... c) {
+ typedef typename c2_types<U, V...>::min_type rest_type;
+ typedef typename c2_types<T, rest_type>::wide_type wide_type;
+ return ({
+ wide_type a_(a), b_(c2_min(b, c...));
+ static_cast<typename c2_types<T, rest_type>::min_type>(a_ < b_ ? a_ : b_);
+ });
+}
+
+/**
+ * \ingroup utils_internal
+ */
+template<typename T, typename U, typename V>
+inline constexpr typename c2_types<T, V>::wide_type c2_clamp(const T a, const U b, const V c) {
+ typedef typename c2_types<T, U, V>::wide_type wide_type;
+ return ({
+ wide_type a_(a), b_(b), c_(c);
+ static_cast<typename c2_types<T, V>::wide_type>(b_ < a_ ? a_ : b_ > c_ ? c_ : b_);
+ });
+}
+
+/// @}
+
+#include <functional>
+template<typename T>
+struct std::less<::c2_cntr_t<T>> {
+ constexpr bool operator()(const ::c2_cntr_t<T> &lh, const ::c2_cntr_t<T> &rh) const {
+ return lh.peeku() < rh.peeku();
+ }
+};
+template<typename T>
+struct std::less_equal<::c2_cntr_t<T>> {
+ constexpr bool operator()(const ::c2_cntr_t<T> &lh, const ::c2_cntr_t<T> &rh) const {
+ return lh.peeku() <= rh.peeku();
+ }
+};
+template<typename T>
+struct std::greater<::c2_cntr_t<T>> {
+ constexpr bool operator()(const ::c2_cntr_t<T> &lh, const ::c2_cntr_t<T> &rh) const {
+ return lh.peeku() > rh.peeku();
+ }
+};
+template<typename T>
+struct std::greater_equal<::c2_cntr_t<T>> {
+ constexpr bool operator()(const ::c2_cntr_t<T> &lh, const ::c2_cntr_t<T> &rh) const {
+ return lh.peeku() >= rh.peeku();
+ }
+};
+
+#endif // C2_H_
diff --git a/media/codec2/include/C2Buffer.h b/media/codec2/include/C2Buffer.h
new file mode 100644
index 0000000..2997f6e
--- /dev/null
+++ b/media/codec2/include/C2Buffer.h
@@ -0,0 +1,2305 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef C2BUFFER_H_
+#define C2BUFFER_H_
+
+#include <C2.h>
+#include <C2BufferBase.h>
+#include <C2Param.h> // for C2Info
+
+#include <memory>
+#include <vector>
+
+#ifdef __ANDROID__
+#include <android-C2Buffer.h>
+#else
+
+typedef void* C2Handle;
+
+#endif
+
+/// \defgroup buffer Buffers
+/// @{
+
+/// \defgroup buffer_sync Synchronization
+/// @{
+
+/**
+ * Synchronization is accomplished using event and fence objects.
+ *
+ * These are cross-process extensions of promise/future infrastructure.
+ * Events are analogous to std::promise<void>, whereas fences are to std::shared_future<void>.
+ *
+ * Fences and events are shareable/copyable.
+ *
+ * Fences are used in two scenarios, and all copied instances refer to the same event.
+ * \todo do events need to be copyable or should they be unique?
+ *
+ * acquire sync fence object: signaled when it is safe for the component or client to access
+ * (the contents of) an object.
+ *
+ * release sync fence object: \todo
+ *
+ * Fences can be backed by hardware. Hardware fences are guaranteed to signal NO MATTER WHAT within
+ * a short (platform specific) amount of time; this guarantee is usually less than 15 msecs.
+ */
+
+/**
+ * Fence object used by components and the framework.
+ *
+ * Implements the waiting for an event, analogous to a 'future'.
+ *
+ * To be implemented by vendors if using HW fences.
+ */
+class C2Fence {
+public:
+ /**
+ * Waits for a fence to be signaled with a timeout.
+ *
+ * \todo a mechanism to cancel a wait - for now the only way to do this is to abandon the
+ * event, but fences are shared so canceling a wait will cancel all waits.
+ *
+ * \param timeoutNs the maximum time to wait in nsecs
+ *
+ * \retval C2_OK the fence has been signaled
+ * \retval C2_TIMED_OUT the fence has not been signaled within the timeout
+ * \retval C2_BAD_STATE the fence has been abandoned without being signaled (it will never
+ * be signaled)
+ * \retval C2_REFUSED no permission to wait for the fence (unexpected - system)
+ * \retval C2_CORRUPTED some unknown error prevented waiting for the fence (unexpected)
+ */
+ c2_status_t wait(c2_nsecs_t timeoutNs);
+
+ /**
+ * Used to check if this fence is valid (if there is a chance for it to be signaled.)
+ * A fence becomes invalid if the controling event is destroyed without it signaling the fence.
+ *
+ * \return whether this fence is valid
+ */
+ bool valid() const;
+
+ /**
+ * Used to check if this fence has been signaled (is ready).
+ *
+ * \return whether this fence has been signaled
+ */
+ bool ready() const;
+
+ /**
+ * Returns a file descriptor that can be used to wait for this fence in a select system call.
+ * \note The returned file descriptor, if valid, must be closed by the caller.
+ *
+ * This can be used in e.g. poll() system calls. This file becomes readable (POLLIN) when the
+ * fence is signaled, and bad (POLLERR) if the fence is abandoned.
+ *
+ * \return a file descriptor representing this fence (with ownership), or -1 if the fence
+ * has already been signaled (\todo or abandoned).
+ *
+ * \todo this must be compatible with fences used by gralloc
+ */
+ int fd() const;
+
+ /**
+ * Returns whether this fence is a hardware-backed fence.
+ * \return whether this is a hardware fence
+ */
+ bool isHW() const;
+
+ /**
+ * Null-fence. A fence that has fired.
+ */
+ constexpr C2Fence() : mImpl(nullptr) { }
+
+private:
+ class Impl;
+ std::shared_ptr<Impl> mImpl;
+ C2Fence(std::shared_ptr<Impl> impl);
+ friend struct _C2FenceFactory;
+};
+
+/**
+ * Event object used by components and the framework.
+ *
+ * Implements the signaling of an event, analogous to a 'promise'.
+ *
+ * Hardware backed events do not go through this object, and must be exposed directly as fences
+ * by vendors.
+ */
+class C2Event {
+public:
+ /**
+ * Returns a fence for this event.
+ */
+ C2Fence fence() const;
+
+ /**
+ * Signals (all) associated fence(s).
+ * This has no effect no effect if the event was already signaled or abandoned.
+ *
+ * \retval C2_OK the fence(s) were successfully signaled
+ * \retval C2_BAD_STATE the fence(s) have already been abandoned or merged (caller error)
+ * \retval C2_DUPLICATE the fence(s) have already been signaled (caller error)
+ * \retval C2_REFUSED no permission to signal the fence (unexpected - system)
+ * \retval C2_CORRUPTED some unknown error prevented signaling the fence(s) (unexpected)
+ */
+ c2_status_t fire();
+
+ /**
+ * Trigger this event from the merging of the supplied fences. This means that it will be
+ * abandoned if any of these fences have been abandoned, and it will be fired if all of these
+ * fences have been signaled.
+ *
+ * \retval C2_OK the merging was successfully done
+ * \retval C2_NO_MEMORY not enough memory to perform the merging
+ * \retval C2_DUPLICATE the fence have already been merged (caller error)
+ * \retval C2_BAD_STATE the fence have already been signaled or abandoned (caller error)
+ * \retval C2_REFUSED no permission to merge the fence (unexpected - system)
+ * \retval C2_CORRUPTED some unknown error prevented merging the fence(s) (unexpected)
+ */
+ c2_status_t merge(std::vector<C2Fence> fences);
+
+ /**
+ * Abandons the event and any associated fence(s).
+ * \note Call this to explicitly abandon an event before it is destructed to avoid a warning.
+ *
+ * This has no effect no effect if the event was already signaled or abandoned.
+ *
+ * \retval C2_OK the fence(s) were successfully signaled
+ * \retval C2_BAD_STATE the fence(s) have already been signaled or merged (caller error)
+ * \retval C2_DUPLICATE the fence(s) have already been abandoned (caller error)
+ * \retval C2_REFUSED no permission to abandon the fence (unexpected - system)
+ * \retval C2_CORRUPTED some unknown error prevented signaling the fence(s) (unexpected)
+ */
+ c2_status_t abandon();
+
+private:
+ class Impl;
+ std::shared_ptr<Impl> mImpl;
+};
+
+/// \addtogroup buf_internal Internal
+/// @{
+
+/**
+ * Interface for objects that encapsulate an updatable status value.
+ */
+struct _C2InnateStatus {
+ inline c2_status_t status() const { return mStatus; }
+
+protected:
+ _C2InnateStatus(c2_status_t status) : mStatus(status) { }
+
+ c2_status_t mStatus; // this status is updatable by the object
+};
+
+/// @}
+
+/**
+ * This is a utility template for objects protected by an acquire fence, so that errors during
+ * acquiring the object are propagated to the object itself.
+ */
+template<typename T>
+class C2Acquirable : public C2Fence {
+public:
+ /**
+ * Acquires the object protected by an acquire fence. Any errors during the mapping will be
+ * passed to the object.
+ *
+ * \return acquired object potentially invalidated if waiting for the fence failed.
+ */
+ T get() {
+ // TODO:
+ // wait();
+ return mT;
+ }
+
+protected:
+ C2Acquirable(c2_status_t error, C2Fence fence, T t) : C2Fence(fence), mInitialError(error), mT(t) { }
+
+private:
+ c2_status_t mInitialError;
+ T mT; // TODO: move instead of copy
+};
+
+/// @}
+
+/// \defgroup linear Linear Data Blocks
+/// @{
+
+/**************************************************************************************************
+ LINEAR ASPECTS, BLOCKS AND VIEWS
+**************************************************************************************************/
+
+/**
+ * Basic segment math support.
+ */
+struct C2Segment {
+ uint32_t offset;
+ uint32_t size;
+
+ inline constexpr C2Segment(uint32_t offset_, uint32_t size_)
+ : offset(offset_),
+ size(size_) {
+ }
+
+ inline constexpr bool isEmpty() const {
+ return size == 0;
+ }
+
+ inline constexpr bool isValid() const {
+ return offset <= ~size;
+ }
+
+ inline constexpr operator bool() const {
+ return isValid() && !isEmpty();
+ }
+
+ inline constexpr bool operator!() const {
+ return !bool(*this);
+ }
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr bool contains(const C2Segment &other) const {
+ if (!isValid() || !other.isValid()) {
+ return false;
+ } else {
+ return offset <= other.offset
+ && offset + size >= other.offset + other.size;
+ }
+ }
+
+ inline constexpr bool operator==(const C2Segment &other) const {
+ if (!isValid()) {
+ return !other.isValid();
+ } else {
+ return offset == other.offset && size == other.size;
+ }
+ }
+
+ inline constexpr bool operator!=(const C2Segment &other) const {
+ return !operator==(other);
+ }
+
+ inline constexpr bool operator>=(const C2Segment &other) const {
+ return contains(other);
+ }
+
+ inline constexpr bool operator>(const C2Segment &other) const {
+ return contains(other) && !operator==(other);
+ }
+
+ inline constexpr bool operator<=(const C2Segment &other) const {
+ return other.contains(*this);
+ }
+
+ inline constexpr bool operator<(const C2Segment &other) const {
+ return other.contains(*this) && !operator==(other);
+ }
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr uint32_t end() const {
+ return offset + size;
+ }
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr C2Segment intersect(const C2Segment &other) const {
+ return C2Segment(c2_max(offset, other.offset),
+ c2_min(end(), other.end()) - c2_max(offset, other.offset));
+ }
+
+ /** clamps end to offset if it overflows */
+ inline constexpr C2Segment normalize() const {
+ return C2Segment(offset, c2_max(offset, end()) - offset);
+ }
+
+ /** clamps end to max if it overflows */
+ inline constexpr C2Segment saturate() const {
+ return C2Segment(offset, c2_min(size, ~offset));
+ }
+
+};
+
+/**
+ * Common aspect for all objects that have a linear capacity.
+ */
+class _C2LinearCapacityAspect {
+/// \name Linear capacity interface
+/// @{
+public:
+ inline constexpr uint32_t capacity() const { return mCapacity; }
+
+ inline constexpr operator C2Segment() const {
+ return C2Segment(0, mCapacity);
+ }
+
+protected:
+
+#if UINTPTR_MAX == 0xffffffff
+ static_assert(sizeof(size_t) == sizeof(uint32_t), "size_t is too big");
+#else
+ static_assert(sizeof(size_t) > sizeof(uint32_t), "size_t is too small");
+ // explicitly disable construction from size_t
+ inline explicit _C2LinearCapacityAspect(size_t capacity) = delete;
+#endif
+
+ inline explicit constexpr _C2LinearCapacityAspect(uint32_t capacity)
+ : mCapacity(capacity) { }
+
+ inline explicit constexpr _C2LinearCapacityAspect(const _C2LinearCapacityAspect *parent)
+ : mCapacity(parent == nullptr ? 0 : parent->capacity()) { }
+
+private:
+ uint32_t mCapacity;
+/// @}
+};
+
+/**
+ * Aspect for objects that have a linear range inside a linear capacity.
+ *
+ * This class is copiable.
+ */
+class _C2LinearRangeAspect : public _C2LinearCapacityAspect {
+/// \name Linear range interface
+/// @{
+public:
+ inline constexpr uint32_t offset() const { return mOffset; }
+ inline constexpr uint32_t endOffset() const { return mOffset + mSize; }
+ inline constexpr uint32_t size() const { return mSize; }
+
+ inline constexpr operator C2Segment() const {
+ return C2Segment(mOffset, mSize);
+ }
+
+private:
+ // subrange of capacity [0, capacity] & [size, size + offset]
+ inline constexpr _C2LinearRangeAspect(uint32_t capacity_, size_t offset, size_t size)
+ : _C2LinearCapacityAspect(capacity_),
+ mOffset(c2_min(offset, capacity())),
+ mSize(c2_min(size, capacity() - mOffset)) {
+ }
+
+protected:
+ // copy constructor (no error check)
+ inline constexpr _C2LinearRangeAspect(const _C2LinearRangeAspect &other)
+ : _C2LinearCapacityAspect(other.capacity()),
+ mOffset(other.offset()),
+ mSize(other.size()) {
+ }
+
+ // parent capacity range [0, capacity]
+ inline constexpr explicit _C2LinearRangeAspect(const _C2LinearCapacityAspect *parent)
+ : _C2LinearCapacityAspect(parent),
+ mOffset(0),
+ mSize(capacity()) {
+ }
+
+ // subrange of parent capacity [0, capacity] & [size, size + offset]
+ inline constexpr _C2LinearRangeAspect(const _C2LinearCapacityAspect *parent, size_t offset, size_t size)
+ : _C2LinearCapacityAspect(parent),
+ mOffset(c2_min(offset, capacity())),
+ mSize(c2_min(size, capacity() - mOffset)) {
+ }
+
+ // subsection of the parent's and [offset, offset + size] ranges
+ inline constexpr _C2LinearRangeAspect(const _C2LinearRangeAspect *parent, size_t offset, size_t size)
+ : _C2LinearCapacityAspect(parent),
+ mOffset(c2_min(c2_max(offset, parent == nullptr ? 0 : parent->offset()), capacity())),
+ mSize(std::min(c2_min(size, parent == nullptr ? 0 : parent->size()), capacity() - mOffset)) {
+ }
+
+public:
+ inline constexpr _C2LinearRangeAspect childRange(size_t offset, size_t size) const {
+ return _C2LinearRangeAspect(
+ mSize,
+ c2_min(c2_max(offset, mOffset), capacity()) - mOffset,
+ c2_min(c2_min(size, mSize), capacity() - c2_min(c2_max(offset, mOffset), capacity())));
+ }
+
+ friend class _C2EditableLinearRangeAspect;
+ // invariants 0 <= mOffset <= mOffset + mSize <= capacity()
+ uint32_t mOffset;
+ uint32_t mSize;
+/// @}
+};
+
+/**
+ * Utility class for safe range calculations using size_t-s.
+ */
+class C2LinearRange : public _C2LinearRangeAspect {
+public:
+ inline constexpr C2LinearRange(const _C2LinearCapacityAspect &parent, size_t offset, size_t size)
+ : _C2LinearRangeAspect(&parent, offset, size) { }
+
+ inline constexpr C2LinearRange(const _C2LinearRangeAspect &parent, size_t offset, size_t size)
+ : _C2LinearRangeAspect(&parent, offset, size) { }
+
+ inline constexpr C2LinearRange intersect(size_t offset, size_t size) const {
+ return C2LinearRange(*this, offset, size);
+ }
+};
+
+/**
+ * Utility class for simple and safe capacity and range construction.
+ */
+class C2LinearCapacity : public _C2LinearCapacityAspect {
+public:
+ inline constexpr explicit C2LinearCapacity(size_t capacity)
+ : _C2LinearCapacityAspect(c2_min(capacity, std::numeric_limits<uint32_t>::max())) { }
+
+ inline constexpr C2LinearRange range(size_t offset, size_t size) const {
+ return C2LinearRange(*this, offset, size);
+ }
+};
+
+/**
+ * Aspect for objects that have an editable linear range.
+ *
+ * This class is copiable.
+ */
+class _C2EditableLinearRangeAspect : public _C2LinearRangeAspect {
+ using _C2LinearRangeAspect::_C2LinearRangeAspect;
+
+public:
+/// \name Editable linear range interface
+/// @{
+
+ /**
+ * Sets the offset to |offset|, while trying to keep the end of the buffer unchanged (e.g.
+ * size will grow if offset is decreased, and may shrink if offset is increased.) Returns
+ * true if successful, which is equivalent to if 0 <= |offset| <= capacity().
+ *
+ * Note: setting offset and size will yield different result depending on the order of the
+ * operations. Always set offset first to ensure proper size.
+ */
+ inline bool setOffset(uint32_t offset) {
+ if (offset > capacity()) {
+ return false;
+ }
+
+ if (offset > mOffset + mSize) {
+ mSize = 0;
+ } else {
+ mSize = mOffset + mSize - offset;
+ }
+ mOffset = offset;
+ return true;
+ }
+
+ /**
+ * Sets the size to |size|. Returns true if successful, which is equivalent to
+ * if 0 <= |size| <= capacity() - offset().
+ *
+ * Note: setting offset and size will yield different result depending on the order of the
+ * operations. Always set offset first to ensure proper size.
+ */
+ inline bool setSize(uint32_t size) {
+ if (size > capacity() - mOffset) {
+ return false;
+ } else {
+ mSize = size;
+ return true;
+ }
+ }
+
+ /**
+ * Sets the offset to |offset| with best effort. Same as setOffset() except that offset will
+ * be clamped to the buffer capacity.
+ *
+ * Note: setting offset and size (even using best effort) will yield different result depending
+ * on the order of the operations. Always set offset first to ensure proper size.
+ */
+ inline void setOffset_be(uint32_t offset) {
+ (void)setOffset(c2_min(offset, capacity()));
+ }
+
+ /**
+ * Sets the size to |size| with best effort. Same as setSize() except that the selected region
+ * will be clamped to the buffer capacity (e.g. size is clamped to [0, capacity() - offset()]).
+ *
+ * Note: setting offset and size (even using best effort) will yield different result depending
+ * on the order of the operations. Always set offset first to ensure proper size.
+ */
+ inline void setSize_be(uint32_t size) {
+ mSize = c2_min(size, capacity() - mOffset);
+ }
+/// @}
+};
+
+/**************************************************************************************************
+ ALLOCATIONS
+**************************************************************************************************/
+
+/// \ingroup allocator Allocation and memory placement
+/// @{
+
+class C2LinearAllocation;
+class C2GraphicAllocation;
+
+/**
+ * Allocators are used by the framework to allocate memory (allocations) for buffers. They can
+ * support either 1D or 2D allocations.
+ *
+ * \note In theory they could support both, but in practice, we will use only one or the other.
+ *
+ * Never constructed on stack.
+ *
+ * Allocators are provided by vendors.
+ */
+class C2Allocator {
+public:
+ /**
+ * Allocator ID type.
+ */
+ typedef uint32_t id_t;
+ enum : id_t {
+ BAD_ID = 0xBADD, // invalid allocator ID
+ };
+
+ /**
+ * Allocation types. This is a bitmask and is used in C2Allocator::Info
+ * to list the supported allocation types of an allocator.
+ */
+ enum type_t : uint32_t {
+ LINEAR = 1 << 0, //
+ GRAPHIC = 1 << 1,
+ };
+
+ /**
+ * Information about an allocator.
+ *
+ * Allocators don't have a query API so all queriable information is stored here.
+ */
+ struct Traits {
+ C2String name; ///< allocator name
+ id_t id; ///< allocator ID
+ type_t supportedTypes; ///< supported allocation types
+ C2MemoryUsage minimumUsage; ///< usage that is minimally required for allocations
+ C2MemoryUsage maximumUsage; ///< usage that is maximally allowed for allocations
+ };
+
+ /**
+ * Returns the unique name of this allocator.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return the name of this allocator.
+ * \retval an empty string if there was not enough memory to allocate the actual name.
+ */
+ virtual C2String getName() const = 0;
+
+ /**
+ * Returns a unique ID for this allocator. This ID is used to get this allocator from the
+ * allocator store, and to identify this allocator across all processes.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return a unique ID for this allocator.
+ */
+ virtual id_t getId() const = 0;
+
+ /**
+ * Returns the allocator traits.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * Allocators don't have a full-fledged query API, only this method.
+ *
+ * \return allocator information
+ */
+ virtual std::shared_ptr<const Traits> getTraits() const = 0;
+
+ /**
+ * Allocates a 1D allocation of given |capacity| and |usage|. If successful, the allocation is
+ * stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
+ *
+ * \param capacity the size of requested allocation (the allocation could be slightly
+ * larger, e.g. to account for any system-required alignment)
+ * \param usage the memory usage info for the requested allocation. \note that the
+ * returned allocation may be later used/mapped with different usage.
+ * The allocator should layout the buffer to be optimized for this usage,
+ * but must support any usage. One exception: protected buffers can
+ * only be used in a protected scenario.
+ * \param allocation pointer to where the allocation shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the allocation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete the allocation
+ * \retval C2_TIMED_OUT the allocation timed out
+ * \retval C2_REFUSED no permission to complete the allocation
+ * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
+ * \retval C2_OMITTED this allocator does not support 1D allocations
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ */
+ virtual c2_status_t newLinearAllocation(
+ uint32_t capacity __unused, C2MemoryUsage usage __unused,
+ std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
+ *allocation = nullptr;
+ return C2_OMITTED;
+ }
+
+ /**
+ * (Re)creates a 1D allocation from a native |handle|. If successful, the allocation is stored
+ * in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
+ *
+ * \param handle the handle for the existing allocation. On success, the allocation will
+ * take ownership of |handle|.
+ * \param allocation pointer to where the allocation shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the allocation was recreated successfully
+ * \retval C2_NO_MEMORY not enough memory to recreate the allocation
+ * \retval C2_TIMED_OUT the recreation timed out (unexpected)
+ * \retval C2_REFUSED no permission to recreate the allocation
+ * \retval C2_BAD_VALUE invalid handle (caller error)
+ * \retval C2_OMITTED this allocator does not support 1D allocations
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ */
+ virtual c2_status_t priorLinearAllocation(
+ const C2Handle *handle __unused,
+ std::shared_ptr<C2LinearAllocation> *allocation /* nonnull */) {
+ *allocation = nullptr;
+ return C2_OMITTED;
+ }
+
+ /**
+ * Allocates a 2D allocation of given |width|, |height|, |format| and |usage|. If successful,
+ * the allocation is stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
+ *
+ * \param width the width of requested allocation (the allocation could be slightly
+ * larger, e.g. to account for any system-required alignment)
+ * \param height the height of requested allocation (the allocation could be slightly
+ * larger, e.g. to account for any system-required alignment)
+ * \param format the pixel format of requested allocation. This could be a vendor
+ * specific format.
+ * \param usage the memory usage info for the requested allocation. \note that the
+ * returned allocation may be later used/mapped with different usage.
+ * The allocator should layout the buffer to be optimized for this usage,
+ * but must support any usage. One exception: protected buffers can
+ * only be used in a protected scenario.
+ * \param allocation pointer to where the allocation shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the allocation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete the allocation
+ * \retval C2_TIMED_OUT the allocation timed out
+ * \retval C2_REFUSED no permission to complete the allocation
+ * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller error)
+ * \retval C2_OMITTED this allocator does not support 2D allocations
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
+ */
+ virtual c2_status_t newGraphicAllocation(
+ uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
+ C2MemoryUsage usage __unused,
+ std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
+ *allocation = nullptr;
+ return C2_OMITTED;
+ }
+
+ /**
+ * (Re)creates a 2D allocation from a native handle. If successful, the allocation is stored
+ * in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
+ *
+ * \param handle the handle for the existing allocation. On success, the allocation will
+ * take ownership of |handle|.
+ * \param allocation pointer to where the allocation shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the allocation was recreated successfully
+ * \retval C2_NO_MEMORY not enough memory to recreate the allocation
+ * \retval C2_TIMED_OUT the recreation timed out (unexpected)
+ * \retval C2_REFUSED no permission to recreate the allocation
+ * \retval C2_BAD_VALUE invalid handle (caller error)
+ * \retval C2_OMITTED this allocator does not support 2D allocations
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during recreation (unexpected)
+ */
+ virtual c2_status_t priorGraphicAllocation(
+ const C2Handle *handle __unused,
+ std::shared_ptr<C2GraphicAllocation> *allocation /* nonnull */) {
+ *allocation = nullptr;
+ return C2_OMITTED;
+ }
+
+ virtual ~C2Allocator() = default;
+protected:
+ C2Allocator() = default;
+};
+
+/**
+ * \ingroup linear allocator
+ * 1D allocation interface.
+ */
+class C2LinearAllocation : public _C2LinearCapacityAspect {
+public:
+ /**
+ * Maps a portion of an allocation starting from |offset| with |size| into local process memory.
+ * Stores the starting address into |addr|, or NULL if the operation was unsuccessful.
+ * |fence| will contain an acquire sync fence object. If it is already
+ * safe to access the buffer contents, then it will contain an empty (already fired) fence.
+ *
+ * \param offset starting position of the portion to be mapped (this does not have to
+ * be page aligned)
+ * \param size size of the portion to be mapped (this does not have to be page
+ * aligned)
+ * \param usage the desired usage. \todo this must be kSoftwareRead and/or
+ * kSoftwareWrite.
+ * \param fence a pointer to a fence object if an async mapping is requested. If
+ * not-null, and acquire fence will be stored here on success, or empty
+ * fence on failure. If null, the mapping will be synchronous.
+ * \param addr a pointer to where the starting address of the mapped portion will be
+ * stored. On failure, nullptr will be stored here.
+ *
+ * \todo Only one portion can be mapped at the same time - this is true for gralloc, but there
+ * is no need for this for 1D buffers.
+ * \todo Do we need to support sync operation as we could just wait for the fence?
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_REFUSED no permission to map the portion
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_DUPLICATE if the allocation is already mapped.
+ * \retval C2_NO_MEMORY not enough memory to complete the operation
+ * \retval C2_BAD_VALUE the parameters (offset/size) are invalid or outside the allocation, or
+ * the usage flags are invalid (caller error)
+ * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
+ */
+ virtual c2_status_t map(
+ size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence /* nullable */,
+ void **addr /* nonnull */) = 0;
+
+ /**
+ * Unmaps a portion of an allocation at |addr| with |size|. These must be parameters previously
+ * passed to and returned by |map|; otherwise, this operation is a no-op.
+ *
+ * \param addr starting address of the mapped region
+ * \param size size of the mapped region
+ * \param fence a pointer to a fence object if an async unmapping is requested. If
+ * not-null, a release fence will be stored here on success, or empty fence
+ * on failure. This fence signals when the original allocation contains
+ * all changes that happened to the mapped region. If null, the unmapping
+ * will be synchronous.
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_NOT_FOUND if the allocation was not mapped previously.
+ * \retval C2_BAD_VALUE the parameters (addr/size) do not correspond to previously mapped
+ * regions (caller error)
+ * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
+ * \retval C2_REFUSED no permission to unmap the portion (unexpected - system)
+ */
+ virtual c2_status_t unmap(void *addr, size_t size, C2Fence *fence /* nullable */) = 0;
+
+ /**
+ * Returns the allocator ID for this allocation. This is useful to put the handle into context.
+ */
+ virtual C2Allocator::id_t getAllocatorId() const = 0;
+
+ /**
+ * Returns a pointer to the allocation handle.
+ */
+ virtual const C2Handle *handle() const = 0;
+
+ /**
+ * Returns true if this is the same allocation as |other|.
+ */
+ virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const = 0;
+
+protected:
+ // \todo should we limit allocation directly?
+ C2LinearAllocation(size_t capacity) : _C2LinearCapacityAspect(c2_min(capacity, UINT32_MAX)) {}
+ virtual ~C2LinearAllocation() = default;
+};
+
+class C2CircularBlock;
+class C2LinearBlock;
+class C2GraphicBlock;
+
+/**
+ * Block pools are used by components to obtain output buffers in an efficient way. They can
+ * support either linear (1D), circular (1D) or graphic (2D) blocks.
+ *
+ * Block pools decouple the recycling of memory/allocations from the components. They are meant to
+ * be an opaque service (there are no public APIs other than obtaining blocks) provided by the
+ * platform. Block pools are also meant to decouple allocations from memory used by buffers. This
+ * is accomplished by allowing pools to allot multiple memory 'blocks' on a single allocation. As
+ * their name suggest, block pools maintain a pool of memory blocks. When a component asks for
+ * a memory block, pools will try to return a free memory block already in the pool. If no such
+ * block exists, they will allocate memory using the backing allocator and allot a block on that
+ * allocation. When blocks are no longer used in the system, they are recycled back to the block
+ * pool and are available as free blocks.
+ *
+ * Never constructed on stack.
+ */
+class C2BlockPool {
+public:
+ /**
+ * Block pool ID type.
+ */
+ typedef uint64_t local_id_t;
+
+ enum : local_id_t {
+ BASIC_LINEAR = 0, ///< ID of basic (unoptimized) block pool for fetching 1D blocks
+ BASIC_GRAPHIC = 1, ///< ID of basic (unoptimized) block pool for fetching 2D blocks
+ PLATFORM_START = 0x10,
+ };
+
+ /**
+ * Returns the ID for this block pool. This ID is used to get this block pool from the platform.
+ * It is only valid in the current process.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return a local ID for this block pool.
+ */
+ virtual local_id_t getLocalId() const = 0;
+
+ /**
+ * Returns the ID of the backing allocator of this block pool.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return the ID of the backing allocator of this block pool.
+ */
+ virtual C2Allocator::id_t getAllocatorId() const = 0;
+
+ /**
+ * Obtains a linear writeable block of given |capacity| and |usage|. If successful, the
+ * block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
+ *
+ * \param capacity the size of requested block.
+ * \param usage the memory usage info for the requested block. Returned blocks will be
+ * optimized for this usage, but may be used with any usage. One exception:
+ * protected blocks/buffers can only be used in a protected scenario.
+ * \param block pointer to where the obtained block shall be stored on success. nullptr will
+ * be stored here on failure
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_REFUSED no permission to complete any required allocation
+ * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
+ * \retval C2_OMITTED this pool does not support linear blocks
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
+ */
+ virtual c2_status_t fetchLinearBlock(
+ uint32_t capacity __unused, C2MemoryUsage usage __unused,
+ std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
+ *block = nullptr;
+ return C2_OMITTED;
+ }
+
+ /**
+ * Obtains a circular writeable block of given |capacity| and |usage|. If successful, the
+ * block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
+ *
+ * \param capacity the size of requested circular block. (note: the size of the obtained
+ * block could be slightly larger, e.g. to accommodate any system-required
+ * alignment)
+ * \param usage the memory usage info for the requested block. Returned blocks will be
+ * optimized for this usage, but may be used with any usage. One exception:
+ * protected blocks/buffers can only be used in a protected scenario.
+ * \param block pointer to where the obtained block shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_REFUSED no permission to complete any required allocation
+ * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
+ * \retval C2_OMITTED this pool does not support circular blocks
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
+ */
+ virtual c2_status_t fetchCircularBlock(
+ uint32_t capacity __unused, C2MemoryUsage usage __unused,
+ std::shared_ptr<C2CircularBlock> *block /* nonnull */) {
+ *block = nullptr;
+ return C2_OMITTED;
+ }
+
+ /**
+ * Obtains a 2D graphic block of given |width|, |height|, |format| and |usage|. If successful,
+ * the block is stored in |block|. Otherwise, |block| is set to 'nullptr'.
+ *
+ * \param width the width of requested block (the obtained block could be slightly larger, e.g.
+ * to accommodate any system-required alignment)
+ * \param height the height of requested block (the obtained block could be slightly larger,
+ * e.g. to accommodate any system-required alignment)
+ * \param format the pixel format of requested block. This could be a vendor specific format.
+ * \param usage the memory usage info for the requested block. Returned blocks will be
+ * optimized for this usage, but may be used with any usage. One exception:
+ * protected blocks/buffers can only be used in a protected scenario.
+ * \param block pointer to where the obtained block shall be stored on success. nullptr
+ * will be stored here on failure
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_NO_MEMORY not enough memory to complete any required allocation
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_REFUSED no permission to complete any required allocation
+ * \retval C2_BAD_VALUE width, height, format or usage are not supported (invalid) (caller
+ * error)
+ * \retval C2_OMITTED this pool does not support 2D blocks
+ * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected)
+ */
+ virtual c2_status_t fetchGraphicBlock(
+ uint32_t width __unused, uint32_t height __unused, uint32_t format __unused,
+ C2MemoryUsage usage __unused,
+ std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
+ *block = nullptr;
+ return C2_OMITTED;
+ }
+
+ virtual ~C2BlockPool() = default;
+protected:
+ C2BlockPool() = default;
+};
+
+/// @}
+
+// ================================================================================================
+// BLOCKS
+// ================================================================================================
+
+/**
+ * Blocks are sections of allocations. They can be either 1D or 2D.
+ */
+
+class C2LinearAllocation;
+
+/**
+ * A 1D block.
+ *
+ * \note capacity() is not meaningful for users of blocks; instead size() is the capacity of the
+ * usable portion. Use and offset() and size() if accessing the block directly through its handle
+ * to represent the allotted range of the underlying allocation to this block.
+ */
+class C2Block1D : public _C2LinearRangeAspect {
+public:
+ /**
+ * Returns the underlying handle for this allocation.
+ *
+ * \note that the block and its block pool has shared ownership of the handle
+ * and if all references to the block are released, the underlying block
+ * allocation may get reused even if a client keeps a clone of this handle.
+ */
+ const C2Handle *handle() const;
+
+ /**
+ * Returns the allocator's ID that created the underlying allocation for this block. This
+ * provides the context for understanding the handle.
+ */
+ C2Allocator::id_t getAllocatorId() const;
+
+protected:
+ class Impl;
+ /** construct a block. */
+ C2Block1D(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range);
+
+ friend struct _C2BlockFactory;
+ std::shared_ptr<Impl> mImpl;
+};
+
+/**
+ * Read view provides read-only access for a linear memory segment.
+ *
+ * This class is copiable.
+ */
+class C2ReadView : public _C2LinearCapacityAspect {
+public:
+ /**
+ * \return pointer to the start of the block or nullptr on error.
+ * This pointer is only valid during the lifetime of this view or until it is released.
+ */
+ const uint8_t *data() const;
+
+ /**
+ * Returns a portion of this view.
+ *
+ * \param offset the start offset of the portion. \note This is clamped to the capacity of this
+ * view.
+ * \param size the size of the portion. \note This is clamped to the remaining data from offset.
+ *
+ * \return a read view containing a portion of this view
+ */
+ C2ReadView subView(size_t offset, size_t size) const;
+
+ /**
+ * \return error during the creation/mapping of this view.
+ */
+ c2_status_t error() const;
+
+ /**
+ * Releases this view. This sets error to C2_NO_INIT.
+ */
+ //void release();
+
+protected:
+ class Impl;
+ C2ReadView(std::shared_ptr<Impl> impl, uint32_t offset, uint32_t size);
+ explicit C2ReadView(c2_status_t error);
+
+private:
+ friend struct _C2BlockFactory;
+ std::shared_ptr<Impl> mImpl;
+ uint32_t mOffset; /**< offset into the linear block backing this read view */
+};
+
+/**
+ * Write view provides read/write access for a linear memory segment.
+ *
+ * This class is copiable. \todo movable only?
+ */
+class C2WriteView : public _C2EditableLinearRangeAspect {
+public:
+ /**
+ * Start of the block.
+ *
+ * \return pointer to the start of the block or nullptr on error.
+ * This pointer is only valid during the lifetime of this view or until it is released.
+ */
+ uint8_t *base();
+
+ /**
+ * \return pointer to the block at the current offset or nullptr on error.
+ * This pointer is only valid during the lifetime of this view or until it is released.
+ */
+ uint8_t *data();
+
+ /**
+ * \return error during the creation/mapping of this view.
+ */
+ c2_status_t error() const;
+
+ /**
+ * Releases this view. This sets error to C2_NO_INIT.
+ */
+ //void release();
+
+protected:
+ class Impl;
+ C2WriteView(std::shared_ptr<Impl> impl);
+ explicit C2WriteView(c2_status_t error);
+
+private:
+ friend struct _C2BlockFactory;
+ std::shared_ptr<Impl> mImpl;
+};
+
+/**
+ * A constant (read-only) linear block (portion of an allocation) with an acquire fence.
+ * Blocks are unmapped when created, and can be mapped into a read view on demand.
+ *
+ * This class is copiable and contains a reference to the allocation that it is based on.
+ */
+class C2ConstLinearBlock : public C2Block1D {
+public:
+ /**
+ * Maps this block into memory and returns a read view for it.
+ *
+ * \return a read view for this block.
+ */
+ C2Acquirable<C2ReadView> map() const;
+
+ /**
+ * Returns a portion of this block.
+ *
+ * \param offset the start offset of the portion. \note This is clamped to the capacity of this
+ * block.
+ * \param size the size of the portion. \note This is clamped to the remaining data from offset.
+ *
+ * \return a constant linear block containing a portion of this block
+ */
+ C2ConstLinearBlock subBlock(size_t offset, size_t size) const;
+
+ /**
+ * Returns the acquire fence for this block.
+ *
+ * \return a fence that must be waited on before reading the block.
+ */
+ C2Fence fence() const { return mFence; }
+
+protected:
+ C2ConstLinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range, C2Fence mFence);
+
+private:
+ friend struct _C2BlockFactory;
+ C2Fence mFence;
+};
+
+/**
+ * Linear block is a writeable 1D block. Once written, it can be shared in whole or in parts with
+ * consumers/readers as read-only const linear block(s).
+ */
+class C2LinearBlock : public C2Block1D {
+public:
+ /**
+ * Maps this block into memory and returns a write view for it.
+ *
+ * \return a write view for this block.
+ */
+ C2Acquirable<C2WriteView> map();
+
+ /**
+ * Creates a read-only const linear block for a portion of this block; optionally protected
+ * by an acquire fence. There are two ways to use this:
+ *
+ * 1) share ready block after writing data into the block. In this case no fence shall be
+ * supplied, and the block shall not be modified after calling this method.
+ * 2) share block metadata before actually (finishing) writing the data into the block. In
+ * this case a fence must be supplied that will be triggered when the data is written.
+ * The block shall be modified only until firing the event for the fence.
+ */
+ C2ConstLinearBlock share(size_t offset, size_t size, C2Fence fence);
+
+protected:
+ C2LinearBlock(std::shared_ptr<Impl> impl, const _C2LinearRangeAspect &range);
+
+ friend struct _C2BlockFactory;
+};
+
+/// @}
+
+/**************************************************************************************************
+ CIRCULAR BLOCKS AND VIEWS
+**************************************************************************************************/
+
+/// \defgroup circular Circular buffer support
+/// @{
+
+/**
+ * Circular blocks can be used to share data between a writer and a reader (and/or other consumers)-
+ * in a memory-efficient way by reusing a section of memory. Circular blocks are a bit more complex
+ * than single reader/single writer schemes to facilitate block-based consuming of data.
+ *
+ * They can operate in two modes:
+ *
+ * 1) one writer that creates blocks to be consumed (this model can be used by components)
+ *
+ * 2) one writer that writes continuously, and one reader that can creates blocks to be consumed
+ * by further recipients (this model is used by the framework, and cannot be used by components.)
+ *
+ * Circular blocks have four segments with running pointers:
+ * - reserved: data reserved and available for the writer
+ * - committed: data committed by the writer and available to the reader (if present)
+ * - used: data used by consumers (if present)
+ * - available: unused data available to be reserved
+ */
+class C2CircularBlock : public C2Block1D {
+ // TODO: add methods
+
+private:
+ size_t mReserved __unused; // end of reserved section
+ size_t mCommitted __unused; // end of committed section
+ size_t mUsed __unused; // end of used section
+ size_t mFree __unused; // end of free section
+};
+
+class _C2CircularBlockSegment : public _C2LinearCapacityAspect {
+public:
+ /**
+ * Returns the available size for this segment.
+ *
+ * \return currently available size for this segment
+ */
+ size_t available() const;
+
+ /**
+ * Reserve some space for this segment from its current start.
+ *
+ * \param size desired space in bytes
+ * \param fence a pointer to an acquire fence. If non-null, the reservation is asynchronous and
+ * a fence will be stored here that will be signaled when the reservation is
+ * complete. If null, the reservation is synchronous.
+ *
+ * \retval C2_OK the space was successfully reserved
+ * \retval C2_NO_MEMORY the space requested cannot be reserved
+ * \retval C2_TIMED_OUT the reservation timed out \todo when?
+ * \retval C2_CORRUPTED some unknown error prevented reserving space. (unexpected)
+ */
+ c2_status_t reserve(size_t size, C2Fence *fence /* nullable */);
+
+ /**
+ * Abandons a portion of this segment. This will move to the beginning of this segment.
+ *
+ * \note This methods is only allowed if this segment is producing blocks.
+ *
+ * \param size number of bytes to abandon
+ *
+ * \retval C2_OK the data was successfully abandoned
+ * \retval C2_TIMED_OUT the operation timed out (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented abandoning the data (unexpected)
+ */
+ c2_status_t abandon(size_t size);
+
+ /**
+ * Share a portion as block(s) with consumers (these are moved to the used section).
+ *
+ * \note This methods is only allowed if this segment is producing blocks.
+ * \note Share does not move the beginning of the segment. (\todo add abandon/offset?)
+ *
+ * \param size number of bytes to share
+ * \param fence fence to be used for the section
+ * \param blocks vector where the blocks of the section are appended to
+ *
+ * \retval C2_OK the portion was successfully shared
+ * \retval C2_NO_MEMORY not enough memory to share the portion
+ * \retval C2_TIMED_OUT the operation timed out (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented sharing the data (unexpected)
+ */
+ c2_status_t share(size_t size, C2Fence fence, std::vector<C2ConstLinearBlock> &blocks);
+
+ /**
+ * Returns the beginning offset of this segment from the start of this circular block.
+ *
+ * @return beginning offset
+ */
+ size_t begin();
+
+ /**
+ * Returns the end offset of this segment from the start of this circular block.
+ *
+ * @return end offset
+ */
+ size_t end();
+};
+
+/**
+ * A circular write-view is a dynamic mapped view for a segment of a circular block. Care must be
+ * taken when using this view so that only the section owned by the segment is modified.
+ */
+class C2CircularWriteView : public _C2LinearCapacityAspect {
+public:
+ /**
+ * Start of the circular block.
+ * \note the segment does not own this pointer.
+ *
+ * \return pointer to the start of the circular block or nullptr on error.
+ */
+ uint8_t *base();
+
+ /**
+ * \return error during the creation/mapping of this view.
+ */
+ c2_status_t error() const;
+};
+
+/**
+ * The writer of a circular buffer.
+ *
+ * Can commit data to a reader (not supported for components) OR share data blocks directly with a
+ * consumer.
+ *
+ * If a component supports outputting data into circular buffers, it must allocate a circular
+ * block and use a circular writer.
+ */
+class C2CircularWriter : public _C2CircularBlockSegment {
+public:
+ /**
+ * Commits a portion of this segment to the next segment. This moves the beginning of the
+ * segment.
+ *
+ * \param size number of bytes to commit to the next segment
+ * \param fence fence used for the commit (the fence must signal before the data is committed)
+ */
+ c2_status_t commit(size_t size, C2Fence fence);
+
+ /**
+ * Maps this block into memory and returns a write view for it.
+ *
+ * \return a write view for this block.
+ */
+ C2Acquirable<C2CircularWriteView> map();
+};
+
+/// @}
+
+/// \defgroup graphic Graphic Data Blocks
+/// @{
+
+/**
+ * C2Rect: rectangle type with non-negative coordinates.
+ *
+ * \note This struct has public fields without getters/setters. All methods are inline.
+ */
+struct C2Rect {
+// public:
+ uint32_t width;
+ uint32_t height;
+ uint32_t left;
+ uint32_t top;
+
+ constexpr inline C2Rect()
+ : C2Rect(0, 0, 0, 0) { }
+
+ constexpr inline C2Rect(uint32_t width_, uint32_t height_)
+ : C2Rect(width_, height_, 0, 0) { }
+
+ constexpr C2Rect inline at(uint32_t left_, uint32_t top_) const {
+ return C2Rect(width, height, left_, top_);
+ }
+
+ // utility methods
+
+ inline constexpr bool isEmpty() const {
+ return width == 0 || height == 0;
+ }
+
+ inline constexpr bool isValid() const {
+ return left <= ~width && top <= ~height;
+ }
+
+ inline constexpr operator bool() const {
+ return isValid() && !isEmpty();
+ }
+
+ inline constexpr bool operator!() const {
+ return !bool(*this);
+ }
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr bool contains(const C2Rect &other) const {
+ if (!isValid() || !other.isValid()) {
+ return false;
+ } else {
+ return left <= other.left && top <= other.top
+ && left + width >= other.left + other.width
+ && top + height >= other.top + other.height;
+ }
+ }
+
+ inline constexpr bool operator==(const C2Rect &other) const {
+ if (!isValid()) {
+ return !other.isValid();
+ } else {
+ return left == other.left && top == other.top
+ && width == other.width && height == other.height;
+ }
+ }
+
+ inline constexpr bool operator!=(const C2Rect &other) const {
+ return !operator==(other);
+ }
+
+ inline constexpr bool operator>=(const C2Rect &other) const {
+ return contains(other);
+ }
+
+ inline constexpr bool operator>(const C2Rect &other) const {
+ return contains(other) && !operator==(other);
+ }
+
+ inline constexpr bool operator<=(const C2Rect &other) const {
+ return other.contains(*this);
+ }
+
+ inline constexpr bool operator<(const C2Rect &other) const {
+ return other.contains(*this) && !operator==(other);
+ }
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr uint32_t right() const {
+ return left + width;
+ }
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr uint32_t bottom() const {
+ return top + height;
+ }
+
+ C2_ALLOW_OVERFLOW
+ inline constexpr C2Rect intersect(const C2Rect &other) const {
+ return C2Rect(c2_min(right(), other.right()) - c2_max(left, other.left),
+ c2_min(bottom(), other.bottom()) - c2_max(top, other.top),
+ c2_max(left, other.left),
+ c2_max(top, other.top));
+ }
+
+ /** clamps right and bottom to top, left if they overflow */
+ inline constexpr C2Rect normalize() const {
+ return C2Rect(c2_max(left, right()) - left, c2_max(top, bottom()) - top, left, top);
+ }
+
+private:
+ /// note: potentially unusual argument order
+ constexpr inline C2Rect(uint32_t width_, uint32_t height_, uint32_t left_, uint32_t top_)
+ : width(width_),
+ height(height_),
+ left(left_),
+ top(top_) { }
+};
+
+/**
+ * Interface for objects that have a width and height (planar capacity).
+ */
+class _C2PlanarCapacityAspect {
+/// \name Planar capacity interface
+/// @{
+public:
+ inline constexpr uint32_t width() const { return _mWidth; }
+ inline constexpr uint32_t height() const { return _mHeight; }
+
+ inline constexpr operator C2Rect() const {
+ return C2Rect(_mWidth, _mHeight);
+ }
+
+protected:
+ inline constexpr _C2PlanarCapacityAspect(uint32_t width, uint32_t height)
+ : _mWidth(width), _mHeight(height) { }
+
+ inline explicit constexpr _C2PlanarCapacityAspect(const _C2PlanarCapacityAspect *parent)
+ : _mWidth(parent == nullptr ? 0 : parent->width()),
+ _mHeight(parent == nullptr ? 0 : parent->height()) { }
+
+private:
+ uint32_t _mWidth;
+ uint32_t _mHeight;
+/// @}
+};
+
+/**
+ * C2PlaneInfo: information on the layout of a singe flexible plane.
+ *
+ * Public fields without getters/setters.
+ */
+struct C2PlaneInfo {
+//public:
+ enum channel_t : uint32_t {
+ CHANNEL_Y, ///< luma
+ CHANNEL_R, ///< red
+ CHANNEL_G, ///< green
+ CHANNEL_B, ///< blue
+ CHANNEL_A, ///< alpha
+ CHANNEL_CR, ///< Cr
+ CHANNEL_CB, ///< Cb
+ } channel;
+
+ int32_t colInc; ///< column increment in bytes. may be negative
+ int32_t rowInc; ///< row increment in bytes. may be negative
+
+ uint32_t colSampling; ///< subsampling compared to width (must be a power of 2)
+ uint32_t rowSampling; ///< subsampling compared to height (must be a power of 2)
+
+ uint32_t allocatedDepth; ///< size of each sample (must be a multiple of 8)
+ uint32_t bitDepth; ///< significant bits per sample
+ /**
+ * the right shift of the significant bits in the sample. E.g. if a 10-bit significant
+ * value is laid out in a 16-bit allocation aligned to LSB (values 0-1023), rightShift
+ * would be 0 as the 16-bit value read from the sample does not need to be right shifted
+ * and can be used as is (after applying a 10-bit mask of 0x3FF).
+ *
+ * +--------+--------+
+ * | VV|VVVVVVVV|
+ * +--------+--------+
+ * 15 8 7 0
+ *
+ * If the value is laid out aligned to MSB, rightShift would be 6, as the value read
+ * from the allocated sample must be right-shifted by 6 to get the actual sample value.
+ *
+ * +--------+--------+
+ * |VVVVVVVV|VV |
+ * +--------+--------+
+ * 15 8 7 0
+ */
+ uint32_t rightShift;
+
+ enum endianness_t : uint32_t {
+ NATIVE,
+ LITTLE_END, // LITTLE_ENDIAN is reserved macro
+ BIG_END, // BIG_ENDIAN is a reserved macro
+ } endianness; ///< endianness of the samples
+
+ /**
+ * The following two fields define the relation between multiple planes. If multiple planes are
+ * interleaved, they share a root plane (whichever plane's start address is the lowest), and
+ * |offset| is the offset of this plane inside the root plane (in bytes). |rootIx| is the index
+ * of the root plane. If a plane is independent, rootIx is its index and offset is 0.
+ */
+ uint32_t rootIx; ///< index of the root plane
+ uint32_t offset; ///< offset of this plane inside of the root plane
+
+ inline constexpr ssize_t minOffset(uint32_t width, uint32_t height) const {
+ ssize_t offs = 0;
+ if (width > 0 && colInc < 0) {
+ offs += colInc * (ssize_t)(width - 1);
+ }
+ if (height > 0 && rowInc < 0) {
+ offs += rowInc * (ssize_t)(height - 1);
+ }
+ return offs;
+ }
+
+ inline constexpr ssize_t maxOffset(uint32_t width, uint32_t height) const {
+ ssize_t offs = (allocatedDepth + 7) >> 3;
+ if (width > 0 && colInc > 0) {
+ offs += colInc * (ssize_t)(width - 1);
+ }
+ if (height > 0 && rowInc > 0) {
+ offs += rowInc * (ssize_t)(height - 1);
+ }
+ return offs;
+ }
+} C2_PACK;
+
+struct C2PlanarLayout {
+//public:
+ enum type_t : uint32_t {
+ TYPE_UNKNOWN = 0,
+ TYPE_YUV = 0x100, ///< YUV image with 3 planes
+ TYPE_YUVA, ///< YUVA image with 4 planes
+ TYPE_RGB, ///< RGB image with 3 planes
+ TYPE_RGBA, ///< RBGA image with 4 planes
+ };
+
+ type_t type; // image type
+ uint32_t numPlanes; // number of component planes
+ uint32_t rootPlanes; // number of layout planes (root planes)
+
+ enum plane_index_t : uint32_t {
+ PLANE_Y = 0,
+ PLANE_U = 1,
+ PLANE_V = 2,
+ PLANE_R = 0,
+ PLANE_G = 1,
+ PLANE_B = 2,
+ PLANE_A = 3,
+ MAX_NUM_PLANES = 4,
+ };
+
+ C2PlaneInfo planes[MAX_NUM_PLANES];
+};
+
+/**
+ * Aspect for objects that have a planar section (crop rectangle).
+ *
+ * This class is copiable.
+ */
+class _C2PlanarSectionAspect : public _C2PlanarCapacityAspect {
+/// \name Planar section interface
+/// @{
+private:
+ inline constexpr _C2PlanarSectionAspect(uint32_t width, uint32_t height, const C2Rect &crop)
+ : _C2PlanarCapacityAspect(width, height),
+ mCrop(C2Rect(std::min(width - std::min(crop.left, width), crop.width),
+ std::min(height - std::min(crop.top, height), crop.height)).at(
+ std::min(crop.left, width),
+ std::min(crop.height, height))) {
+ }
+
+public:
+ // crop can be an empty rect, does not have to line up with subsampling
+ // NOTE: we do not support floating-point crop
+ inline constexpr C2Rect crop() const { return mCrop; }
+
+ /**
+ * Returns a child planar section for |crop|, where the capacity represents this section.
+ */
+ inline constexpr _C2PlanarSectionAspect childSection(const C2Rect &crop) const {
+ return _C2PlanarSectionAspect(
+ mCrop.width, mCrop.height,
+ // crop and translate |crop| rect
+ C2Rect(c2_min(mCrop.right() - c2_clamp(mCrop.left, crop.left, mCrop.right()),
+ crop.width),
+ c2_min(mCrop.bottom() - c2_clamp(mCrop.top, crop.top, mCrop.bottom()),
+ crop.height))
+ .at(c2_clamp(mCrop.left, crop.left, mCrop.right()) - mCrop.left,
+ c2_clamp(mCrop.top, crop.top, mCrop.bottom()) - mCrop.top));
+ }
+
+protected:
+ inline constexpr _C2PlanarSectionAspect(const _C2PlanarCapacityAspect *parent)
+ : _C2PlanarCapacityAspect(parent), mCrop(width(), height()) {}
+
+ inline constexpr _C2PlanarSectionAspect(const _C2PlanarCapacityAspect *parent, const C2Rect &crop)
+ : _C2PlanarCapacityAspect(parent),
+ mCrop(parent == nullptr ? C2Rect() : ((C2Rect)*parent).intersect(crop).normalize()) { }
+
+ inline constexpr _C2PlanarSectionAspect(const _C2PlanarSectionAspect *parent, const C2Rect &crop)
+ : _C2PlanarCapacityAspect(parent),
+ mCrop(parent == nullptr ? C2Rect() : parent->crop().intersect(crop).normalize()) { }
+
+private:
+ friend class _C2EditablePlanarSectionAspect;
+ C2Rect mCrop;
+/// @}
+};
+
+/**
+ * Aspect for objects that have an editable planar section (crop rectangle).
+ *
+ * This class is copiable.
+ */
+class _C2EditablePlanarSectionAspect : public _C2PlanarSectionAspect {
+/// \name Planar section interface
+/// @{
+ using _C2PlanarSectionAspect::_C2PlanarSectionAspect;
+
+public:
+ // crop can be an empty rect, does not have to line up with subsampling
+ // NOTE: we do not support floating-point crop
+ inline constexpr C2Rect crop() const { return mCrop; }
+
+ /**
+ * Sets crop to crop intersected with [(0,0) .. (width, height)]
+ */
+ inline void setCrop_be(const C2Rect &crop) {
+ mCrop.left = std::min(width(), crop.left);
+ mCrop.top = std::min(height(), crop.top);
+ // It's guaranteed that mCrop.left <= width() && mCrop.top <= height()
+ mCrop.width = std::min(width() - mCrop.left, crop.width);
+ mCrop.height = std::min(height() - mCrop.top, crop.height);
+ }
+
+ /**
+ * If crop is within the dimensions of this object, it sets crop to it.
+ *
+ * \return true iff crop is within the dimensions of this object
+ */
+ inline bool setCrop(const C2Rect &crop) {
+ if (width() < crop.width || height() < crop.height
+ || width() - crop.width < crop.left || height() - crop.height < crop.top) {
+ return false;
+ }
+ mCrop = crop;
+ return true;
+ }
+/// @}
+};
+
+/**
+ * Utility class for safe range calculations using size_t-s.
+ */
+class C2PlanarSection : public _C2PlanarSectionAspect {
+public:
+ inline constexpr C2PlanarSection(const _C2PlanarCapacityAspect &parent, const C2Rect &crop)
+ : _C2PlanarSectionAspect(&parent, crop) { }
+
+ inline constexpr C2PlanarSection(const _C2PlanarSectionAspect &parent, const C2Rect &crop)
+ : _C2PlanarSectionAspect(&parent, crop) { }
+
+ inline constexpr C2PlanarSection intersect(const C2Rect &crop) const {
+ return C2PlanarSection(*this, crop);
+ }
+};
+
+/**
+ * Utility class for simple and safe planar capacity and section construction.
+ */
+class C2PlanarCapacity : public _C2PlanarCapacityAspect {
+public:
+ inline constexpr explicit C2PlanarCapacity(size_t width, size_t height)
+ : _C2PlanarCapacityAspect(c2_min(width, std::numeric_limits<uint32_t>::max()),
+ c2_min(height, std::numeric_limits<uint32_t>::max())) { }
+
+ inline constexpr C2PlanarSection section(const C2Rect &crop) const {
+ return C2PlanarSection(*this, crop);
+ }
+};
+
+
+/**
+ * \ingroup graphic allocator
+ * 2D allocation interface.
+ */
+class C2GraphicAllocation : public _C2PlanarCapacityAspect {
+public:
+ /**
+ * Maps a rectangular section (as defined by |rect|) of a 2D allocation into local process
+ * memory for flexible access. On success, it fills out |layout| with the plane specifications
+ * and fills the |addr| array with pointers to the first byte of the top-left pixel of each
+ * plane used. Otherwise, it leaves |layout| and |addr| untouched. |fence| will contain
+ * an acquire sync fence object. If it is already safe to access the
+ * buffer contents, then it will be an empty (already fired) fence.
+ *
+ * Safe regions for the pointer addresses returned can be gotten via C2LayoutInfo.minOffset()/
+ * maxOffset().
+ *
+ * \param rect section to be mapped (this does not have to be aligned)
+ * \param usage the desired usage. \todo this must be kSoftwareRead and/or
+ * kSoftwareWrite.
+ * \param fence a pointer to a fence object if an async mapping is requested. If
+ * not-null, and acquire fence will be stored here on success, or empty
+ * fence on failure. If null, the mapping will be synchronous.
+ * \param layout a pointer to where the mapped planes' descriptors will be
+ * stored. On failure, nullptr will be stored here.
+ * \param addr pointer to an array with at least C2PlanarLayout::MAX_NUM_PLANES
+ * elements. Only layout.numPlanes elements will be modified on success.
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_REFUSED no permission to map the section
+ * \retval C2_DUPLICATE there is already a mapped region and this allocation cannot support
+ * multi-mapping (caller error)
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_NO_MEMORY not enough memory to complete the operation
+ * \retval C2_BAD_VALUE the parameters (rect) are invalid or outside the allocation, or the
+ * usage flags are invalid (caller error)
+ * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
+
+ */
+ virtual c2_status_t map(
+ C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
+ C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) = 0;
+
+ /**
+ * Unmaps a section of an allocation at |addr| with |rect|. These must be parameters previously
+ * passed to and returned by |map|; otherwise, this operation is a no-op.
+ *
+ * \param addr pointer to an array with at least C2PlanarLayout::MAX_NUM_PLANES
+ * elements containing the starting addresses of the mapped layers
+ * \param rect boundaries of the mapped section
+ * \param fence a pointer to a fence object if an async unmapping is requested. If
+ * not-null, a release fence will be stored here on success, or empty fence
+ * on failure. This fence signals when the original allocation contains
+ * all changes that happened to the mapped section. If null, the unmapping
+ * will be synchronous.
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_TIMED_OUT the operation timed out
+ * \retval C2_NOT_FOUND there is no such mapped region (caller error)
+ * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
+ * \retval C2_REFUSED no permission to unmap the section (unexpected - system)
+ */
+ virtual c2_status_t unmap(
+ uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) = 0;
+
+ /**
+ * Returns the allocator ID for this allocation. This is useful to put the handle into context.
+ */
+ virtual C2Allocator::id_t getAllocatorId() const = 0;
+
+ /**
+ * Returns a pointer to the allocation handle.
+ */
+ virtual const C2Handle *handle() const = 0;
+
+ /**
+ * Returns true if this is the same allocation as |other|.
+ */
+ virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const = 0;
+
+protected:
+ using _C2PlanarCapacityAspect::_C2PlanarCapacityAspect;
+ virtual ~C2GraphicAllocation() = default;
+};
+
+class C2GraphicAllocation;
+
+/**
+ * A 2D block.
+ *
+ * \note width()/height() is not meaningful for users of blocks; instead, crop().width() and
+ * crop().height() is the capacity of the usable portion. Use and crop() if accessing the block
+ * directly through its handle to represent the allotted region of the underlying allocation to this
+ * block.
+ */
+class C2Block2D : public _C2PlanarSectionAspect {
+public:
+ /**
+ * Returns the underlying handle for this allocation.
+ *
+ * \note that the block and its block pool has shared ownership of the handle
+ * and if all references to the block are released, the underlying block
+ * allocation may get reused even if a client keeps a clone of this handle.
+ */
+ const C2Handle *handle() const;
+
+ /**
+ * Returns the allocator's ID that created the underlying allocation for this block. This
+ * provides the context for understanding the handle.
+ */
+ C2Allocator::id_t getAllocatorId() const;
+
+protected:
+ class Impl;
+ C2Block2D(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect §ion);
+
+ friend struct _C2BlockFactory;
+ std::shared_ptr<Impl> mImpl;
+};
+
+/**
+ * Graphic view provides read or read-write access for a graphic block.
+ *
+ * This class is copiable.
+ *
+ * \note Due to the subsampling of graphic buffers, a read view must still contain a crop rectangle
+ * to ensure subsampling is followed. This results in nearly identical interface between read and
+ * write views, so C2GraphicView can encompass both of them.
+ */
+class C2GraphicView : public _C2EditablePlanarSectionAspect {
+public:
+ /**
+ * \return array of pointers (of layout().numPlanes elements) to the start of the planes or
+ * nullptr on error. Regardless of crop rect, they always point to the top-left corner of each
+ * plane. Access outside of the crop rect results in an undefined behavior.
+ */
+ const uint8_t *const *data() const;
+
+ /**
+ * \return array of pointers (of layout().numPlanes elements) to the start of the planes or
+ * nullptr on error. Regardless of crop rect, they always point to the top-left corner of each
+ * plane. Access outside of the crop rect results in an undefined behavior.
+ */
+ uint8_t *const *data();
+
+ /**
+ * \return layout of the graphic block to interpret the returned data.
+ */
+ const C2PlanarLayout layout() const;
+
+ /**
+ * Returns a section of this view.
+ *
+ * \param rect the dimension of the section. \note This is clamped to the crop of this view.
+ *
+ * \return a read view containing the requested section of this view
+ */
+ const C2GraphicView subView(const C2Rect &rect) const;
+ C2GraphicView subView(const C2Rect &rect);
+
+ /**
+ * \return error during the creation/mapping of this view.
+ */
+ c2_status_t error() const;
+
+protected:
+ class Impl;
+ C2GraphicView(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect §ion);
+ explicit C2GraphicView(c2_status_t error);
+
+private:
+ friend struct _C2BlockFactory;
+ std::shared_ptr<Impl> mImpl;
+};
+
+/**
+ * A constant (read-only) graphic block (portion of an allocation) with an acquire fence.
+ * Blocks are unmapped when created, and can be mapped into a read view on demand.
+ *
+ * This class is copiable and contains a reference to the allocation that it is based on.
+ */
+class C2ConstGraphicBlock : public C2Block2D {
+public:
+ /**
+ * Maps this block into memory and returns a read view for it.
+ *
+ * \return a read view for this block.
+ */
+ C2Acquirable<const C2GraphicView> map() const;
+
+ /**
+ * Returns a section of this block.
+ *
+ * \param rect the coordinates of the section. \note This is clamped to the crop rectangle of
+ * this block.
+ *
+ * \return a constant graphic block containing a portion of this block
+ */
+ C2ConstGraphicBlock subBlock(const C2Rect &rect) const;
+
+ /**
+ * Returns the acquire fence for this block.
+ *
+ * \return a fence that must be waited on before reading the block.
+ */
+ C2Fence fence() const { return mFence; }
+
+protected:
+ C2ConstGraphicBlock(
+ std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect §ion, C2Fence fence);
+
+private:
+ friend struct _C2BlockFactory;
+ C2Fence mFence;
+};
+
+/**
+ * Graphic block is a writeable 2D block. Once written, it can be shared in whole or in part with
+ * consumers/readers as read-only const graphic block.
+ */
+class C2GraphicBlock : public C2Block2D {
+public:
+ /**
+ * Maps this block into memory and returns a write view for it.
+ *
+ * \return a write view for this block.
+ */
+ C2Acquirable<C2GraphicView> map();
+
+ /**
+ * Creates a read-only const linear block for a portion of this block; optionally protected
+ * by an acquire fence. There are two ways to use this:
+ *
+ * 1) share ready block after writing data into the block. In this case no fence shall be
+ * supplied, and the block shall not be modified after calling this method.
+ * 2) share block metadata before actually (finishing) writing the data into the block. In
+ * this case a fence must be supplied that will be triggered when the data is written.
+ * The block shall be modified only until firing the event for the fence.
+ */
+ C2ConstGraphicBlock share(const C2Rect &crop, C2Fence fence);
+
+protected:
+ C2GraphicBlock(std::shared_ptr<Impl> impl, const _C2PlanarSectionAspect §ion);
+
+ friend struct _C2BlockFactory;
+};
+
+/// @}
+
+/// \defgroup buffer_onj Buffer objects
+/// @{
+
+// ================================================================================================
+// BUFFERS
+// ================================================================================================
+
+/// \todo: Do we still need this?
+///
+// There are 2 kinds of buffers: linear or graphic. Linear buffers can contain a single block, or
+// a list of blocks (LINEAR_CHUNKS). Support for list of blocks is optional, and can allow consuming
+// data from circular buffers or scattered data sources without extra memcpy. Currently, list of
+// graphic blocks is not supported.
+
+class C2LinearBuffer; // read-write buffer
+class C2GraphicBuffer; // read-write buffer
+class C2LinearChunksBuffer;
+
+/**
+ * C2BufferData: the main, non-meta data of a buffer. A buffer can contain either linear blocks
+ * or graphic blocks, and can contain either a single block or multiple blocks. This is determined
+ * by its type.
+ */
+class C2BufferData {
+public:
+ /**
+ * The type of buffer data.
+ */
+ enum type_t : uint32_t {
+ INVALID, ///< invalid buffer type. Do not use.
+ LINEAR, ///< the buffer contains a single linear block
+ LINEAR_CHUNKS, ///< the buffer contains one or more linear blocks
+ GRAPHIC, ///< the buffer contains a single graphic block
+ GRAPHIC_CHUNKS, ///< the buffer contains one of more graphic blocks
+ };
+ typedef type_t Type; // deprecated
+
+ /**
+ * Gets the type of this buffer (data).
+ * \return the type of this buffer data.
+ */
+ type_t type() const;
+
+ /**
+ * Gets the linear blocks of this buffer.
+ * \return a constant list of const linear blocks of this buffer.
+ * \retval empty list if this buffer does not contain linear block(s).
+ */
+ const std::vector<C2ConstLinearBlock> linearBlocks() const;
+
+ /**
+ * Gets the graphic blocks of this buffer.
+ * \return a constant list of const graphic blocks of this buffer.
+ * \retval empty list if this buffer does not contain graphic block(s).
+ */
+ const std::vector<C2ConstGraphicBlock> graphicBlocks() const;
+
+private:
+ class Impl;
+ std::shared_ptr<Impl> mImpl;
+
+protected:
+ // no public constructor
+ explicit C2BufferData(const std::vector<C2ConstLinearBlock> &blocks);
+ explicit C2BufferData(const std::vector<C2ConstGraphicBlock> &blocks);
+};
+
+/**
+ * C2Buffer: buffer base class. These are always used as shared_ptrs. Though the underlying buffer
+ * objects (native buffers, ion buffers, or dmabufs) are reference-counted by the system,
+ * C2Buffers hold only a single reference.
+ *
+ * These objects cannot be used on the stack.
+ */
+class C2Buffer {
+public:
+ /**
+ * Gets the buffer's data.
+ *
+ * \return the buffer's data.
+ */
+ const C2BufferData data() const;
+
+ /**
+ * These will still work if used in onDeathNotify.
+ */
+#if 0
+ inline std::shared_ptr<C2LinearBuffer> asLinearBuffer() const {
+ return mType == LINEAR ? std::shared_ptr::reinterpret_cast<C2LinearBuffer>(this) : nullptr;
+ }
+
+ inline std::shared_ptr<C2GraphicBuffer> asGraphicBuffer() const {
+ return mType == GRAPHIC ? std::shared_ptr::reinterpret_cast<C2GraphicBuffer>(this) : nullptr;
+ }
+
+ inline std::shared_ptr<C2CircularBuffer> asCircularBuffer() const {
+ return mType == CIRCULAR ? std::shared_ptr::reinterpret_cast<C2CircularBuffer>(this) : nullptr;
+ }
+#endif
+
+ ///@name Pre-destroy notification handling
+ ///@{
+
+ /**
+ * Register for notification just prior to the destruction of this object.
+ */
+ typedef void (*OnDestroyNotify) (const C2Buffer *buf, void *arg);
+
+ /**
+ * Registers for a pre-destroy notification. This is called just prior to the destruction of
+ * this buffer (when this buffer is no longer valid.)
+ *
+ * \param onDestroyNotify the notification callback
+ * \param arg an arbitrary parameter passed to the callback
+ *
+ * \retval C2_OK the registration was successful.
+ * \retval C2_DUPLICATE a notification was already registered for this callback and argument
+ * \retval C2_NO_MEMORY not enough memory to register for this callback
+ * \retval C2_CORRUPTED an unknown error prevented the registration (unexpected)
+ */
+ c2_status_t registerOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+
+ /**
+ * Unregisters a previously registered pre-destroy notification.
+ *
+ * \param onDestroyNotify the notification callback
+ * \param arg an arbitrary parameter passed to the callback
+ *
+ * \retval C2_OK the unregistration was successful.
+ * \retval C2_NOT_FOUND the notification was not found
+ * \retval C2_CORRUPTED an unknown error prevented the registration (unexpected)
+ */
+ c2_status_t unregisterOnDestroyNotify(OnDestroyNotify onDestroyNotify, void *arg = nullptr);
+
+ ///@}
+
+ virtual ~C2Buffer() = default;
+
+ ///@name Buffer-specific arbitrary metadata handling
+ ///@{
+
+ /**
+ * Gets the list of metadata associated with this buffer.
+ *
+ * \return a constant list of info objects associated with this buffer.
+ */
+ const std::vector<std::shared_ptr<const C2Info>> info() const;
+
+ /**
+ * Attaches (or updates) an (existing) metadata for this buffer.
+ * If the metadata is stream specific, the stream information will be reset.
+ *
+ * \param info Metadata to update
+ *
+ * \retval C2_OK the metadata was successfully attached/updated.
+ * \retval C2_NO_MEMORY not enough memory to attach the metadata (this return value is not
+ * used if the same kind of metadata is already attached to the buffer).
+ */
+ c2_status_t setInfo(const std::shared_ptr<C2Info> &info);
+
+ /**
+ * Checks if there is a certain type of metadata attached to this buffer.
+ *
+ * \param index the parameter type of the metadata
+ *
+ * \return true iff there is a metadata with the parameter type attached to this buffer.
+ */
+ bool hasInfo(C2Param::Type index) const;
+
+ /**
+ * Checks if there is a certain type of metadata attached to this buffer, and returns a
+ * shared pointer to it if there is. Returns an empty shared pointer object (nullptr) if there
+ * is not.
+ *
+ * \param index the parameter type of the metadata
+ *
+ * \return shared pointer to the metadata.
+ */
+ std::shared_ptr<const C2Info> getInfo(C2Param::Type index) const;
+
+ /**
+ * Removes a metadata from the buffer.
+ */
+ std::shared_ptr<C2Info> removeInfo(C2Param::Type index);
+ ///@}
+
+ /**
+ * Creates a buffer containing a single linear block.
+ *
+ * \param block the content of the buffer.
+ *
+ * \return shared pointer to the created buffer.
+ */
+ static std::shared_ptr<C2Buffer> CreateLinearBuffer(const C2ConstLinearBlock &block);
+
+ /**
+ * Creates a buffer containing a single graphic block.
+ *
+ * \param block the content of the buffer.
+ *
+ * \return shared pointer to the created buffer.
+ */
+ static std::shared_ptr<C2Buffer> CreateGraphicBuffer(const C2ConstGraphicBlock &block);
+
+
+
+protected:
+ // no public constructor
+ explicit C2Buffer(const std::vector<C2ConstLinearBlock> &blocks);
+ explicit C2Buffer(const std::vector<C2ConstGraphicBlock> &blocks);
+
+private:
+ class Impl;
+ std::shared_ptr<Impl> mImpl;
+// Type _mType;
+};
+
+/**
+ * An extension of C2Info objects that can contain arbitrary buffer data.
+ *
+ * \note This object is not describable and contains opaque data.
+ */
+class C2InfoBuffer {
+public:
+ /**
+ * Gets the index of this info object.
+ *
+ * \return the parameter index.
+ */
+ const C2Param::Index index() const;
+
+ /**
+ * Gets the buffer's data.
+ *
+ * \return the buffer's data.
+ */
+ const C2BufferData data() const;
+};
+
+/// @}
+
+/// \cond INTERNAL
+
+/// \todo These are no longer used
+
+/// \addtogroup linear
+/// @{
+
+/** \deprecated */
+class C2LinearBuffer
+ : public C2Buffer, public _C2LinearRangeAspect,
+ public std::enable_shared_from_this<C2LinearBuffer> {
+public:
+ /** \todo what is this? */
+ const C2Handle *handle() const;
+
+protected:
+ inline C2LinearBuffer(const C2ConstLinearBlock &block);
+
+private:
+ class Impl;
+ Impl *mImpl;
+};
+
+class C2ReadCursor;
+
+class C2WriteCursor {
+public:
+ uint32_t remaining() const; // remaining data to be read
+ void commit(); // commits the current position. discard data before current position
+ void reset() const; // resets position to the last committed position
+ // slices off at most |size| bytes, and moves cursor ahead by the number of bytes
+ // sliced off.
+ C2ReadCursor slice(uint32_t size) const;
+ // slices off at most |size| bytes, and moves cursor ahead by the number of bytes
+ // sliced off.
+ C2WriteCursor reserve(uint32_t size);
+ // bool read(T&);
+ // bool write(T&);
+ C2Fence waitForSpace(uint32_t size);
+};
+
+/// @}
+
+/// \addtogroup graphic
+/// @{
+
+struct C2ColorSpace {
+//public:
+ enum Standard {
+ BT601,
+ BT709,
+ BT2020,
+ // TODO
+ };
+
+ enum Range {
+ LIMITED,
+ FULL,
+ // TODO
+ };
+
+ enum TransferFunction {
+ BT709Transfer,
+ BT2020Transfer,
+ HybridLogGamma2,
+ HybridLogGamma4,
+ // TODO
+ };
+};
+
+/** \deprecated */
+class C2GraphicBuffer : public C2Buffer {
+public:
+ // constant attributes
+ inline uint32_t width() const { return mWidth; }
+ inline uint32_t height() const { return mHeight; }
+ inline uint32_t format() const { return mFormat; }
+ inline const C2MemoryUsage usage() const { return mUsage; }
+
+ // modifiable attributes
+
+
+ virtual const C2ColorSpace colorSpace() const = 0;
+ // best effort
+ virtual void setColorSpace_be(const C2ColorSpace &colorSpace) = 0;
+ virtual bool setColorSpace(const C2ColorSpace &colorSpace) = 0;
+
+ const C2Handle *handle() const;
+
+protected:
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint32_t mFormat;
+ C2MemoryUsage mUsage;
+
+ class Impl;
+ Impl *mImpl;
+};
+
+/// @}
+
+/// \endcond
+
+/// @}
+
+#endif // C2BUFFER_H_
diff --git a/media/codec2/include/C2BufferBase.h b/media/codec2/include/C2BufferBase.h
new file mode 100644
index 0000000..2bd48f0
--- /dev/null
+++ b/media/codec2/include/C2BufferBase.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef C2BUFFER_BASE_H_
+#define C2BUFFER_BASE_H_
+
+/// \defgroup allocator Allocation and memory placement
+/// @{
+
+/**
+ * Buffer/memory usage bits. These shall be used by the allocators to select optimal memory type/
+ * pool and buffer layout. Usage bits are conceptually separated into read and write usage, while
+ * the buffer use life-cycle is separated into producers (writers) and consumers (readers).
+ * These two concepts are related but not equivalent: consumers may only read buffers and only
+ * producers may write to buffers; note, however, that buffer producers may also want or need to
+ * read the buffers.
+ *
+ * Read and write buffer usage bits shall be or-ed to arrive at the full buffer usage. Admittedly,
+ * this does not account for the amount of reading and writing (e.g. a buffer may have one or more
+ * readers); however, the proper information necessary to properly weigh the various usages would be
+ * the amount of data read/written for each usage type. This would result in an integer array of
+ * size 64 (or the number of distinct usages) for memory usage, and likely such detailed information
+ * would not always be available.
+ *
+ * That platform-agnostic Codec 2.0 API only defines the bare minimum usages. Platforms shall define
+ * usage bits that are appropriate for the platform.
+ */
+struct C2MemoryUsage {
+// public:
+ /**
+ * Buffer read usage.
+ */
+ enum read_t : uint64_t {
+ /** Buffer is read by the CPU. */
+ CPU_READ = 1 << 0,
+ /**
+ * Buffer shall only be read by trusted hardware. The definition of trusted hardware is
+ * platform specific, but this flag is reserved to prevent mapping this block into CPU
+ * readable memory resulting in bus fault. This flag can be used when buffer access must be
+ * protected.
+ */
+ READ_PROTECTED = 1 << 1,
+ };
+
+ /**
+ * Buffer write usage.
+ */
+ enum write_t : uint64_t {
+ /** Buffer is writted to by the CPU. */
+ CPU_WRITE = 1 << 2,
+ /**
+ * Buffer shall only be written to by trusted hardware. The definition of trusted hardware
+ * is platform specific, but this flag is reserved to prevent mapping this block into CPU
+ * writable memory resulting in bus fault. This flag can be used when buffer integrity must
+ * be protected.
+ */
+ WRITE_PROTECTED = 1 << 3,
+ };
+
+ enum : uint64_t {
+ /**
+ * Buffer usage bits reserved for the platform. We don't separately reserve read and
+ * write usages as platforms may have asymmetric distribution between them.
+ */
+ PLATFORM_MASK = ~(CPU_READ | CPU_WRITE | READ_PROTECTED | WRITE_PROTECTED),
+ };
+
+ /** Create a usage from separate consumer and producer usage mask. \deprecated */
+ inline C2MemoryUsage(uint64_t consumer, uint64_t producer)
+ : expected(consumer | producer) { }
+
+ inline explicit C2MemoryUsage(uint64_t expected_)
+ : expected(expected_) { }
+
+ uint64_t expected; // expected buffer usage
+};
+
+/// @}
+
+#endif // C2BUFFER_BASE_H_
+
diff --git a/media/codec2/include/C2Component.h b/media/codec2/include/C2Component.h
new file mode 100644
index 0000000..8810725
--- /dev/null
+++ b/media/codec2/include/C2Component.h
@@ -0,0 +1,975 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef C2COMPONENT_H_
+
+#define C2COMPONENT_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <list>
+#include <memory>
+#include <vector>
+#include <functional>
+
+#include <C2Enum.h>
+#include <C2Param.h>
+#include <C2Work.h>
+
+/// \defgroup components Components
+/// @{
+
+struct C2FieldSupportedValuesQuery {
+ enum type_t : uint32_t {
+ POSSIBLE, ///< query all possible values regardless of other settings
+ CURRENT, ///< query currently possible values given dependent settings
+ };
+
+private:
+ C2ParamField _mField;
+ type_t _mType;
+public:
+ c2_status_t status;
+ C2FieldSupportedValues values;
+
+ C2FieldSupportedValuesQuery(const C2ParamField &field_, type_t type_)
+ : _mField(field_), _mType(type_), status(C2_NO_INIT) { }
+
+ static C2FieldSupportedValuesQuery
+ Current(const C2ParamField &field_) {
+ return C2FieldSupportedValuesQuery(field_, CURRENT);
+ }
+
+ static C2FieldSupportedValuesQuery
+ Possible(const C2ParamField &field_) {
+ return C2FieldSupportedValuesQuery(field_, POSSIBLE);
+ }
+
+ inline C2ParamField field() const { return _mField; };
+
+ inline type_t type() const { return _mType; }
+};
+
+/**
+ * Component interface object. This object contains all of the configuration of a potential or
+ * actual component. It can be created and used independently of an actual C2Component instance to
+ * query support and parameters for various component settings and configurations for a potential
+ * component. Actual components also expose this interface.
+ */
+
+class C2ComponentInterface {
+public:
+ // ALWAYS AVAILABLE METHODS
+ // =============================================================================================
+
+ /**
+ * Returns the name of this component or component interface object.
+ * This is a unique name for this component or component interface 'class'; however, multiple
+ * instances of this component SHALL have the same name.
+ *
+ * When attached to a component, this method MUST be supported in any component state.
+ * This call does not change the state nor the internal configuration of the component.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return the name of this component or component interface object.
+ * \retval an empty string if there was not enough memory to allocate the actual name.
+ */
+ virtual C2String getName() const = 0;
+
+ /**
+ * Returns a unique ID for this component or interface object.
+ * This ID is used as work targets, unique work IDs, and when configuring tunneling.
+ *
+ * When attached to a component, this method MUST be supported in any component state.
+ * This call does not change the state nor the internal configuration of the component.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return a unique node ID for this component or component interface instance.
+ */
+ virtual c2_node_id_t getId() const = 0;
+
+ /**
+ * Queries a set of parameters from the component or interface object.
+ * Querying is performed at best effort: the component SHALL query all supported parameters and
+ * skip unsupported ones, heap allocated parameters that could not be allocated or parameters
+ * that could not be queried without blocking. Any errors are communicated in the return value.
+ * Additionally, preallocated (e.g. stack) parameters that could not be queried are invalidated.
+ * Invalid or blocking parameters to be allocated on the heap are omitted from the result.
+ *
+ * \note Parameter values do not depend on the order of query.
+ *
+ * \todo This method cannot be used to query info-buffers. Is that a problem?
+ *
+ * When attached to a component, this method MUST be supported in any component state except
+ * released.
+ * This call does not change the state nor the internal configuration of the component.
+ *
+ * This method has a variable blocking behavior based on state.
+ * In the stopped state this method MUST be "non-blocking" and return within 1ms.
+ * In the running states this method may be momentarily blocking, but MUST return within 5ms.
+ *
+ * \param[in,out] stackParams a list of params queried. These are initialized specific to each
+ * setting; e.g. size and index are set and rest of the members are
+ * cleared.
+ * \note Flexible settings that are of incorrect size will be
+ * invalidated.
+ * \param[in] heapParamIndices a vector of param indices for params to be queried and returned
+ * on the heap. These parameters will be returned in heapParams.
+ * Unsupported param indices will be ignored.
+ * \param[in] mayBlock if true (C2_MAY_BLOCK), implementation may momentarily block.
+ * Otherwise (C2_DONT_BLOCK), it must be "non-blocking".
+ * \param[out] heapParams a list of params where to which the supported heap parameters
+ * will be appended in the order they appear in heapParamIndices.
+ *
+ * \retval C2_OK all parameters could be queried
+ * \retval C2_BAD_INDEX all supported parameters could be queried, but some parameters were not
+ * supported
+ * \retval C2_BAD_STATE when called in the released component state (user error)
+ * (this error code is only allowed for interfaces connected to components)
+ * \retval C2_NO_MEMORY could not allocate memory for a supported parameter
+ * \retval C2_BLOCKING the operation must block to complete but mayBlock is false
+ * (this error code is only allowed for interfaces connected to components)
+ * \retval C2_TIMED_OUT could not query the parameters within the time limit (unexpected)
+ * (this error code is only allowed for interfaces connected to components
+ * in the running state)
+ * \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
+ * (unexpected)
+ * (this error code is only allowed for interfaces connected to components)
+ */
+ virtual c2_status_t query_vb(
+ const std::vector<C2Param*> &stackParams,
+ const std::vector<C2Param::Index> &heapParamIndices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
+
+ /**
+ * Sets a set of parameters for the component or interface object.
+ *
+ * Tuning is performed at best effort: the component SHALL process the configuration updates in
+ * the order they appear in |params|. If any parameter update fails, the component shall
+ * communicate the failure in the return value and in |failures|, and still process the
+ * remaining parameters. Unsupported parameters are skipped, though they are communicated in
+ * ther return value. Most parameters are updated at best effort - such that even if client
+ * specifies an unsupported value for a field, the closest supported value is used. On the
+ * other hand, strict parameters only accept specific values for their fields, and if the client
+ * specifies an unsupported value, the parameter setting shall fail for that field.
+ * If the client tries to change the value of a field that requires momentary blocking without
+ * setting |mayBlock| to C2_MAY_BLOCK, that parameter shall also be skipped and a specific
+ * return value shall be used. Final values for all parameters set are propagated back to the
+ * caller in |params|.
+ *
+ * \note Parameter tuning DOES depend on the order of the tuning parameters. E.g. some parameter
+ * update may allow some subsequent values for further parameter updates.
+ *
+ * When attached to a component, this method MUST be supported in any component state except
+ * released.
+ *
+ * This method has a variable blocking behavior based on state.
+ * In the stopped state this method MUST be "non-blocking" and return within 1ms.
+ * In the running states this method may be momentarily blocking, but MUST return within 5ms.
+ *
+ * \param[in,out] params a list of parameter updates. These will be updated to the actual
+ * parameter values after the updates (this is because tuning is performed
+ * at best effort).
+ * \todo params that could not be updated are not marked here, so are
+ * confusing - are they "existing" values or intended to be configured
+ * values?
+ * \param[in] mayBlock if true (C2_MAY_BLOCK), implementation may momentarily block.
+ * Otherwise (C2_DONT_BLOCK), it must be "non-blocking".
+ * \param[out] failures a list of parameter failures and optional guidance
+ *
+ * \retval C2_OK all parameters could be updated successfully
+ * \retval C2_BAD_INDEX all supported parameters could be updated successfully, but some
+ * parameters were not supported
+ * \retval C2_BAD_VALUE some supported parameters could not be updated successfully because
+ * they contained unsupported values. These are returned in |failures|.
+ * \retval C2_BAD_STATE when called in the released component state (user error)
+ * (this error code is only allowed for interfaces connected to components)
+ * \retval C2_NO_MEMORY some supported parameters could not be updated successfully because
+ * they contained unsupported values, but could not allocate a failure
+ * object for them.
+ * \retval C2_TIMED_OUT could not set the parameters within the time limit (unexpected)
+ * (this error code is only allowed for interfaces connected to components
+ * in the running state)
+ * \retval C2_BLOCKING the operation must block to complete but mayBlock is false
+ * (this error code is only allowed for interfaces connected to components)
+ * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
+ * (unexpected)
+ * (this error code is only allowed for interfaces connected to components)
+ */
+ virtual c2_status_t config_vb(
+ const std::vector<C2Param*> ¶ms,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+
+ // TUNNELING
+ // =============================================================================================
+
+ /**
+ * Creates a tunnel from this component to the target component.
+ *
+ * If the component is successfully created, subsequent work items queued may include a
+ * tunneled path between these components.
+ *
+ * When attached to a component, this method MUST be supported in any component state except
+ * released.
+ *
+ * This method may be momentarily blocking, but MUST return within 5ms.
+ *
+ * \retval C2_OK the tunnel was successfully created
+ * \retval C2_BAD_INDEX the target component does not exist
+ * \retval C2_DUPLICATE the tunnel already exists
+ * \retval C2_OMITTED tunneling is not supported by this component
+ * \retval C2_CANNOT_DO the specific tunnel is not supported
+ * \retval C2_BAD_STATE when called in the released component state (user error)
+ * (this error code is only allowed for interfaces connected to components)
+ *
+ * \retval C2_TIMED_OUT could not create the tunnel within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented the creation of the tunnel (unexpected)
+ * (this error code is only allowed for interfaces connected to components)
+ */
+ virtual c2_status_t createTunnel_sm(c2_node_id_t targetComponent) = 0;
+
+ /**
+ * Releases a tunnel from this component to the target component.
+ *
+ * The release of a tunnel is delayed while there are pending work items for the tunnel.
+ * After releasing a tunnel, subsequent work items queued MUST NOT include a tunneled
+ * path between these components.
+ *
+ * When attached to a component, this method MUST be supported in any component state except
+ * released.
+ *
+ * This method may be momentarily blocking, but MUST return within 5ms.
+ *
+ * \retval C2_OK the tunnel was marked for release successfully
+ * \retval C2_BAD_INDEX the target component does not exist
+ * \retval C2_NOT_FOUND the tunnel does not exist
+ * \retval C2_OMITTED tunneling is not supported by this component
+ * \retval C2_BAD_STATE when called in the released component state (user error)
+ * (this error code is only allowed for interfaces connected to components)
+ *
+ * \retval C2_TIMED_OUT could not mark the tunnel for release within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented the release of the tunnel (unexpected)
+ * (this error code is only allowed for interfaces connected to components)
+ */
+ virtual c2_status_t releaseTunnel_sm(c2_node_id_t targetComponent) = 0;
+
+ // REFLECTION MECHANISM (USED FOR EXTENSION)
+ // =============================================================================================
+
+ /**
+ * Returns the set of supported parameters.
+ *
+ * When attached to a component, this method MUST be supported in any component state except
+ * released.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \param[out] params a vector of supported parameters will be appended to this vector.
+ *
+ * \retval C2_OK the operation completed successfully.
+ * \retval C2_BAD_STATE when called in the released component state (user error)
+ * (this error code is only allowed for interfaces connected to components)
+ * \retval C2_NO_MEMORY not enough memory to complete this method.
+ */
+ virtual c2_status_t querySupportedParams_nb(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const = 0;
+
+ /**
+ * Retrieves the supported values for the queried fields.
+ *
+ * Client SHALL set the parameter-field specifier and the type of supported values query (e.g.
+ * currently supported values, or potential supported values) in fields.
+ * Upon return the component SHALL fill in the supported values for the fields listed as well
+ * as a status for each field. Component shall process all fields queried even if some queries
+ * fail.
+ *
+ * When attached to a component, this method MUST be supported in any component state except
+ * released.
+ *
+ * This method has a variable blocking behavior based on state.
+ * In the stopped state this method MUST be "non-blocking" and return within 1ms.
+ * In the running states this method may be momentarily blocking, but MUST return within 5ms.
+ *
+ * \param[in out] fields a vector of fields descriptor structures.
+ * \param[in] mayBlock if true (C2_MAY_BLOCK), implementation may momentarily block.
+ * Otherwise (C2_DONT_BLOCK), it must be "non-blocking".
+ *
+ * \retval C2_OK the operation completed successfully.
+ * \retval C2_BAD_STATE when called in the released component state (user error)
+ * (this error code is only allowed for interfaces connected to components)
+ * \retval C2_BAD_INDEX at least one field was not recognized as a component field
+ * \retval C2_TIMED_OUT could not query supported values within the time limit (unexpected)
+ * (this error code is only allowed for interfaces connected to components
+ * in the running state)
+ * \retval C2_BLOCKING the operation must block to complete but mayBlock is false
+ * (this error code is only allowed for interfaces connected to components)
+ * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
+ * (this error code is only allowed for interfaces connected to components)
+ */
+ virtual c2_status_t querySupportedValues_vb(
+ std::vector<C2FieldSupportedValuesQuery> &fields, c2_blocking_t mayBlock) const = 0;
+
+ virtual ~C2ComponentInterface() = default;
+};
+
+class C2Component {
+public:
+ class Listener {
+ public:
+ virtual void onWorkDone_nb(std::weak_ptr<C2Component> component,
+ std::list<std::unique_ptr<C2Work>> workItems) = 0;
+
+ virtual void onTripped_nb(std::weak_ptr<C2Component> component,
+ std::vector<std::shared_ptr<C2SettingResult>> settingResult) = 0;
+
+ virtual void onError_nb(std::weak_ptr<C2Component> component,
+ uint32_t errorCode) = 0;
+
+ // virtual void onTunnelReleased(<from>, <to>) = 0;
+
+ // virtual void onComponentReleased(<id>) = 0;
+
+ virtual ~Listener() = default;
+ };
+
+ /**
+ * Sets the listener for this component
+ *
+ * This method MUST be supported in all states except released.
+ * The listener can only be set to non-null value in stopped state (that does not include
+ * tripped or error). It can be set to nullptr in both stopped and running states.
+ * Components only use the listener in running state.
+ *
+ * If listener is nullptr, the component SHALL guarantee that no more listener callbacks are
+ * done to the original listener once this method returns. (Any pending listener callbacks will
+ * need to be completed during this call - hence this call may be temporarily blocking.)
+ *
+ * This method has a variable blocking behavior based on state.
+ * In the stopped state this method MUST be "non-blocking" and return within 1ms.
+ * In the running states this method may be momentarily blocking, but MUST return within 5ms.
+ *
+ * Component SHALL handle listener notifications from the same thread (the thread used is
+ * at the component's discretion.)
+ *
+ * \note This could also be accomplished by passing a weak_ptr to a component-specific listener
+ * here and requiring the client to always promote the weak_ptr before any callback. This would
+ * put the burden on the client to clear the listener - wait for its deletion - at which point
+ * it is guaranteed that no more listener callbacks will occur.
+ *
+ * \param[in] listener the component listener object
+ * \param[in] mayBlock if true (C2_MAY_BLOCK), implementation may momentarily block.
+ * Otherwise (C2_DONT_BLOCK), it must be "non-blocking".
+ *
+ * \retval C2_BAD_STATE attempting to change the listener in the running state to a non-null
+ * value (user error), or called in the released state
+ * \retval C2_BLOCKING the operation must block to complete but mayBlock is false
+ * \retval C2_OK listener was updated successfully.
+ */
+ virtual c2_status_t setListener_vb(
+ const std::shared_ptr<Listener> &listener, c2_blocking_t mayBlock) = 0;
+
+ /// component domain (e.g. audio or video)
+ enum domain_t : uint32_t;
+
+ /// component kind (e.g. encoder, decoder or filter)
+ enum kind_t : uint32_t;
+
+ /// component rank. This number is used to determine component ordering (the lower the sooner)
+ /// in the component list.
+ typedef uint32_t rank_t;
+
+ /// component attributes
+ enum attrib_t : uint64_t;
+
+ /**
+ * Information about a component.
+ */
+ struct Traits {
+ // public:
+ C2String name; ///< name of the component
+ domain_t domain; ///< component domain
+ kind_t kind; ///< component kind
+ rank_t rank; ///< component rank
+ C2String mediaType; ///< media type supported by the component
+
+ /**
+ * name alias(es) for backward compatibility.
+ * \note Multiple components can have the same alias as long as their media-type differs.
+ */
+ std::vector<C2StringLiteral> aliases; ///< name aliases for backward compatibility
+ };
+
+ // METHODS AVAILABLE WHEN RUNNING
+ // =============================================================================================
+
+ /**
+ * Queues up work for the component.
+ *
+ * This method MUST be supported in running (including tripped and error) states.
+ *
+ * This method MUST be "non-blocking" and return within 1 ms
+ *
+ * It is acceptable for this method to return OK and return an error value using the
+ * onWorkDone() callback.
+ *
+ * \retval C2_OK the work was successfully queued
+ * \retval C2_BAD_INDEX some component(s) in the work do(es) not exist
+ * \retval C2_CANNOT_DO the components are not tunneled
+ * \retval C2_BAD_STATE when called in the stopped or released state (user error)
+ *
+ * \retval C2_NO_MEMORY not enough memory to queue the work
+ * \retval C2_CORRUPTED some unknown error prevented queuing the work (unexpected)
+ */
+ virtual c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) = 0;
+
+ /**
+ * Announces a work to be queued later for the component. This reserves a slot for the queue
+ * to ensure correct work ordering even if the work is queued later.
+ *
+ * This method MUST be supported in running (including tripped and error) states.
+ *
+ * This method MUST be "non-blocking" and return within 1 ms
+ *
+ * \retval C2_OK the work announcement has been successfully recorded
+ * \retval C2_BAD_INDEX some component(s) in the work outline do(es) not exist
+ * \retval C2_CANNOT_DO the componentes are not tunneled
+ * \retval C2_BAD_STATE when called in the stopped or released state (user error)
+ *
+ * \retval C2_NO_MEMORY not enough memory to record the work announcement
+ * \retval C2_CORRUPTED some unknown error prevented recording the announcement (unexpected)
+ *
+ * \todo Can this be rolled into queue_nb?
+ * \todo Expose next work item for each component to detect stalls
+ */
+ virtual c2_status_t announce_nb(const std::vector<C2WorkOutline> &items) = 0;
+
+ enum flush_mode_t : uint32_t {
+ /// flush work from this component only
+ FLUSH_COMPONENT,
+
+ /// flush work from this component and all components connected downstream from it via
+ /// tunneling
+ FLUSH_CHAIN = (1 << 16),
+ };
+
+ /**
+ * Discards and abandons any pending work for the component, and optionally any component
+ * downstream.
+ *
+ * \todo define this: we could flush all work before last item queued for component across all
+ * components linked to this; flush only work items that are queued to this
+ * component
+ * \todo return work # of last flushed item; or all flushed (but not returned items)
+ * \todo we could make flush take a work item and flush all work before/after that item to allow
+ * TBD (slicing/seek?)
+ * \todo we could simply take a list of numbers and flush those... this is bad for decoders
+ * also, what would happen to fine grade references?
+ *
+ * This method MUST be supported in running (including tripped and error) states.
+ *
+ * This method may be momentarily blocking, but must return within 5ms.
+ *
+ * Work that could be immediately abandoned/discarded SHALL be returned in |flushedWork|; this
+ * can be done in an arbitrary order.
+ *
+ * Work that could not be abandoned or discarded immediately SHALL be marked to be
+ * discarded at the earliest opportunity, and SHALL be returned via the onWorkDone() callback.
+ * This shall be completed within 500ms.
+ *
+ * \param mode flush mode
+ *
+ * \retval C2_OK the component has been successfully flushed
+ * \retval C2_BAD_STATE when called in the stopped or released state (user error)
+ * \retval C2_TIMED_OUT the flush could not be completed within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented flushing from completion (unexpected)
+ */
+ virtual c2_status_t flush_sm(flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
+
+ enum drain_mode_t : uint32_t {
+ /// drain component only and add an "end-of-stream" marker. Component shall process all
+ /// queued work and complete the current stream. If new input is received, it shall start
+ /// a new stream. \todo define what a stream is.
+ DRAIN_COMPONENT_WITH_EOS,
+ /// drain component without setting "end-of-stream" marker. Component shall process all
+ /// queued work but shall expect more work items for the same stream.
+ DRAIN_COMPONENT_NO_EOS = (1 << 0),
+
+ /// marks the last work item with a persistent "end-of-stream" marker that will drain
+ /// downstream components
+ /// \todo this may confuse work-ordering downstream
+ DRAIN_CHAIN = (1 << 16),
+
+ /**
+ * \todo define this; we could place EOS to all upstream components, just this component, or
+ * all upstream and downstream component.
+ * \todo should EOS carry over to downstream components?
+ */
+ };
+
+ /**
+ * Drains the component, and optionally downstream components. This is a signalling method;
+ * as such it does not wait for any work completion.
+ *
+ * Marks last work item as "drain-till-here", so component is notified not to wait for further
+ * work before it processes work already queued. This method can also used to set the
+ * end-of-stream flag after work has been queued. Client can continue to queue further work
+ * immediately after this method returns.
+ *
+ * This method MUST be supported in running (including tripped) states.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * Work that is completed SHALL be returned via the onWorkDone() callback.
+ *
+ * \param mode drain mode
+ *
+ * \retval C2_OK the drain request has been successfully recorded
+ * \retval C2_BAD_STATE when called in the stopped or released state (user error)
+ * \retval C2_BAD_VALUE the drain mode is not supported by the component
+ * \todo define supported modes discovery
+ * \retval C2_TIMED_OUT the flush could not be completed within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented flushing from completion (unexpected)
+ */
+ virtual c2_status_t drain_nb(drain_mode_t mode) = 0;
+
+ // STATE CHANGE METHODS
+ // =============================================================================================
+
+ /**
+ * Starts the component.
+ *
+ * This method MUST be supported in stopped state, as well as during the tripped state.
+ *
+ * If the return value is C2_OK, the component shall be in the running state.
+ * If the return value is C2_BAD_STATE or C2_DUPLICATE, no state change is expected as a
+ * response to this call.
+ * Otherwise, the component shall be in the stopped state.
+ *
+ * \note If a component is in the tripped state and start() is called while the component
+ * configuration still results in a trip, start shall succeed and a new onTripped callback
+ * should be used to communicate the configuration conflict that results in the new trip.
+ *
+ * \todo This method MUST return within 500ms. Seems this should be able to return quickly, as
+ * there are no immediate guarantees. Though there are guarantees for responsiveness immediately
+ * after start returns.
+ *
+ * \retval C2_OK the component has started (or resumed) successfully
+ * \retval C2_DUPLICATE when called during another start call from another thread
+ * \retval C2_BAD_STATE when called in any state other than the stopped state or tripped state,
+ * including when called during another state change call from another
+ * thread (user error)
+ * \retval C2_NO_MEMORY not enough memory to start the component
+ * \retval C2_TIMED_OUT the component could not be started within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented starting the component (unexpected)
+ */
+ virtual c2_status_t start() = 0;
+
+ /**
+ * Stops the component.
+ *
+ * This method MUST be supported in running (including tripped) state.
+ *
+ * This method MUST return withing 500ms.
+ *
+ * Upon this call, all pending work SHALL be abandoned and all buffer references SHALL be
+ * released.
+ * If the return value is C2_BAD_STATE or C2_DUPLICATE, no state change is expected as a
+ * response to this call.
+ * For all other return values, the component shall be in the stopped state.
+ *
+ * \todo should this return completed work, since client will just free it? Perhaps just to
+ * verify accounting.
+ *
+ * This does not alter any settings and tunings that may have resulted in a tripped state.
+ * (Is this material given the definition? Perhaps in case we want to start again.)
+ *
+ * \retval C2_OK the component has started successfully
+ * \retval C2_DUPLICATE when called during another stop call from another thread
+ * \retval C2_BAD_STATE when called in any state other than the running state, including when
+ * called during another state change call from another thread (user error)
+ * \retval C2_TIMED_OUT the component could not be stopped within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented stopping the component (unexpected)
+ */
+ virtual c2_status_t stop() = 0;
+
+ /**
+ * Resets the component.
+ *
+ * This method MUST be supported in all (including tripped) states other than released.
+ *
+ * This method MUST be supported during any other blocking call.
+ *
+ * This method MUST return withing 500ms.
+ *
+ * After this call returns all work SHALL be abandoned, all buffer references SHALL be released.
+ * If the return value is C2_BAD_STATE or C2_DUPLICATE, no state change is expected as a
+ * response to this call.
+ * For all other return values, the component shall be in the stopped state.
+ *
+ * \todo should this return completed work, since client will just free it? Also, if it unblocks
+ * a stop, where should completed work be returned?
+ *
+ * This brings settings back to their default - "guaranteeing" no tripped space.
+ *
+ * \todo reclaim support - it seems that since ownership is passed, this will allow reclaiming
+ * stuff.
+ *
+ * \retval C2_OK the component has been reset
+ * \retval C2_DUPLICATE when called during another reset call from another thread
+ * \retval C2_BAD_STATE when called in the released state
+ * \retval C2_TIMED_OUT the component could not be reset within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented resetting the component (unexpected)
+ */
+ virtual c2_status_t reset() = 0;
+
+ /**
+ * Releases the component.
+ *
+ * This method MUST be supported in stopped state.
+ *
+ * This method MUST return withing 500ms. Upon return all references shall be abandoned.
+ *
+ * \retval C2_OK the component has been released
+ * \retval C2_DUPLICATE the component is already released
+ * \retval C2_BAD_STATE the component is running
+ * \retval C2_TIMED_OUT the component could not be released within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented releasing the component (unexpected)
+ */
+ virtual c2_status_t release() = 0;
+
+ /**
+ * Returns the interface for this component.
+ *
+ * \return the component interface
+ */
+ virtual std::shared_ptr<C2ComponentInterface> intf() = 0;
+
+ virtual ~C2Component() = default;
+};
+
+C2ENUM(C2Component::kind_t, uint32_t,
+ KIND_OTHER,
+ KIND_DECODER,
+ KIND_ENCODER
+);
+
+C2ENUM(C2Component::domain_t, uint32_t,
+ DOMAIN_OTHER,
+ DOMAIN_VIDEO,
+ DOMAIN_AUDIO,
+ DOMAIN_IMAGE
+);
+
+class C2FrameInfoParser {
+public:
+ /**
+ * \return the content type supported by this info parser.
+ *
+ * \todo this may be redundant
+ */
+ virtual C2StringLiteral getType() const = 0;
+
+ /**
+ * \return a vector of supported parameter indices parsed by this info parser.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \todo sticky vs. non-sticky params? this may be communicated by param-reflector.
+ */
+ virtual const std::vector<C2Param::Index> getParsedParams() const = 0;
+
+ /**
+ * Resets this info parser. This brings this parser to its initial state after creation.
+ *
+ * This method SHALL return within 5ms.
+ *
+ * \retval C2_OK the info parser was reset
+ * \retval C2_TIMED_OUT could not reset the parser within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented the resetting of the parser (unexpected)
+ */
+ virtual c2_status_t reset() { return C2_OK; }
+
+ virtual c2_status_t parseFrame(C2FrameData &frame);
+
+ virtual ~C2FrameInfoParser() = default;
+};
+
+class C2AllocatorStore {
+public:
+ typedef C2Allocator::id_t id_t;
+
+ enum : C2Allocator::id_t {
+ DEFAULT_LINEAR, ///< basic linear allocator type
+ DEFAULT_GRAPHIC, ///< basic graphic allocator type
+ PLATFORM_START = 0x10,
+ VENDOR_START = 0x100,
+ BAD_ID = C2Allocator::BAD_ID, ///< DO NOT USE
+ };
+
+ /**
+ * Returns the unique name of this allocator store.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return the name of this allocator store.
+ * \retval an empty string if there was not enough memory to allocate the actual name.
+ */
+ virtual C2String getName() const = 0;
+
+ /**
+ * Returns the set of allocators supported by this allocator store.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \retval vector of allocator information (as shared pointers)
+ * \retval an empty vector if there was not enough memory to allocate the whole vector.
+ */
+ virtual std::vector<std::shared_ptr<const C2Allocator::Traits>> listAllocators_nb() const = 0;
+
+ /**
+ * Retrieves/creates a shared allocator object.
+ *
+ * This method MUST be return within 5ms.
+ *
+ * The allocator is created on first use, and the same allocator is returned on subsequent
+ * concurrent uses in the same process. The allocator is freed when it is no longer referenced.
+ *
+ * \param id the ID of the allocator to create. This is defined by the store, but
+ * the ID of the default linear and graphic allocators is formalized.
+ * \param allocator shared pointer where the created allocator is stored. Cleared on failure
+ * and updated on success.
+ *
+ * \retval C2_OK the allocator was created successfully
+ * \retval C2_TIMED_OUT could not create the allocator within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented the creation of the allocator (unexpected)
+ *
+ * \retval C2_NOT_FOUND no such allocator
+ * \retval C2_NO_MEMORY not enough memory to create the allocator
+ */
+ virtual c2_status_t fetchAllocator(id_t id, std::shared_ptr<C2Allocator>* const allocator) = 0;
+
+ virtual ~C2AllocatorStore() = default;
+};
+
+class C2ComponentStore {
+public:
+ /**
+ * Returns the name of this component or component interface object.
+ * This is a unique name for this component or component interface 'class'; however, multiple
+ * instances of this component SHALL have the same name.
+ *
+ * This method MUST be supported in any state. This call does not change the state nor the
+ * internal states of the component.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return the name of this component or component interface object.
+ * \retval an empty string if there was not enough memory to allocate the actual name.
+ */
+ virtual C2String getName() const = 0;
+
+ /**
+ * Creates a component.
+ *
+ * This method SHALL return within 100ms.
+ *
+ * \param name name of the component to create
+ * \param component shared pointer where the created component is stored. Cleared on
+ * failure and updated on success.
+ *
+ * \retval C2_OK the component was created successfully
+ * \retval C2_TIMED_OUT could not create the component within the time limit (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented the creation of the component (unexpected)
+ *
+ * \retval C2_NOT_FOUND no such component
+ * \retval C2_NO_MEMORY not enough memory to create the component
+ */
+ virtual c2_status_t createComponent(
+ C2String name, std::shared_ptr<C2Component>* const component) = 0;
+
+ /**
+ * Creates a component interface.
+ *
+ * This method SHALL return within 100ms.
+ *
+ * \param name name of the component interface to create
+ * \param interface shared pointer where the created interface is stored
+ *
+ * \retval C2_OK the component interface was created successfully
+ * \retval C2_TIMED_OUT could not create the component interface within the time limit
+ * (unexpected)
+ * \retval C2_CORRUPTED some unknown error prevented the creation of the component interface
+ * (unexpected)
+ *
+ * \retval C2_NOT_FOUND no such component interface
+ * \retval C2_NO_MEMORY not enough memory to create the component interface
+ *
+ * \todo Do we need an interface, or could this just be a component that is never started?
+ */
+ virtual c2_status_t createInterface(
+ C2String name, std::shared_ptr<C2ComponentInterface>* const interface) = 0;
+
+ /**
+ * Returns the list of components supported by this component store.
+ *
+ * This method MUST return within 500ms.
+ *
+ * \retval vector of component information.
+ */
+ virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() = 0;
+
+ // -------------------------------------- UTILITY METHODS --------------------------------------
+
+ // on-demand buffer layout conversion (swizzling)
+ //
+ virtual c2_status_t copyBuffer(
+ std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) = 0;
+
+ // -------------------------------------- CONFIGURATION API -----------------------------------
+ // e.g. for global settings (system-wide stride, etc.)
+
+ /**
+ * Queries a set of system-wide parameters.
+ * Querying is performed at best effort: the store SHALL query all supported parameters and
+ * skip unsupported ones, or heap allocated parameters that could not be allocated. Any errors
+ * are communicated in the return value. Additionally, preallocated (e.g. stack) parameters that
+ * could not be queried are invalidated. Parameters to be allocated on the heap are omitted from
+ * the result.
+ *
+ * \note Parameter values do not depend on the order of query.
+ *
+ * This method may be momentarily blocking, but MUST return within 5ms.
+ *
+ * \param stackParams a list of params queried. These are initialized specific to each
+ * setting; e.g. size and index are set and rest of the members are
+ * cleared.
+ * NOTE: Flexible settings that are of incorrect size will be invalidated.
+ * \param heapParamIndices a vector of param indices for params to be queried and returned on the
+ * heap. These parameters will be returned in heapParams. Unsupported param
+ * indices will be ignored.
+ * \param heapParams a list of params where to which the supported heap parameters will be
+ * appended in the order they appear in heapParamIndices.
+ *
+ * \retval C2_OK all parameters could be queried
+ * \retval C2_BAD_INDEX all supported parameters could be queried, but some parameters were not
+ * supported
+ * \retval C2_NO_MEMORY could not allocate memory for a supported parameter
+ * \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
+ * (unexpected)
+ */
+ virtual c2_status_t query_sm(
+ const std::vector<C2Param*> &stackParams,
+ const std::vector<C2Param::Index> &heapParamIndices,
+ std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
+
+ /**
+ * Sets a set of system-wide parameters.
+ *
+ * \note There are no settable system-wide parameters defined thus far, but may be added in the
+ * future.
+ *
+ * Tuning is performed at best effort: the store SHALL update all supported configuration at
+ * best effort (unless configured otherwise) and skip unsupported ones. Any errors are
+ * communicated in the return value and in |failures|.
+ *
+ * \note Parameter tuning DOES depend on the order of the tuning parameters. E.g. some parameter
+ * update may allow some subsequent parameter update.
+ *
+ * This method may be momentarily blocking, but MUST return within 5ms.
+ *
+ * \param params a list of parameter updates. These will be updated to the actual
+ * parameter values after the updates (this is because tuning is performed
+ * at best effort).
+ * \todo params that could not be updated are not marked here, so are
+ * confusing - are they "existing" values or intended to be configured
+ * values?
+ * \param failures a list of parameter failures
+ *
+ * \retval C2_OK all parameters could be updated successfully
+ * \retval C2_BAD_INDEX all supported parameters could be updated successfully, but some
+ * parameters were not supported
+ * \retval C2_BAD_VALUE some supported parameters could not be updated successfully because
+ * they contained unsupported values. These are returned in |failures|.
+ * \retval C2_NO_MEMORY some supported parameters could not be updated successfully because
+ * they contained unsupported values, but could not allocate a failure
+ * object for them.
+ * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
+ * (unexpected)
+ */
+ virtual c2_status_t config_sm(
+ const std::vector<C2Param*> ¶ms,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+
+ // REFLECTION MECHANISM (USED FOR EXTENSION)
+ // =============================================================================================
+
+ /**
+ * Returns the parameter reflector.
+ *
+ * This is used to describe parameter fields. This is shared for all components created by
+ * this component store.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \return a shared parameter reflector object.
+ */
+ virtual std::shared_ptr<C2ParamReflector> getParamReflector() const = 0;
+
+ /**
+ * Returns the set of supported parameters.
+ *
+ * This method MUST be "non-blocking" and return within 1ms.
+ *
+ * \param[out] params a vector of supported parameters will be appended to this vector.
+ *
+ * \retval C2_OK the operation completed successfully.
+ * \retval C2_NO_MEMORY not enough memory to complete this method.
+ */
+ virtual c2_status_t querySupportedParams_nb(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const = 0;
+
+ /**
+ * Retrieves the supported values for the queried fields.
+ *
+ * Client SHALL set the parameter-field specifier and the type of supported values query (e.g.
+ * currently supported values, or potential supported values) in fields.
+ * Upon return the store SHALL fill in the supported values for the fields listed as well
+ * as a status for each field. Store shall process all fields queried even if some queries
+ * fail.
+ *
+ * This method may be momentarily blocking, but MUST return within 5ms.
+ *
+ * \param[in out] fields a vector of fields descriptor structures.
+ *
+ * \retval C2_OK the operation completed successfully.
+ * \retval C2_BAD_INDEX at least one field was not recognized as a component store field
+ */
+ virtual c2_status_t querySupportedValues_sm(
+ std::vector<C2FieldSupportedValuesQuery> &fields) const = 0;
+
+ virtual ~C2ComponentStore() = default;
+};
+
+// ================================================================================================
+
+/// @}
+
+#endif // C2COMPONENT_H_
diff --git a/media/codec2/include/C2Config.h b/media/codec2/include/C2Config.h
new file mode 100644
index 0000000..799ade4
--- /dev/null
+++ b/media/codec2/include/C2Config.h
@@ -0,0 +1,2179 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef C2CONFIG_H_
+#define C2CONFIG_H_
+
+#include <C2.h>
+#include <C2Component.h>
+#include <C2Enum.h>
+#include <C2ParamDef.h>
+
+/// \defgroup config Component configuration
+/// @{
+
+/**
+ * Enumerated boolean.
+ */
+C2ENUM(c2_bool_t, uint32_t,
+ C2_FALSE, ///< true
+ C2_TRUE, ///< false
+)
+
+typedef C2SimpleValueStruct<c2_bool_t> C2BoolValue;
+
+typedef C2SimpleValueStruct<C2EasyEnum<c2_bool_t>> C2EasyBoolValue;
+
+/**
+ * Enumerated set tri-state.
+ *
+ * Used for optional configurations to distinguish between values set by the client,
+ * default values set by the component, or unset values.
+ */
+C2ENUM(c2_set_t, uint32_t,
+ C2_UNSET, // parameter is unset and has no value
+ C2_SET, // parameter is/has been set by the client
+ C2_DEFAULT, // parameter has not been set by the client, but is set by the component
+)
+
+/** Enumerations used by configuration parameters */
+struct C2Config {
+ enum aac_packaging_t : uint32_t; ///< AAC packaging (RAW vs ADTS)
+ enum aac_sbr_mode_t : uint32_t; ///< AAC SBR mode
+ enum api_feature_t : uint64_t; ///< API features
+ enum api_level_t : uint32_t; ///< API level
+ enum bitrate_mode_t : uint32_t; ///< bitrate control mode
+ enum drc_compression_mode_t : int32_t; ///< DRC compression mode
+ enum drc_effect_type_t : int32_t; ///< DRC effect type
+ enum intra_refresh_mode_t : uint32_t; ///< intra refresh modes
+ enum level_t : uint32_t; ///< coding level
+ enum ordinal_key_t : uint32_t; ///< work ordering keys
+ enum pcm_encoding_t : uint32_t; ///< PCM encoding
+ enum picture_type_t : uint32_t; ///< picture types
+ enum platform_feature_t : uint64_t; ///< platform features
+ enum platform_level_t : uint32_t; ///< platform level
+ enum prepend_header_mode_t : uint32_t; ///< prepend header operational modes
+ enum profile_t : uint32_t; ///< coding profile
+ enum scaling_method_t : uint32_t; ///< scaling methods
+ enum scan_order_t : uint32_t; ///< scan orders
+ enum secure_mode_t : uint32_t; ///< secure/protected modes
+ enum supplemental_info_t : uint32_t; ///< supplemental information types
+ enum tiling_mode_t : uint32_t; ///< tiling modes
+};
+
+namespace {
+
+enum C2ParamIndexKind : C2Param::type_index_t {
+ C2_PARAM_INDEX_INVALID = 0x0, ///< do not use
+ C2_PARAM_INDEX_STRUCT_START = 0x1, ///< struct only indices
+ C2_PARAM_INDEX_PARAM_START = 0x800, ///< regular parameters
+ C2_PARAM_INDEX_CODER_PARAM_START = 0x1000, ///< en/transcoder parameters
+ C2_PARAM_INDEX_PICTURE_PARAM_START = 0x1800, ///< image/video parameters
+ C2_PARAM_INDEX_VIDEO_PARAM_START = 0x2000, ///< video parameters
+ C2_PARAM_INDEX_IMAGE_PARAM_START = 0x2800, ///< image parameters
+ C2_PARAM_INDEX_AUDIO_PARAM_START = 0x3000, ///< image parameters
+ C2_PARAM_INDEX_PLATFORM_START = 0x4000, ///< platform-defined parameters
+
+ /* =================================== structure indices =================================== */
+
+ kParamIndexColorXy = C2_PARAM_INDEX_STRUCT_START,
+ kParamIndexMasteringDisplayColorVolume,
+ kParamIndexChromaOffset,
+ kParamIndexGopLayer,
+
+ /* =================================== parameter indices =================================== */
+
+ kParamIndexApiLevel = C2_PARAM_INDEX_PARAM_START,
+ kParamIndexApiFeatures,
+
+ /* ------------------------------------ all components ------------------------------------ */
+
+ /* generic component characteristics */
+ kParamIndexName,
+ kParamIndexAliases,
+ kParamIndexKind,
+ kParamIndexDomain,
+ kParamIndexAttributes,
+ kParamIndexTimeStretch,
+
+ /* coding characteristics */
+ kParamIndexProfileLevel,
+ kParamIndexInitData,
+ kParamIndexSupplementalData,
+ kParamIndexSubscribedSupplementalData,
+
+ /* pipeline characteristics */
+ kParamIndexMediaType,
+ kParamIndexDelayRequest,
+ kParamIndexDelay,
+ kParamIndexMaxReferenceAge,
+ kParamIndexMaxReferenceCount,
+ kParamIndexReorderBufferDepth,
+ kParamIndexReorderKey,
+ kParamIndexStreamCount,
+ kParamIndexSubscribedParamIndices,
+ kParamIndexSuggestedBufferCount,
+ kParamIndexBatchSize,
+ kParamIndexCurrentWork,
+ kParamIndexLastWorkQueued,
+
+ /* memory allocation */
+ kParamIndexAllocators,
+ kParamIndexBlockPools,
+ kParamIndexBufferType,
+ kParamIndexUsage,
+ kParamIndexOutOfMemory,
+ kParamIndexMaxBufferSize,
+
+ /* misc. state */
+ kParamIndexTripped,
+ kParamIndexConfigCounter,
+
+ /* resources */
+ kParamIndexResourcesNeeded,
+ kParamIndexResourcesReserved,
+ kParamIndexOperatingRate,
+ kParamIndexRealTimePriority,
+
+ /* protected content */
+ kParamIndexSecureMode,
+
+ /* ------------------------------------ (trans/en)coders ------------------------------------ */
+
+ kParamIndexBitrate = C2_PARAM_INDEX_CODER_PARAM_START,
+ kParamIndexBitrateMode,
+ kParamIndexQuality,
+ kParamIndexComplexity,
+ kParamIndexPrependHeaderMode,
+
+ /* --------------------------------- image/video components --------------------------------- */
+
+ kParamIndexPictureSize = C2_PARAM_INDEX_PICTURE_PARAM_START,
+ kParamIndexCropRect,
+ kParamIndexPixelFormat,
+ kParamIndexRotation,
+ kParamIndexPixelAspectRatio,
+ kParamIndexScaledPictureSize,
+ kParamIndexScaledCropRect,
+ kParamIndexScalingMethod,
+ kParamIndexColorInfo,
+ kParamIndexColorAspects,
+ kParamIndexHdrStaticMetadata,
+ kParamIndexDefaultColorAspects,
+
+ kParamIndexBlockSize,
+ kParamIndexBlockCount,
+ kParamIndexBlockRate,
+
+ kParamIndexPictureTypeMask,
+ kParamIndexPictureType,
+
+ /* ------------------------------------ video components ------------------------------------ */
+
+ kParamIndexFrameRate = C2_PARAM_INDEX_VIDEO_PARAM_START,
+ kParamIndexMaxBitrate,
+ kParamIndexMaxFrameRate,
+ kParamIndexMaxPictureSize,
+ kParamIndexGop,
+ kParamIndexSyncFrameInterval,
+ kParamIndexRequestSyncFrame,
+ kParamIndexTemporalLayering,
+ kParamIndexLayerIndex,
+ kParamIndexLayerCount,
+ kParamIndexIntraRefresh,
+
+ /* ------------------------------------ image components ------------------------------------ */
+
+ kParamIndexTileLayout = C2_PARAM_INDEX_IMAGE_PARAM_START,
+ kParamIndexTileHandling,
+
+ /* ------------------------------------ audio components ------------------------------------ */
+
+ kParamIndexSampleRate = C2_PARAM_INDEX_AUDIO_PARAM_START,
+ kParamIndexChannelCount,
+ kParamIndexPcmEncoding,
+ kParamIndexAacPackaging,
+ kParamIndexMaxChannelCount,
+ kParamIndexAacSbrMode, // aac encode, enum
+ kParamIndexDrcEncodedTargetLevel, // drc, float (dBFS)
+ kParamIndexDrcTargetReferenceLevel, // drc, float (dBFS)
+ kParamIndexDrcCompression, // drc, enum
+ kParamIndexDrcBoostFactor, // drc, float (0-1)
+ kParamIndexDrcAttenuationFactor, // drc, float (0-1)
+ kParamIndexDrcEffectType, // drc, enum
+
+ /* ============================== platform-defined parameters ============================== */
+
+ kParamIndexPlatformLevel = C2_PARAM_INDEX_PLATFORM_START, // all, u32
+ kParamIndexPlatformFeatures, // all, u64 mask
+ kParamIndexStoreIonUsage, // store, struct
+ kParamIndexAspectsToDataSpace, // store, struct
+ kParamIndexFlexiblePixelFormatDescriptor, // store, struct
+ kParamIndexFlexiblePixelFormatDescriptors, // store, struct[]
+ kParamIndexDataSpaceToAspects, // store, struct
+ kParamIndexDataSpace, // u32
+ kParamIndexSurfaceScaling, // u32
+
+ // input surface
+ kParamIndexInputSurfaceEos, // input-surface, eos
+ kParamIndexTimedControl, // struct
+ kParamIndexStartAt, // input-surface, struct
+ kParamIndexSuspendAt, // input-surface, struct
+ kParamIndexResumeAt, // input-surface, struct
+ kParamIndexStopAt, // input-surface, struct
+ kParamIndexTimeOffset, // input-surface, struct
+ kParamIndexMinFrameRate, // input-surface, float
+ kParamIndexTimestampGapAdjustment, // input-surface, struct
+
+ kParamIndexSurfaceAllocator, // u32
+
+ // deprecated indices due to renaming
+ kParamIndexAacStreamFormat = kParamIndexAacPackaging,
+ kParamIndexCsd = kParamIndexInitData,
+ kParamIndexMaxVideoSizeHint = kParamIndexMaxPictureSize,
+ kParamIndexMime = kParamIndexMediaType,
+ kParamIndexRequestedInfos = kParamIndexSubscribedParamIndices,
+
+
+ // deprecated indices due to removal
+ kParamIndexSupportedParams = 0xDEAD0000,
+ kParamIndexReadOnlyParams,
+ kParamIndexTemporal,
+};
+
+}
+
+/**
+ * Codec 2.0 parameter types follow the following naming convention:
+ *
+ * C2<group><domain><index><type>
+ *
+ * E.g. C2StreamPictureSizeInfo: group="" domain="Stream" index="PictureSize" type="Info".
+ * Group is somewhat arbitrary, but denotes kind of objects the parameter is defined.
+ * At this point we use Component and Store to distinguish basic component/store parameters.
+ *
+ * Parameter keys are named C2_PARAMKEY_[<group>_]<domain>_<index> as type is not expected
+ * to distinguish parameters. E.g. a component could change the type of the parameter and it
+ * is not expected users would need to change the key.
+ */
+
+/* ----------------------------------------- API level ----------------------------------------- */
+
+enum C2Config::api_level_t : uint32_t {
+ API_L0_1 = 0, ///< support for API level 0.1
+};
+
+// read-only
+typedef C2GlobalParam<C2Setting, C2SimpleValueStruct<C2Config::api_level_t>, kParamIndexApiLevel>
+ C2ApiLevelSetting;
+constexpr char C2_PARAMKEY_API_LEVEL[] = "api.level";
+
+enum C2Config::api_feature_t : uint64_t {
+ API_REFLECTION = (1U << 0), ///< ability to list supported parameters
+ API_VALUES = (1U << 1), ///< ability to list supported values for each parameter
+ API_CURRENT_VALUES = (1U << 2), ///< ability to list currently supported values for each parameter
+ API_DEPENDENCY = (1U << 3), ///< have a defined parameter dependency
+
+ API_STREAMS = (1ULL << 32), ///< supporting variable number of streams
+
+ API_TUNNELING = (1ULL << 48), ///< tunneling API
+};
+
+// read-only
+typedef C2GlobalParam<C2Setting, C2SimpleValueStruct<C2Config::api_feature_t>, kParamIndexApiFeatures>
+ C2ApiFeaturesSetting;
+constexpr char C2_PARAMKEY_API_FEATURES[] = "api.features";
+
+/* ----------------------------- generic component characteristics ----------------------------- */
+
+/**
+ * The name of the component.
+ *
+ * This must contain only alphanumeric characters or dot '.', hyphen '-', plus '+', or
+ * underline '_'. The name of each component must be unique.
+ *
+ * For Android: Component names must start with 'c2.' followed by the company name or abbreviation
+ * and another dot, e.g. 'c2.android.'. Use of lowercase is preferred but not required.
+ */
+// read-only
+typedef C2GlobalParam<C2Setting, C2StringValue, kParamIndexName> C2ComponentNameSetting;
+constexpr char C2_PARAMKEY_COMPONENT_NAME[] = "component.name";
+
+/**
+ * Alternate names (aliases) of the component.
+ *
+ * This is a comma ',' separated list of alternate component names. Unlike component names that
+ * must be unique, multiple components can have the same alias.
+ */
+// read-only
+typedef C2GlobalParam<C2Setting, C2StringValue, kParamIndexAliases> C2ComponentAliasesSetting;
+constexpr char C2_PARAMKEY_COMPONENT_ALIASES[] = "component.aliases";
+
+/**
+ * Component kind.
+ */
+// read-only
+typedef C2GlobalParam<C2Setting, C2SimpleValueStruct<C2Component::kind_t>, kParamIndexKind>
+ C2ComponentKindSetting;
+constexpr char C2_PARAMKEY_COMPONENT_KIND[] = "component.kind";
+
+/**
+ * Component domain.
+ */
+// read-only
+typedef C2GlobalParam<C2Setting, C2SimpleValueStruct<C2Component::domain_t>, kParamIndexDomain>
+ C2ComponentDomainSetting;
+typedef C2ComponentDomainSetting C2ComponentDomainInfo; // deprecated
+typedef C2Component::domain_t C2DomainKind; // deprecated
+constexpr char C2_PARAMKEY_COMPONENT_DOMAIN[] = "component.domain";
+
+constexpr C2Component::domain_t C2DomainAudio = C2Component::DOMAIN_AUDIO; // deprecated
+constexpr C2Component::domain_t C2DomainOther = C2Component::DOMAIN_OTHER; // deprecate
+constexpr C2Component::domain_t C2DomainVideo = C2Component::DOMAIN_VIDEO; // deprecate
+
+/**
+ * Component attributes.
+ *
+ * These are a set of flags provided by the component characterizing its processing algorithm.
+ */
+C2ENUM(C2Component::attrib_t, uint64_t,
+ ATTRIB_IS_TEMPORAL = 1u << 0, ///< component input ordering matters for processing
+)
+
+// read-only
+typedef C2GlobalParam<C2Setting, C2SimpleValueStruct<C2Component::attrib_t>, kParamIndexAttributes>
+ C2ComponentAttributesSetting;
+constexpr char C2_PARAMKEY_COMPONENT_ATTRIBUTES[] = "component.attributes";
+
+// deprecated
+typedef C2ComponentAttributesSetting C2ComponentTemporalInfo;
+
+/**
+ * Time stretching.
+ *
+ * This is the ratio between the rate of the input timestamp, and the rate of the output timestamp.
+ * E.g. if this is 4.0, for every 1 seconds of input timestamp difference, the output shall differ
+ * by 4 seconds.
+ */
+typedef C2GlobalParam<C2Tuning, C2FloatValue, kParamIndexTimeStretch> C2ComponentTimeStretchTuning;
+constexpr char C2_PARAMKEY_TIME_STRETCH[] = "algo.time-stretch";
+
+/* ----------------------------------- coding characteristics ----------------------------------- */
+
+/**
+ * Profile and level.
+ *
+ * Profile determines the tools used by the component.
+ * Level determines the level of resources used by the component.
+ */
+
+namespace {
+
+enum : uint32_t {
+ _C2_PL_MP2V_BASE = 0x1000,
+ _C2_PL_AAC_BASE = 0x2000,
+ _C2_PL_H263_BASE = 0x3000,
+ _C2_PL_MP4V_BASE = 0x4000,
+ _C2_PL_AVC_BASE = 0x5000,
+ _C2_PL_HEVC_BASE = 0x6000,
+ _C2_PL_VP9_BASE = 0x7000,
+ _C2_PL_DV_BASE = 0x8000,
+
+ C2_PROFILE_LEVEL_VENDOR_START = 0x70000000,
+};
+
+}
+
+enum C2Config::profile_t : uint32_t {
+ PROFILE_UNUSED = 0, ///< profile is not used by this media type
+
+ // AAC (MPEG-2 Part 7 and MPEG-4 Part 3) profiles
+ PROFILE_AAC_LC = _C2_PL_AAC_BASE, ///< AAC Low-Complexity
+ PROFILE_AAC_MAIN, ///< AAC Main
+ PROFILE_AAC_SSR, ///< AAC Scalable Sampling Rate
+ PROFILE_AAC_LTP, ///< AAC Long Term Prediction
+ PROFILE_AAC_HE, ///< AAC High-Efficiency
+ PROFILE_AAC_SCALABLE, ///< AAC Scalable
+ PROFILE_AAC_ER_LC, ///< AAC Error Resilient Low-Complexity
+ PROFILE_AAC_ER_SCALABLE, ///< AAC Error Resilient Scalable
+ PROFILE_AAC_LD, ///< AAC Low Delay
+ PROFILE_AAC_HE_PS, ///< AAC High-Efficiency Parametric Stereo
+ PROFILE_AAC_ELD, ///< AAC Enhanced Low Delay
+ PROFILE_AAC_XHE, ///< AAC Extended High-Efficiency
+
+ // MPEG-2 Video profiles
+ PROFILE_MP2V_SIMPLE = _C2_PL_MP2V_BASE, ///< MPEG-2 Video (H.262) Simple
+ PROFILE_MP2V_MAIN, ///< MPEG-2 Video (H.262) Main
+ PROFILE_MP2V_SNR_SCALABLE, ///< MPEG-2 Video (H.262) SNR Scalable
+ PROFILE_MP2V_SPATIALLY_SCALABLE, ///< MPEG-2 Video (H.262) Spatially Scalable
+ PROFILE_MP2V_HIGH, ///< MPEG-2 Video (H.262) High
+ PROFILE_MP2V_422, ///< MPEG-2 Video (H.262) 4:2:2
+ PROFILE_MP2V_MULTIVIEW, ///< MPEG-2 Video (H.262) Multi-view
+
+ // H.263 profiles
+ PROFILE_H263_BASELINE = _C2_PL_H263_BASE, ///< H.263 Baseline (Profile 0)
+ PROFILE_H263_H320, ///< H.263 H.320 Coding Efficiency Version 2 Backward-Compatibility (Profile 1)
+ PROFILE_H263_V1BC, ///< H.263 Version 1 Backward-Compatibility (Profile 2)
+ PROFILE_H263_ISWV2, ///< H.263 Version 2 Interactive and Streaming Wireless (Profile 3)
+ PROFILE_H263_ISWV3, ///< H.263 Version 3 Interactive and Streaming Wireless (Profile 4)
+ PROFILE_H263_HIGH_COMPRESSION, ///< H.263 Conversational High Compression (Profile 5)
+ PROFILE_H263_INTERNET, ///< H.263 Conversational Internet (Profile 6)
+ PROFILE_H263_INTERLACE, ///< H.263 Conversational Interlace (Profile 7)
+ PROFILE_H263_HIGH_LATENCY, ///< H.263 High Latency (Profile 8)
+
+ // MPEG-4 Part 2 (Video) Natural Visual Profiles
+ PROFILE_MP4V_SIMPLE, ///< MPEG-4 Video Simple
+ PROFILE_MP4V_SIMPLE_SCALABLE, ///< MPEG-4 Video Simple Scalable
+ PROFILE_MP4V_CORE, ///< MPEG-4 Video Core
+ PROFILE_MP4V_MAIN, ///< MPEG-4 Video Main
+ PROFILE_MP4V_NBIT, ///< MPEG-4 Video N-Bit
+ PROFILE_MP4V_ARTS, ///< MPEG-4 Video Advanced Realtime Simple
+ PROFILE_MP4V_CORE_SCALABLE, ///< MPEG-4 Video Core Scalable
+ PROFILE_MP4V_ACE, ///< MPEG-4 Video Advanced Coding Efficiency
+ PROFILE_MP4V_ADVANCED_CORE, ///< MPEG-4 Video Advanced Core
+ PROFILE_MP4V_SIMPLE_STUDIO, ///< MPEG-4 Video Simple Studio
+ PROFILE_MP4V_CORE_STUDIO, ///< MPEG-4 Video Core Studio
+ PROFILE_MP4V_ADVANCED_SIMPLE, ///< MPEG-4 Video Advanced Simple
+ PROFILE_MP4V_FGS, ///< MPEG-4 Video Fine Granularity Scalable
+
+ // AVC / MPEG-4 Part 10 (H.264) profiles
+ PROFILE_AVC_BASELINE = _C2_PL_AVC_BASE, ///< AVC (H.264) Baseline
+ PROFILE_AVC_CONSTRAINED_BASELINE, ///< AVC (H.264) Constrained Baseline
+ PROFILE_AVC_MAIN, ///< AVC (H.264) Main
+ PROFILE_AVC_EXTENDED, ///< AVC (H.264) Extended
+ PROFILE_AVC_HIGH, ///< AVC (H.264) High
+ PROFILE_AVC_PROGRESSIVE_HIGH, ///< AVC (H.264) Progressive High
+ PROFILE_AVC_CONSTRAINED_HIGH, ///< AVC (H.264) Constrained High
+ PROFILE_AVC_HIGH_10, ///< AVC (H.264) High 10
+ PROFILE_AVC_PROGRESSIVE_HIGH_10, ///< AVC (H.264) Progressive High 10
+ PROFILE_AVC_HIGH_422, ///< AVC (H.264) High 4:2:2
+ PROFILE_AVC_HIGH_444_PREDICTIVE, ///< AVC (H.264) High 4:4:4 Predictive
+ PROFILE_AVC_HIGH_10_INTRA, ///< AVC (H.264) High 10 Intra
+ PROFILE_AVC_HIGH_422_INTRA, ///< AVC (H.264) High 4:2:2 Intra
+ PROFILE_AVC_HIGH_444_INTRA, ///< AVC (H.264) High 4:4:4 Intra
+ PROFILE_AVC_CAVLC_444_INTRA, ///< AVC (H.264) CAVLC 4:4:4 Intra
+ PROFILE_AVC_SCALABLE_BASELINE = _C2_PL_AVC_BASE + 0x100, ///< AVC (H.264) Scalable Baseline
+ PROFILE_AVC_SCALABLE_CONSTRAINED_BASELINE, ///< AVC (H.264) Scalable Constrained Baseline
+ PROFILE_AVC_SCALABLE_HIGH, ///< AVC (H.264) Scalable High
+ PROFILE_AVC_SCALABLE_CONSTRAINED_HIGH, ///< AVC (H.264) Scalable Constrained High
+ PROFILE_AVC_SCALABLE_HIGH_INTRA, ///< AVC (H.264) Scalable High Intra
+ PROFILE_AVC_MULTIVIEW_HIGH = _C2_PL_AVC_BASE + 0x200, ///< AVC (H.264) Multiview High
+ PROFILE_AVC_STEREO_HIGH, ///< AVC (H.264) Stereo High
+ PROFILE_AVC_MFC_HIGH, ///< AVC (H.264) MFC High
+ PROFILE_AVC_MULTIVIEW_DEPTH_HIGH = _C2_PL_AVC_BASE + 0x300, ///< AVC (H.264) Multiview Depth High
+ PROFILE_AVC_MFC_DEPTH_HIGH, ///< AVC (H.264) MFC Depth High
+ PROFILE_AVC_ENHANCED_MULTIVIEW_DEPTH_HIGH = _C2_PL_AVC_BASE + 0x400, ///< AVC (H.264) Enhanced Multiview Depth High
+
+ // HEVC profiles
+ PROFILE_HEVC_MAIN = _C2_PL_HEVC_BASE, ///< HEVC (H.265) Main
+ PROFILE_HEVC_MAIN_10, ///< HEVC (H.265) Main 10
+ PROFILE_HEVC_MAIN_STILL, ///< HEVC (H.265) Main Still Picture
+ PROFILE_HEVC_MONO = _C2_PL_HEVC_BASE + 0x100, ///< HEVC (H.265) Monochrome
+ PROFILE_HEVC_MONO_12, ///< HEVC (H.265) Monochrome 12
+ PROFILE_HEVC_MONO_16, ///< HEVC (H.265) Monochrome 16
+ PROFILE_HEVC_MAIN_12, ///< HEVC (H.265) Main 12
+ PROFILE_HEVC_MAIN_422_10, ///< HEVC (H.265) Main 4:2:2 10
+ PROFILE_HEVC_MAIN_422_12, ///< HEVC (H.265) Main 4:2:2 12
+ PROFILE_HEVC_MAIN_444, ///< HEVC (H.265) Main 4:4:4
+ PROFILE_HEVC_MAIN_444_10, ///< HEVC (H.265) Main 4:4:4 10
+ PROFILE_HEVC_MAIN_444_12, ///< HEVC (H.265) Main 4:4:4 12
+ PROFILE_HEVC_MAIN_INTRA, ///< HEVC (H.265) Main Intra
+ PROFILE_HEVC_MAIN_10_INTRA, ///< HEVC (H.265) Main 10 Intra
+ PROFILE_HEVC_MAIN_12_INTRA, ///< HEVC (H.265) Main 12 Intra
+ PROFILE_HEVC_MAIN_422_10_INTRA, ///< HEVC (H.265) Main 4:2:2 10 Intra
+ PROFILE_HEVC_MAIN_422_12_INTRA, ///< HEVC (H.265) Main 4:2:2 12 Intra
+ PROFILE_HEVC_MAIN_444_INTRA, ///< HEVC (H.265) Main 4:4:4 Intra
+ PROFILE_HEVC_MAIN_444_10_INTRA, ///< HEVC (H.265) Main 4:4:4 10 Intra
+ PROFILE_HEVC_MAIN_444_12_INTRA, ///< HEVC (H.265) Main 4:4:4 12 Intra
+ PROFILE_HEVC_MAIN_444_16_INTRA, ///< HEVC (H.265) Main 4:4:4 16 Intra
+ PROFILE_HEVC_MAIN_444_STILL, ///< HEVC (H.265) Main 4:4:4 Still Picture
+ PROFILE_HEVC_MAIN_444_16_STILL, ///< HEVC (H.265) Main 4:4:4 16 Still Picture
+ PROFILE_HEVC_HIGH_444 = _C2_PL_HEVC_BASE + 0x200, ///< HEVC (H.265) High Throughput 4:4:4
+ PROFILE_HEVC_HIGH_444_10, ///< HEVC (H.265) High Throughput 4:4:4 10
+ PROFILE_HEVC_HIGH_444_14, ///< HEVC (H.265) High Throughput 4:4:4 14
+ PROFILE_HEVC_HIGH_444_16_INTRA, ///< HEVC (H.265) High Throughput 4:4:4 16 Intra
+ PROFILE_HEVC_SX_MAIN = _C2_PL_HEVC_BASE + 0x300, ///< HEVC (H.265) Screen-Extended Main
+ PROFILE_HEVC_SX_MAIN_10, ///< HEVC (H.265) Screen-Extended Main 10
+ PROFILE_HEVC_SX_MAIN_444, ///< HEVC (H.265) Screen-Extended Main 4:4:4
+ PROFILE_HEVC_SX_MAIN_444_10, ///< HEVC (H.265) Screen-Extended Main 4:4:4 10
+ PROFILE_HEVC_SX_HIGH_444, ///< HEVC (H.265) Screen-Extended High Throughput 4:4:4
+ PROFILE_HEVC_SX_HIGH_444_10, ///< HEVC (H.265) Screen-Extended High Throughput 4:4:4 10
+ PROFILE_HEVC_SX_HIGH_444_14, ///< HEVC (H.265) Screen-Extended High Throughput 4:4:4 14
+ PROFILE_HEVC_MULTIVIEW_MAIN = _C2_PL_HEVC_BASE + 0x400, ///< HEVC (H.265) Multiview Main
+ PROFILE_HEVC_SCALABLE_MAIN = _C2_PL_HEVC_BASE + 0x500, ///< HEVC (H.265) Scalable Main
+ PROFILE_HEVC_SCALABLE_MAIN_10, ///< HEVC (H.265) Scalable Main 10
+ PROFILE_HEVC_SCALABLE_MONO = _C2_PL_HEVC_BASE + 0x600, ///< HEVC (H.265) Scalable Monochrome
+ PROFILE_HEVC_SCALABLE_MONO_12, ///< HEVC (H.265) Scalable Monochrome 12
+ PROFILE_HEVC_SCALABLE_MONO_16, ///< HEVC (H.265) Scalable Monochrome 16
+ PROFILE_HEVC_SCALABLE_MAIN_444, ///< HEVC (H.265) Scalable Main 4:4:4
+ PROFILE_HEVC_3D_MAIN = _C2_PL_HEVC_BASE + 0x700, ///< HEVC (H.265) 3D Main
+
+ // VP9 profiles
+ PROFILE_VP9_0 = _C2_PL_VP9_BASE, ///< VP9 Profile 0 (4:2:0)
+ PROFILE_VP9_1, ///< VP9 Profile 1 (4:2:2 or 4:4:4)
+ PROFILE_VP9_2, ///< VP9 Profile 2 (4:2:0, 10 or 12 bit)
+ PROFILE_VP9_3, ///< VP9 Profile 3 (4:2:2 or 4:4:4, 10 or 12 bit)
+
+ // Dolby Vision profiles
+ PROFILE_DV_AV_PER = _C2_PL_DV_BASE + 0, ///< Dolby Vision dvav.per profile (deprecated)
+ PROFILE_DV_AV_PEN, ///< Dolby Vision dvav.pen profile (deprecated)
+ PROFILE_DV_HE_DER, ///< Dolby Vision dvhe.der profile (deprecated)
+ PROFILE_DV_HE_DEN, ///< Dolby Vision dvhe.den profile (deprecated)
+ PROFILE_DV_HE_04 = _C2_PL_DV_BASE + 4, ///< Dolby Vision dvhe.04 profile
+ PROFILE_DV_HE_05 = _C2_PL_DV_BASE + 5, ///< Dolby Vision dvhe.05 profile
+ PROFILE_DV_HE_DTH, ///< Dolby Vision dvhe.dth profile (deprecated)
+ PROFILE_DV_HE_07 = _C2_PL_DV_BASE + 7, ///< Dolby Vision dvhe.07 profile
+ PROFILE_DV_HE_08 = _C2_PL_DV_BASE + 8, ///< Dolby Vision dvhe.08 profile
+ PROFILE_DV_AV_09 = _C2_PL_DV_BASE + 9, ///< Dolby Vision dvav.09 profile
+};
+
+enum C2Config::level_t : uint32_t {
+ LEVEL_UNUSED = 0, ///< level is not used by this media type
+
+ // MPEG-2 Video levels
+ LEVEL_MP2V_LOW = _C2_PL_MP2V_BASE, ///< MPEG-2 Video (H.262) Low Level
+ LEVEL_MP2V_MAIN, ///< MPEG-2 Video (H.262) Main Level
+ LEVEL_MP2V_HIGH_1440, ///< MPEG-2 Video (H.262) High 1440 Level
+ LEVEL_MP2V_HIGH, ///< MPEG-2 Video (H.262) High Level
+ LEVEL_MP2V_HIGHP, ///< MPEG-2 Video (H.262) HighP Level
+
+ // H.263 levels
+ LEVEL_H263_10 = _C2_PL_H263_BASE, ///< H.263 Level 10
+ LEVEL_H263_20, ///< H.263 Level 20
+ LEVEL_H263_30, ///< H.263 Level 30
+ LEVEL_H263_40, ///< H.263 Level 40
+ LEVEL_H263_45, ///< H.263 Level 45
+ LEVEL_H263_50, ///< H.263 Level 50
+ LEVEL_H263_60, ///< H.263 Level 60
+ LEVEL_H263_70, ///< H.263 Level 70
+
+ // MPEG-4 Part 2 (Video) levels
+ LEVEL_MP4V_0 = _C2_PL_MP4V_BASE, ///< MPEG-4 Video Level 0
+ LEVEL_MP4V_0B, ///< MPEG-4 Video Level 0b
+ LEVEL_MP4V_1, ///< MPEG-4 Video Level 1
+ LEVEL_MP4V_2, ///< MPEG-4 Video Level 2
+ LEVEL_MP4V_3, ///< MPEG-4 Video Level 3
+ LEVEL_MP4V_3B, ///< MPEG-4 Video Level 3b
+ LEVEL_MP4V_4, ///< MPEG-4 Video Level 4
+ LEVEL_MP4V_4A, ///< MPEG-4 Video Level 4a
+ LEVEL_MP4V_5, ///< MPEG-4 Video Level 5
+ LEVEL_MP4V_6, ///< MPEG-4 Video Level 6
+
+ // AVC / MPEG-4 Part 10 (H.264) levels
+ LEVEL_AVC_1 = _C2_PL_AVC_BASE, ///< AVC (H.264) Level 1
+ LEVEL_AVC_1B, ///< AVC (H.264) Level 1b
+ LEVEL_AVC_1_1, ///< AVC (H.264) Level 1.1
+ LEVEL_AVC_1_2, ///< AVC (H.264) Level 1.2
+ LEVEL_AVC_1_3, ///< AVC (H.264) Level 1.3
+ LEVEL_AVC_2, ///< AVC (H.264) Level 2
+ LEVEL_AVC_2_1, ///< AVC (H.264) Level 2.1
+ LEVEL_AVC_2_2, ///< AVC (H.264) Level 2.2
+ LEVEL_AVC_3, ///< AVC (H.264) Level 3
+ LEVEL_AVC_3_1, ///< AVC (H.264) Level 3.1
+ LEVEL_AVC_3_2, ///< AVC (H.264) Level 3.2
+ LEVEL_AVC_4, ///< AVC (H.264) Level 4
+ LEVEL_AVC_4_1, ///< AVC (H.264) Level 4.1
+ LEVEL_AVC_4_2, ///< AVC (H.264) Level 4.2
+ LEVEL_AVC_5, ///< AVC (H.264) Level 5
+ LEVEL_AVC_5_1, ///< AVC (H.264) Level 5.1
+ LEVEL_AVC_5_2, ///< AVC (H.264) Level 5.2
+
+ // HEVC (H.265) tiers and levels
+ LEVEL_HEVC_MAIN_1 = _C2_PL_HEVC_BASE, ///< HEVC (H.265) Main Tier Level 1
+ LEVEL_HEVC_MAIN_2, ///< HEVC (H.265) Main Tier Level 2
+ LEVEL_HEVC_MAIN_2_1, ///< HEVC (H.265) Main Tier Level 2.1
+ LEVEL_HEVC_MAIN_3, ///< HEVC (H.265) Main Tier Level 3
+ LEVEL_HEVC_MAIN_3_1, ///< HEVC (H.265) Main Tier Level 3.1
+ LEVEL_HEVC_MAIN_4, ///< HEVC (H.265) Main Tier Level 4
+ LEVEL_HEVC_MAIN_4_1, ///< HEVC (H.265) Main Tier Level 4.1
+ LEVEL_HEVC_MAIN_5, ///< HEVC (H.265) Main Tier Level 5
+ LEVEL_HEVC_MAIN_5_1, ///< HEVC (H.265) Main Tier Level 5.1
+ LEVEL_HEVC_MAIN_5_2, ///< HEVC (H.265) Main Tier Level 5.2
+ LEVEL_HEVC_MAIN_6, ///< HEVC (H.265) Main Tier Level 6
+ LEVEL_HEVC_MAIN_6_1, ///< HEVC (H.265) Main Tier Level 6.1
+ LEVEL_HEVC_MAIN_6_2, ///< HEVC (H.265) Main Tier Level 6.2
+
+ LEVEL_HEVC_HIGH_4 = _C2_PL_HEVC_BASE + 0x100, ///< HEVC (H.265) High Tier Level 4
+ LEVEL_HEVC_HIGH_4_1, ///< HEVC (H.265) High Tier Level 4.1
+ LEVEL_HEVC_HIGH_5, ///< HEVC (H.265) High Tier Level 5
+ LEVEL_HEVC_HIGH_5_1, ///< HEVC (H.265) High Tier Level 5.1
+ LEVEL_HEVC_HIGH_5_2, ///< HEVC (H.265) High Tier Level 5.2
+ LEVEL_HEVC_HIGH_6, ///< HEVC (H.265) High Tier Level 6
+ LEVEL_HEVC_HIGH_6_1, ///< HEVC (H.265) High Tier Level 6.1
+ LEVEL_HEVC_HIGH_6_2, ///< HEVC (H.265) High Tier Level 6.2
+
+ // VP9 levels
+ LEVEL_VP9_1 = _C2_PL_VP9_BASE, ///< VP9 Level 1
+ LEVEL_VP9_1_1, ///< VP9 Level 1.1
+ LEVEL_VP9_2, ///< VP9 Level 2
+ LEVEL_VP9_2_1, ///< VP9 Level 2.1
+ LEVEL_VP9_3, ///< VP9 Level 3
+ LEVEL_VP9_3_1, ///< VP9 Level 3.1
+ LEVEL_VP9_4, ///< VP9 Level 4
+ LEVEL_VP9_4_1, ///< VP9 Level 4.1
+ LEVEL_VP9_5, ///< VP9 Level 5
+ LEVEL_VP9_5_1, ///< VP9 Level 5.1
+ LEVEL_VP9_5_2, ///< VP9 Level 5.2
+ LEVEL_VP9_6, ///< VP9 Level 6
+ LEVEL_VP9_6_1, ///< VP9 Level 6.1
+ LEVEL_VP9_6_2, ///< VP9 Level 6.2
+
+ // Dolby Vision level
+ LEVEL_DV_MAIN_HD_24 = _C2_PL_DV_BASE, ///< Dolby Vision main tier hd24
+ LEVEL_DV_MAIN_HD_30, ///< Dolby Vision main tier hd30
+ LEVEL_DV_MAIN_FHD_24, ///< Dolby Vision main tier fhd24
+ LEVEL_DV_MAIN_FHD_30, ///< Dolby Vision main tier fhd30
+ LEVEL_DV_MAIN_FHD_60, ///< Dolby Vision main tier fhd60
+ LEVEL_DV_MAIN_UHD_24, ///< Dolby Vision main tier uhd24
+ LEVEL_DV_MAIN_UHD_30, ///< Dolby Vision main tier uhd30
+ LEVEL_DV_MAIN_UHD_48, ///< Dolby Vision main tier uhd48
+ LEVEL_DV_MAIN_UHD_60, ///< Dolby Vision main tier uhd60
+
+ LEVEL_DV_HIGH_HD_24 = _C2_PL_DV_BASE + 0x100, ///< Dolby Vision high tier hd24
+ LEVEL_DV_HIGH_HD_30, ///< Dolby Vision high tier hd30
+ LEVEL_DV_HIGH_FHD_24, ///< Dolby Vision high tier fhd24
+ LEVEL_DV_HIGH_FHD_30, ///< Dolby Vision high tier fhd30
+ LEVEL_DV_HIGH_FHD_60, ///< Dolby Vision high tier fhd60
+ LEVEL_DV_HIGH_UHD_24, ///< Dolby Vision high tier uhd24
+ LEVEL_DV_HIGH_UHD_30, ///< Dolby Vision high tier uhd30
+ LEVEL_DV_HIGH_UHD_48, ///< Dolby Vision high tier uhd48
+ LEVEL_DV_HIGH_UHD_60, ///< Dolby Vision high tier uhd60
+};
+
+struct C2ProfileLevelStruct {
+ C2Config::profile_t profile; ///< coding profile
+ C2Config::level_t level; ///< coding level
+
+ C2ProfileLevelStruct(
+ C2Config::profile_t profile_ = C2Config::PROFILE_UNUSED,
+ C2Config::level_t level_ = C2Config::LEVEL_UNUSED)
+ : profile(profile_), level(level_) { }
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(ProfileLevel)
+ C2FIELD(profile, "profile")
+ C2FIELD(level, "level")
+};
+
+// TODO: may need to make this explicit (have .set member)
+typedef C2StreamParam<C2Info, C2ProfileLevelStruct, kParamIndexProfileLevel>
+ C2StreamProfileLevelInfo;
+constexpr char C2_PARAMKEY_PROFILE_LEVEL[] = "coded.pl";
+#define C2_PARAMKEY_STREAM_PROFILE_LEVEL C2_PARAMKEY_PROFILE_LEVEL
+
+/**
+ * Codec-specific initialization data.
+ *
+ * This is initialization data for the codec.
+ *
+ * For AVC/HEVC, these are the concatenated SPS/PPS/VPS NALs.
+ *
+ * TODO: define for other codecs.
+ */
+typedef C2StreamParam<C2Info, C2BlobValue, kParamIndexInitData> C2StreamInitDataInfo;
+typedef C2StreamInitDataInfo C2StreamCsdInfo; // deprecated
+constexpr char C2_PARAMKEY_INIT_DATA[] = "coded.init-data";
+#define C2_PARAMKEY_STREAM_INIT_DATA C2_PARAMKEY_INIT_DATA
+
+/**
+ * Supplemental Data.
+ *
+ * This is coding-specific supplemental informational data, e.g. SEI for AVC/HEVC.
+ * This structure is not a configuration so it does not have a parameter key.
+ * This structure shall be returned in the configuration update, and can be repeated as needed
+ * in the same update.
+ */
+C2ENUM(C2Config::supplemental_info_t, uint32_t,
+ INFO_NONE = 0,
+
+ INFO_PREFIX_SEI_UNIT = 0x10000, ///< prefix SEI payload types add this flag
+ INFO_SUFFIX_SEI_UNIT = 0x20000, ///< suffix SEI payload types add this flag
+
+ INFO_SEI_USER_DATA = INFO_PREFIX_SEI_UNIT | 4, ///< closed-captioning data (ITU-T T35)
+ INFO_SEI_MDCV = INFO_PREFIX_SEI_UNIT | 137, ///< mastering display color volume
+ INFO_SET_USER_DATA_SFX = INFO_SUFFIX_SEI_UNIT | 4, ///< closed-captioning data (ITU-T T35)
+
+ INFO_VENDOR_START = 0x70000000
+)
+
+struct C2SupplementalDataStruct {
+ C2SupplementalDataStruct()
+ : type_(INFO_NONE) { }
+
+ C2SupplementalDataStruct(
+ size_t flexCount, C2Config::supplemental_info_t type, std::vector<uint8_t> data_)
+ : type_(type) {
+ memcpy(data, &data_[0], c2_min(data_.size(), flexCount));
+ }
+
+ C2Config::supplemental_info_t type_;
+ uint8_t data[];
+
+ DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(SupplementalData, data)
+ C2FIELD(type_, "type")
+ C2FIELD(data, "data")
+};
+typedef C2StreamParam<C2Info, C2SupplementalDataStruct, kParamIndexSupplementalData>
+ C2StreamSupplementalDataInfo;
+
+/**
+ * Supplemental Data Subscription
+ */
+typedef C2StreamParam<C2Tuning, C2SimpleArrayStruct<C2Config::supplemental_info_t>,
+ kParamIndexSubscribedSupplementalData>
+ C2StreamSubscribedSupplementalDataTuning;
+constexpr char C2_PARAMKEY_SUBSCRIBED_SUPPLEMENTAL_DATA[] = "output.subscribed-supplemental";
+
+/* ---------------------------------- pipeline characteristics ---------------------------------- */
+
+/**
+ * Media-type.
+ *
+ * This is defined for both port and stream, but stream media type may be a subtype of the
+ * port media type.
+ */
+typedef C2PortParam<C2Setting, C2StringValue, kParamIndexMediaType> C2PortMediaTypeSetting;
+typedef C2PortMediaTypeSetting C2PortMimeConfig; // deprecated
+constexpr char C2_PARAMKEY_INPUT_MEDIA_TYPE[] = "input.media-type";
+constexpr char C2_PARAMKEY_OUTPUT_MEDIA_TYPE[] = "output.media-type";
+#define C2_NAME_INPUT_PORT_MIME_SETTING C2_PARAMKEY_INPUT_MEDIA_TYPE
+#define C2_NAME_OUTPUT_PORT_MIME_SETTING C2_PARAMKEY_OUTPUT_MEDIA_TYPE
+
+typedef C2StreamParam<C2Setting, C2StringValue, kParamIndexMediaType> C2StreamMediaTypeSetting;
+
+/**
+ * Pipeline delays.
+ *
+ * Input delay is the number of additional input frames requested by the component to process
+ * an input frame.
+ *
+ * Output delay is the number of additional output frames that need to be generated before an
+ * output can be released by the component.
+ *
+ * Pipeline delay is the number of additional frames that are processed at one time by the
+ * component.
+ *
+ * As these may vary from frame to frame, the number is the maximum required value. E.g. if
+ * input delay is 0, the component is expected to consume each frame queued even if no further
+ * frames are queued. Similarly, if input delay is 1, as long as there are always exactly 2
+ * outstanding input frames queued to the component, it shall produce output.
+ */
+
+typedef C2PortParam<C2Tuning, C2Uint32Value, kParamIndexDelayRequest> C2PortRequestedDelayTuning;
+typedef C2PortRequestedDelayTuning C2PortRequestedLatencyTuning; // deprecated
+constexpr char C2_PARAMKEY_INPUT_DELAY_REQUEST[] = "input.delay.requested";
+constexpr char C2_PARAMKEY_OUTPUT_DELAY_REQUEST[] = "output.delay.requested";
+
+typedef C2GlobalParam<C2Tuning, C2Uint32Value, kParamIndexDelayRequest>
+ C2RequestedPipelineDelayTuning;
+typedef C2RequestedPipelineDelayTuning C2ComponentRequestedLatencyTuning; // deprecated
+constexpr char C2_PARAMKEY_PIPELINE_DELAY_REQUEST[] = "pipeline-delay.requested";
+
+// read-only
+typedef C2PortParam<C2Tuning, C2Uint32Value, kParamIndexDelay> C2PortActualDelayTuning;
+typedef C2PortActualDelayTuning C2PortLatencyInfo; // deprecated
+constexpr char C2_PARAMKEY_INPUT_DELAY[] = "input.delay.actual";
+constexpr char C2_PARAMKEY_OUTPUT_DELAY[] = "output.delay.actual";
+
+// read-only
+typedef C2GlobalParam<C2Tuning, C2Uint32Value, kParamIndexDelay> C2ActualPipelineDelayTuning;
+typedef C2ActualPipelineDelayTuning C2ComponentLatencyInfo; // deprecated
+constexpr char C2_PARAMKEY_PIPELINE_DELAY[] = "algo.delay.actual";
+
+/**
+ * Reference characteristics.
+ *
+ * The component may hold onto input and output buffers even after completing the corresponding
+ * work item.
+ *
+ * Max reference age is the longest number of additional frame processing that a component may
+ * hold onto a buffer for. Max reference count is the number of buffers that a component may
+ * hold onto at the same time at the worst case. These numbers assume single frame per buffers.
+ *
+ * Use max-uint32 if there is no limit for the max age or count.
+ */
+typedef C2StreamParam<C2Tuning, C2Uint32Value, kParamIndexMaxReferenceAge>
+ C2StreamMaxReferenceAgeTuning;
+constexpr char C2_PARAMKEY_INPUT_MAX_REFERENCE_AGE[] = "input.reference.max-age";
+constexpr char C2_PARAMKEY_OUTPUT_MAX_REFERENCE_AGE[] = "output.reference.max-age";
+
+typedef C2StreamParam<C2Tuning, C2Uint32Value, kParamIndexMaxReferenceCount>
+ C2StreamMaxReferenceCountTuning;
+constexpr char C2_PARAMKEY_INPUT_MAX_REFERENCE_COUNT[] = "input.reference.max-count";
+constexpr char C2_PARAMKEY_OUTPUT_MAX_REFERENCE_COUNT[] = "output.reference.max-count";
+
+/**
+ * Output reordering.
+ *
+ * The size of the window to use for output buffer reordering. 0 is interpreted as 1.
+ */
+// output only
+typedef C2PortParam<C2Tuning, C2Uint32Value, kParamIndexReorderBufferDepth>
+ C2PortReorderBufferDepthTuning;
+constexpr char C2_PARAMKEY_OUTPUT_REORDER_DEPTH[] = "output.reorder.depth";
+
+C2ENUM(C2Config::ordinal_key_t, uint32_t,
+ ORDINAL,
+ TIMESTAMP,
+ CUSTOM)
+
+// read-only, output only
+typedef C2PortParam<C2Setting, C2SimpleValueStruct<C2Config::ordinal_key_t>, kParamIndexReorderKey>
+ C2PortReorderKeySetting;
+constexpr char C2_PARAMKEY_OUTPUT_REORDER_KEY[] = "output.reorder.key";
+
+/**
+ * Stream count.
+ */
+// private
+typedef C2PortParam<C2Tuning, C2Uint32Value, kParamIndexStreamCount> C2PortStreamCountTuning;
+typedef C2PortStreamCountTuning C2PortStreamCountConfig; // deprecated
+constexpr char C2_PARAMKEY_INPUT_STREAM_COUNT[] = "input.stream-count";
+constexpr char C2_PARAMKEY_OUTPUT_STREAM_COUNT[] = "output.stream-count";
+
+/**
+ * Config update subscription.
+ */
+// private
+typedef C2GlobalParam<C2Tuning, C2Uint32Array, kParamIndexSubscribedParamIndices>
+ C2SubscribedParamIndicesTuning;
+constexpr char C2_PARAMKEY_SUBSCRIBED_PARAM_INDICES[] = "output.subscribed-indices";
+
+/**
+ * Suggested buffer (C2Frame) count. This is a suggestion by the component for the number of
+ * input and output frames allocated for the component's use in the buffer pools.
+ *
+ * Component shall set the acceptable range of buffers allocated for it. E.g. client shall
+ * allocate at least the minimum required value.
+ */
+// read-only
+typedef C2PortParam<C2Tuning, C2Uint64Array, kParamIndexSuggestedBufferCount>
+ C2PortSuggestedBufferCountTuning;
+constexpr char C2_PARAMKEY_INPUT_SUGGESTED_BUFFER_COUNT[] = "input.buffers.pool-size";
+constexpr char C2_PARAMKEY_OUTPUT_SUGGESTED_BUFFER_COUNT[] = "output.buffers.pool-size";
+
+/**
+ * Input/output batching.
+ *
+ * For input, component requests that client batches work in batches of specified size. For output,
+ * client requests that the component batches work completion in given batch size.
+ * Value 0 means don't care.
+ */
+typedef C2PortParam<C2Tuning, C2Uint64Array, kParamIndexBatchSize> C2PortBatchSizeTuning;
+constexpr char C2_PARAMKEY_INPUT_BATCH_SIZE[] = "input.buffers.batch-size";
+constexpr char C2_PARAMKEY_OUTPUT_BATCH_SIZE[] = "output.buffers.batch-size";
+
+/**
+ * Current & last work ordinals.
+ *
+ * input port: last work queued to component.
+ * output port: last work completed by component.
+ * global: current work.
+ */
+typedef C2PortParam<C2Tuning, C2WorkOrdinalStruct, kParamIndexLastWorkQueued> C2LastWorkQueuedTuning;
+typedef C2GlobalParam<C2Tuning, C2WorkOrdinalStruct, kParamIndexCurrentWork> C2CurrentWorkTuning;
+
+
+/* ------------------------------------- memory allocation ------------------------------------- */
+
+/**
+ * Allocators to use.
+ *
+ * These are requested by the component.
+ *
+ * If none specified, client will use the default allocator ID based on the component domain and
+ * kind.
+ */
+typedef C2PortParam<C2Tuning, C2SimpleArrayStruct<C2Allocator::id_t>, kParamIndexAllocators>
+ C2PortAllocatorsTuning;
+constexpr char C2_PARAMKEY_INPUT_ALLOCATORS[] = "input.buffers.allocator-ids";
+constexpr char C2_PARAMKEY_OUTPUT_ALLOCATORS[] = "output.buffers.allocator-ids";
+
+typedef C2GlobalParam<C2Tuning, C2SimpleArrayStruct<C2Allocator::id_t>, kParamIndexAllocators>
+ C2PrivateAllocatorsTuning;
+constexpr char C2_PARAMKEY_PRIVATE_ALLOCATORS[] = "algo.buffers.allocator-ids";
+
+/**
+ * Allocator to use for outputting to surface.
+ *
+ * Components can optionally request allocator type for outputting to surface.
+ *
+ * If none specified, client will use the default BufferQueue-backed allocator ID for outputting to
+ * surface.
+ */
+typedef C2PortParam<C2Tuning, C2Uint32Value, kParamIndexSurfaceAllocator>
+ C2PortSurfaceAllocatorTuning;
+constexpr char C2_PARAMKEY_OUTPUT_SURFACE_ALLOCATOR[] = "output.buffers.surface-allocator-id";
+
+/**
+ * Block pools to use.
+ *
+ * These are allocated by the client for the component using the allocator IDs specified by the
+ * component. This is not used for the input port.
+ */
+typedef C2PortParam<C2Tuning, C2SimpleArrayStruct<C2BlockPool::local_id_t>, kParamIndexBlockPools>
+ C2PortBlockPoolsTuning;
+constexpr char C2_PARAMKEY_OUTPUT_BLOCK_POOLS[] = "output.buffers.pool-ids";
+
+typedef C2GlobalParam<C2Tuning, C2SimpleArrayStruct<C2BlockPool::local_id_t>, kParamIndexBlockPools>
+ C2PrivateBlockPoolsTuning;
+constexpr char C2_PARAMKEY_PRIVATE_BLOCK_POOLS[] = "algo.buffers.pool-ids";
+
+/**
+ * The max number of private allocations at any one time by the component.
+ * (This is an array with a corresponding value for each private allocator)
+ */
+typedef C2GlobalParam<C2Tuning, C2Uint32Array, kParamIndexMaxReferenceCount>
+ C2MaxPrivateBufferCountTuning;
+constexpr char C2_PARAMKEY_MAX_PRIVATE_BUFFER_COUNT[] = "algo.buffers.max-count";
+
+/**
+ * Buffer type
+ *
+ * This is provided by the component for the client to allocate the proper buffer type for the
+ * input port, and can be provided by the client to control the buffer type for the output.
+ */
+// private
+typedef C2StreamParam<C2Setting, C2SimpleValueStruct<C2EasyEnum<C2BufferData::type_t>>,
+ kParamIndexBufferType>
+ C2StreamBufferTypeSetting;
+
+constexpr C2BufferData::type_t C2FormatAudio = C2BufferData::LINEAR; // deprecated
+constexpr C2BufferData::type_t C2FormatCompressed = C2BufferData::LINEAR; // deprecated
+constexpr C2BufferData::type_t C2FormatVideo = C2BufferData::GRAPHIC; // deprecated
+typedef C2BufferData::type_t C2FormatKind; // deprecated
+
+typedef C2StreamBufferTypeSetting C2StreamFormatConfig; // deprecated
+constexpr char C2_PARAMKEY_INPUT_STREAM_BUFFER_TYPE[] = "input.buffers.type";
+constexpr char C2_PARAMKEY_OUTPUT_STREAM_BUFFER_TYPE[] = "output.buffers.type";
+
+// deprecated
+#define C2_NAME_INPUT_STREAM_FORMAT_SETTING C2_PARAMKEY_INPUT_STREAM_BUFFER_TYPE
+#define C2_NAME_OUTPUT_STREAM_FORMAT_SETTING C2_PARAMKEY_OUTPUT_STREAM_BUFFER_TYPE
+
+/**
+ * Memory usage.
+ *
+ * Suggested by component for input and negotiated between client and component for output.
+ */
+typedef C2StreamParam<C2Tuning, C2Uint64Value, kParamIndexUsage> C2StreamUsageTuning;
+constexpr char C2_PARAMKEY_INPUT_STREAM_USAGE[] = "input.buffers.usage";
+constexpr char C2_PARAMKEY_OUTPUT_STREAM_USAGE[] = "output.buffers.usage";
+// deprecated
+#define C2_NAME_INPUT_STREAM_USAGE_SETTING C2_PARAMKEY_INPUT_STREAM_USAGE
+
+/**
+ * Picture (video or image frame) size.
+ */
+struct C2PictureSizeStruct {
+ inline C2PictureSizeStruct()
+ : width(0), height(0) { }
+
+ inline C2PictureSizeStruct(uint32_t width_, uint32_t height_)
+ : width(width_), height(height_) { }
+
+ uint32_t width; ///< video width
+ uint32_t height; ///< video height
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(PictureSize)
+ C2FIELD(width, "width")
+ C2FIELD(height, "height")
+};
+
+/**
+ * Out of memory signaling
+ *
+ * This is a configuration for the client to mark that it cannot allocate necessary private and/
+ * or output buffers to continue operation, and to signal the failing configuration.
+ */
+struct C2OutOfMemoryStruct {
+ C2BlockPool::local_id_t pool; ///< pool ID that failed the allocation
+ uint64_t usage; ///< memory usage used
+ C2PictureSizeStruct planar; ///< buffer dimensions to be allocated if 2D
+ uint32_t format; ///< pixel format to be used if 2D
+ uint32_t capacity; ///< buffer capacity to be allocated if 1D
+ c2_bool_t outOfMemory; ///< true if component is out of memory
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(OutOfMemory)
+ C2FIELD(pool, "pool")
+ C2FIELD(usage, "usage")
+ C2FIELD(planar, "planar")
+ C2FIELD(format, "format")
+ C2FIELD(capacity, "capacity")
+ C2FIELD(outOfMemory, "out-of-memory")
+};
+
+typedef C2GlobalParam<C2Tuning, C2OutOfMemoryStruct, kParamIndexOutOfMemory> C2OutOfMemoryTuning;
+constexpr char C2_PARAMKEY_OUT_OF_MEMORY[] = "algo.oom";
+
+/**
+ * Max buffer size
+ *
+ * This is a hint provided by the component for the maximum buffer size expected on a stream for the
+ * current configuration on its input and output streams. This is communicated to clients so they
+ * can preallocate input buffers, or configure downstream components that require a maximum size on
+ * their buffers.
+ *
+ * Read-only. Required to be provided by components on all compressed streams.
+ */
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexMaxBufferSize> C2StreamMaxBufferSizeInfo;
+constexpr char C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE[] = "input.buffers.max-size";
+constexpr char C2_PARAMKEY_OUTPUT_MAX_BUFFER_SIZE[] = "output.buffers.max-size";
+
+#define C2_NAME_STREAM_MAX_BUFFER_SIZE_SETTING C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE
+
+/* ---------------------------------------- misc. state ---------------------------------------- */
+
+/**
+ * Tripped state,
+ *
+ * This state exists to be able to provide reasoning for a tripped state during normal
+ * interface operations, as well as to allow client to trip the component on demand.
+ */
+typedef C2GlobalParam<C2Tuning, C2BoolValue, kParamIndexTripped>
+ C2TrippedTuning;
+constexpr char C2_PARAMKEY_TRIPPED[] = "algo.tripped";
+
+/**
+ * Configuration counters.
+ *
+ * Configurations are tracked using three counters. The input counter is incremented exactly
+ * once with each work accepted by the component. The output counter is incremented exactly
+ * once with each work completed by the component (in the order of work completion). The
+ * global counter is incremented exactly once during to each config() call. These counters
+ * shall be read-only.
+ *
+ * TODO: these should be counters.
+ */
+typedef C2PortParam<C2Tuning, C2Uint64Value, kParamIndexConfigCounter> C2PortConfigCounterTuning;
+typedef C2GlobalParam<C2Tuning, C2Uint64Value, kParamIndexConfigCounter> C2ConfigCounterTuning;
+constexpr char C2_PARAMKEY_INPUT_COUNTER[] = "input.buffers.counter";
+constexpr char C2_PARAMKEY_OUTPUT_COUNTER[] = "output.buffers.counter";
+constexpr char C2_PARAMKEY_CONFIG_COUNTER[] = "algo.config.counter";
+
+/* ----------------------------------------- resources ----------------------------------------- */
+
+/**
+ * Resources needed and resources reserved for current configuration.
+ *
+ * Resources are tracked as a vector of positive numbers. Available resources are defined by
+ * the vendor.
+ *
+ * By default, no resources are reserved for a component. If resource reservation is successful,
+ * the component shall be able to use those resources exclusively. If however, the component is
+ * not using all of the reserved resources, those may be shared with other components.
+ *
+ * TODO: define some of the resources.
+ */
+typedef C2GlobalParam<C2Tuning, C2Uint64Array, kParamIndexResourcesNeeded> C2ResourcesNeededTuning;
+typedef C2GlobalParam<C2Tuning, C2Uint64Array, kParamIndexResourcesReserved>
+ C2ResourcesReservedTuning;
+constexpr char C2_PARAMKEY_RESOURCES_NEEDED[] = "resources.needed";
+constexpr char C2_PARAMKEY_RESOURCES_RESERVED[] = "resources.reserved";
+
+/**
+ * Operating rate.
+ *
+ * Operating rate is the expected rate of work through the component. Negative values is
+ * invalid.
+ *
+ * TODO: this could distinguish set value
+ */
+typedef C2GlobalParam<C2Tuning, C2FloatValue, kParamIndexOperatingRate> C2OperatingRateTuning;
+constexpr char C2_PARAMKEY_OPERATING_RATE[] = "algo.rate";
+
+/**
+ * Realtime / operating point.
+ *
+ * Priority value defines the operating point for the component. Operating points are defined by
+ * the vendor. Priority value of 0 means that the client requires operation at the given operating
+ * rate. Priority values -1 and below define operating points in decreasing performance. In this
+ * case client expects best effort without exceeding the specific operating point. This allows
+ * client to run components deeper in the background by using larger priority values. In these
+ * cases operating rate is a hint for the maximum rate that the client anticipates.
+ *
+ * Operating rate and priority are used in tandem. E.g. if there are components that run at a
+ * higher operating point (priority) it will make more resources available for components at
+ * a lower operating point, so operating rate can be used to gate those components.
+ *
+ * Positive priority values are not defined at the moment and shall be treated equivalent to 0.
+ */
+typedef C2GlobalParam<C2Tuning, C2Int32Value, kParamIndexRealTimePriority>
+ C2RealTimePriorityTuning;
+constexpr char C2_PARAMKEY_PRIORITY[] = "algo.priority";
+
+/* ------------------------------------- protected content ------------------------------------- */
+
+/**
+ * Secure mode.
+ */
+C2ENUM(C2Config::secure_mode_t, uint32_t,
+ SM_UNPROTECTED, ///< no content protection
+ SM_READ_PROTECTED, ///< input and output buffers shall be protected from reading
+)
+
+typedef C2GlobalParam<C2Tuning, C2SimpleValueStruct<C2Config::secure_mode_t>, kParamIndexSecureMode>
+ C2SecureModeTuning;
+constexpr char C2_PARAMKEY_SECURE_MODE[] = "algo.secure-mode";
+
+/* ===================================== ENCODER COMPONENTS ===================================== */
+
+/**
+ * Bitrate
+ */
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexBitrate> C2StreamBitrateInfo;
+typedef C2StreamBitrateInfo C2BitrateTuning; // deprecated
+constexpr char C2_PARAMKEY_BITRATE[] = "coded.bitrate";
+#define C2_NAME_STREAM_BITRATE_SETTING C2_PARAMKEY_BITRATE
+
+/**
+ * Bitrate mode.
+ *
+ * TODO: refine this with bitrate ranges and suggested window
+ */
+C2ENUM(C2Config::bitrate_mode_t, uint32_t,
+ BITRATE_CONST_SKIP_ALLOWED = 0, ///< constant bitrate, frame skipping allowed
+ BITRATE_CONST = 1, ///< constant bitrate, keep all frames
+ BITRATE_VARIABLE_SKIP_ALLOWED = 2, ///< bitrate can vary, frame skipping allowed
+ BITRATE_VARIABLE = 3, ///< bitrate can vary, keep all frames
+ BITRATE_IGNORE = 7, ///< bitrate can be exceeded at will to achieve
+ ///< quality or other settings
+
+ // bitrate modes are composed of the following flags
+ BITRATE_FLAG_KEEP_ALL_FRAMES = 1,
+ BITRATE_FLAG_CAN_VARY = 2,
+ BITRATE_FLAG_CAN_EXCEED = 4,
+)
+
+typedef C2StreamParam<C2Tuning, C2SimpleValueStruct<C2Config::bitrate_mode_t>,
+ kParamIndexBitrateMode>
+ C2StreamBitrateModeTuning;
+constexpr char C2_PARAMKEY_BITRATE_MODE[] = "algo.bitrate-mode";
+
+/**
+ * Quality.
+ *
+ * This is defined by each component, the higher the better the output quality at the expense of
+ * less compression efficiency. This setting is defined for the output streams in case the
+ * component can support varying quality on each stream, or as an output port tuning in case the
+ * quality is global to all streams.
+ */
+typedef C2StreamParam<C2Tuning, C2Uint32Value, kParamIndexQuality> C2StreamQualityTuning;
+typedef C2PortParam<C2Tuning, C2Uint32Value, kParamIndexQuality> C2QualityTuning;
+constexpr char C2_PARAMKEY_QUALITY[] = "algo.quality";
+
+/**
+ * Complexity.
+ *
+ * This is defined by each component, this higher the value, the more resources the component
+ * will use to produce better quality at the same compression efficiency or better compression
+ * efficiency at the same quality. This setting is defined for the output streams in case the
+ * component can support varying complexity on each stream, or as an output port tuning in case the
+ * quality is global to all streams
+ */
+typedef C2StreamParam<C2Tuning, C2Uint32Value, kParamIndexComplexity> C2StreamComplexityTuning;
+typedef C2PortParam<C2Tuning, C2Uint32Value, kParamIndexComplexity> C2ComplexityTuning;
+constexpr char C2_PARAMKEY_COMPLEXITY[] = "algo.complexity";
+
+/**
+ * Header (init-data) handling around sync frames.
+ */
+C2ENUM(C2Config::prepend_header_mode_t, uint32_t,
+ /**
+ * don't prepend header. Signal header only through C2StreamInitDataInfo.
+ */
+ PREPEND_HEADER_TO_NONE,
+
+ /**
+ * prepend header before the first output frame and thereafter before the next sync frame
+ * if it changes.
+ */
+ PREPEND_HEADER_ON_CHANGE,
+
+ /**
+ * prepend header before every sync frame.
+ */
+ PREPEND_HEADER_TO_ALL_SYNC,
+)
+
+typedef C2GlobalParam<C2Setting, C2BoolValue, kParamIndexPrependHeaderMode>
+ C2PrependHeaderModeSetting;
+constexpr char C2_PARAMKEY_PREPEND_HEADER_MODE[] = "output.buffers.prepend-header";
+
+/* =================================== IMAGE/VIDEO COMPONENTS =================================== */
+
+/*
+ * Order of transformation is:
+ *
+ * crop => (scaling => scaled-crop) => sample-aspect-ratio => flip => rotation
+ */
+
+/**
+ * Picture (image- and video frame) size.
+ *
+ * This is used for the output of the video decoder, and the input of the video encoder.
+ */
+typedef C2PictureSizeStruct C2VideoSizeStruct; // deprecated
+
+typedef C2StreamParam<C2Info, C2PictureSizeStruct, kParamIndexPictureSize> C2StreamPictureSizeInfo;
+constexpr char C2_PARAMKEY_PICTURE_SIZE[] = "raw.size";
+#define C2_PARAMKEY_STREAM_PICTURE_SIZE C2_PARAMKEY_PICTURE_SIZE
+#define C2_NAME_STREAM_VIDEO_SIZE_INFO C2_PARAMKEY_PICTURE_SIZE
+typedef C2StreamPictureSizeInfo C2VideoSizeStreamInfo; // deprecated
+typedef C2StreamPictureSizeInfo C2VideoSizeStreamTuning; // deprecated
+#define C2_NAME_STREAM_VIDEO_SIZE_SETTING C2_PARAMKEY_PICTURE_SIZE
+
+/**
+ * Crop rectangle.
+ */
+struct C2RectStruct : C2Rect {
+ C2RectStruct() = default;
+ C2RectStruct(const C2Rect &rect) : C2Rect(rect) { }
+
+ bool operator==(const C2RectStruct &) = delete;
+ bool operator!=(const C2RectStruct &) = delete;
+
+ DEFINE_AND_DESCRIBE_BASE_C2STRUCT(Rect)
+ C2FIELD(width, "width")
+ C2FIELD(height, "height")
+ C2FIELD(left, "left")
+ C2FIELD(top, "top")
+};
+
+typedef C2StreamParam<C2Info, C2RectStruct, kParamIndexCropRect> C2StreamCropRectInfo;
+constexpr char C2_PARAMKEY_CROP_RECT[] = "raw.crop";
+constexpr char C2_PARAMKEY_CODED_CROP_RECT[] = "coded.crop";
+
+/**
+ * Pixel format.
+ */
+// TODO: define some
+
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexPixelFormat> C2StreamPixelFormatInfo;
+constexpr char C2_PARAMKEY_PIXEL_FORMAT[] = "raw.pixel-format";
+
+/**
+ * Extended rotation information also incorporating a flip.
+ *
+ * Rotation is counter clock-wise.
+ */
+struct C2RotationStruct {
+ C2RotationStruct(int32_t rotation = 0)
+ : flip(0), value(rotation) { }
+
+ int32_t flip; ///< horizontal flip (left-right flip applied prior to rotation)
+ int32_t value; ///< rotation in degrees counter clockwise
+
+ DEFINE_AND_DESCRIBE_BASE_C2STRUCT(Rotation)
+ C2FIELD(flip, "flip")
+ C2FIELD(value, "value")
+};
+
+typedef C2StreamParam<C2Info, C2RotationStruct, kParamIndexRotation> C2StreamRotationInfo;
+constexpr char C2_PARAMKEY_ROTATION[] = "raw.rotation";
+constexpr char C2_PARAMKEY_VUI_ROTATION[] = "coded.vui.rotation";
+
+/**
+ * Pixel (sample) aspect ratio.
+ */
+typedef C2StreamParam<C2Info, C2PictureSizeStruct, kParamIndexPixelAspectRatio>
+ C2StreamPixelAspectRatioInfo;
+constexpr char C2_PARAMKEY_PIXEL_ASPECT_RATIO[] = "raw.sar";
+constexpr char C2_PARAMKEY_VUI_PIXEL_ASPECT_RATIO[] = "coded.vui.sar";
+
+/**
+ * In-line scaling.
+ *
+ * Components can optionally support scaling of raw image/video frames. Or scaling only a
+ * portion of raw image/video frames (scaled-crop).
+ */
+
+C2ENUM(C2Config::scaling_method_t, uint32_t,
+ SCALING_ARBITRARY, ///< arbitrary, unspecified
+)
+
+typedef C2StreamParam<C2Tuning, C2SimpleValueStruct<C2Config::scaling_method_t>,
+ kParamIndexScalingMethod>
+ C2StreamScalingMethodTuning;
+constexpr char C2_PARAMKEY_SCALING_MODE[] = "raw.scaling-method";
+#define C2_PARAMKEY_STREAM_SCALING_MODE C2_PARAMKEY_SCALING_MODE
+
+typedef C2StreamParam<C2Tuning, C2PictureSizeStruct, kParamIndexScaledPictureSize>
+ C2StreamScaledPictureSizeTuning;
+constexpr char C2_PARAMKEY_SCALED_PICTURE_SIZE[] = "raw.scaled-size";
+#define C2_PARAMKEY_STREAM_SCALED_PICTURE_SIZE C2_PARAMKEY_SCALED_PICTURE_SIZE
+
+typedef C2StreamParam<C2Tuning, C2RectStruct, kParamIndexScaledCropRect>
+ C2StreamScaledCropRectTuning;
+constexpr char C2_PARAMKEY_SCALED_CROP_RECT[] = "raw.scaled-crop";
+
+/* ------------------------------------- color information ------------------------------------- */
+
+/**
+ * Color Info
+ *
+ * Chroma location can vary for top and bottom fields, so use an array, that can have 0 to 2
+ * values. Empty array is used for non YUV formats.
+ */
+
+struct C2Color {
+ enum matrix_t : uint32_t; ///< matrix coefficient (YUV <=> RGB)
+ enum plane_layout_t : uint32_t; ///< plane layout for flexible formats
+ enum primaries_t : uint32_t; ///< color primaries and white point
+ enum range_t : uint32_t; ///< range of color component values
+ enum subsampling_t : uint32_t; ///< chroma subsampling
+ enum transfer_t : uint32_t; ///< transfer function
+};
+
+/// Chroma subsampling
+C2ENUM(C2Color::subsampling_t, uint32_t,
+ MONOCHROME, ///< there are no Cr nor Cb planes
+ MONOCHROME_ALPHA, ///< there are no Cr nor Cb planes, but there is an alpha plane
+ RGB, ///< RGB
+ RGBA, ///< RGBA
+ YUV_420, ///< Cr and Cb planes are subsampled by 2 both horizontally and vertically
+ YUV_422, ///< Cr and Cb planes are subsampled horizontally
+ YUV_444, ///< Cr and Cb planes are not subsampled
+ YUVA_444, ///< Cr and Cb planes are not subsampled, there is an alpha plane
+)
+
+struct C2ChromaOffsetStruct {
+ // chroma offsets defined by ITU
+ constexpr static C2ChromaOffsetStruct ITU_YUV_444() { return { 0.0f, 0.0f }; }
+ constexpr static C2ChromaOffsetStruct ITU_YUV_422() { return { 0.0f, 0.0f }; }
+ constexpr static C2ChromaOffsetStruct ITU_YUV_420_0() { return { 0.0f, 0.5f }; }
+ constexpr static C2ChromaOffsetStruct ITU_YUV_420_1() { return { 0.5f, 0.5f }; }
+ constexpr static C2ChromaOffsetStruct ITU_YUV_420_2() { return { 0.0f, 0.0f }; }
+ constexpr static C2ChromaOffsetStruct ITU_YUV_420_3() { return { 0.5f, 0.0f }; }
+ constexpr static C2ChromaOffsetStruct ITU_YUV_420_4() { return { 0.0f, 1.0f }; }
+ constexpr static C2ChromaOffsetStruct ITU_YUV_420_5() { return { 0.5f, 1.0f }; }
+
+ float x; ///< x offset in pixels (towards right)
+ float y; ///< y offset in pixels (towards down)
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(ChromaOffset)
+ C2FIELD(x, "x")
+ C2FIELD(y, "y")
+};
+
+struct C2ColorInfoStruct {
+ C2ColorInfoStruct()
+ : bitDepth(8), subsampling(C2Color::YUV_420) { }
+
+ uint32_t bitDepth;
+ C2Color::subsampling_t subsampling;
+ C2ChromaOffsetStruct locations[]; // max 2 elements
+
+ C2ColorInfoStruct(
+ size_t /* flexCount */, uint32_t bitDepth_, C2Color::subsampling_t subsampling_)
+ : bitDepth(bitDepth_), subsampling(subsampling_) { }
+
+ C2ColorInfoStruct(
+ size_t flexCount, uint32_t bitDepth_, C2Color::subsampling_t subsampling_,
+ std::initializer_list<C2ChromaOffsetStruct> locations_)
+ : bitDepth(bitDepth_), subsampling(subsampling_) {
+ size_t ix = 0;
+ for (const C2ChromaOffsetStruct &location : locations_) {
+ if (ix == flexCount) {
+ break;
+ }
+ locations[ix] = location;
+ ++ix;
+ }
+ }
+
+ DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(ColorInfo, locations)
+ C2FIELD(bitDepth, "bit-depth")
+ C2FIELD(subsampling, "subsampling")
+ C2FIELD(locations, "locations")
+};
+
+typedef C2StreamParam<C2Info, C2ColorInfoStruct, kParamIndexColorInfo> C2StreamColorInfo;
+constexpr char C2_PARAMKEY_COLOR_INFO[] = "raw.color-format";
+constexpr char C2_PARAMKEY_CODED_COLOR_INFO[] = "coded.color-format";
+
+/**
+ * Color Aspects
+ */
+
+/* The meaning of the following enumerators is as described in ITU-T H.273. */
+
+/// Range
+C2ENUM(C2Color::range_t, uint32_t,
+ RANGE_UNSPECIFIED, ///< range is unspecified
+ RANGE_FULL, ///< full range
+ RANGE_LIMITED, ///< limited range
+
+ RANGE_VENDOR_START = 0x80, ///< vendor-specific range values start here
+ RANGE_OTHER = 0XFF ///< max value, reserved for undefined values
+)
+
+/// Color primaries
+C2ENUM(C2Color::primaries_t, uint32_t,
+ PRIMARIES_UNSPECIFIED, ///< primaries are unspecified
+ PRIMARIES_BT709, ///< Rec.ITU-R BT.709-6 or equivalent
+ PRIMARIES_BT470_M, ///< Rec.ITU-R BT.470-6 System M or equivalent
+ PRIMARIES_BT601_625, ///< Rec.ITU-R BT.601-6 625 or equivalent
+ PRIMARIES_BT601_525, ///< Rec.ITU-R BT.601-6 525 or equivalent
+ PRIMARIES_GENERIC_FILM, ///< Generic Film
+ PRIMARIES_BT2020, ///< Rec.ITU-R BT.2020 or equivalent
+ PRIMARIES_RP431, ///< SMPTE RP 431-2 or equivalent
+ PRIMARIES_EG432, ///< SMPTE EG 432-1 or equivalent
+ PRIMARIES_EBU3213, ///< EBU Tech.3213-E or equivalent
+ ///
+ PRIMARIES_VENDOR_START = 0x80, ///< vendor-specific primaries values start here
+ PRIMARIES_OTHER = 0xff ///< max value, reserved for undefined values
+)
+
+/// Transfer function
+C2ENUM(C2Color::transfer_t, uint32_t,
+ TRANSFER_UNSPECIFIED, ///< transfer is unspecified
+ TRANSFER_LINEAR, ///< Linear transfer characteristics
+ TRANSFER_SRGB, ///< sRGB or equivalent
+ TRANSFER_170M, ///< SMPTE 170M or equivalent (e.g. BT.601/709/2020)
+ TRANSFER_GAMMA22, ///< Assumed display gamma 2.2
+ TRANSFER_GAMMA28, ///< Assumed display gamma 2.8
+ TRANSFER_ST2084, ///< SMPTE ST 2084 for 10/12/14/16 bit systems
+ TRANSFER_HLG, ///< ARIB STD-B67 hybrid-log-gamma
+
+ TRANSFER_240M = 0x40, ///< SMPTE 240M or equivalent
+ TRANSFER_XVYCC, ///< IEC 61966-2-4 or equivalent
+ TRANSFER_BT1361, ///< Rec.ITU-R BT.1361 extended gamut
+ TRANSFER_ST428, ///< SMPTE ST 428-1 or equivalent
+ ///
+ TRANSFER_VENDOR_START = 0x80, ///< vendor-specific transfer values start here
+ TRANSFER_OTHER = 0xff ///< max value, reserved for undefined values
+)
+
+/// Matrix coefficient
+C2ENUM(C2Color::matrix_t, uint32_t,
+ MATRIX_UNSPECIFIED, ///< matrix coefficients are unspecified
+ MATRIX_BT709, ///< Rec.ITU-R BT.709-5 or equivalent
+ MATRIX_FCC47_73_682, ///< FCC Title 47 CFR 73.682 or equivalent (KR=0.30, KB=0.11)
+ MATRIX_BT601, ///< Rec.ITU-R BT.470, BT.601-6 625 or equivalent
+ MATRIX_240M, ///< SMPTE 240M or equivalent
+ MATRIX_BT2020, ///< Rec.ITU-R BT.2020 non-constant luminance
+ MATRIX_BT2020_CONSTANT, ///< Rec.ITU-R BT.2020 constant luminance
+ MATRIX_VENDOR_START = 0x80, ///< vendor-specific matrix coefficient values start here
+ MATRIX_OTHER = 0xff, ///< max value, reserved for undefined values
+
+ MATRIX_SMPTE240M = MATRIX_240M, // deprecated
+ MATRIX_BT2020CONSTANT = MATRIX_BT2020_CONSTANT, // deprecated
+)
+
+constexpr C2Color::matrix_t MATRIX_BT470_6M = MATRIX_FCC47_73_682; // deprecated
+constexpr C2Color::matrix_t MATRIX_BT709_5 = MATRIX_BT709; // deprecated
+constexpr C2Color::matrix_t MATRIX_BT601_6 = MATRIX_BT601; // deprecated
+
+struct C2ColorAspectsStruct {
+ C2Color::range_t range;
+ C2Color::primaries_t primaries;
+ C2Color::transfer_t transfer;
+ C2Color::matrix_t matrix;
+
+ C2ColorAspectsStruct()
+ : range(C2Color::RANGE_UNSPECIFIED),
+ primaries(C2Color::PRIMARIES_UNSPECIFIED),
+ transfer(C2Color::TRANSFER_UNSPECIFIED),
+ matrix(C2Color::MATRIX_UNSPECIFIED) { }
+
+ C2ColorAspectsStruct(C2Color::range_t range_, C2Color::primaries_t primaries_,
+ C2Color::transfer_t transfer_, C2Color::matrix_t matrix_)
+ : range(range_), primaries(primaries_), transfer(transfer_), matrix(matrix_) {}
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(ColorAspects)
+ C2FIELD(range, "range")
+ C2FIELD(primaries, "primaries")
+ C2FIELD(transfer, "transfer")
+ C2FIELD(matrix, "matrix")
+};
+
+typedef C2StreamParam<C2Info, C2ColorAspectsStruct, kParamIndexColorAspects>
+ C2StreamColorAspectsInfo;
+constexpr char C2_PARAMKEY_COLOR_ASPECTS[] = "raw.color";
+constexpr char C2_PARAMKEY_VUI_COLOR_ASPECTS[] = "coded.vui.color";
+
+/**
+ * Default color aspects to use. These come from the container or client and shall be handled
+ * according to the coding standard.
+ */
+typedef C2StreamParam<C2Tuning, C2ColorAspectsStruct, kParamIndexDefaultColorAspects>
+ C2StreamColorAspectsTuning;
+constexpr char C2_PARAMKEY_DEFAULT_COLOR_ASPECTS[] = "default.color";
+
+/**
+ * HDR Static Metadata Info.
+ */
+struct C2ColorXyStruct {
+ float x; ///< x color coordinate in xyY space [0-1]
+ float y; ///< y color coordinate in xyY space [0-1]
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(ColorXy)
+ C2FIELD(x, "x")
+ C2FIELD(y, "y")
+};
+
+struct C2MasteringDisplayColorVolumeStruct {
+ C2ColorXyStruct red; ///< coordinates of red display primary
+ C2ColorXyStruct green; ///< coordinates of green display primary
+ C2ColorXyStruct blue; ///< coordinates of blue display primary
+ C2ColorXyStruct white; ///< coordinates of white point
+
+ float maxLuminance; ///< max display mastering luminance in cd/m^2
+ float minLuminance; ///< min display mastering luminance in cd/m^2
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(MasteringDisplayColorVolume)
+ C2FIELD(red, "red")
+ C2FIELD(green, "green")
+ C2FIELD(blue, "blue")
+ C2FIELD(white, "white")
+
+ C2FIELD(maxLuminance, "max-luminance")
+ C2FIELD(minLuminance, "min-luminance")
+};
+
+struct C2HdrStaticMetadataStruct {
+ C2MasteringDisplayColorVolumeStruct mastering;
+
+ // content descriptors
+ float maxCll; ///< max content light level (pixel luminance) in cd/m^2
+ float maxFall; ///< max frame average light level (frame luminance) in cd/m^2
+
+ DEFINE_AND_DESCRIBE_BASE_C2STRUCT(HdrStaticMetadata)
+ C2FIELD(mastering, "mastering")
+ C2FIELD(maxCll, "max-cll")
+ C2FIELD(maxFall, "max-fall")
+};
+typedef C2StreamParam<C2Info, C2HdrStaticMetadataStruct, kParamIndexHdrStaticMetadata>
+ C2StreamHdrStaticInfo;
+constexpr char C2_PARAMKEY_HDR_STATIC_INFO[] = "raw.hdr-static-info";
+
+/* ------------------------------------ block-based coding ----------------------------------- */
+
+/**
+ * Block-size, block count and block rate. Used to determine or communicate profile-level
+ * requirements.
+ */
+typedef C2StreamParam<C2Info, C2PictureSizeStruct, kParamIndexBlockSize> C2StreamBlockSizeInfo;
+constexpr char C2_PARAMKEY_BLOCK_SIZE[] = "coded.block-size";
+
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexBlockCount> C2StreamBlockCountInfo;
+constexpr char C2_PARAMKEY_BLOCK_COUNT[] = "coded.block-count";
+
+typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexBlockRate> C2StreamBlockRateInfo;
+constexpr char C2_PARAMKEY_BLOCK_RATE[] = "coded.block-rate";
+
+/* ====================================== VIDEO COMPONENTS ====================================== */
+
+/**
+ * Frame rate (coded and port for raw data)
+ *
+ * Coded frame rates are what is represented in the compressed bitstream and should correspond to
+ * the timestamp.
+ *
+ * Frame rates on raw ports should still correspond to the timestamps.
+ *
+ * For slow motion or timelapse recording, the timestamp shall be adjusted prior to feeding an
+ * encoder, and the time stretch parameter should be used to signal the relationship between
+ * timestamp and real-world time.
+ */
+typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexFrameRate> C2StreamFrameRateInfo;
+constexpr char C2_PARAMKEY_FRAME_RATE[] = "coded.frame-rate";
+#define C2_NAME_STREAM_FRAME_RATE_SETTING C2_PARAMKEY_FRAME_RATE
+
+typedef C2PortParam<C2Info, C2FloatValue, kParamIndexFrameRate> C2PortFrameRateInfo;
+constexpr char C2_PARAMKEY_INPUT_FRAME_RATE[] = "input.frame-rate";
+constexpr char C2_PARAMKEY_OUTPUT_FRAME_RATE[] = "output.frame-rate";
+
+/**
+ * Time stretch. Ratio between real-world time and timestamp. E.g. time stretch of 4.0 means that
+ * timestamp grows 1/4 the speed of real-world time (e.g. 4x slo-mo input). This can be used to
+ * optimize encoding.
+ */
+typedef C2PortParam<C2Info, C2FloatValue, kParamIndexTimeStretch> C2PortTimeStretchInfo;
+constexpr char C2_PARAMKEY_INPUT_TIME_STRETCH[] = "input.time-stretch";
+constexpr char C2_PARAMKEY_OUTPUT_TIME_STRETCH[] = "output.time-stretch";
+
+/**
+ * Max video frame size.
+ */
+typedef C2StreamParam<C2Tuning, C2PictureSizeStruct, kParamIndexMaxPictureSize>
+ C2StreamMaxPictureSizeTuning;
+typedef C2StreamMaxPictureSizeTuning C2MaxVideoSizeHintPortSetting;
+constexpr char C2_PARAMKEY_MAX_PICTURE_SIZE[] = "raw.max-size";
+
+/**
+ * Picture type mask.
+ */
+C2ENUM(C2Config::picture_type_t, uint32_t,
+ SYNC_FRAME = (1 << 0), ///< sync frame, e.g. IDR
+ I_FRAME = (1 << 1), ///< intra frame that is completely encoded
+ P_FRAME = (1 << 2), ///< inter predicted frame from previous frames
+ B_FRAME = (1 << 3), ///< backward predicted (out-of-order) frame
+)
+
+typedef C2Config::picture_type_t C2PictureTypeMask; // deprecated
+constexpr C2Config::picture_type_t C2PictureTypeKeyFrame = C2Config::SYNC_FRAME; // deprecated
+
+/**
+ * Allowed picture types.
+ */
+typedef C2StreamParam<C2Tuning, C2SimpleValueStruct<C2EasyEnum<C2Config::picture_type_t>>,
+ kParamIndexPictureTypeMask>
+ C2StreamPictureTypeMaskTuning;
+constexpr char C2_PARAMKEY_PICTURE_TYPE_MASK[] = "coding.picture-type-mask";
+
+/**
+ * Resulting picture type
+ */
+typedef C2StreamParam<C2Info, C2SimpleValueStruct<C2EasyEnum<C2Config::picture_type_t>>,
+ kParamIndexPictureType>
+ C2StreamPictureTypeInfo;
+typedef C2StreamPictureTypeInfo C2StreamPictureTypeMaskInfo;
+constexpr char C2_PARAMKEY_PICTURE_TYPE[] = "coded.picture-type";
+
+/**
+ * GOP specification.
+ *
+ * GOP is specified in layers between sync frames, by specifying the number of specific type of
+ * frames between the previous type (starting with sync frames for the first layer):
+ *
+ * E.g.
+ * - 4 I frames between each sync frame
+ * - 2 P frames between each I frame
+ * - 1 B frame between each P frame
+ *
+ * [ { I, 4 }, { P, 2 }, { B, 1 } ] ==> (Sync)BPBPB IBPBPB IBPBPB IBPBPB IBPBPB (Sync)BPBPB
+ *
+ * For infinite GOP, I layer can be omitted (as the first frame is always a sync frame.):
+ *
+ * [ { P, MAX_UINT } ] ==> (Sync)PPPPPPPPPPPPPPPPPP...
+ *
+ * Sync frames can also be requested on demand, and as a time-based interval. For time-based
+ * interval, if there hasn't been a sync frame in at least the given time, the next I frame shall
+ * be encoded as a sync frame. For sync request, the next I frame shall be encoded as a sync frame.
+ *
+ * Temporal layering will determine GOP structure other than the I frame count between sync
+ * frames.
+ */
+struct C2GopLayerStruct {
+ C2GopLayerStruct(C2Config::picture_type_t type, uint32_t count_)
+ : type_(type), count(count_) { }
+
+ C2Config::picture_type_t type_;
+ uint32_t count;
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(GopLayer)
+ C2FIELD(type_, "type")
+ C2FIELD(count, "count")
+};
+
+typedef C2StreamParam<C2Tuning, C2SimpleArrayStruct<C2GopLayerStruct>, kParamIndexGop>
+ C2StreamGopTuning;
+constexpr char C2_PARAMKEY_GOP[] = "coding.gop";
+
+/**
+ * Sync frame can be requested on demand by the client.
+ *
+ * If true, the next I frame shall be encoded as a sync frame. This config can be passed
+ * synchronously with the work, or directly to the component - leading to different result.
+ * If it is passed with work, it shall take effect when that work item is being processed (so
+ * the first I frame at or after that work item shall be a sync frame).
+ */
+typedef C2StreamParam<C2Tuning, C2EasyBoolValue, kParamIndexRequestSyncFrame>
+ C2StreamRequestSyncFrameTuning;
+constexpr char C2_PARAMKEY_REQUEST_SYNC_FRAME[] = "coding.request-sync-frame";
+
+/**
+ * Sync frame interval in time domain (timestamp).
+ *
+ * If there hasn't been a sync frame in at least this value, the next intra frame shall be encoded
+ * as a sync frame. The value of MAX_I64 or a negative value means no sync frames after the first
+ * frame. A value of 0 means all sync frames.
+ */
+typedef C2StreamParam<C2Tuning, C2Int64Value, kParamIndexSyncFrameInterval>
+ C2StreamSyncFrameIntervalTuning;
+constexpr char C2_PARAMKEY_SYNC_FRAME_INTERVAL[] = "coding.sync-frame-interval";
+// deprecated
+#define C2_PARAMKEY_SYNC_FRAME_PERIOD C2_PARAMKEY_SYNC_FRAME_INTERVAL
+
+/**
+ * Temporal layering
+ *
+ * Layer index is a value between 0 and layer count - 1. Layers with higher index have higher
+ * frequency:
+ * 0
+ * 1 1
+ * 2 2 2 2
+ */
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexLayerIndex> C2StreamLayerIndexInfo;
+constexpr char C2_PARAMKEY_LAYER_INDEX[] = "coded.layer-index";
+
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexLayerCount> C2StreamLayerCountInfo;
+constexpr char C2_PARAMKEY_LAYER_COUNT[] = "coded.layer-count";
+
+struct C2TemporalLayeringStruct {
+ C2TemporalLayeringStruct()
+ : layerCount(0), bLayerCount(0) { }
+
+ C2TemporalLayeringStruct(size_t /* flexCount */, uint32_t layerCount_, uint32_t bLayerCount_)
+ : layerCount(layerCount_), bLayerCount(c2_min(layerCount_, bLayerCount_)) { }
+
+ C2TemporalLayeringStruct(size_t flexCount, uint32_t layerCount_, uint32_t bLayerCount_,
+ std::initializer_list<float> ratios)
+ : layerCount(layerCount_), bLayerCount(c2_min(layerCount_, bLayerCount_)) {
+ size_t ix = 0;
+ for (float ratio : ratios) {
+ if (ix == flexCount) {
+ break;
+ }
+ bitrateRatios[ix++] = ratio;
+ }
+ }
+
+ uint32_t layerCount; ///< total number of layers (0 means no temporal layering)
+ uint32_t bLayerCount; ///< total number of bidirectional layers (<= num layers)
+ /**
+ * Bitrate budgets for each layer and the layers below, given as a ratio of the total
+ * stream bitrate. This can be omitted or partially specififed by the client while configuring,
+ * in which case the component shall fill in appropriate values for the missing layers.
+ * This must be provided by the component when queried for at least layer count - 1 (as the
+ * last layer's budget is always 1.0).
+ */
+ float bitrateRatios[]; ///< 1.0-based
+
+ DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(TemporalLayering, bitrateRatios)
+ C2FIELD(layerCount, "layer-count")
+ C2FIELD(bLayerCount, "b-layer-count")
+ C2FIELD(bitrateRatios, "bitrate-ratios")
+};
+
+typedef C2StreamParam<C2Tuning, C2TemporalLayeringStruct, kParamIndexTemporalLayering>
+ C2StreamTemporalLayeringTuning;
+constexpr char C2_PARAMKEY_TEMPORAL_LAYERING[] = "coding.temporal-layering";
+
+/**
+ * Intra-refresh.
+ */
+
+C2ENUM(C2Config::intra_refresh_mode_t, uint32_t,
+ INTRA_REFRESH_DISABLED, ///< no intra refresh
+ INTRA_REFRESH_ARBITRARY, ///< arbitrary, unspecified
+)
+
+struct C2IntraRefreshStruct {
+ C2IntraRefreshStruct()
+ : mode(C2Config::INTRA_REFRESH_DISABLED), period(0.) { }
+
+ C2IntraRefreshStruct(C2Config::intra_refresh_mode_t mode_, float period_)
+ : mode(mode_), period(period_) { }
+
+ C2Config::intra_refresh_mode_t mode; ///< refresh mode
+ float period; ///< intra refresh period in frames (must be >= 1), 0 means disabled
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(IntraRefresh)
+ C2FIELD(mode, "mode")
+ C2FIELD(period, "period")
+};
+
+typedef C2StreamParam<C2Tuning, C2IntraRefreshStruct, kParamIndexIntraRefresh>
+ C2StreamIntraRefreshTuning;
+constexpr char C2_PARAMKEY_INTRA_REFRESH[] = "coding.intra-refresh";
+
+/* ====================================== IMAGE COMPONENTS ====================================== */
+
+/**
+ * Tile layout.
+ *
+ * This described how the image is decomposed into tiles.
+ */
+C2ENUM(C2Config::scan_order_t, uint32_t,
+ SCAN_LEFT_TO_RIGHT_THEN_DOWN
+)
+
+struct C2TileLayoutStruct {
+ C2PictureSizeStruct tile; ///< tile size
+ uint32_t columnCount; ///< number of tiles horizontally
+ uint32_t rowCount; ///< number of tiles vertically
+ C2Config::scan_order_t order; ///< tile order
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(TileLayout)
+ C2FIELD(tile, "tile")
+ C2FIELD(columnCount, "columns")
+ C2FIELD(rowCount, "rows")
+ C2FIELD(order, "order")
+};
+
+typedef C2StreamParam<C2Info, C2TileLayoutStruct, kParamIndexTileLayout> C2StreamTileLayoutInfo;
+constexpr char C2_PARAMKEY_TILE_LAYOUT[] = "coded.tile-layout";
+
+/**
+ * Tile handling.
+ *
+ * Whether to concatenate tiles or output them each.
+ */
+C2ENUM(C2Config::tiling_mode_t, uint32_t,
+ TILING_SEPARATE, ///< output each tile in a separate onWorkDone
+ TILING_CONCATENATE ///< output one work completion per frame (concatenate tiles)
+)
+
+typedef C2StreamParam<C2Tuning, C2TileLayoutStruct, kParamIndexTileHandling>
+ C2StreamTileHandlingTuning;
+constexpr char C2_PARAMKEY_TILE_HANDLING[] = "coding.tile-handling";
+
+/* ====================================== AUDIO COMPONENTS ====================================== */
+
+/**
+ * Sample rate
+ */
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexSampleRate> C2StreamSampleRateInfo;
+constexpr char C2_PARAMKEY_SAMPLE_RATE[] = "raw.sample-rate";
+constexpr char C2_PARAMKEY_CODED_SAMPLE_RATE[] = "coded.sample-rate";
+// deprecated
+#define C2_NAME_STREAM_SAMPLE_RATE_SETTING C2_PARAMKEY_SAMPLE_RATE
+
+/**
+ * Channel count.
+ */
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexChannelCount> C2StreamChannelCountInfo;
+constexpr char C2_PARAMKEY_CHANNEL_COUNT[] = "raw.channel-count";
+constexpr char C2_PARAMKEY_CODED_CHANNEL_COUNT[] = "coded.channel-count";
+// deprecated
+#define C2_NAME_STREAM_CHANNEL_COUNT_SETTING C2_PARAMKEY_CHANNEL_COUNT
+
+/**
+ * Max channel count. Used to limit the number of coded or decoded channels.
+ */
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexMaxChannelCount> C2StreamMaxChannelCountInfo;
+constexpr char C2_PARAMKEY_MAX_CHANNEL_COUNT[] = "raw.max-channel-count";
+constexpr char C2_PARAMKEY_MAX_CODED_CHANNEL_COUNT[] = "coded.max-channel-count";
+
+/**
+ * Audio sample format (PCM encoding)
+ */
+C2ENUM(C2Config::pcm_encoding_t, uint32_t,
+ PCM_16,
+ PCM_8,
+ PCM_FLOAT
+)
+
+typedef C2StreamParam<C2Info, C2SimpleValueStruct<C2Config::pcm_encoding_t>, kParamIndexPcmEncoding>
+ C2StreamPcmEncodingInfo;
+constexpr char C2_PARAMKEY_PCM_ENCODING[] = "raw.pcm-encoding";
+constexpr char C2_PARAMKEY_CODED_PCM_ENCODING[] = "coded.pcm-encoding";
+
+/**
+ * AAC SBR Mode. Used during encoding.
+ */
+C2ENUM(C2Config::aac_sbr_mode_t, uint32_t,
+ AAC_SBR_OFF,
+ AAC_SBR_SINGLE_RATE,
+ AAC_SBR_DUAL_RATE,
+ AAC_SBR_AUTO ///< let the codec decide
+)
+
+typedef C2StreamParam<C2Info, C2SimpleValueStruct<C2Config::aac_sbr_mode_t>, kParamIndexAacSbrMode>
+ C2StreamAacSbrModeTuning;
+constexpr char C2_PARAMKEY_AAC_SBR_MODE[] = "coding.aac-sbr-mode";
+
+/**
+ * DRC Compression. Used during decoding.
+ */
+C2ENUM(C2Config::drc_compression_mode_t, int32_t,
+ DRC_COMPRESSION_ODM_DEFAULT, ///< odm's default
+ DRC_COMPRESSION_NONE,
+ DRC_COMPRESSION_LIGHT,
+ DRC_COMPRESSION_HEAVY ///<
+)
+
+typedef C2StreamParam<C2Info, C2SimpleValueStruct<C2Config::drc_compression_mode_t>,
+ kParamIndexDrcCompression>
+ C2StreamDrcCompressionModeTuning;
+constexpr char C2_PARAMKEY_DRC_COMPRESSION_MODE[] = "coding.drc.compression-mode";
+
+/**
+ * DRC target reference level in dBFS. Used during decoding.
+ */
+typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexDrcTargetReferenceLevel>
+ C2StreamDrcTargetReferenceLevelTuning;
+constexpr char C2_PARAMKEY_DRC_TARGET_REFERENCE_LEVEL[] = "coding.drc.reference-level";
+
+/**
+ * DRC target reference level in dBFS. Used during decoding.
+ */
+typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexDrcEncodedTargetLevel>
+ C2StreamDrcEncodedTargetLevelTuning;
+constexpr char C2_PARAMKEY_DRC_ENCODED_TARGET_LEVEL[] = "coding.drc.encoded-level";
+
+/**
+ * DRC target reference level in dBFS. Used during decoding.
+ */
+typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexDrcBoostFactor>
+ C2StreamDrcBoostFactorTuning;
+constexpr char C2_PARAMKEY_DRC_BOOST_FACTOR[] = "coding.drc.boost-factor";
+
+/**
+ * DRC target reference level in dBFS. Used during decoding.
+ */
+typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexDrcAttenuationFactor>
+ C2StreamDrcAttenuationFactorTuning;
+constexpr char C2_PARAMKEY_DRC_ATTENUATION_FACTOR[] = "coding.drc.attenuation-factor";
+
+/**
+ * DRC Effect Type (see ISO 23003-4) Uniform Dynamic Range Control. Used during decoding.
+ */
+C2ENUM(C2Config::drc_effect_type_t, int32_t,
+ DRC_EFFECT_ODM_DEFAULT = -2, ///< odm's default
+ DRC_EFFECT_OFF = -1, ///< no DRC
+ DRC_EFFECT_NONE = 0, ///< no DRC except to prevent clipping
+ DRC_EFFECT_LATE_NIGHT,
+ DRC_EFFECT_NOISY_ENVIRONMENT,
+ DRC_EFFECT_LIMITED_PLAYBACK_RANGE,
+ DRC_EFFECT_LOW_PLAYBACK_LEVEL,
+ DRC_EFFECT_DIALOG_ENHANCEMENT,
+ DRC_EFFECT_GENERAL_COMPRESSION
+)
+
+typedef C2StreamParam<C2Info, C2SimpleValueStruct<C2Config::drc_effect_type_t>,
+ kParamIndexDrcEffectType>
+ C2StreamDrcEffectTypeTuning;
+constexpr char C2_PARAMKEY_DRC_EFFECT_TYPE[] = "coding.drc.effect-type";
+
+/* --------------------------------------- AAC components --------------------------------------- */
+
+/**
+ * AAC stream format
+ */
+C2ENUM(C2Config::aac_packaging_t, uint32_t,
+ AAC_PACKAGING_RAW,
+ AAC_PACKAGING_ADTS
+)
+
+typedef C2Config::aac_packaging_t C2AacStreamFormatKind; // deprecated
+// deprecated
+constexpr C2Config::aac_packaging_t C2AacStreamFormatRaw = C2Config::AAC_PACKAGING_RAW;
+constexpr C2Config::aac_packaging_t C2AacStreamFormatAdts = C2Config::AAC_PACKAGING_ADTS;
+
+typedef C2StreamParam<C2Info, C2SimpleValueStruct<C2EasyEnum<C2Config::aac_packaging_t>>,
+ kParamIndexAacPackaging> C2StreamAacPackagingInfo;
+typedef C2StreamAacPackagingInfo C2StreamAacFormatInfo;
+constexpr char C2_PARAMKEY_AAC_PACKAGING[] = "coded.aac-packaging";
+#define C2_NAME_STREAM_AAC_FORMAT_SETTING C2_PARAMKEY_AAC_PACKAGING
+
+/* ================================ PLATFORM-DEFINED PARAMETERS ================================ */
+
+/**
+ * Platform level and features.
+ */
+enum C2Config::platform_level_t : uint32_t {
+ PLATFORM_P, ///< support for Android 9.0 feature set
+};
+
+// read-only
+typedef C2GlobalParam<C2Setting, C2SimpleValueStruct<C2Config::platform_level_t>,
+ kParamIndexPlatformLevel>
+ C2PlatformLevelSetting;
+constexpr char C2_PARAMKEY_PLATFORM_LEVEL[] = "api.platform-level";
+
+enum C2Config::platform_feature_t : uint64_t {
+ // no platform-specific features have been defined
+};
+
+// read-only
+typedef C2GlobalParam<C2Setting, C2SimpleValueStruct<C2Config::platform_feature_t>,
+ kParamIndexPlatformFeatures>
+ C2PlatformFeaturesSetting;
+constexpr char C2_PARAMKEY_PLATFORM_FEATURES[] = "api.platform-features";
+
+/**
+ * This structure describes the preferred ion allocation parameters for a given memory usage.
+ */
+struct C2StoreIonUsageStruct {
+ inline C2StoreIonUsageStruct() {
+ memset(this, 0, sizeof(*this));
+ }
+
+ inline C2StoreIonUsageStruct(uint64_t usage_, uint32_t capacity_)
+ : usage(usage_), capacity(capacity_), heapMask(0), allocFlags(0), minAlignment(0) { }
+
+ uint64_t usage; ///< C2MemoryUsage
+ uint32_t capacity; ///< capacity
+ int32_t heapMask; ///< ion heapMask
+ int32_t allocFlags; ///< ion allocation flags
+ uint32_t minAlignment; ///< minimum alignment
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(StoreIonUsage)
+ C2FIELD(usage, "usage")
+ C2FIELD(capacity, "capacity")
+ C2FIELD(heapMask, "heap-mask")
+ C2FIELD(allocFlags, "alloc-flags")
+ C2FIELD(minAlignment, "min-alignment")
+};
+
+// store, private
+typedef C2GlobalParam<C2Info, C2StoreIonUsageStruct, kParamIndexStoreIonUsage>
+ C2StoreIonUsageInfo;
+
+/**
+ * Flexible pixel format descriptors
+ */
+struct C2FlexiblePixelFormatDescriptorStruct {
+ uint32_t pixelFormat;
+ uint32_t bitDepth;
+ C2Color::subsampling_t subsampling;
+ C2Color::plane_layout_t layout;
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(FlexiblePixelFormatDescriptor)
+ C2FIELD(pixelFormat, "pixel-format")
+ C2FIELD(bitDepth, "bit-depth")
+ C2FIELD(subsampling, "subsampling")
+ C2FIELD(layout, "layout")
+};
+
+/**
+ * Plane layout of flexible pixel formats.
+ *
+ * bpp: bytes per color component, e.g. 1 for 8-bit formats, and 2 for 10-16-bit formats.
+ */
+C2ENUM(C2Color::plane_layout_t, uint32_t,
+ /** Unknown layout */
+ UNKNOWN_LAYOUT,
+
+ /** Planar layout with rows of each plane packed (colInc = bpp) */
+ PLANAR_PACKED,
+
+ /** Semiplanar layout with rows of each plane packed (colInc_Y/A = bpp (planar),
+ * colInc_Cb/Cr = 2*bpp (interleaved). Used only for YUV(A) formats. */
+ SEMIPLANAR_PACKED,
+
+ /** Interleaved packed. colInc = N*bpp (N are the number of color components) */
+ INTERLEAVED_PACKED,
+
+ /** Interleaved aligned. colInc = smallest power of 2 >= N*bpp (N are the number of color
+ * components) */
+ INTERLEAVED_ALIGNED
+)
+
+typedef C2GlobalParam<C2Info, C2SimpleArrayStruct<C2FlexiblePixelFormatDescriptorStruct>,
+ kParamIndexFlexiblePixelFormatDescriptors>
+ C2StoreFlexiblePixelFormatDescriptorsInfo;
+
+/**
+ * This structure describes the android dataspace for a raw video/image frame.
+ */
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexDataSpace> C2StreamDataSpaceInfo;
+constexpr char C2_PARAMKEY_DATA_SPACE[] = "raw.data-space";
+
+/**
+ * This structure describes the android surface scaling mode for a raw video/image frame.
+ */
+typedef C2StreamParam<C2Info, C2Uint32Value, kParamIndexSurfaceScaling> C2StreamSurfaceScalingInfo;
+constexpr char C2_PARAMKEY_SURFACE_SCALING_MODE[] = "raw.surface-scaling";
+
+/* ======================================= INPUT SURFACE ======================================= */
+
+/**
+ * Input surface EOS
+ */
+typedef C2GlobalParam<C2Tuning, C2EasyBoolValue, kParamIndexInputSurfaceEos>
+ C2InputSurfaceEosTuning;
+constexpr char C2_PARAMKEY_INPUT_SURFACE_EOS[] = "input-surface.eos";
+#define C2_NAME_INPUT_SURFACE_EOS_TUNING C2_PARAMKEY_INPUT_SURFACE_EOS
+
+/**
+ * Start/suspend/resume/stop controls and timestamps for input surface.
+ *
+ * TODO: make these counters
+ */
+
+struct C2TimedControlStruct {
+ c2_bool_t enabled; ///< control is enabled
+ int64_t timestamp; ///< if enabled, time the control should take effect
+
+ C2TimedControlStruct()
+ : enabled(C2_FALSE), timestamp(0) { }
+
+ /* implicit */ C2TimedControlStruct(uint64_t timestamp_)
+ : enabled(C2_TRUE), timestamp(timestamp_) { }
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(TimedControl)
+ C2FIELD(enabled, "enabled")
+ C2FIELD(timestamp, "timestamp")
+};
+
+typedef C2PortParam<C2Tuning, C2TimedControlStruct, kParamIndexStartAt>
+ C2PortStartTimestampTuning;
+constexpr char C2_PARAMKEY_INPUT_SURFACE_START_AT[] = "input-surface.start";
+typedef C2PortParam<C2Tuning, C2TimedControlStruct, kParamIndexSuspendAt>
+ C2PortSuspendTimestampTuning;
+constexpr char C2_PARAMKEY_INPUT_SURFACE_SUSPEND_AT[] = "input-surface.suspend";
+typedef C2PortParam<C2Tuning, C2TimedControlStruct, kParamIndexResumeAt>
+ C2PortResumeTimestampTuning;
+constexpr char C2_PARAMKEY_INPUT_SURFACE_RESUME_AT[] = "input-surface.resume";
+typedef C2PortParam<C2Tuning, C2TimedControlStruct, kParamIndexStopAt>
+ C2PortStopTimestampTuning;
+constexpr char C2_PARAMKEY_INPUT_SURFACE_STOP_AT[] = "input-surface.stop";
+
+/**
+ * Time offset for input surface. Input timestamp to codec is surface buffer timestamp plus this
+ * time offset.
+ */
+typedef C2GlobalParam<C2Tuning, C2Int64Value, kParamIndexTimeOffset> C2ComponentTimeOffsetTuning;
+constexpr char C2_PARAMKEY_INPUT_SURFACE_TIME_OFFSET[] = "input-surface.time-offset";
+
+/**
+ * Minimum fps for input surface.
+ *
+ * Repeat frame to meet this.
+ */
+typedef C2PortParam<C2Tuning, C2FloatValue, kParamIndexMinFrameRate> C2PortMinFrameRateTuning;
+constexpr char C2_PARAMKEY_INPUT_SURFACE_MIN_FRAME_RATE[] = "input-surface.min-frame-rate";
+
+/**
+ * Timestamp adjustment (override) for input surface buffers. These control the input timestamp
+ * fed to the codec, but do not impact the output timestamp.
+ */
+struct C2TimestampGapAdjustmentStruct {
+ /// control modes
+ enum mode_t : uint32_t;
+
+ inline C2TimestampGapAdjustmentStruct();
+
+ inline C2TimestampGapAdjustmentStruct(mode_t mode_, uint64_t value_)
+ : mode(mode_), value(value_) { }
+
+ mode_t mode; ///< control mode
+ uint64_t value; ///< control value for gap between two timestamp
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(TimestampGapAdjustment)
+ C2FIELD(mode, "mode")
+ C2FIELD(value, "value")
+};
+
+C2ENUM(C2TimestampGapAdjustmentStruct::mode_t, uint32_t,
+ NONE,
+ MIN_GAP,
+ FIXED_GAP,
+);
+
+inline C2TimestampGapAdjustmentStruct::C2TimestampGapAdjustmentStruct()
+ : mode(C2TimestampGapAdjustmentStruct::NONE), value(0) { }
+
+typedef C2PortParam<C2Tuning, C2TimestampGapAdjustmentStruct> C2PortTimestampGapTuning;
+constexpr char C2_PARAMKEY_INPUT_SURFACE_TIMESTAMP_ADJUSTMENT[] = "input-surface.timestamp-adjustment";
+
+/// @}
+
+#endif // C2CONFIG_H_
diff --git a/media/codec2/include/C2Enum.h b/media/codec2/include/C2Enum.h
new file mode 100644
index 0000000..b0fad8f
--- /dev/null
+++ b/media/codec2/include/C2Enum.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef C2ENUM_H_
+#define C2ENUM_H_
+
+#include <C2Param.h>
+#include <_C2MacroUtils.h>
+
+#include <utility>
+#include <vector>
+
+/** \file
+ * Tools for easier enum support.
+ */
+
+/// \cond INTERNAL
+
+/* ---------------------------- UTILITIES FOR ENUMERATION REFLECTION ---------------------------- */
+
+/**
+ * Utility class that allows ignoring enum value assignment (e.g. both '(_C2EnumConst)kValue = x'
+ * and '(_C2EnumConst)kValue' will eval to kValue.
+ */
+template<typename T>
+class _C2EnumConst {
+public:
+ // implicit conversion from T
+ inline _C2EnumConst(T value) : _mValue(value) {}
+ // implicit conversion to T
+ inline operator T() { return _mValue; }
+ // implicit conversion to C2Value::Primitive
+ inline operator C2Value::Primitive() { return (T)_mValue; }
+ // ignore assignment and return T here to avoid implicit conversion to T later
+ inline T &operator =(T value __unused) { return _mValue; }
+private:
+ T _mValue;
+};
+
+/// mapper to get name of enum
+/// \note this will contain any initialization, which we will remove when converting to lower-case
+#define _C2_GET_ENUM_NAME(x, y) #x
+/// mapper to get value of enum
+#define _C2_GET_ENUM_VALUE(x, type) (_C2EnumConst<type>)x
+
+/// \endcond
+
+class _C2EnumUtils {
+ static C2String camelCaseToDashed(C2String name);
+
+ static std::vector<C2String> sanitizeEnumValueNames(
+ const std::vector<C2StringLiteral> names,
+ C2StringLiteral _prefix = nullptr);
+
+ friend class C2UtilTest_EnumUtilsTest_Test;
+
+public:
+ // this may not be used...
+ static C2_HIDE std::vector<C2String> parseEnumValuesFromString(C2StringLiteral value);
+
+ template<typename T>
+ static C2_HIDE C2FieldDescriptor::NamedValuesType sanitizeEnumValues(
+ std::vector<T> values,
+ std::vector<C2StringLiteral> names,
+ C2StringLiteral prefix = nullptr) {
+ C2FieldDescriptor::NamedValuesType namedValues;
+ std::vector<C2String> sanitizedNames = sanitizeEnumValueNames(names, prefix);
+ for (size_t i = 0; i < values.size() && i < sanitizedNames.size(); ++i) {
+ namedValues.emplace_back(sanitizedNames[i], values[i]);
+ }
+ return namedValues;
+ }
+
+ template<typename E>
+ static C2_HIDE C2FieldDescriptor::NamedValuesType customEnumValues(
+ std::vector<std::pair<C2StringLiteral, E>> items) {
+ C2FieldDescriptor::NamedValuesType namedValues;
+ for (auto &item : items) {
+ namedValues.emplace_back(item.first, item.second);
+ }
+ return namedValues;
+ }
+};
+
+#define DEFINE_C2_ENUM_VALUE_AUTO_HELPER(name, type, prefix, ...) \
+ _DEFINE_C2_ENUM_VALUE_AUTO_HELPER(__C2_GENERATE_GLOBAL_VARS__, name, type, prefix, \
+ ##__VA_ARGS__)
+#define _DEFINE_C2_ENUM_VALUE_AUTO_HELPER(enabled, name, type, prefix, ...) \
+ __DEFINE_C2_ENUM_VALUE_AUTO_HELPER(enabled, name, type, prefix, ##__VA_ARGS__)
+#define __DEFINE_C2_ENUM_VALUE_AUTO_HELPER(enabled, name, type, prefix, ...) \
+ ___DEFINE_C2_ENUM_VALUE_AUTO_HELPER##enabled(name, type, prefix, ##__VA_ARGS__)
+#define ___DEFINE_C2_ENUM_VALUE_AUTO_HELPER(name, type, prefix, ...) \
+template<> \
+C2FieldDescriptor::NamedValuesType C2FieldDescriptor::namedValuesFor(const name &r __unused) { \
+ return _C2EnumUtils::sanitizeEnumValues( \
+ std::vector<C2Value::Primitive> { _C2_MAP(_C2_GET_ENUM_VALUE, type, __VA_ARGS__) }, \
+ { _C2_MAP(_C2_GET_ENUM_NAME, type, __VA_ARGS__) }, \
+ prefix); \
+}
+#define ___DEFINE_C2_ENUM_VALUE_AUTO_HELPER__C2_GENERATE_GLOBAL_VARS__(name, type, prefix, ...)
+
+#define DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(name, names) \
+ _DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(__C2_GENERATE_GLOBAL_VARS__, name, names)
+#define _DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(enabled, name, names) \
+ __DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(enabled, name, names)
+#define __DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(enabled, name, names) \
+ ___DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER##enabled(name, names)
+#define ___DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(name, names) \
+template<> \
+C2FieldDescriptor::NamedValuesType C2FieldDescriptor::namedValuesFor(const name &r __unused) { \
+ return _C2EnumUtils::customEnumValues( \
+ std::vector<std::pair<C2StringLiteral, name>> names); \
+}
+#define ___DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER__C2_GENERATE_GLOBAL_VARS__(name, names)
+
+/**
+ * Defines an enum type with the default named value mapper. The default mapper
+ * finds and removes the longest common prefix across all of the enum value names, and
+ * replaces camel-case separators with dashes ('-').
+ *
+ * This macro must be used in the global scope and namespace.
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ * C2ENUM(c2_enum_t, uint32_t,
+ * C2_VALUE1,
+ * C2_VALUE2 = 5,
+ * C2_VALUE3 = C2_VALUE1 + 1)
+ * // named values are: C2_VALUE1 => "1", C2_VALUE2 => "2", ...
+ * // longest common prefix is "C2_VALUE"
+ * ~~~~~~~~~~~~~
+ *
+ * \param name name of the enum type (This can be an inner class enum.)
+ * \param type underlying type
+ */
+#define C2ENUM(name, type, ...) \
+enum name : type { __VA_ARGS__ }; \
+DEFINE_C2_ENUM_VALUE_AUTO_HELPER(name, type, nullptr, __VA_ARGS__)
+
+/**
+ * Defines an enum type with the default named value mapper but custom prefix. The default
+ * mapper removes the prefix from all of the enum value names (if present), and
+ * inserts dashes at camel-case separators (lowHigh becomes low-high) and also replaces
+ * non-leading underscores with dashes ('-').
+ *
+ * This macro must be used in the global scope and namespace.
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ * C2ENUM_CUSTOM_PREFIX(c2_enum_t, uint32_t, "C2_",
+ * C2_VALUE1,
+ * C2_VALUE2 = 5,
+ * C2_VALUE3 = C2_VALUE1 + 1)
+ * // named values are: C2_VALUE1 => "VALUE1", C2_VALUE2 => "VALUE2", ...
+ * ~~~~~~~~~~~~~
+ *
+ * \param name name of the enum type (This can be an inner class enum.)
+ * \param type underlying type
+ * \param prefix prefix to remove
+ */
+#define C2ENUM_CUSTOM_PREFIX(name, type, prefix, ...) \
+enum name : type { __VA_ARGS__ }; \
+DEFINE_C2_ENUM_VALUE_AUTO_HELPER(name, type, prefix, __VA_ARGS__)
+
+/**
+ * Defines an enum type with custom names.
+ *
+ * This macro must be used in the global scope and namespace.
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ * C2ENUM_CUSTOM_NAMES(SomeStruct::c2_enum_t, uint32_t, ({
+ * { "One", SomeStruct::C2_VALUE1 },
+ * { "Two", SomeStruct::C2_VALUE2 },
+ * { "Three", SomeStruct::C2_VALUE3 } }),
+ * C2_VALUE1,
+ * C2_VALUE2 = 5,
+ * C2_VALUE3 = C2_VALUE1 + 1)
+ *
+ * // named values are: C2_VALUE1 => "One", C2_VALUE2 => "Two", ...
+ * ~~~~~~~~~~~~~
+ */
+#define C2ENUM_CUSTOM_NAMES(name, type, names, ...) \
+enum name : type { __VA_ARGS__ }; \
+DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(name, names)
+
+/**
+ * Make enums usable as their integral types.
+ *
+ * Note: this makes them not usable in printf()
+ */
+template<class E>
+struct C2EasyEnum {
+ using U = typename std::underlying_type<E>::type;
+ E value;
+ // define conversion functions
+ inline constexpr operator E() const { return value; }
+ inline constexpr C2EasyEnum(E value_) : value(value_) { }
+ inline constexpr C2EasyEnum(U value_) : value(E(value_)) { }
+ inline constexpr C2EasyEnum() = default;
+};
+
+// make C2EasyEnum behave like a regular enum
+
+namespace std {
+ template<typename E>
+ struct underlying_type<C2EasyEnum<E>> {
+ typedef typename underlying_type<E>::type type;
+ };
+
+ template<typename E>
+ struct is_enum<C2EasyEnum<E>> {
+ constexpr static bool value = true;
+ };
+}
+
+#endif // C2ENUM_H_
+
diff --git a/media/codec2/include/C2Param.h b/media/codec2/include/C2Param.h
new file mode 100644
index 0000000..40be3b3
--- /dev/null
+++ b/media/codec2/include/C2Param.h
@@ -0,0 +1,1673 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef C2PARAM_H_
+#define C2PARAM_H_
+
+#include <C2.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+/// \addtogroup Parameters
+/// @{
+
+/// \defgroup internal Internal helpers.
+
+/*!
+ * \file
+ * PARAMETERS: SETTINGs, TUNINGs, and INFOs
+ * ===
+ *
+ * These represent miscellaneous control and metadata information and are likely copied into
+ * kernel space. Therefore, these are C-like structures designed to carry just a small amount of
+ * information. We are using C++ to be able to add constructors, as well as non-virtual and class
+ * methods.
+ *
+ * ==Specification details:
+ *
+ * Restrictions:
+ * - must be POD struct, e.g. no vtable (no virtual destructor)
+ * - must have the same size in 64-bit and 32-bit mode (no size_t)
+ * - as such, no pointer members
+ * - some common member field names are reserved as they are defined as methods for all
+ * parameters:
+ * they are: size, type, kind, index and stream
+ *
+ * Behavior:
+ * - Params can be global (not related to input or output), related to input or output,
+ * or related to an input/output stream.
+ * - All params are queried/set using a unique param index, which incorporates a potential stream
+ * index and/or port.
+ * - Querying (supported) params MUST never fail.
+ * - All params MUST have default values.
+ * - If some fields have "unsupported" or "invalid" values during setting, this SHOULD be
+ * communicated to the app.
+ * a) Ideally, this should be avoided. When setting parameters, in general, component should do
+ * "best effort" to apply all settings. It should change "invalid/unsupported" values to the
+ * nearest supported values.
+ * - This is communicated to the client by changing the source values in tune()/
+ * configure().
+ * b) If falling back to a supported value is absolutely impossible, the component SHALL return
+ * an error for the specific setting, but should continue to apply other settings.
+ * TODO: this currently may result in unintended results.
+ *
+ * **NOTE:** unlike OMX, params are not versioned. Instead, a new struct with new param index
+ * SHALL be added as new versions are required.
+ *
+ * The proper subtype (Setting, Info or Param) is incorporated into the class type. Define structs
+ * to define multiple subtyped versions of related parameters.
+ *
+ * ==Implementation details:
+ *
+ * - Use macros to define parameters
+ * - All parameters must have a default constructor
+ * - This is only used for instantiating the class in source (e.g. will not be used
+ * when building a parameter by the framework from key/value pairs.)
+ */
+
+/// \ingroup internal
+
+/**
+ * Parameter base class.
+ */
+struct C2Param {
+ // param index encompasses the following:
+ //
+ // - kind (setting, tuning, info, struct)
+ // - scope
+ // - direction (global, input, output)
+ // - stream flag
+ // - stream ID (usually 0)
+ // - and the parameter's type (core index)
+ // - flexible parameter flag
+ // - vendor extension flag
+ // - type index (this includes the vendor extension flag)
+ //
+ // layout:
+ //
+ // kind : <------- scope -------> : <----- core index ----->
+ // +------+-----+---+------+--------+----|------+--------------+
+ // | kind | dir | - |stream|streamID|flex|vendor| type index |
+ // +------+-----+---+------+--------+----+------+--------------+
+ // bit: 31..30 29.28 25 24 .. 17 16 15 14 .. 0
+ //
+public:
+ /**
+ * C2Param kinds, usable as bitmaps.
+ */
+ enum kind_t : uint32_t {
+ NONE = 0,
+ STRUCT = (1 << 0),
+ INFO = (1 << 1),
+ SETTING = (1 << 2),
+ TUNING = (1 << 3) | SETTING, // tunings are settings
+ };
+
+ /**
+ * The parameter type index specifies the underlying parameter type of a parameter as
+ * an integer value.
+ *
+ * Parameter types are divided into two groups: platform types and vendor types.
+ *
+ * Platform types are defined by the platform and are common for all implementations.
+ *
+ * Vendor types are defined by each vendors, so they may differ between implementations.
+ * It is recommended that vendor types be the same for all implementations by a specific
+ * vendor.
+ */
+ typedef uint32_t type_index_t;
+ enum : uint32_t {
+ TYPE_INDEX_VENDOR_START = 0x00008000, ///< vendor indices SHALL start after this
+ };
+
+ /**
+ * Core index is the underlying parameter type for a parameter. It is used to describe the
+ * layout of the parameter structure regardless of the component or parameter kind/scope.
+ *
+ * It is used to identify and distinguish global parameters, and also parameters on a given
+ * port or stream. They must be unique for the set of global parameters, as well as for the
+ * set of parameters on each port or each stream, but the same core index can be used for
+ * parameters on different streams or ports, as well as for global parameters and port/stream
+ * parameters.
+ *
+ * Multiple parameter types can share the same layout.
+ *
+ * \note The layout for all parameters with the same core index across all components must
+ * be identical.
+ */
+ struct CoreIndex {
+ //public:
+ enum : uint32_t {
+ IS_FLEX_FLAG = 0x00010000,
+ };
+
+ protected:
+ enum : uint32_t {
+ KIND_MASK = 0xC0000000,
+ KIND_STRUCT = 0x00000000,
+ KIND_TUNING = 0x40000000,
+ KIND_SETTING = 0x80000000,
+ KIND_INFO = 0xC0000000,
+
+ DIR_MASK = 0x30000000,
+ DIR_GLOBAL = 0x20000000,
+ DIR_UNDEFINED = DIR_MASK, // MUST have all bits set
+ DIR_INPUT = 0x00000000,
+ DIR_OUTPUT = 0x10000000,
+
+ IS_STREAM_FLAG = 0x02000000,
+ STREAM_ID_MASK = 0x01FE0000,
+ STREAM_ID_SHIFT = 17,
+ MAX_STREAM_ID = STREAM_ID_MASK >> STREAM_ID_SHIFT,
+ STREAM_MASK = IS_STREAM_FLAG | STREAM_ID_MASK,
+
+ IS_VENDOR_FLAG = 0x00008000,
+ TYPE_INDEX_MASK = 0x0000FFFF,
+ CORE_MASK = TYPE_INDEX_MASK | IS_FLEX_FLAG,
+ };
+
+ public:
+ /// constructor/conversion from uint32_t
+ inline CoreIndex(uint32_t index) : mIndex(index) { }
+
+ // no conversion from uint64_t
+ inline CoreIndex(uint64_t index) = delete;
+
+ /// returns true iff this is a vendor extension parameter
+ inline bool isVendor() const { return mIndex & IS_VENDOR_FLAG; }
+
+ /// returns true iff this is a flexible parameter (with variable size)
+ inline bool isFlexible() const { return mIndex & IS_FLEX_FLAG; }
+
+ /// returns the core index
+ /// This is the combination of the parameter type index and the flexible flag.
+ inline uint32_t coreIndex() const { return mIndex & CORE_MASK; }
+
+ /// returns the parameter type index
+ inline type_index_t typeIndex() const { return mIndex & TYPE_INDEX_MASK; }
+
+ DEFINE_FIELD_AND_MASK_BASED_COMPARISON_OPERATORS(CoreIndex, mIndex, CORE_MASK)
+
+ protected:
+ uint32_t mIndex;
+ };
+
+ /**
+ * Type encompasses the parameter's kind (tuning, setting, info), its scope (whether the
+ * parameter is global, input or output, and whether it is for a stream) and the its base
+ * index (which also determines its layout).
+ */
+ struct Type : public CoreIndex {
+ //public:
+ /// returns true iff this is a global parameter (not for input nor output)
+ inline bool isGlobal() const { return (mIndex & DIR_MASK) == DIR_GLOBAL; }
+ /// returns true iff this is an input or input stream parameter
+ inline bool forInput() const { return (mIndex & DIR_MASK) == DIR_INPUT; }
+ /// returns true iff this is an output or output stream parameter
+ inline bool forOutput() const { return (mIndex & DIR_MASK) == DIR_OUTPUT; }
+
+ /// returns true iff this is a stream parameter
+ inline bool forStream() const { return mIndex & IS_STREAM_FLAG; }
+ /// returns true iff this is a port (input or output) parameter
+ inline bool forPort() const { return !forStream() && !isGlobal(); }
+
+ /// returns the parameter type: the parameter index without the stream ID
+ inline uint32_t type() const { return mIndex & (~STREAM_ID_MASK); }
+
+ /// return the kind (struct, info, setting or tuning) of this param
+ inline kind_t kind() const {
+ switch (mIndex & KIND_MASK) {
+ case KIND_STRUCT: return STRUCT;
+ case KIND_INFO: return INFO;
+ case KIND_SETTING: return SETTING;
+ case KIND_TUNING: return TUNING;
+ default: return NONE; // should not happen
+ }
+ }
+
+ /// constructor/conversion from uint32_t
+ inline Type(uint32_t index) : CoreIndex(index) { }
+
+ // no conversion from uint64_t
+ inline Type(uint64_t index) = delete;
+
+ DEFINE_FIELD_AND_MASK_BASED_COMPARISON_OPERATORS(Type, mIndex, ~STREAM_ID_MASK)
+
+ private:
+ friend struct C2Param; // for setPort()
+ friend struct C2Tuning; // for KIND_TUNING
+ friend struct C2Setting; // for KIND_SETTING
+ friend struct C2Info; // for KIND_INFO
+ // for DIR_GLOBAL
+ template<typename T, typename S, int I, class F> friend struct C2GlobalParam;
+ template<typename T, typename S, int I, class F> friend struct C2PortParam; // for kDir*
+ template<typename T, typename S, int I, class F> friend struct C2StreamParam; // for kDir*
+ friend struct _C2ParamInspector; // for testing
+
+ /**
+ * Sets the port/stream direction.
+ * @return true on success, false if could not set direction (e.g. it is global param).
+ */
+ inline bool setPort(bool output) {
+ if (isGlobal()) {
+ return false;
+ } else {
+ mIndex = (mIndex & ~DIR_MASK) | (output ? DIR_OUTPUT : DIR_INPUT);
+ return true;
+ }
+ }
+ };
+
+ /**
+ * index encompasses all remaining information: basically the stream ID.
+ */
+ struct Index : public Type {
+ /// returns the index as uint32_t
+ inline operator uint32_t() const { return mIndex; }
+
+ /// constructor/conversion from uint32_t
+ inline Index(uint32_t index) : Type(index) { }
+
+ /// copy constructor
+ inline Index(const Index &index) = default;
+
+ // no conversion from uint64_t
+ inline Index(uint64_t index) = delete;
+
+ /// returns the stream ID or ~0 if not a stream
+ inline unsigned stream() const {
+ return forStream() ? rawStream() : ~0U;
+ }
+
+ /// Returns an index with stream field set to given stream.
+ inline Index withStream(unsigned stream) const {
+ Index ix = mIndex;
+ (void)ix.setStream(stream);
+ return ix;
+ }
+
+ /// sets the port (direction). Returns true iff successful.
+ inline Index withPort(bool output) const {
+ Index ix = mIndex;
+ (void)ix.setPort(output);
+ return ix;
+ }
+
+ DEFINE_FIELD_BASED_COMPARISON_OPERATORS(Index, mIndex)
+
+ private:
+ friend struct C2Param; // for setStream, MakeStreamId, isValid
+ friend struct _C2ParamInspector; // for testing
+
+ /**
+ * @return true if the type is valid, e.g. direction is not undefined AND
+ * stream is 0 if not a stream param.
+ */
+ inline bool isValid() const {
+ // there is no Type::isValid (even though some of this check could be
+ // performed on types) as this is only used on index...
+ return (forStream() ? rawStream() < MAX_STREAM_ID : rawStream() == 0)
+ && (mIndex & DIR_MASK) != DIR_UNDEFINED;
+ }
+
+ /// returns the raw stream ID field
+ inline unsigned rawStream() const {
+ return (mIndex & STREAM_ID_MASK) >> STREAM_ID_SHIFT;
+ }
+
+ /// returns the streamId bitfield for a given |stream|. If stream is invalid,
+ /// returns an invalid bitfield.
+ inline static uint32_t MakeStreamId(unsigned stream) {
+ // saturate stream ID (max value is invalid)
+ if (stream > MAX_STREAM_ID) {
+ stream = MAX_STREAM_ID;
+ }
+ return (stream << STREAM_ID_SHIFT) & STREAM_ID_MASK;
+ }
+
+ inline bool convertToStream(bool output, unsigned stream) {
+ mIndex = (mIndex & ~DIR_MASK) | IS_STREAM_FLAG;
+ (void)setPort(output);
+ return setStream(stream);
+ }
+
+ inline void convertToPort(bool output) {
+ mIndex = (mIndex & ~(DIR_MASK | IS_STREAM_FLAG));
+ (void)setPort(output);
+ }
+
+ inline void convertToGlobal() {
+ mIndex = (mIndex & ~(DIR_MASK | IS_STREAM_FLAG)) | DIR_GLOBAL;
+ }
+
+ /**
+ * Sets the stream index.
+ * \return true on success, false if could not set index (e.g. not a stream param).
+ */
+ inline bool setStream(unsigned stream) {
+ if (forStream()) {
+ mIndex = (mIndex & ~STREAM_ID_MASK) | MakeStreamId(stream);
+ return this->stream() < MAX_STREAM_ID;
+ }
+ return false;
+ }
+ };
+
+public:
+ // public getters for Index methods
+
+ /// returns true iff this is a vendor extension parameter
+ inline bool isVendor() const { return _mIndex.isVendor(); }
+ /// returns true iff this is a flexible parameter
+ inline bool isFlexible() const { return _mIndex.isFlexible(); }
+ /// returns true iff this is a global parameter (not for input nor output)
+ inline bool isGlobal() const { return _mIndex.isGlobal(); }
+ /// returns true iff this is an input or input stream parameter
+ inline bool forInput() const { return _mIndex.forInput(); }
+ /// returns true iff this is an output or output stream parameter
+ inline bool forOutput() const { return _mIndex.forOutput(); }
+
+ /// returns true iff this is a stream parameter
+ inline bool forStream() const { return _mIndex.forStream(); }
+ /// returns true iff this is a port (input or output) parameter
+ inline bool forPort() const { return _mIndex.forPort(); }
+
+ /// returns the stream ID or ~0 if not a stream
+ inline unsigned stream() const { return _mIndex.stream(); }
+
+ /// returns the parameter type: the parameter index without the stream ID
+ inline Type type() const { return _mIndex.type(); }
+
+ /// returns the index of this parameter
+ /// \todo: should we restrict this to C2ParamField?
+ inline uint32_t index() const { return (uint32_t)_mIndex; }
+
+ /// returns the core index of this parameter
+ inline CoreIndex coreIndex() const { return _mIndex.coreIndex(); }
+
+ /// returns the kind of this parameter
+ inline kind_t kind() const { return _mIndex.kind(); }
+
+ /// returns the size of the parameter or 0 if the parameter is invalid
+ inline size_t size() const { return _mSize; }
+
+ /// returns true iff the parameter is valid
+ inline operator bool() const { return _mIndex.isValid() && _mSize > 0; }
+
+ /// returns true iff the parameter is invalid
+ inline bool operator!() const { return !operator bool(); }
+
+ // equality is done by memcmp (use equals() to prevent any overread)
+ inline bool operator==(const C2Param &o) const {
+ return equals(o) && memcmp(this, &o, _mSize) == 0;
+ }
+ inline bool operator!=(const C2Param &o) const { return !operator==(o); }
+
+ /// safe(r) type cast from pointer and size
+ inline static C2Param* From(void *addr, size_t len) {
+ // _mSize must fit into size, but really C2Param must also to be a valid param
+ if (len < sizeof(C2Param)) {
+ return nullptr;
+ }
+ // _mSize must match length
+ C2Param *param = (C2Param*)addr;
+ if (param->_mSize != len) {
+ return nullptr;
+ }
+ return param;
+ }
+
+ /// Returns managed clone of |orig| at heap.
+ inline static std::unique_ptr<C2Param> Copy(const C2Param &orig) {
+ if (orig.size() == 0) {
+ return nullptr;
+ }
+ void *mem = ::operator new (orig.size());
+ C2Param *param = new (mem) C2Param(orig.size(), orig._mIndex);
+ param->updateFrom(orig);
+ return std::unique_ptr<C2Param>(param);
+ }
+
+ /// Returns managed clone of |orig| as a stream parameter at heap.
+ inline static std::unique_ptr<C2Param> CopyAsStream(
+ const C2Param &orig, bool output, unsigned stream) {
+ std::unique_ptr<C2Param> copy = Copy(orig);
+ if (copy) {
+ copy->_mIndex.convertToStream(output, stream);
+ }
+ return copy;
+ }
+
+ /// Returns managed clone of |orig| as a port parameter at heap.
+ inline static std::unique_ptr<C2Param> CopyAsPort(const C2Param &orig, bool output) {
+ std::unique_ptr<C2Param> copy = Copy(orig);
+ if (copy) {
+ copy->_mIndex.convertToPort(output);
+ }
+ return copy;
+ }
+
+ /// Returns managed clone of |orig| as a global parameter at heap.
+ inline static std::unique_ptr<C2Param> CopyAsGlobal(const C2Param &orig) {
+ std::unique_ptr<C2Param> copy = Copy(orig);
+ if (copy) {
+ copy->_mIndex.convertToGlobal();
+ }
+ return copy;
+ }
+
+#if 0
+ template<typename P, class=decltype(C2Param(P()))>
+ P *As() { return P::From(this); }
+ template<typename P>
+ const P *As() const { return const_cast<const P*>(P::From(const_cast<C2Param*>(this))); }
+#endif
+
+protected:
+ /// sets the stream field. Returns true iff successful.
+ inline bool setStream(unsigned stream) {
+ return _mIndex.setStream(stream);
+ }
+
+ /// sets the port (direction). Returns true iff successful.
+ inline bool setPort(bool output) {
+ return _mIndex.setPort(output);
+ }
+
+public:
+ /// invalidate this parameter. There is no recovery from this call; e.g. parameter
+ /// cannot be 'corrected' to be valid.
+ inline void invalidate() { _mSize = 0; }
+
+ // if other is the same kind of (valid) param as this, copy it into this and return true.
+ // otherwise, do not copy anything, and return false.
+ inline bool updateFrom(const C2Param &other) {
+ if (other._mSize <= _mSize && other._mIndex == _mIndex && _mSize > 0) {
+ memcpy(this, &other, other._mSize);
+ return true;
+ }
+ return false;
+ }
+
+protected:
+ // returns |o| if it is a null ptr, or if can suitably be a param of given |type| (e.g. has
+ // same type (ignoring stream ID), and size). Otherwise, returns null. If |checkDir| is false,
+ // allow undefined or different direction (e.g. as constructed from C2PortParam() vs.
+ // C2PortParam::input), but still require equivalent type (stream, port or global); otherwise,
+ // return null.
+ inline static const C2Param* IfSuitable(
+ const C2Param* o, size_t size, Type type, size_t flexSize = 0, bool checkDir = true) {
+ if (o == nullptr || o->_mSize < size || (flexSize && ((o->_mSize - size) % flexSize))) {
+ return nullptr;
+ } else if (checkDir) {
+ return o->_mIndex.type() == type.mIndex ? o : nullptr;
+ } else if (o->_mIndex.isGlobal()) {
+ return nullptr;
+ } else {
+ return ((o->_mIndex.type() ^ type.mIndex) & ~Type::DIR_MASK) ? nullptr : o;
+ }
+ }
+
+ /// base constructor
+ inline C2Param(uint32_t paramSize, Index paramIndex)
+ : _mSize(paramSize),
+ _mIndex(paramIndex) {
+ if (paramSize > sizeof(C2Param)) {
+ memset(this + 1, 0, paramSize - sizeof(C2Param));
+ }
+ }
+
+ /// base constructor with stream set
+ inline C2Param(uint32_t paramSize, Index paramIndex, unsigned stream)
+ : _mSize(paramSize),
+ _mIndex(paramIndex | Index::MakeStreamId(stream)) {
+ if (paramSize > sizeof(C2Param)) {
+ memset(this + 1, 0, paramSize - sizeof(C2Param));
+ }
+ if (!forStream()) {
+ invalidate();
+ }
+ }
+
+private:
+ friend struct _C2ParamInspector; // for testing
+
+ /// returns true iff |o| has the same size and index as this. This performs the
+ /// basic check for equality.
+ inline bool equals(const C2Param &o) const {
+ return _mSize == o._mSize && _mIndex == o._mIndex;
+ }
+
+ uint32_t _mSize;
+ Index _mIndex;
+};
+
+/// \ingroup internal
+/// allow C2Params access to private methods, e.g. constructors
+#define C2PARAM_MAKE_FRIENDS \
+ template<typename U, typename S, int I, class F> friend struct C2GlobalParam; \
+ template<typename U, typename S, int I, class F> friend struct C2PortParam; \
+ template<typename U, typename S, int I, class F> friend struct C2StreamParam; \
+
+/**
+ * Setting base structure for component method signatures. Wrap constructors.
+ */
+struct C2Setting : public C2Param {
+protected:
+ template<typename ...Args>
+ inline C2Setting(const Args(&... args)) : C2Param(args...) { }
+public: // TODO
+ enum : uint32_t { PARAM_KIND = Type::KIND_SETTING };
+};
+
+/**
+ * Tuning base structure for component method signatures. Wrap constructors.
+ */
+struct C2Tuning : public C2Setting {
+protected:
+ template<typename ...Args>
+ inline C2Tuning(const Args(&... args)) : C2Setting(args...) { }
+public: // TODO
+ enum : uint32_t { PARAM_KIND = Type::KIND_TUNING };
+};
+
+/**
+ * Info base structure for component method signatures. Wrap constructors.
+ */
+struct C2Info : public C2Param {
+protected:
+ template<typename ...Args>
+ inline C2Info(const Args(&... args)) : C2Param(args...) { }
+public: // TODO
+ enum : uint32_t { PARAM_KIND = Type::KIND_INFO };
+};
+
+/**
+ * Structure uniquely specifying a field in an arbitrary structure.
+ *
+ * \note This structure is used differently in C2FieldDescriptor to
+ * identify array fields, such that _mSize is the size of each element. This is
+ * because the field descriptor contains the array-length, and we want to keep
+ * a relevant element size for variable length arrays.
+ */
+struct _C2FieldId {
+//public:
+ /**
+ * Constructor used for C2FieldDescriptor that removes the array extent.
+ *
+ * \param[in] offset pointer to the field in an object at address 0.
+ */
+ template<typename T, class B=typename std::remove_extent<T>::type>
+ inline _C2FieldId(T* offset)
+ : // offset is from "0" so will fit on 32-bits
+ _mOffset((uint32_t)(uintptr_t)(offset)),
+ _mSize(sizeof(B)) { }
+
+ /**
+ * Direct constructor from offset and size.
+ *
+ * \param[in] offset offset of the field.
+ * \param[in] size size of the field.
+ */
+ inline _C2FieldId(size_t offset, size_t size)
+ : _mOffset(offset), _mSize(size) {}
+
+ /**
+ * Constructor used to identify a field in an object.
+ *
+ * \param U[type] pointer to the object that contains this field. This is needed in case the
+ * field is in an (inherited) base class, in which case T will be that base class.
+ * \param pm[im] member pointer to the field
+ */
+ template<typename R, typename T, typename U, typename B=typename std::remove_extent<R>::type>
+ inline _C2FieldId(U *, R T::* pm)
+ : _mOffset((uint32_t)(uintptr_t)(&(((U*)256)->*pm)) - 256u),
+ _mSize(sizeof(B)) { }
+
+ /**
+ * Constructor used to identify a field in an object.
+ *
+ * \param pm[im] member pointer to the field
+ */
+ template<typename R, typename T, typename B=typename std::remove_extent<R>::type>
+ inline _C2FieldId(R T::* pm)
+ : _mOffset((uint32_t)(uintptr_t)(&(((T*)0)->*pm))),
+ _mSize(sizeof(B)) { }
+
+ inline bool operator==(const _C2FieldId &other) const {
+ return _mOffset == other._mOffset && _mSize == other._mSize;
+ }
+
+ inline bool operator<(const _C2FieldId &other) const {
+ return _mOffset < other._mOffset ||
+ // NOTE: order parent structure before sub field
+ (_mOffset == other._mOffset && _mSize > other._mSize);
+ }
+
+ DEFINE_OTHER_COMPARISON_OPERATORS(_C2FieldId)
+
+#if 0
+ inline uint32_t offset() const { return _mOffset; }
+ inline uint32_t size() const { return _mSize; }
+#endif
+
+#if defined(FRIEND_TEST)
+ friend void PrintTo(const _C2FieldId &d, ::std::ostream*);
+#endif
+
+private:
+ friend struct _C2ParamInspector;
+ friend struct C2FieldDescriptor;
+
+ uint32_t _mOffset; // offset of field
+ uint32_t _mSize; // size of field
+};
+
+/**
+ * Structure uniquely specifying a 'field' in a configuration. The field
+ * can be a field of a configuration, a subfield of a field of a configuration,
+ * and even the whole configuration. Moreover, if the field can point to an
+ * element in a array field, or to the entire array field.
+ *
+ * This structure is used for querying supported values for a field, as well
+ * as communicating configuration failures and conflicts when trying to change
+ * a configuration for a component/interface or a store.
+ */
+struct C2ParamField {
+//public:
+ /**
+ * Create a field identifier using a configuration parameter (variable),
+ * and a pointer to member.
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ *
+ * struct C2SomeParam {
+ * uint32_t mField;
+ * uint32_t mArray[2];
+ * C2OtherStruct mStruct;
+ * uint32_t mFlexArray[];
+ * } *mParam;
+ *
+ * C2ParamField(mParam, &mParam->mField);
+ * C2ParamField(mParam, &mParam->mArray);
+ * C2ParamField(mParam, &mParam->mArray[0]);
+ * C2ParamField(mParam, &mParam->mStruct.mSubField);
+ * C2ParamField(mParam, &mParam->mFlexArray);
+ * C2ParamField(mParam, &mParam->mFlexArray[2]);
+ *
+ * ~~~~~~~~~~~~~
+ *
+ * \todo fix what this is for T[] (for now size becomes T[1])
+ *
+ * \note this does not work for 64-bit members as it triggers a
+ * 'taking address of packed member' warning.
+ *
+ * \param param pointer to parameter
+ * \param offset member pointer
+ */
+ template<typename S, typename T>
+ inline C2ParamField(S* param, T* offset)
+ : _mIndex(param->index()),
+ _mFieldId((T*)((uintptr_t)offset - (uintptr_t)param)) {}
+
+ template<typename S, typename T>
+ inline static C2ParamField Make(S& param, T& offset) {
+ return C2ParamField(param.index(), (uintptr_t)&offset - (uintptr_t)¶m, sizeof(T));
+ }
+
+ /**
+ * Create a field identifier using a configuration parameter (variable),
+ * and a member pointer. This method cannot be used to refer to an
+ * array element or a subfield.
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ *
+ * C2SomeParam mParam;
+ * C2ParamField(&mParam, &C2SomeParam::mMemberField);
+ *
+ * ~~~~~~~~~~~~~
+ *
+ * \param p pointer to parameter
+ * \param T member pointer to the field member
+ */
+ template<typename R, typename T, typename U>
+ inline C2ParamField(U *p, R T::* pm) : _mIndex(p->index()), _mFieldId(p, pm) { }
+
+ /**
+ * Create a field identifier to a configuration parameter (variable).
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ *
+ * C2SomeParam mParam;
+ * C2ParamField(&mParam);
+ *
+ * ~~~~~~~~~~~~~
+ *
+ * \param param pointer to parameter
+ */
+ template<typename S>
+ inline C2ParamField(S* param)
+ : _mIndex(param->index()), _mFieldId(0u, param->size()) { }
+
+ /** Copy constructor. */
+ inline C2ParamField(const C2ParamField &other) = default;
+
+ /**
+ * Equality operator.
+ */
+ inline bool operator==(const C2ParamField &other) const {
+ return _mIndex == other._mIndex && _mFieldId == other._mFieldId;
+ }
+
+ /**
+ * Ordering operator.
+ */
+ inline bool operator<(const C2ParamField &other) const {
+ return _mIndex < other._mIndex ||
+ (_mIndex == other._mIndex && _mFieldId < other._mFieldId);
+ }
+
+ DEFINE_OTHER_COMPARISON_OPERATORS(C2ParamField)
+
+protected:
+ inline C2ParamField(C2Param::Index index, uint32_t offset, uint32_t size)
+ : _mIndex(index), _mFieldId(offset, size) {}
+
+private:
+ friend struct _C2ParamInspector;
+
+ C2Param::Index _mIndex; ///< parameter index
+ _C2FieldId _mFieldId; ///< field identifier
+};
+
+/**
+ * A shared (union) representation of numeric values
+ */
+class C2Value {
+public:
+ /// A union of supported primitive types.
+ union Primitive {
+ // first member is always zero initialized so it must be the largest
+ uint64_t u64; ///< uint64_t value
+ int64_t i64; ///< int64_t value
+ c2_cntr64_t c64; ///< c2_cntr64_t value
+ uint32_t u32; ///< uint32_t value
+ int32_t i32; ///< int32_t value
+ c2_cntr32_t c32; ///< c2_cntr32_t value
+ float fp; ///< float value
+
+ // constructors - implicit
+ Primitive(uint64_t value) : u64(value) { }
+ Primitive(int64_t value) : i64(value) { }
+ Primitive(c2_cntr64_t value) : c64(value) { }
+ Primitive(uint32_t value) : u32(value) { }
+ Primitive(int32_t value) : i32(value) { }
+ Primitive(c2_cntr32_t value) : c32(value) { }
+ Primitive(uint8_t value) : u32(value) { }
+ Primitive(char value) : i32(value) { }
+ Primitive(float value) : fp(value) { }
+
+ // allow construction from enum type
+ template<typename E, typename = typename std::enable_if<std::is_enum<E>::value>::type>
+ Primitive(E value)
+ : Primitive(static_cast<typename std::underlying_type<E>::type>(value)) { }
+
+ Primitive() : u64(0) { }
+
+ /** gets value out of the union */
+ template<typename T> const T &ref() const;
+
+ // verify that we can assume standard aliasing
+ static_assert(sizeof(u64) == sizeof(i64), "");
+ static_assert(sizeof(u64) == sizeof(c64), "");
+ static_assert(sizeof(u32) == sizeof(i32), "");
+ static_assert(sizeof(u32) == sizeof(c32), "");
+ };
+ // verify that we can assume standard aliasing
+ static_assert(offsetof(Primitive, u64) == offsetof(Primitive, i64), "");
+ static_assert(offsetof(Primitive, u64) == offsetof(Primitive, c64), "");
+ static_assert(offsetof(Primitive, u32) == offsetof(Primitive, i32), "");
+ static_assert(offsetof(Primitive, u32) == offsetof(Primitive, c32), "");
+
+ enum type_t : uint32_t {
+ NO_INIT,
+ INT32,
+ UINT32,
+ CNTR32,
+ INT64,
+ UINT64,
+ CNTR64,
+ FLOAT,
+ };
+
+ template<typename T, bool = std::is_enum<T>::value>
+ inline static constexpr type_t TypeFor() {
+ using U = typename std::underlying_type<T>::type;
+ return TypeFor<U>();
+ }
+
+ // deprectated
+ template<typename T, bool B = std::is_enum<T>::value>
+ inline static constexpr type_t typeFor() {
+ return TypeFor<T, B>();
+ }
+
+ // constructors - implicit
+ template<typename T>
+ C2Value(T value) : _mType(typeFor<T>()), _mValue(value) { }
+
+ C2Value() : _mType(NO_INIT) { }
+
+ inline type_t type() const { return _mType; }
+
+ template<typename T>
+ inline bool get(T *value) const {
+ if (_mType == typeFor<T>()) {
+ *value = _mValue.ref<T>();
+ return true;
+ }
+ return false;
+ }
+
+ /// returns the address of the value
+ void *get() const {
+ return _mType == NO_INIT ? nullptr : (void*)&_mValue;
+ }
+
+ /// returns the size of the contained value
+ size_t inline sizeOf() const {
+ return SizeFor(_mType);
+ }
+
+ static size_t SizeFor(type_t type) {
+ switch (type) {
+ case INT32:
+ case UINT32:
+ case CNTR32: return sizeof(_mValue.i32);
+ case INT64:
+ case UINT64:
+ case CNTR64: return sizeof(_mValue.i64);
+ case FLOAT: return sizeof(_mValue.fp);
+ default: return 0;
+ }
+ }
+
+private:
+ type_t _mType;
+ Primitive _mValue;
+};
+
+template<> inline const int32_t &C2Value::Primitive::ref<int32_t>() const { return i32; }
+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; }
+
+// provide types for enums and uint8_t, char even though we don't provide reading as them
+template<> constexpr C2Value::type_t C2Value::TypeFor<char, false>() { return INT32; }
+template<> constexpr C2Value::type_t C2Value::TypeFor<int32_t, false>() { return INT32; }
+template<> constexpr C2Value::type_t C2Value::TypeFor<int64_t, false>() { return INT64; }
+template<> constexpr C2Value::type_t C2Value::TypeFor<uint8_t, false>() { return UINT32; }
+template<> constexpr C2Value::type_t C2Value::TypeFor<uint32_t, false>() { return UINT32; }
+template<> constexpr C2Value::type_t C2Value::TypeFor<uint64_t, false>() { return UINT64; }
+template<> constexpr C2Value::type_t C2Value::TypeFor<c2_cntr32_t, false>() { return CNTR32; }
+template<> constexpr C2Value::type_t C2Value::TypeFor<c2_cntr64_t, false>() { return CNTR64; }
+template<> constexpr C2Value::type_t C2Value::TypeFor<float, false>() { return FLOAT; }
+
+// forward declare easy enum template
+template<typename E> struct C2EasyEnum;
+
+/**
+ * field descriptor. A field is uniquely defined by an index into a parameter.
+ * (Note: Stream-id is not captured as a field.)
+ *
+ * Ordering of fields is by offset. In case of structures, it is depth first,
+ * with a structure taking an index just before and in addition to its members.
+ */
+struct C2FieldDescriptor {
+//public:
+ /** field types and flags
+ * \note: only 32-bit and 64-bit fields are supported (e.g. no boolean, as that
+ * is represented using INT32).
+ */
+ enum type_t : uint32_t {
+ // 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
+ STRING = 0x100, ///< fixed-size string (POD)
+ BLOB, ///< blob. Blobs have no sub-elements and can be thought of as byte arrays;
+ ///< however, bytes cannot be individually addressed by clients.
+
+ // complex types
+ STRUCT_FLAG = 0x20000, ///< structs. Marked with this flag in addition to their coreIndex.
+ };
+
+ typedef std::pair<C2String, C2Value::Primitive> NamedValueType;
+ typedef std::vector<NamedValueType> NamedValuesType;
+ //typedef std::pair<std::vector<C2String>, std::vector<C2Value::Primitive>> NamedValuesType;
+
+ /**
+ * Template specialization that returns the named values for a type.
+ *
+ * \todo hide from client.
+ *
+ * \return a vector of name-value pairs.
+ */
+ template<typename B>
+ static NamedValuesType namedValuesFor(const B &);
+
+ /** specialization for easy enums */
+ template<typename E>
+ inline static NamedValuesType namedValuesFor(const C2EasyEnum<E> &) {
+ return namedValuesFor(*(E*)nullptr);
+ }
+
+private:
+ template<typename B, bool enabled=std::is_arithmetic<B>::value || std::is_enum<B>::value>
+ struct C2_HIDE _NamedValuesGetter;
+
+public:
+ inline C2FieldDescriptor(uint32_t type, uint32_t extent, C2String name, size_t offset, size_t size)
+ : _mType((type_t)type), _mExtent(extent), _mName(name), _mFieldId(offset, size) { }
+
+ inline C2FieldDescriptor(const C2FieldDescriptor &) = default;
+
+ template<typename T, class B=typename std::remove_extent<T>::type>
+ inline C2FieldDescriptor(const T* offset, const char *name)
+ : _mType(this->GetType((B*)nullptr)),
+ _mExtent(std::is_array<T>::value ? std::extent<T>::value : 1),
+ _mName(name),
+ _mNamedValues(_NamedValuesGetter<B>::getNamedValues()),
+ _mFieldId(offset) {}
+
+/*
+ template<typename T, typename B=typename std::remove_extent<T>::type>
+ inline C2FieldDescriptor<T, B, false>(T* offset, const char *name)
+ : _mType(this->GetType((B*)nullptr)),
+ _mExtent(std::is_array<T>::value ? std::extent<T>::value : 1),
+ _mName(name),
+ _mFieldId(offset) {}
+*/
+
+ /// \deprecated
+ template<typename T, typename S, class B=typename std::remove_extent<T>::type>
+ inline C2FieldDescriptor(S*, T S::* field, const char *name)
+ : _mType(this->GetType((B*)nullptr)),
+ _mExtent(std::is_array<T>::value ? std::extent<T>::value : 1),
+ _mName(name),
+ _mFieldId(&(((S*)0)->*field)) {}
+
+ /// returns the type of this field
+ inline type_t type() const { return _mType; }
+ /// returns the length of the field in case it is an array. Returns 0 for
+ /// T[] arrays, returns 1 for T[1] arrays as well as if the field is not an array.
+ inline size_t extent() const { return _mExtent; }
+ /// returns the name of the field
+ inline C2String name() const { return _mName; }
+
+ const NamedValuesType &namedValues() const { return _mNamedValues; }
+
+#if defined(FRIEND_TEST)
+ friend void PrintTo(const C2FieldDescriptor &, ::std::ostream*);
+ friend bool operator==(const C2FieldDescriptor &, const C2FieldDescriptor &);
+ FRIEND_TEST(C2ParamTest_ParamFieldList, VerifyStruct);
+#endif
+
+private:
+ /**
+ * Construct an offseted field descriptor.
+ */
+ inline C2FieldDescriptor(const C2FieldDescriptor &desc, size_t offset)
+ : _mType(desc._mType), _mExtent(desc._mExtent),
+ _mName(desc._mName), _mNamedValues(desc._mNamedValues),
+ _mFieldId(desc._mFieldId._mOffset + offset, desc._mFieldId._mSize) { }
+
+ type_t _mType;
+ uint32_t _mExtent; // the last member can be arbitrary length if it is T[] array,
+ // extending to the end of the parameter (this is marked with
+ // 0). T[0]-s are not fields.
+ C2String _mName;
+ NamedValuesType _mNamedValues;
+
+ _C2FieldId _mFieldId; // field identifier (offset and size)
+
+ // NOTE: We do not capture default value(s) here as that may depend on the component.
+ // NOTE: We also do not capture bestEffort, as 1) this should be true for most fields,
+ // 2) this is at parameter granularity.
+
+ // 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; }
+
+ template<typename T,
+ class=typename std::enable_if<std::is_enum<T>::value>::type>
+ inline static type_t GetType(T*) {
+ typename std::underlying_type<T>::type underlying(0);
+ return GetType(&underlying);
+ }
+
+ // verify C2Struct by having a FieldList() and a CORE_INDEX.
+ template<typename T,
+ class=decltype(T::CORE_INDEX + 1), class=decltype(T::FieldList())>
+ inline static type_t GetType(T*) {
+ static_assert(!std::is_base_of<C2Param, T>::value, "cannot use C2Params as fields");
+ return (type_t)(T::CORE_INDEX | STRUCT_FLAG);
+ }
+
+ friend struct _C2ParamInspector;
+};
+
+// no named values for compound types
+template<typename B>
+struct C2FieldDescriptor::_NamedValuesGetter<B, false> {
+ inline static C2FieldDescriptor::NamedValuesType getNamedValues() {
+ return NamedValuesType();
+ }
+};
+
+template<typename B>
+struct C2FieldDescriptor::_NamedValuesGetter<B, true> {
+ inline static C2FieldDescriptor::NamedValuesType getNamedValues() {
+ return C2FieldDescriptor::namedValuesFor(*(B*)nullptr);
+ }
+};
+
+#define DEFINE_NO_NAMED_VALUES_FOR(type) \
+template<> inline C2FieldDescriptor::NamedValuesType C2FieldDescriptor::namedValuesFor(const type &) { \
+ return NamedValuesType(); \
+}
+
+// We cannot subtype constructor for enumerated types so insted define no named values for
+// 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)
+
+/**
+ * Describes the fields of a structure.
+ */
+struct C2StructDescriptor {
+public:
+ /// Returns the core index of the struct
+ inline C2Param::CoreIndex coreIndex() const { return _mType.coreIndex(); }
+
+ // Returns the number of fields in this struct (not counting any recursive fields).
+ // Must be at least 1 for valid structs.
+ inline size_t numFields() const { return _mFields.size(); }
+
+ // Returns the list of direct fields (not counting any recursive fields).
+ typedef std::vector<C2FieldDescriptor>::const_iterator field_iterator;
+ inline field_iterator cbegin() const { return _mFields.cbegin(); }
+ inline field_iterator cend() const { return _mFields.cend(); }
+
+ // only supplying const iterator - but these names are needed for range based loops
+ inline field_iterator begin() const { return _mFields.cbegin(); }
+ inline field_iterator end() const { return _mFields.cend(); }
+
+ template<typename T>
+ inline C2StructDescriptor(T*)
+ : C2StructDescriptor(T::CORE_INDEX, T::FieldList()) { }
+
+ inline C2StructDescriptor(
+ C2Param::CoreIndex type,
+ const std::vector<C2FieldDescriptor> &fields)
+ : _mType(type), _mFields(fields) { }
+
+private:
+ friend struct _C2ParamInspector;
+
+ inline C2StructDescriptor(
+ C2Param::CoreIndex type,
+ std::vector<C2FieldDescriptor> &&fields)
+ : _mType(type), _mFields(std::move(fields)) { }
+
+ const C2Param::CoreIndex _mType;
+ const std::vector<C2FieldDescriptor> _mFields;
+};
+
+/**
+ * Describes parameters for a component.
+ */
+struct C2ParamDescriptor {
+public:
+ /**
+ * Returns whether setting this param is required to configure this component.
+ * This can only be true for builtin params for platform-defined components (e.g. video and
+ * audio encoders/decoders, video/audio filters).
+ * For vendor-defined components, it can be true even for vendor-defined params,
+ * but it is not recommended, in case the component becomes platform-defined.
+ */
+ inline bool isRequired() const { return _mAttrib & IS_REQUIRED; }
+
+ /**
+ * Returns whether this parameter is persistent. This is always true for C2Tuning and C2Setting,
+ * but may be false for C2Info. If true, this parameter persists across frames and applies to
+ * the current and subsequent frames. If false, this C2Info parameter only applies to the
+ * current frame and is not assumed to have the same value (or even be present) on subsequent
+ * frames, unless it is specified for those frames.
+ */
+ inline bool isPersistent() const { return _mAttrib & IS_PERSISTENT; }
+
+ inline bool isStrict() const { return _mAttrib & IS_STRICT; }
+
+ inline bool isReadOnly() const { return _mAttrib & IS_READ_ONLY; }
+
+ inline bool isVisible() const { return !(_mAttrib & IS_HIDDEN); }
+
+ inline bool isPublic() const { return !(_mAttrib & IS_INTERNAL); }
+
+ /// Returns the name of this param.
+ /// This defaults to the underlying C2Struct's name, but could be altered for a component.
+ inline C2String name() const { return _mName; }
+
+ /// Returns the parameter index
+ inline C2Param::Index index() const { return _mIndex; }
+
+ /// Returns the indices of parameters that this parameter has a dependency on
+ inline const std::vector<C2Param::Index> &dependencies() const { return _mDependencies; }
+
+ /// \deprecated
+ template<typename T>
+ inline C2ParamDescriptor(bool isRequired, C2StringLiteral name, const T*)
+ : _mIndex(T::PARAM_TYPE),
+ _mAttrib(IS_PERSISTENT | (isRequired ? IS_REQUIRED : 0)),
+ _mName(name) { }
+
+ /// \deprecated
+ inline C2ParamDescriptor(
+ bool isRequired, C2StringLiteral name, C2Param::Index index)
+ : _mIndex(index),
+ _mAttrib(IS_PERSISTENT | (isRequired ? IS_REQUIRED : 0)),
+ _mName(name) { }
+
+ enum attrib_t : uint32_t {
+ // flags that default on
+ IS_REQUIRED = 1u << 0, ///< parameter is required to be specified
+ IS_PERSISTENT = 1u << 1, ///< parameter retains its value
+ // flags that default off
+ IS_STRICT = 1u << 2, ///< parameter is strict
+ IS_READ_ONLY = 1u << 3, ///< parameter is publicly read-only
+ IS_HIDDEN = 1u << 4, ///< parameter shall not be visible to clients
+ IS_INTERNAL = 1u << 5, ///< parameter shall not be used by framework (other than testing)
+ IS_CONST = 1u << 6 | IS_READ_ONLY, ///< parameter is publicly const (hence read-only)
+ };
+
+ inline C2ParamDescriptor(
+ C2Param::Index index, attrib_t attrib, C2StringLiteral name)
+ : _mIndex(index),
+ _mAttrib(attrib),
+ _mName(name) { }
+
+ inline C2ParamDescriptor(
+ C2Param::Index index, attrib_t attrib, C2String &&name,
+ std::vector<C2Param::Index> &&dependencies)
+ : _mIndex(index),
+ _mAttrib(attrib),
+ _mName(name),
+ _mDependencies(std::move(dependencies)) { }
+
+private:
+ const C2Param::Index _mIndex;
+ const uint32_t _mAttrib;
+ const C2String _mName;
+ std::vector<C2Param::Index> _mDependencies;
+
+ friend struct _C2ParamInspector;
+};
+
+DEFINE_ENUM_OPERATORS(::C2ParamDescriptor::attrib_t)
+
+
+/// \ingroup internal
+/// Define a structure without CORE_INDEX.
+/// \note _FIELD_LIST is used only during declaration so that C2Struct declarations can end with
+/// a simple list of C2FIELD-s and closing bracket. Mark it unused as it is not used in templated
+/// structs.
+#define DEFINE_BASE_C2STRUCT(name) \
+private: \
+ const static std::vector<C2FieldDescriptor> _FIELD_LIST __unused; /**< structure fields */ \
+public: \
+ typedef C2##name##Struct _type; /**< type name shorthand */ \
+ static const std::vector<C2FieldDescriptor> FieldList(); /**< structure fields factory */
+
+/// Define a structure with matching CORE_INDEX.
+#define DEFINE_C2STRUCT(name) \
+public: \
+ enum : uint32_t { CORE_INDEX = kParamIndex##name }; \
+ DEFINE_BASE_C2STRUCT(name)
+
+/// Define a flexible structure without CORE_INDEX.
+#define DEFINE_BASE_FLEX_C2STRUCT(name, flexMember) \
+public: \
+ FLEX(C2##name##Struct, flexMember) \
+ DEFINE_BASE_C2STRUCT(name)
+
+/// Define a flexible structure with matching CORE_INDEX.
+#define DEFINE_FLEX_C2STRUCT(name, flexMember) \
+public: \
+ FLEX(C2##name##Struct, flexMember) \
+ enum : uint32_t { CORE_INDEX = kParamIndex##name | C2Param::CoreIndex::IS_FLEX_FLAG }; \
+ DEFINE_BASE_C2STRUCT(name)
+
+/// \ingroup internal
+/// Describe a structure of a templated structure.
+// Use list... as the argument gets resubsitituted and it contains commas. Alternative would be
+// to wrap list in an expression, e.g. ({ std::vector<C2FieldDescriptor> list; })) which converts
+// it from an initializer list to a vector.
+#define DESCRIBE_TEMPLATED_C2STRUCT(strukt, list...) \
+ _DESCRIBE_TEMPLATABLE_C2STRUCT(template<>, strukt, __C2_GENERATE_GLOBAL_VARS__, list)
+
+/// \deprecated
+/// Describe the fields of a structure using an initializer list.
+#define DESCRIBE_C2STRUCT(name, list...) \
+ _DESCRIBE_TEMPLATABLE_C2STRUCT(, C2##name##Struct, __C2_GENERATE_GLOBAL_VARS__, list)
+
+/// \ingroup internal
+/// Macro layer to get value of enabled that is passed in as a macro variable
+#define _DESCRIBE_TEMPLATABLE_C2STRUCT(template, strukt, enabled, list...) \
+ __DESCRIBE_TEMPLATABLE_C2STRUCT(template, strukt, enabled, list)
+
+/// \ingroup internal
+/// Macro layer to resolve to the specific macro based on macro variable
+#define __DESCRIBE_TEMPLATABLE_C2STRUCT(template, strukt, enabled, list...) \
+ ___DESCRIBE_TEMPLATABLE_C2STRUCT##enabled(template, strukt, list)
+
+#define ___DESCRIBE_TEMPLATABLE_C2STRUCT(template, strukt, list...) \
+ template \
+ const std::vector<C2FieldDescriptor> strukt::FieldList() { return list; }
+
+#define ___DESCRIBE_TEMPLATABLE_C2STRUCT__C2_GENERATE_GLOBAL_VARS__(template, strukt, list...)
+
+/**
+ * Describe a field of a structure.
+ * These must be in order.
+ *
+ * There are two ways to use this macro:
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ * struct C2VideoWidthStruct {
+ * int32_t width;
+ * C2VideoWidthStruct() {} // optional default constructor
+ * C2VideoWidthStruct(int32_t _width) : width(_width) {}
+ *
+ * DEFINE_AND_DESCRIBE_C2STRUCT(VideoWidth)
+ * C2FIELD(width, "width")
+ * };
+ * ~~~~~~~~~~~~~
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ * struct C2VideoWidthStruct {
+ * int32_t width;
+ * C2VideoWidthStruct() = default; // optional default constructor
+ * C2VideoWidthStruct(int32_t _width) : width(_width) {}
+ *
+ * DEFINE_C2STRUCT(VideoWidth)
+ * } C2_PACK;
+ *
+ * DESCRIBE_C2STRUCT(VideoWidth, {
+ * C2FIELD(width, "width")
+ * })
+ * ~~~~~~~~~~~~~
+ *
+ * For flexible structures (those ending in T[]), use the flexible macros:
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ * struct C2VideoFlexWidthsStruct {
+ * int32_t widths[];
+ * C2VideoFlexWidthsStruct(); // must have a default constructor
+ *
+ * private:
+ * // may have private constructors taking number of widths as the first argument
+ * // This is used by the C2Param factory methods, e.g.
+ * // C2VideoFlexWidthsGlobalParam::AllocUnique(size_t, int32_t);
+ * C2VideoFlexWidthsStruct(size_t flexCount, int32_t value) {
+ * for (size_t i = 0; i < flexCount; ++i) {
+ * widths[i] = value;
+ * }
+ * }
+ *
+ * // If the last argument is T[N] or std::initializer_list<T>, the flexCount will
+ * // be automatically calculated and passed by the C2Param factory methods, e.g.
+ * // int widths[] = { 1, 2, 3 };
+ * // C2VideoFlexWidthsGlobalParam::AllocUnique(widths);
+ * template<unsigned N>
+ * C2VideoFlexWidthsStruct(size_t flexCount, const int32_t(&init)[N]) {
+ * for (size_t i = 0; i < flexCount; ++i) {
+ * widths[i] = init[i];
+ * }
+ * }
+ *
+ * DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(VideoFlexWidths, widths)
+ * C2FIELD(widths, "widths")
+ * };
+ * ~~~~~~~~~~~~~
+ *
+ * ~~~~~~~~~~~~~ (.cpp)
+ * struct C2VideoFlexWidthsStruct {
+ * int32_t mWidths[];
+ * C2VideoFlexWidthsStruct(); // must have a default constructor
+ *
+ * DEFINE_FLEX_C2STRUCT(VideoFlexWidths, mWidths)
+ * } C2_PACK;
+ *
+ * DESCRIBE_C2STRUCT(VideoFlexWidths, {
+ * C2FIELD(mWidths, "widths")
+ * })
+ * ~~~~~~~~~~~~~
+ *
+ */
+#define DESCRIBE_C2FIELD(member, name) \
+ C2FieldDescriptor(&((_type*)(nullptr))->member, name),
+
+#define C2FIELD(member, name) _C2FIELD(member, name, __C2_GENERATE_GLOBAL_VARS__)
+/// \if 0
+#define _C2FIELD(member, name, enabled) __C2FIELD(member, name, enabled)
+#define __C2FIELD(member, name, enabled) DESCRIBE_C2FIELD##enabled(member, name)
+#define DESCRIBE_C2FIELD__C2_GENERATE_GLOBAL_VARS__(member, name)
+/// \endif
+
+/// Define a structure with matching CORE_INDEX and start describing its fields.
+/// This must be at the end of the structure definition.
+#define DEFINE_AND_DESCRIBE_C2STRUCT(name) \
+ _DEFINE_AND_DESCRIBE_C2STRUCT(name, DEFINE_C2STRUCT, __C2_GENERATE_GLOBAL_VARS__)
+
+/// Define a base structure (with no CORE_INDEX) and start describing its fields.
+/// This must be at the end of the structure definition.
+#define DEFINE_AND_DESCRIBE_BASE_C2STRUCT(name) \
+ _DEFINE_AND_DESCRIBE_C2STRUCT(name, DEFINE_BASE_C2STRUCT, __C2_GENERATE_GLOBAL_VARS__)
+
+/// Define a flexible structure with matching CORE_INDEX and start describing its fields.
+/// This must be at the end of the structure definition.
+#define DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(name, flexMember) \
+ _DEFINE_AND_DESCRIBE_FLEX_C2STRUCT( \
+ name, flexMember, DEFINE_FLEX_C2STRUCT, __C2_GENERATE_GLOBAL_VARS__)
+
+/// Define a flexible base structure (with no CORE_INDEX) and start describing its fields.
+/// This must be at the end of the structure definition.
+#define DEFINE_AND_DESCRIBE_BASE_FLEX_C2STRUCT(name, flexMember) \
+ _DEFINE_AND_DESCRIBE_FLEX_C2STRUCT( \
+ name, flexMember, DEFINE_BASE_FLEX_C2STRUCT, __C2_GENERATE_GLOBAL_VARS__)
+
+/// \if 0
+/*
+ Alternate declaration of field definitions in case no field list is to be generated.
+ The specific macro is chosed based on the value of __C2_GENERATE_GLOBAL_VARS__ (whether it is
+ defined (to be empty) or not. This requires two level of macro substitution.
+ TRICKY: use namespace declaration to handle closing bracket that is normally after
+ these macros.
+*/
+
+#define _DEFINE_AND_DESCRIBE_C2STRUCT(name, defineMacro, enabled) \
+ __DEFINE_AND_DESCRIBE_C2STRUCT(name, defineMacro, enabled)
+#define __DEFINE_AND_DESCRIBE_C2STRUCT(name, defineMacro, enabled) \
+ ___DEFINE_AND_DESCRIBE_C2STRUCT##enabled(name, defineMacro)
+#define ___DEFINE_AND_DESCRIBE_C2STRUCT__C2_GENERATE_GLOBAL_VARS__(name, defineMacro) \
+ defineMacro(name) } C2_PACK; namespace {
+#define ___DEFINE_AND_DESCRIBE_C2STRUCT(name, defineMacro) \
+ defineMacro(name) } C2_PACK; \
+ const std::vector<C2FieldDescriptor> C2##name##Struct::FieldList() { return _FIELD_LIST; } \
+ const std::vector<C2FieldDescriptor> C2##name##Struct::_FIELD_LIST = {
+
+#define _DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(name, flexMember, defineMacro, enabled) \
+ __DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(name, flexMember, defineMacro, enabled)
+#define __DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(name, flexMember, defineMacro, enabled) \
+ ___DEFINE_AND_DESCRIBE_FLEX_C2STRUCT##enabled(name, flexMember, defineMacro)
+#define ___DEFINE_AND_DESCRIBE_FLEX_C2STRUCT__C2_GENERATE_GLOBAL_VARS__(name, flexMember, defineMacro) \
+ defineMacro(name, flexMember) } C2_PACK; namespace {
+#define ___DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(name, flexMember, defineMacro) \
+ defineMacro(name, flexMember) } C2_PACK; \
+ const std::vector<C2FieldDescriptor> C2##name##Struct::FieldList() { return _FIELD_LIST; } \
+ const std::vector<C2FieldDescriptor> C2##name##Struct::_FIELD_LIST = {
+/// \endif
+
+
+/**
+ * Parameter reflector class.
+ *
+ * This class centralizes the description of parameter structures. This can be shared
+ * by multiple components as describing a parameter does not imply support of that
+ * parameter. However, each supported parameter and any dependent structures within
+ * must be described by the parameter reflector provided by a component.
+ */
+class C2ParamReflector {
+public:
+ /**
+ * Describes a parameter structure.
+ *
+ * \param[in] coreIndex the core index of the parameter structure containing at least the
+ * core index
+ *
+ * \return the description of the parameter structure
+ * \retval nullptr if the parameter is not supported by this reflector
+ *
+ * This methods shall not block and return immediately.
+ *
+ * \note this class does not take a set of indices because we would then prefer
+ * to also return any dependent structures, and we don't want this logic to be
+ * repeated in each reflector. Alternately, this could just return a map of all
+ * descriptions, but we want to conserve memory if client only wants the description
+ * of a few indices.
+ */
+ virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const = 0;
+
+protected:
+ virtual ~C2ParamReflector() = default;
+};
+
+/**
+ * Generic supported values for a field.
+ *
+ * This can be either a range or a set of values. The range can be a simple range, an arithmetic,
+ * geometric or multiply-accumulate series with a clear minimum and maximum value. Values can
+ * be discrete values, or can optionally represent flags to be or-ed.
+ *
+ * \note Do not use flags to represent bitfields. Use individual values or separate fields instead.
+ */
+struct C2FieldSupportedValues {
+//public:
+ enum type_t {
+ EMPTY, ///< no supported values
+ RANGE, ///< a numeric range that can be continuous or discrete
+ VALUES, ///< a list of values
+ FLAGS ///< a list of flags that can be OR-ed
+ };
+
+ type_t type; /** Type of values for this field. */
+
+ typedef C2Value::Primitive Primitive;
+
+ /**
+ * Range specifier for supported value. Used if type is RANGE.
+ *
+ * If step is 0 and num and denom are both 1, the supported values are any value, for which
+ * min <= value <= max.
+ *
+ * Otherwise, the range represents a geometric/arithmetic/multiply-accumulate series, where
+ * successive supported values can be derived from previous values (starting at min), using the
+ * following formula:
+ * v[0] = min
+ * v[i] = v[i-1] * num / denom + step for i >= 1, while min < v[i] <= max.
+ */
+ struct {
+ /** Lower end of the range (inclusive). */
+ Primitive min;
+ /** Upper end of the range (inclusive if permitted by series). */
+ Primitive max;
+ /** Step between supported values. */
+ Primitive step;
+ /** Numerator of a geometric series. */
+ Primitive num;
+ /** Denominator of a geometric series. */
+ Primitive denom;
+ } range;
+
+ /**
+ * List of values. Used if type is VALUES or FLAGS.
+ *
+ * If type is VALUES, this is the list of supported values in decreasing preference.
+ *
+ * If type is FLAGS, this vector contains { min-mask, flag1, flag2... }. Basically, the first
+ * value is the required set of flags to be set, and the rest of the values are flags that can
+ * be set independently. FLAGS is only supported for integral types. Supported flags should
+ * not overlap, as it can make validation non-deterministic. The standard validation method
+ * is that starting from the original value, if each flag is removed when fully present (the
+ * min-mask must be fully present), we shall arrive at 0.
+ */
+ std::vector<Primitive> values;
+
+ C2FieldSupportedValues()
+ : type(EMPTY) {
+ }
+
+ template<typename T>
+ C2FieldSupportedValues(T min, T max, T step = T(std::is_floating_point<T>::value ? 0 : 1))
+ : type(RANGE),
+ range{min, max, step, (T)1, (T)1} { }
+
+ template<typename T>
+ C2FieldSupportedValues(T min, T max, T num, T den) :
+ type(RANGE),
+ range{min, max, (T)0, num, den} { }
+
+ template<typename T>
+ C2FieldSupportedValues(T min, T max, T step, T num, T den)
+ : type(RANGE),
+ range{min, max, step, num, den} { }
+
+ /// \deprecated
+ template<typename T>
+ C2FieldSupportedValues(bool flags, std::initializer_list<T> list)
+ : type(flags ? FLAGS : VALUES),
+ range{(T)0, (T)0, (T)0, (T)0, (T)0} {
+ for (T value : list) {
+ values.emplace_back(value);
+ }
+ }
+
+ /// \deprecated
+ template<typename T>
+ C2FieldSupportedValues(bool flags, const std::vector<T>& list)
+ : type(flags ? FLAGS : VALUES),
+ range{(T)0, (T)0, (T)0, (T)0, (T)0} {
+ for(T value : list) {
+ values.emplace_back(value);
+ }
+ }
+
+ /// \internal
+ /// \todo: create separate values vs. flags initializer as for flags we want
+ /// to list both allowed and required flags
+ template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)0))>
+ C2FieldSupportedValues(bool flags, const T*)
+ : type(flags ? FLAGS : VALUES),
+ range{(T)0, (T)0, (T)0, (T)0, (T)0} {
+ C2FieldDescriptor::NamedValuesType named = C2FieldDescriptor::namedValuesFor(*(T*)0);
+ if (flags) {
+ values.emplace_back(0); // min-mask defaults to 0
+ }
+ for (const C2FieldDescriptor::NamedValueType &item : named){
+ values.emplace_back(item.second);
+ }
+ }
+};
+
+/**
+ * Supported values for a specific field.
+ *
+ * This is a pair of the field specifier together with an optional supported values object.
+ * This structure is used when reporting parameter configuration failures and conflicts.
+ */
+struct C2ParamFieldValues {
+ C2ParamField paramOrField; ///< the field or parameter
+ /// optional supported values for the field if paramOrField specifies an actual field that is
+ /// numeric (non struct, blob or string). Supported values for arrays (including string and
+ /// blobs) describe the supported values for each element (character for string, and bytes for
+ /// blobs). It is optional for read-only strings and blobs.
+ std::unique_ptr<C2FieldSupportedValues> values;
+
+ // This struct is meant to be move constructed.
+ C2_DEFAULT_MOVE(C2ParamFieldValues);
+
+ // Copy constructor/assignment is also provided as this object may get copied.
+ C2ParamFieldValues(const C2ParamFieldValues &other)
+ : paramOrField(other.paramOrField),
+ values(other.values ? std::make_unique<C2FieldSupportedValues>(*other.values) : nullptr) { }
+
+ C2ParamFieldValues& operator=(const C2ParamFieldValues &other) {
+ paramOrField = other.paramOrField;
+ values = other.values ? std::make_unique<C2FieldSupportedValues>(*other.values) : nullptr;
+ return *this;
+ }
+
+
+ /**
+ * Construct with no values.
+ */
+ C2ParamFieldValues(const C2ParamField ¶mOrField_)
+ : paramOrField(paramOrField_) { }
+
+ /**
+ * Construct with values.
+ */
+ C2ParamFieldValues(const C2ParamField ¶mOrField_, const C2FieldSupportedValues &values_)
+ : paramOrField(paramOrField_),
+ values(std::make_unique<C2FieldSupportedValues>(values_)) { }
+
+ /**
+ * Construct from fields.
+ */
+ C2ParamFieldValues(const C2ParamField ¶mOrField_, std::unique_ptr<C2FieldSupportedValues> &&values_)
+ : paramOrField(paramOrField_),
+ values(std::move(values_)) { }
+};
+
+/// @}
+
+// include debug header for C2Params.h if C2Debug.h was already included
+#ifdef C2UTILS_DEBUG_H_
+#include <util/C2Debug-param.h>
+#endif
+
+#endif // C2PARAM_H_
diff --git a/media/codec2/include/C2ParamDef.h b/media/codec2/include/C2ParamDef.h
new file mode 100644
index 0000000..0a33283
--- /dev/null
+++ b/media/codec2/include/C2ParamDef.h
@@ -0,0 +1,931 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+/** \file
+ * Templates used to declare parameters.
+ */
+#ifndef C2PARAM_DEF_H_
+#define C2PARAM_DEF_H_
+
+#include <type_traits>
+
+#include <C2Param.h>
+
+/// \addtogroup Parameters
+/// @{
+
+/* ======================== UTILITY TEMPLATES FOR PARAMETER DEFINITIONS ======================== */
+
+/// \addtogroup internal
+/// @{
+
+/// Helper class that checks if a type has equality and inequality operators.
+struct C2_HIDE _C2Comparable_impl
+{
+ template<typename S, typename=decltype(S() == S())>
+ static std::true_type TestEqual(int);
+ template<typename>
+ static std::false_type TestEqual(...);
+
+ template<typename S, typename=decltype(S() != S())>
+ static std::true_type TestNotEqual(int);
+ template<typename>
+ static std::false_type TestNotEqual(...);
+};
+
+/**
+ * Helper template that returns if a type has equality and inequality operators.
+ *
+ * Use as _C2Comparable<typename S>::value.
+ */
+template<typename S>
+struct C2_HIDE _C2Comparable
+ : public std::integral_constant<bool, decltype(_C2Comparable_impl::TestEqual<S>(0))::value
+ || decltype(_C2Comparable_impl::TestNotEqual<S>(0))::value> {
+};
+
+/// Helper class that checks if a type has a CORE_INDEX constant.
+struct C2_HIDE _C2CoreIndexHelper_impl
+{
+ template<typename S, int=S::CORE_INDEX>
+ static std::true_type TestCoreIndex(int);
+ template<typename>
+ static std::false_type TestCoreIndex(...);
+};
+
+/// Macro that defines and thus overrides a type's CORE_INDEX for a setting
+#define _C2_CORE_INDEX_OVERRIDE(coreIndex) \
+public: \
+ enum : uint32_t { CORE_INDEX = coreIndex };
+
+
+/// Helper template that adds a CORE_INDEX to a type if it does not have one (for testing)
+template<typename S, int CoreIndex>
+struct C2_HIDE _C2AddCoreIndex : public S {
+ _C2_CORE_INDEX_OVERRIDE(CoreIndex)
+};
+
+/**
+ * \brief Helper class to check struct requirements for parameters.
+ *
+ * Features:
+ * - verify default constructor, no virtual methods, and no equality operators.
+ * - expose PARAM_TYPE, and non-flex FLEX_SIZE.
+ */
+template<typename S, int CoreIndex, unsigned TypeFlags>
+struct C2_HIDE _C2StructCheck {
+ static_assert(
+ std::is_default_constructible<S>::value, "C2 structure must have default constructor");
+ static_assert(!std::is_polymorphic<S>::value, "C2 structure must not have virtual methods");
+ static_assert(!_C2Comparable<S>::value, "C2 structure must not have operator== or !=");
+
+public:
+ enum : uint32_t {
+ PARAM_TYPE = CoreIndex | TypeFlags
+ };
+
+protected:
+ enum : uint32_t {
+ FLEX_SIZE = 0,
+ };
+};
+
+/// Helper class that checks if a type has an integer FLEX_SIZE member.
+struct C2_HIDE _C2Flexible_impl {
+ /// specialization for types that have a FLEX_SIZE member
+ template<typename S, unsigned=S::FLEX_SIZE>
+ static std::true_type TestFlexSize(int);
+ template<typename>
+ static std::false_type TestFlexSize(...);
+};
+
+/// Helper template that returns if a type has an integer FLEX_SIZE member.
+template<typename S>
+struct C2_HIDE _C2Flexible
+ : public std::integral_constant<bool, decltype(_C2Flexible_impl::TestFlexSize<S>(0))::value> {
+};
+
+/// Macro to test if a type is flexible (has a FLEX_SIZE member).
+#define IF_FLEXIBLE(S) ENABLE_IF(_C2Flexible<S>::value)
+/// Shorthand for std::enable_if
+#define ENABLE_IF(cond) typename std::enable_if<cond>::type
+
+template<typename T, typename V=void>
+struct C2_HIDE _c2_enable_if_type {
+ typedef V type;
+};
+
+/// Helper template that exposes the flexible subtype of a struct.
+template<typename S, typename E=void>
+struct C2_HIDE _C2FlexHelper {
+ typedef void FlexType;
+ enum : uint32_t { FLEX_SIZE = 0 };
+};
+
+/// Specialization for flexible types. This only works if _FlexMemberType is public.
+template<typename S>
+struct C2_HIDE _C2FlexHelper<S,
+ typename _c2_enable_if_type<typename S::_FlexMemberType>::type> {
+ typedef typename _C2FlexHelper<typename S::_FlexMemberType>::FlexType FlexType;
+ enum : uint32_t { FLEX_SIZE = _C2FlexHelper<typename S::_FlexMemberType>::FLEX_SIZE };
+};
+
+/// Specialization for flex arrays.
+template<typename S>
+struct C2_HIDE _C2FlexHelper<S[],
+ typename std::enable_if<std::is_void<typename _C2FlexHelper<S>::FlexType>::value>::type> {
+ typedef S FlexType;
+ enum : uint32_t { FLEX_SIZE = sizeof(S) };
+};
+
+/**
+ * \brief Helper class to check flexible struct requirements and add common operations.
+ *
+ * Features:
+ * - expose CORE_INDEX and FieldList (this is normally inherited from the struct, but flexible
+ * structs cannot be base classes and thus inherited from)
+ * - disable copy assignment and construction (TODO: this is already done in the FLEX macro for the
+ * flexible struct, so may not be needed here)
+ */
+template<typename S, int ParamIndex, unsigned TypeFlags>
+struct C2_HIDE _C2FlexStructCheck :
+// add flexible flag as _C2StructCheck defines PARAM_TYPE
+ public _C2StructCheck<S, ParamIndex | C2Param::CoreIndex::IS_FLEX_FLAG, TypeFlags> {
+public:
+ enum : uint32_t {
+ /// \hideinitializer
+ CORE_INDEX = ParamIndex | C2Param::CoreIndex::IS_FLEX_FLAG, ///< flexible struct core-index
+ };
+
+ inline static const std::vector<C2FieldDescriptor> FieldList() { return S::FieldList(); }
+
+ // default constructor needed because of the disabled copy constructor
+ inline _C2FlexStructCheck() = default;
+
+protected:
+ // cannot copy flexible params
+ _C2FlexStructCheck(const _C2FlexStructCheck<S, ParamIndex, TypeFlags> &) = delete;
+ _C2FlexStructCheck& operator= (const _C2FlexStructCheck<S, ParamIndex, TypeFlags> &) = delete;
+
+ // constants used for helper methods
+ enum : uint32_t {
+ /// \hideinitializer
+ FLEX_SIZE = _C2FlexHelper<S>::FLEX_SIZE, ///< size of flexible type
+ /// \hideinitializer
+ MAX_SIZE = (uint32_t)std::min((size_t)UINT32_MAX, SIZE_MAX), // TODO: is this always u32 max?
+ /// \hideinitializer
+ BASE_SIZE = sizeof(S) + sizeof(C2Param), ///< size of the base param
+ };
+
+ /// returns the allocated size of this param with flexCount, or 0 if it would overflow.
+ inline static size_t CalcSize(size_t flexCount, size_t size = BASE_SIZE) {
+ if (flexCount <= (MAX_SIZE - size) / S::FLEX_SIZE) {
+ return size + S::FLEX_SIZE * flexCount;
+ }
+ return 0;
+ }
+
+ /// dynamic new operator usable for params of type S
+ inline void* operator new(size_t size, size_t flexCount) noexcept {
+ // TODO: assert(size == BASE_SIZE);
+ size = CalcSize(flexCount, size);
+ if (size > 0) {
+ return ::operator new(size);
+ }
+ return nullptr;
+ }
+};
+
+/// Define From() cast operators for params.
+#define DEFINE_CAST_OPERATORS(_Type) \
+ inline static _Type* From(C2Param *other) { \
+ return (_Type*)C2Param::IfSuitable( \
+ other, sizeof(_Type), _Type::PARAM_TYPE, _Type::FLEX_SIZE, \
+ (_Type::PARAM_TYPE & T::Index::DIR_UNDEFINED) != T::Index::DIR_UNDEFINED); \
+ } \
+ inline static const _Type* From(const C2Param *other) { \
+ return const_cast<const _Type*>(From(const_cast<C2Param *>(other))); \
+ } \
+ inline static _Type* From(std::nullptr_t) { return nullptr; } \
+
+/**
+ * Define flexible allocators (AllocShared or AllocUnique) for flexible params.
+ * - P::AllocXyz(flexCount, args...): allocate for given flex-count. This maps to
+ * T(flexCount, args...)\
+ *
+ * Clang does not support args... followed by templated param as args... eats it. Hence,
+ * provide specializations where the initializer replaces the flexCount.
+ *
+ * Specializations that deduce flexCount:
+ * - P::AllocXyz(T[], args...): allocate for size of (and with) init array.
+ * - P::AllocXyz(std::initializer_list<T>, args...): allocate for size of (and with) initializer
+ * list.
+ * - P::AllocXyz(std::vector<T>, args...): allocate for size of (and with) init vector.
+ * These specializations map to T(flexCount = size-of-init, args..., init)
+ */
+#define DEFINE_FLEXIBLE_ALLOC(_Type, S, ptr, Ptr) \
+ template<typename ...Args> \
+ inline static std::ptr##_ptr<_Type> Alloc##Ptr(size_t flexCount, const Args(&... args)) { \
+ return std::ptr##_ptr<_Type>(new(flexCount) _Type(flexCount, args...)); \
+ } \
+ template<typename ...Args, typename U=typename S::FlexType> \
+ inline static std::ptr##_ptr<_Type> Alloc##Ptr( \
+ const std::initializer_list<U> &init, const Args(&... args)) { \
+ return std::ptr##_ptr<_Type>(new(init.size()) _Type(init.size(), args..., init)); \
+ } \
+ template<typename ...Args, typename U=typename S::FlexType> \
+ inline static std::ptr##_ptr<_Type> Alloc##Ptr( \
+ const std::vector<U> &init, const Args(&... args)) { \
+ return std::ptr##_ptr<_Type>(new(init.size()) _Type(init.size(), args..., init)); \
+ } \
+ template<typename ...Args, typename U=typename S::FlexType, unsigned N> \
+ inline static std::ptr##_ptr<_Type> Alloc##Ptr(const U(&init)[N], const Args(&... args)) { \
+ return std::ptr##_ptr<_Type>(new(N) _Type(N, args..., init)); \
+ } \
+
+/**
+ * Define flexible methods AllocShared, AllocUnique and flexCount.
+ */
+#define DEFINE_FLEXIBLE_METHODS(_Type, S) \
+ DEFINE_FLEXIBLE_ALLOC(_Type, S, shared, Shared) \
+ DEFINE_FLEXIBLE_ALLOC(_Type, S, unique, Unique) \
+ inline size_t flexCount() const { \
+ static_assert(sizeof(_Type) == _Type::BASE_SIZE, "incorrect BASE_SIZE"); \
+ size_t sz = this->size(); \
+ if (sz >= sizeof(_Type)) { \
+ return (sz - sizeof(_Type)) / _Type::FLEX_SIZE; \
+ } \
+ return 0; \
+ } \
+
+/// Mark flexible member variable and make structure flexible.
+#define FLEX(cls, m) \
+ C2_DO_NOT_COPY(cls) \
+private: \
+ C2PARAM_MAKE_FRIENDS \
+ /** \if 0 */ \
+ template<typename, typename> friend struct _C2FlexHelper; \
+public: \
+ typedef decltype(m) _FlexMemberType; \
+ /* default constructor with flexCount */ \
+ inline cls(size_t) : cls() {} \
+ /* constexpr static _FlexMemberType cls::* flexMember = &cls::m; */ \
+ typedef typename _C2FlexHelper<_FlexMemberType>::FlexType FlexType; \
+ static_assert(\
+ !std::is_void<FlexType>::value, \
+ "member is not flexible, or a flexible array of a flexible type"); \
+ enum : uint32_t { FLEX_SIZE = _C2FlexHelper<_FlexMemberType>::FLEX_SIZE }; \
+ /** \endif */ \
+
+/// @}
+
+/**
+ * Global-parameter template.
+ *
+ * Base template to define a global setting/tuning or info based on a structure and
+ * an optional ParamIndex. Global parameters are not tied to a port (input or output).
+ *
+ * Parameters wrap structures by prepending a (parameter) header. The fields of the wrapped
+ * structure can be accessed directly, and constructors and potential public methods are also
+ * wrapped.
+ *
+ * \tparam T param type C2Setting, C2Tuning or C2Info
+ * \tparam S wrapped structure
+ * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
+ * structures.
+ */
+template<typename T, typename S, int ParamIndex=S::CORE_INDEX, class Flex=void>
+struct C2_HIDE C2GlobalParam : public T, public S,
+ public _C2StructCheck<S, ParamIndex, T::PARAM_KIND | T::Type::DIR_GLOBAL> {
+ _C2_CORE_INDEX_OVERRIDE(ParamIndex)
+private:
+ typedef C2GlobalParam<T, S, ParamIndex> _Type;
+
+public:
+ /// Wrapper around base structure's constructor.
+ template<typename ...Args>
+ inline C2GlobalParam(const Args(&... args)) : T(sizeof(_Type), _Type::PARAM_TYPE), S(args...) { }
+
+ DEFINE_CAST_OPERATORS(_Type)
+};
+
+/**
+ * Global-parameter template for flexible structures.
+ *
+ * Base template to define a global setting/tuning or info based on a flexible structure and
+ * an optional ParamIndex. Global parameters are not tied to a port (input or output).
+ *
+ * \tparam T param type C2Setting, C2Tuning or C2Info
+ * \tparam S wrapped flexible structure
+ * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
+ * structures.
+ *
+ * Parameters wrap structures by prepending a (parameter) header. The fields and methods of flexible
+ * structures can be accessed via the m member variable; however, the constructors of the structure
+ * are wrapped directly. (This is because flexible types cannot be subclassed.)
+ */
+template<typename T, typename S, int ParamIndex>
+struct C2_HIDE C2GlobalParam<T, S, ParamIndex, IF_FLEXIBLE(S)>
+ : public T, public _C2FlexStructCheck<S, ParamIndex, T::PARAM_KIND | T::Type::DIR_GLOBAL> {
+private:
+ typedef C2GlobalParam<T, S, ParamIndex> _Type;
+
+ /// Wrapper around base structure's constructor.
+ template<typename ...Args>
+ inline C2GlobalParam(size_t flexCount, const Args(&... args))
+ : T(_Type::CalcSize(flexCount), _Type::PARAM_TYPE), m(flexCount, args...) { }
+
+public:
+ S m; ///< wrapped flexible structure
+
+ DEFINE_FLEXIBLE_METHODS(_Type, S)
+ DEFINE_CAST_OPERATORS(_Type)
+};
+
+/**
+ * Port-parameter template.
+ *
+ * Base template to define a port setting/tuning or info based on a structure and
+ * an optional ParamIndex. Port parameters are tied to a port (input or output), but not to a
+ * specific stream.
+ *
+ * \tparam T param type C2Setting, C2Tuning or C2Info
+ * \tparam S wrapped structure
+ * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
+ * structures.
+ *
+ * Parameters wrap structures by prepending a (parameter) header. The fields of the wrapped
+ * structure can be accessed directly, and constructors and potential public methods are also
+ * wrapped.
+ *
+ * There are 3 flavors of port parameters: unspecified, input and output. Parameters with
+ * unspecified port expose a setPort method, and add an initial port parameter to the constructor.
+ */
+template<typename T, typename S, int ParamIndex=S::CORE_INDEX, class Flex=void>
+struct C2_HIDE C2PortParam : public T, public S,
+ private _C2StructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_UNDEFINED> {
+ _C2_CORE_INDEX_OVERRIDE(ParamIndex)
+private:
+ typedef C2PortParam<T, S, ParamIndex> _Type;
+
+public:
+ /// Default constructor.
+ inline C2PortParam() : T(sizeof(_Type), _Type::PARAM_TYPE) { }
+ template<typename ...Args>
+ /// Wrapper around base structure's constructor while specifying port/direction.
+ inline C2PortParam(bool _output, const Args(&... args))
+ : T(sizeof(_Type), _output ? output::PARAM_TYPE : input::PARAM_TYPE), S(args...) { }
+ /// Set port/direction.
+ inline void setPort(bool output) { C2Param::setPort(output); }
+
+ DEFINE_CAST_OPERATORS(_Type)
+
+ /// Specialization for an input port parameter.
+ struct input : public T, public S,
+ public _C2StructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_INPUT> {
+ _C2_CORE_INDEX_OVERRIDE(ParamIndex)
+ /// Wrapper around base structure's constructor.
+ template<typename ...Args>
+ inline input(const Args(&... args)) : T(sizeof(_Type), input::PARAM_TYPE), S(args...) { }
+
+ DEFINE_CAST_OPERATORS(input)
+
+ };
+
+ /// Specialization for an output port parameter.
+ struct output : public T, public S,
+ public _C2StructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_OUTPUT> {
+ _C2_CORE_INDEX_OVERRIDE(ParamIndex)
+ /// Wrapper around base structure's constructor.
+ template<typename ...Args>
+ inline output(const Args(&... args)) : T(sizeof(_Type), output::PARAM_TYPE), S(args...) { }
+
+ DEFINE_CAST_OPERATORS(output)
+ };
+};
+
+/**
+ * Port-parameter template for flexible structures.
+ *
+ * Base template to define a port setting/tuning or info based on a flexible structure and
+ * an optional ParamIndex. Port parameters are tied to a port (input or output), but not to a
+ * specific stream.
+ *
+ * \tparam T param type C2Setting, C2Tuning or C2Info
+ * \tparam S wrapped flexible structure
+ * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
+ * structures.
+ *
+ * Parameters wrap structures by prepending a (parameter) header. The fields and methods of flexible
+ * structures can be accessed via the m member variable; however, the constructors of the structure
+ * are wrapped directly. (This is because flexible types cannot be subclassed.)
+ *
+ * There are 3 flavors of port parameters: unspecified, input and output. Parameters with
+ * unspecified port expose a setPort method, and add an initial port parameter to the constructor.
+ */
+template<typename T, typename S, int ParamIndex>
+struct C2_HIDE C2PortParam<T, S, ParamIndex, IF_FLEXIBLE(S)>
+ : public T, public _C2FlexStructCheck<S, ParamIndex, T::PARAM_KIND | T::Type::DIR_UNDEFINED> {
+private:
+ typedef C2PortParam<T, S, ParamIndex> _Type;
+
+ /// Default constructor for basic allocation: new(flexCount) P.
+ inline C2PortParam(size_t flexCount) : T(_Type::CalcSize(flexCount), _Type::PARAM_TYPE) { }
+ template<typename ...Args>
+ /// Wrapper around base structure's constructor while also specifying port/direction.
+ inline C2PortParam(size_t flexCount, bool _output, const Args(&... args))
+ : T(_Type::CalcSize(flexCount), _output ? output::PARAM_TYPE : input::PARAM_TYPE),
+ m(flexCount, args...) { }
+
+public:
+ /// Set port/direction.
+ inline void setPort(bool output) { C2Param::setPort(output); }
+
+ S m; ///< wrapped flexible structure
+
+ DEFINE_FLEXIBLE_METHODS(_Type, S)
+ DEFINE_CAST_OPERATORS(_Type)
+
+ /// Specialization for an input port parameter.
+ struct input : public T,
+ public _C2FlexStructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_INPUT> {
+ private:
+ /// Wrapper around base structure's constructor while also specifying port/direction.
+ template<typename ...Args>
+ inline input(size_t flexCount, const Args(&... args))
+ : T(_Type::CalcSize(flexCount), input::PARAM_TYPE), m(flexCount, args...) { }
+
+ public:
+ S m; ///< wrapped flexible structure
+
+ DEFINE_FLEXIBLE_METHODS(input, S)
+ DEFINE_CAST_OPERATORS(input)
+ };
+
+ /// Specialization for an output port parameter.
+ struct output : public T,
+ public _C2FlexStructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_OUTPUT> {
+ private:
+ /// Wrapper around base structure's constructor while also specifying port/direction.
+ template<typename ...Args>
+ inline output(size_t flexCount, const Args(&... args))
+ : T(_Type::CalcSize(flexCount), output::PARAM_TYPE), m(flexCount, args...) { }
+
+ public:
+ S m; ///< wrapped flexible structure
+
+ DEFINE_FLEXIBLE_METHODS(output, S)
+ DEFINE_CAST_OPERATORS(output)
+ };
+};
+
+/**
+ * Stream-parameter template.
+ *
+ * Base template to define a stream setting/tuning or info based on a structure and
+ * an optional ParamIndex. Stream parameters are tied to a specific stream on a port (input or
+ * output).
+ *
+ * \tparam T param type C2Setting, C2Tuning or C2Info
+ * \tparam S wrapped structure
+ * \tparam ParamIndex optional paramter index override. Must be specified for base/reused
+ * structures.
+ *
+ * Parameters wrap structures by prepending a (parameter) header. The fields of the wrapped
+ * structure can be accessed directly, and constructors and potential public methods are also
+ * wrapped.
+ *
+ * There are 3 flavors of stream parameters: unspecified port, input and output. All of these expose
+ * a setStream method and an extra initial streamID parameter for the constructor. Moreover,
+ * parameters with unspecified port expose a setPort method, and add an additional initial port
+ * parameter to the constructor.
+ */
+template<typename T, typename S, int ParamIndex=S::CORE_INDEX, class Flex=void>
+struct C2_HIDE C2StreamParam : public T, public S,
+ private _C2StructCheck<S, ParamIndex,
+ T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Index::DIR_UNDEFINED> {
+ _C2_CORE_INDEX_OVERRIDE(ParamIndex)
+private:
+ typedef C2StreamParam<T, S, ParamIndex> _Type;
+
+public:
+ /// Default constructor. Port/direction and stream-ID is undefined.
+ inline C2StreamParam() : T(sizeof(_Type), _Type::PARAM_TYPE) { }
+ /// Wrapper around base structure's constructor while also specifying port/direction and
+ /// stream-ID.
+ template<typename ...Args>
+ inline C2StreamParam(bool _output, unsigned stream, const Args(&... args))
+ : T(sizeof(_Type), _output ? output::PARAM_TYPE : input::PARAM_TYPE, stream),
+ S(args...) { }
+ /// Set port/direction.
+ inline void setPort(bool output) { C2Param::setPort(output); }
+ /// Set stream-id. \retval true if the stream-id was successfully set.
+ inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
+
+ DEFINE_CAST_OPERATORS(_Type)
+
+ /// Specialization for an input stream parameter.
+ struct input : public T, public S,
+ public _C2StructCheck<S, ParamIndex,
+ T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Type::DIR_INPUT> {
+ _C2_CORE_INDEX_OVERRIDE(ParamIndex)
+
+ /// Default constructor. Stream-ID is undefined.
+ inline input() : T(sizeof(_Type), input::PARAM_TYPE) { }
+ /// Wrapper around base structure's constructor while also specifying stream-ID.
+ template<typename ...Args>
+ inline input(unsigned stream, const Args(&... args))
+ : T(sizeof(_Type), input::PARAM_TYPE, stream), S(args...) { }
+ /// Set stream-id. \retval true if the stream-id was successfully set.
+ inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
+
+ DEFINE_CAST_OPERATORS(input)
+ };
+
+ /// Specialization for an output stream parameter.
+ struct output : public T, public S,
+ public _C2StructCheck<S, ParamIndex,
+ T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Type::DIR_OUTPUT> {
+ _C2_CORE_INDEX_OVERRIDE(ParamIndex)
+
+ /// Default constructor. Stream-ID is undefined.
+ inline output() : T(sizeof(_Type), output::PARAM_TYPE) { }
+ /// Wrapper around base structure's constructor while also specifying stream-ID.
+ template<typename ...Args>
+ inline output(unsigned stream, const Args(&... args))
+ : T(sizeof(_Type), output::PARAM_TYPE, stream), S(args...) { }
+ /// Set stream-id. \retval true if the stream-id was successfully set.
+ inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
+
+ DEFINE_CAST_OPERATORS(output)
+ };
+};
+
+/**
+ * Stream-parameter template for flexible structures.
+ *
+ * Base template to define a stream setting/tuning or info based on a flexible structure and
+ * an optional ParamIndex. Stream parameters are tied to a specific stream on a port (input or
+ * output).
+ *
+ * \tparam T param type C2Setting, C2Tuning or C2Info
+ * \tparam S wrapped flexible structure
+ * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
+ * structures.
+ *
+ * Parameters wrap structures by prepending a (parameter) header. The fields and methods of flexible
+ * structures can be accessed via the m member variable; however, the constructors of the structure
+ * are wrapped directly. (This is because flexible types cannot be subclassed.)
+ *
+ * There are 3 flavors of stream parameters: unspecified port, input and output. All of these expose
+ * a setStream method and an extra initial streamID parameter for the constructor. Moreover,
+ * parameters with unspecified port expose a setPort method, and add an additional initial port
+ * parameter to the constructor.
+ */
+template<typename T, typename S, int ParamIndex>
+struct C2_HIDE C2StreamParam<T, S, ParamIndex, IF_FLEXIBLE(S)>
+ : public T,
+ public _C2FlexStructCheck<S, ParamIndex,
+ T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Index::DIR_UNDEFINED> {
+private:
+ typedef C2StreamParam<T, S, ParamIndex> _Type;
+ /// Default constructor. Port/direction and stream-ID is undefined.
+ inline C2StreamParam(size_t flexCount) : T(_Type::CalcSize(flexCount), _Type::PARAM_TYPE, 0u) { }
+ /// Wrapper around base structure's constructor while also specifying port/direction and
+ /// stream-ID.
+ template<typename ...Args>
+ inline C2StreamParam(size_t flexCount, bool _output, unsigned stream, const Args(&... args))
+ : T(_Type::CalcSize(flexCount), _output ? output::PARAM_TYPE : input::PARAM_TYPE, stream),
+ m(flexCount, args...) { }
+
+public:
+ S m; ///< wrapped flexible structure
+
+ /// Set port/direction.
+ inline void setPort(bool output) { C2Param::setPort(output); }
+ /// Set stream-id. \retval true if the stream-id was successfully set.
+ inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
+
+ DEFINE_FLEXIBLE_METHODS(_Type, S)
+ DEFINE_CAST_OPERATORS(_Type)
+
+ /// Specialization for an input stream parameter.
+ struct input : public T,
+ public _C2FlexStructCheck<S, ParamIndex,
+ T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Type::DIR_INPUT> {
+ private:
+ /// Default constructor. Stream-ID is undefined.
+ inline input(size_t flexCount) : T(_Type::CalcSize(flexCount), input::PARAM_TYPE) { }
+ /// Wrapper around base structure's constructor while also specifying stream-ID.
+ template<typename ...Args>
+ inline input(size_t flexCount, unsigned stream, const Args(&... args))
+ : T(_Type::CalcSize(flexCount), input::PARAM_TYPE, stream), m(flexCount, args...) { }
+
+ public:
+ S m; ///< wrapped flexible structure
+
+ /// Set stream-id. \retval true if the stream-id was successfully set.
+ inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
+
+ DEFINE_FLEXIBLE_METHODS(input, S)
+ DEFINE_CAST_OPERATORS(input)
+ };
+
+ /// Specialization for an output stream parameter.
+ struct output : public T,
+ public _C2FlexStructCheck<S, ParamIndex,
+ T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Type::DIR_OUTPUT> {
+ private:
+ /// Default constructor. Stream-ID is undefined.
+ inline output(size_t flexCount) : T(_Type::CalcSize(flexCount), output::PARAM_TYPE) { }
+ /// Wrapper around base structure's constructor while also specifying stream-ID.
+ template<typename ...Args>
+ inline output(size_t flexCount, unsigned stream, const Args(&... args))
+ : T(_Type::CalcSize(flexCount), output::PARAM_TYPE, stream), m(flexCount, args...) { }
+
+ public:
+ S m; ///< wrapped flexible structure
+
+ /// Set stream-id. \retval true if the stream-id was successfully set.
+ inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
+
+ DEFINE_FLEXIBLE_METHODS(output, S)
+ DEFINE_CAST_OPERATORS(output)
+ };
+};
+
+/* ======================== SIMPLE VALUE PARAMETERS ======================== */
+
+/**
+ * \ingroup internal
+ * A structure template encapsulating a single element with default constructors and no core-index.
+ */
+template<typename T>
+struct C2SimpleValueStruct {
+ T value; ///< simple value of the structure
+ // Default constructor.
+ inline C2SimpleValueStruct() = default;
+ // Constructor with an initial value.
+ inline C2SimpleValueStruct(T value) : value(value) {}
+ DEFINE_BASE_C2STRUCT(SimpleValue)
+};
+
+// TODO: move this and next to some generic place
+/**
+ * Interface to a block of (mapped) memory containing an array of some type (T).
+ */
+template<typename T>
+struct C2MemoryBlock {
+ /// \returns the number of elements in this block.
+ virtual size_t size() const = 0;
+ /// \returns a const pointer to the start of this block. Care must be taken to not read outside
+ /// the block.
+ virtual const T *data() const = 0; // TODO: should this be friend access only in some C2Memory module?
+ /// \returns a pointer to the start of this block. Care must be taken to not read or write
+ /// outside the block.
+ inline T *data() { return const_cast<T*>(const_cast<const C2MemoryBlock*>(this)->data()); }
+
+protected:
+ // TODO: for now it should never be deleted as C2MemoryBlock
+ virtual ~C2MemoryBlock() = default;
+};
+
+/**
+ * Interface to a block of memory containing a constant (constexpr) array of some type (T).
+ */
+template<typename T>
+struct C2ConstMemoryBlock : public C2MemoryBlock<T> {
+ virtual const T * data() const { return _mData; }
+ virtual size_t size() const { return _mSize; }
+
+ /// Constructor.
+ template<unsigned N>
+ inline constexpr C2ConstMemoryBlock(const T(&init)[N]) : _mData(init), _mSize(N) {}
+
+private:
+ const T *_mData;
+ const size_t _mSize;
+};
+
+/// \addtogroup internal
+/// @{
+
+/// Helper class to initialize flexible arrays with various initalizers.
+struct _C2ValueArrayHelper {
+ // char[]-s are used as null terminated strings, so the last element is never inited.
+
+ /// Initialize a flexible array using a constexpr memory block.
+ template<typename T>
+ static void init(T(&array)[], size_t arrayLen, const C2MemoryBlock<T> &block) {
+ // reserve last element for terminal 0 for strings
+ if (arrayLen && std::is_same<T, char>::value) {
+ --arrayLen;
+ }
+ if (block.data()) {
+ memcpy(array, block.data(), std::min(arrayLen, block.size()) * sizeof(T));
+ }
+ }
+
+ /// Initialize a flexible array using an initializer list.
+ template<typename T>
+ static void init(T(&array)[], size_t arrayLen, const std::initializer_list<T> &init) {
+ size_t ix = 0;
+ // reserve last element for terminal 0 for strings
+ if (arrayLen && std::is_same<T, char>::value) {
+ --arrayLen;
+ }
+ for (const T &item : init) {
+ if (ix == arrayLen) {
+ break;
+ }
+ array[ix++] = item;
+ }
+ }
+
+ /// Initialize a flexible array using a vector.
+ template<typename T>
+ static void init(T(&array)[], size_t arrayLen, const std::vector<T> &init) {
+ size_t ix = 0;
+ // reserve last element for terminal 0 for strings
+ if (arrayLen && std::is_same<T, char>::value) {
+ --arrayLen;
+ }
+ for (const T &item : init) {
+ if (ix == arrayLen) {
+ break;
+ }
+ array[ix++] = item;
+ }
+ }
+
+ /// Initialize a flexible array using another flexible array.
+ template<typename T, unsigned N>
+ static void init(T(&array)[], size_t arrayLen, const T(&str)[N]) {
+ // reserve last element for terminal 0 for strings
+ if (arrayLen && std::is_same<T, char>::value) {
+ --arrayLen;
+ }
+ if (arrayLen) {
+ memcpy(array, str, std::min(arrayLen, (size_t)N) * sizeof(T));
+ }
+ }
+};
+
+/**
+ * Specialization for a flexible blob and string arrays. A structure template encapsulating a single
+ * flexible array member with default flexible constructors and no core-index. This type cannot be
+ * constructed on its own as it's size is 0.
+ *
+ * \internal This is different from C2SimpleArrayStruct<T[]> simply because its member has the name
+ * as value to reflect this is a single value.
+ */
+template<typename T>
+struct C2SimpleValueStruct<T[]> {
+ static_assert(std::is_same<T, char>::value || std::is_same<T, uint8_t>::value,
+ "C2SimpleValueStruct<T[]> is only for BLOB or STRING");
+ T value[];
+
+ inline C2SimpleValueStruct() = default;
+ DEFINE_BASE_C2STRUCT(SimpleValue)
+ FLEX(C2SimpleValueStruct, value)
+
+private:
+ inline C2SimpleValueStruct(size_t flexCount, const C2MemoryBlock<T> &block) {
+ _C2ValueArrayHelper::init(value, flexCount, block);
+ }
+
+ inline C2SimpleValueStruct(size_t flexCount, const std::initializer_list<T> &init) {
+ _C2ValueArrayHelper::init(value, flexCount, init);
+ }
+
+ inline C2SimpleValueStruct(size_t flexCount, const std::vector<T> &init) {
+ _C2ValueArrayHelper::init(value, flexCount, init);
+ }
+
+ template<unsigned N>
+ inline C2SimpleValueStruct(size_t flexCount, const T(&init)[N]) {
+ _C2ValueArrayHelper::init(value, flexCount, init);
+ }
+};
+
+/// @}
+
+/**
+ * A structure template encapsulating a single flexible array element of a specific type (T) with
+ * default constructors and no core-index. This type cannot be constructed on its own as it's size
+ * is 0. Instead, it is meant to be used as a parameter, e.g.
+ *
+ * typedef C2StreamParam<C2Info, C2SimpleArrayStruct<C2MyFancyStruct>,
+ * kParamIndexMyFancyArrayStreamParam> C2MyFancyArrayStreamInfo;
+ */
+template<typename T>
+struct C2SimpleArrayStruct {
+ static_assert(!std::is_same<T, char>::value && !std::is_same<T, uint8_t>::value,
+ "use C2SimpleValueStruct<T[]> is for BLOB or STRING");
+
+ T values[]; ///< array member
+ /// Default constructor
+ inline C2SimpleArrayStruct() = default;
+ DEFINE_BASE_FLEX_C2STRUCT(SimpleArray, values)
+ //FLEX(C2SimpleArrayStruct, values)
+
+private:
+ /// Construct from a C2MemoryBlock.
+ /// Used only by the flexible parameter allocators (AllocUnique & AllocShared).
+ inline C2SimpleArrayStruct(size_t flexCount, const C2MemoryBlock<T> &block) {
+ _C2ValueArrayHelper::init(values, flexCount, block);
+ }
+
+ /// Construct from an initializer list.
+ /// Used only by the flexible parameter allocators (AllocUnique & AllocShared).
+ inline C2SimpleArrayStruct(size_t flexCount, const std::initializer_list<T> &init) {
+ _C2ValueArrayHelper::init(values, flexCount, init);
+ }
+
+ /// Construct from an vector.
+ /// Used only by the flexible parameter allocators (AllocUnique & AllocShared).
+ inline C2SimpleArrayStruct(size_t flexCount, const std::vector<T> &init) {
+ _C2ValueArrayHelper::init(values, flexCount, init);
+ }
+
+ /// Construct from another flexible array.
+ /// Used only by the flexible parameter allocators (AllocUnique & AllocShared).
+ template<unsigned N>
+ inline C2SimpleArrayStruct(size_t flexCount, const T(&init)[N]) {
+ _C2ValueArrayHelper::init(values, flexCount, init);
+ }
+};
+
+/**
+ * \addtogroup simplevalue Simple value and array structures.
+ * @{
+ *
+ * Simple value structures.
+ *
+ * Structures containing a single simple value. These can be reused to easily define simple
+ * parameters of various types:
+ *
+ * typedef C2PortParam<C2Tuning, C2Int32Value, kParamIndexMyIntegerPortParam>
+ * C2MyIntegerPortParamTuning;
+ *
+ * They contain a single member (value or values) that is described as "value" or "values".
+ *
+ * These structures don't define a core index, and as such, they cannot be used in structure
+ * declarations. Use type[] instead, such as int32_t field[].
+ */
+/// A 32-bit signed integer parameter in value, described as "value"
+typedef C2SimpleValueStruct<int32_t> C2Int32Value;
+/// A 32-bit signed integer array parameter in values, described as "values"
+typedef C2SimpleArrayStruct<int32_t> C2Int32Array;
+/// A 32-bit unsigned integer parameter in value, described as "value"
+typedef C2SimpleValueStruct<uint32_t> C2Uint32Value;
+/// A 32-bit unsigned integer array parameter in values, described as "values"
+typedef C2SimpleArrayStruct<uint32_t> C2Uint32Array;
+/// A 64-bit signed integer parameter in value, described as "value"
+typedef C2SimpleValueStruct<int64_t> C2Int64Value;
+/// A 64-bit signed integer array parameter in values, described as "values"
+typedef C2SimpleArrayStruct<int64_t> C2Int64Array;
+/// A 64-bit unsigned integer parameter in value, described as "value"
+typedef C2SimpleValueStruct<uint64_t> C2Uint64Value;
+/// A 64-bit unsigned integer array parameter in values, described as "values"
+typedef C2SimpleArrayStruct<uint64_t> C2Uint64Array;
+/// A float parameter in value, described as "value"
+typedef C2SimpleValueStruct<float> C2FloatValue;
+/// A float array parameter in values, described as "values"
+typedef C2SimpleArrayStruct<float> C2FloatArray;
+/// A blob flexible parameter in value, described as "value"
+typedef C2SimpleValueStruct<uint8_t[]> C2BlobValue;
+/// A string flexible parameter in value, described as "value"
+typedef C2SimpleValueStruct<char[]> C2StringValue;
+
+template<typename T>
+const std::vector<C2FieldDescriptor> C2SimpleValueStruct<T>::FieldList() {
+ return { DESCRIBE_C2FIELD(value, "value") };
+}
+template<typename T>
+const std::vector<C2FieldDescriptor> C2SimpleValueStruct<T[]>::FieldList() {
+ return { DESCRIBE_C2FIELD(value, "value") };
+}
+template<typename T>
+const std::vector<C2FieldDescriptor> C2SimpleArrayStruct<T>::FieldList() {
+ return { DESCRIBE_C2FIELD(values, "values") };
+}
+
+/// @}
+
+/// @}
+
+#endif // C2PARAM_DEF_H_
diff --git a/media/codec2/include/C2Work.h b/media/codec2/include/C2Work.h
new file mode 100644
index 0000000..6923f3e
--- /dev/null
+++ b/media/codec2/include/C2Work.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef C2WORK_H_
+
+#define C2WORK_H_
+
+#include <C2Buffer.h>
+#include <C2Param.h>
+
+#include <memory>
+#include <list>
+#include <vector>
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/// \defgroup work Work and data processing
+/// @{
+
+/**
+ * Information describing the reason a parameter settings may fail, or
+ * may be overriden.
+ */
+struct C2SettingResult {
+ enum Failure : uint32_t {
+ /* parameter failures below */
+ BAD_TYPE, ///< parameter is not supported
+ BAD_PORT, ///< parameter is not supported on the specific port
+ BAD_INDEX, ///< parameter is not supported on the specific stream
+ READ_ONLY, ///< parameter is read-only and cannot be set
+ MISMATCH, ///< parameter mismatches input data
+
+ /* field failures below */
+ BAD_VALUE, ///< strict parameter does not accept value for the field at all
+ CONFLICT, ///< strict parameter field value is in conflict with an/other setting(s)
+
+ /// parameter field is out of range due to other settings (this failure mode
+ /// can only be used for strict calculated parameters)
+ UNSUPPORTED,
+
+ /// field does not access the requested parameter value at all. It has been corrected to
+ /// the closest supported value. This failure mode is provided to give guidance as to what
+ /// are the currently supported values for this field (which may be a subset of the at-all-
+ /// potential values)
+ INFO_BAD_VALUE,
+
+ /// requested parameter value is in conflict with an/other setting(s)
+ /// and has been corrected to the closest supported value. This failure
+ /// mode is given to provide guidance as to what are the currently supported values as well
+ /// as to optionally provide suggestion to the client as to how to enable the requested
+ /// parameter value.
+ INFO_CONFLICT,
+ };
+
+ Failure failure; ///< failure code
+
+ /// Failing (or corrected) field or parameterand optionally, currently supported values for the
+ /// field. Values must only be set for field failures other than BAD_VALUE, and only if they are
+ /// different from the globally supported values (e.g. due to restrictions by another param or
+ /// input data).
+ C2ParamFieldValues field;
+
+ /// Conflicting parameters or fields with optional suggestions with (optional) suggested values
+ /// for any conflicting fields to avoid the conflict. Must only be set for CONFLICT, UNSUPPORTED
+ /// and INFO_CONFLICT failure codes.
+ std::vector<C2ParamFieldValues> conflicts;
+};
+
+// ================================================================================================
+// WORK
+// ================================================================================================
+
+/** Unique ID for a processing node. */
+typedef uint32_t c2_node_id_t;
+
+enum {
+ kParamIndexWorkOrdinal,
+};
+
+/**
+ * Information for ordering work items on a component port.
+ */
+struct C2WorkOrdinalStruct {
+//public:
+ c2_cntr64_t timestamp; /** frame timestamp in microseconds */
+ c2_cntr64_t frameIndex; /** submission ordinal on the initial component */
+ c2_cntr64_t customOrdinal; /** can be given by the component, e.g. decode order */
+
+ DEFINE_AND_DESCRIBE_C2STRUCT(WorkOrdinal)
+ C2FIELD(timestamp, "timestamp")
+ C2FIELD(frameIndex, "frame-index")
+ C2FIELD(customOrdinal, "custom-ordinal")
+};
+
+/**
+ * This structure represents a Codec 2.0 frame with its metadata.
+ *
+ * A frame basically consists of an ordered sets of buffers, configuration changes and info buffers
+ * along with some non-configuration metadata.
+ */
+struct C2FrameData {
+//public:
+ enum flags_t : uint32_t {
+ /**
+ * For input frames: no output frame shall be generated when processing this frame, but
+ * metadata shall still be processed.
+ * For output frames: this frame shall be discarded and but metadata is still valid.
+ */
+ FLAG_DROP_FRAME = (1 << 0),
+ /**
+ * This frame is the last frame of the current stream. Further frames are part of a new
+ * stream.
+ */
+ FLAG_END_OF_STREAM = (1 << 1),
+ /**
+ * This frame shall be discarded with its metadata.
+ * This flag is only set by components - e.g. as a response to the flush command.
+ */
+ FLAG_DISCARD_FRAME = (1 << 2),
+ /**
+ * This frame is not the last frame produced for the input.
+ *
+ * This flag is normally set by the component - e.g. when an input frame results in multiple
+ * output frames, this flag is set on all but the last output frame.
+ *
+ * Also, when components are chained, this flag should be propagated down the
+ * work chain. That is, if set on an earlier frame of a work-chain, it should be propagated
+ * to all later frames in that chain. Additionally, components down the chain could set
+ * this flag even if not set earlier, e.g. if multiple output frame is generated at that
+ * component for the input frame.
+ */
+ FLAG_INCOMPLETE = (1 << 3),
+ /**
+ * This frame contains only codec-specific configuration data, and no actual access unit.
+ *
+ * \deprecated pass codec configuration with using the \todo codec-specific configuration
+ * info together with the access unit.
+ */
+ FLAG_CODEC_CONFIG = (1u << 31),
+ };
+
+ /**
+ * Frame flags */
+ flags_t flags;
+ C2WorkOrdinalStruct ordinal;
+ std::vector<std::shared_ptr<C2Buffer>> buffers;
+ //< for initial work item, these may also come from the parser - if provided
+ //< for output buffers, these are the responses to requestedInfos
+ std::vector<std::unique_ptr<C2Param>> configUpdate;
+ std::vector<std::shared_ptr<C2InfoBuffer>> infoBuffers;
+};
+
+struct C2Worklet {
+//public:
+ // IN
+ c2_node_id_t component;
+
+ /** Configuration changes to be applied before processing this worklet. */
+ std::vector<std::unique_ptr<C2Tuning>> tunings;
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+
+ // OUT
+ C2FrameData output;
+};
+
+/**
+ * Information about partial work-chains not part of the current work items.
+ *
+ * To be defined later.
+ */
+struct C2WorkChainInfo;
+
+/**
+ * This structure holds information about all a single work item.
+ *
+ * This structure shall be passed by the client to the component for the first worklet. As such,
+ * worklets must not be empty. The ownership of this object is passed.
+ */
+struct C2Work {
+//public:
+ /// additional work chain info not part of this work
+ std::shared_ptr<C2WorkChainInfo> chainInfo;
+
+ /// The input data to be processed as part of this work/work-chain. This is provided by the
+ /// client with ownership. When the work is returned (via onWorkDone), the input buffer-pack's
+ /// buffer vector shall contain nullptrs.
+ C2FrameData input;
+
+ /// The chain of components, tunings (including output buffer pool IDs) and info requests that the
+ /// data must pass through. If this has more than a single element, the tunnels between successive
+ /// components of the worklet chain must have been (successfully) pre-registered at the time that
+ /// the work is submitted. Allocating the output buffers in the worklets is the responsibility of
+ /// each component. Upon work submission, each output buffer-pack shall be an appropriately sized
+ /// vector containing nullptrs. When the work is completed/returned to the client, output buffers
+ /// pointers from all but the final worklet shall be nullptrs.
+ std::list<std::unique_ptr<C2Worklet>> worklets;
+
+ /// Number of worklets successfully processed in this chain. This shall be initialized to 0 by the
+ /// client when the work is submitted. It shall contain the number of worklets that were
+ /// successfully processed when the work is returned to the client. If this is less then the number
+ /// of worklets, result must not be success. It must be in the range of [0, worklets.size()].
+ uint32_t workletsProcessed;
+
+ /// The final outcome of the work (corresponding to the current workletsProcessed). If 0 when
+ /// work is returned, it is assumed that all worklets have been processed.
+ c2_status_t result;
+};
+
+/**
+ * Information about a future work to be submitted to the component. The information is used to
+ * reserve the work for work ordering purposes.
+ */
+struct C2WorkOutline {
+//public:
+ C2WorkOrdinalStruct ordinal;
+ std::vector<c2_node_id_t> chain;
+};
+
+/// @}
+
+#endif // C2WORK_H_
diff --git a/media/codec2/include/_C2MacroUtils.h b/media/codec2/include/_C2MacroUtils.h
new file mode 100644
index 0000000..04e9ba5
--- /dev/null
+++ b/media/codec2/include/_C2MacroUtils.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef C2UTILS_MACRO_UTILS_H_
+#define C2UTILS_MACRO_UTILS_H_
+
+/** \file
+ * Macro utilities for the utils library used by Codec2 implementations.
+ */
+
+/// \if 0
+
+/* --------------------------------- VARIABLE ARGUMENT COUNTING --------------------------------- */
+
+// remove empty arguments - _C2_ARG() expands to '', while _C2_ARG(x) expands to ', x'
+// _C2_ARGn(...) does the same for n arguments
+#define _C2_ARG(...) , ##__VA_ARGS__
+#define _C2_ARG2(_1, _2) _C2_ARG(_1) _C2_ARG(_2)
+#define _C2_ARG4(_1, _2, _3, _4) _C2_ARG2(_1, _2) _C2_ARG2(_3, _4)
+#define _C2_ARG8(_1, _2, _3, _4, _5, _6, _7, _8) _C2_ARG4(_1, _2, _3, _4) _C2_ARG4(_5, _6, _7, _8)
+#define _C2_ARG16(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \
+ _C2_ARG8(_1, _2, _3, _4, _5, _6, _7, _8) _C2_ARG8(_9, _10, _11, _12, _13, _14, _15, _16)
+
+// return the 65th argument
+#define _C2_ARGC_3(_, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+ _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, \
+ _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, \
+ _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, ...) _64
+
+/// \endif
+
+/**
+ * Returns the number of arguments.
+ */
+// We do this by prepending 1 and appending 65 designed values such that the 65th element
+// will be the number of arguments.
+#define _C2_ARGC(...) _C2_ARGC_1(0, ##__VA_ARGS__, \
+ 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, \
+ 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \
+ 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+
+/// \if 0
+
+// step 1. remove empty arguments - this is needed to allow trailing comma in enum definitions
+// (NOTE: we don't know which argument will have this trailing comma so we have to try all)
+#define _C2_ARGC_1(_, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
+ _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, \
+ _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, \
+ _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, ...) \
+ _C2_ARGC_2(_ _C2_ARG(_0) \
+ _C2_ARG16(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \
+ _C2_ARG16(_17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32) \
+ _C2_ARG16(_33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48) \
+ _C2_ARG16(_49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64), \
+ ##__VA_ARGS__)
+
+// step 2. this is needed as removed arguments cannot be passed directly as empty into a macro
+#define _C2_ARGC_2(...) _C2_ARGC_3(__VA_ARGS__)
+
+/// \endif
+
+/* -------------------------------- VARIABLE ARGUMENT CONVERSION -------------------------------- */
+
+/// \if 0
+
+// macros that convert _1, _2, _3, ... to fn(_1, arg), fn(_2, arg), fn(_3, arg), ...
+#define _C2_MAP_64(fn, arg, head, ...) fn(head, arg), _C2_MAP_63(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_63(fn, arg, head, ...) fn(head, arg), _C2_MAP_62(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_62(fn, arg, head, ...) fn(head, arg), _C2_MAP_61(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_61(fn, arg, head, ...) fn(head, arg), _C2_MAP_60(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_60(fn, arg, head, ...) fn(head, arg), _C2_MAP_59(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_59(fn, arg, head, ...) fn(head, arg), _C2_MAP_58(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_58(fn, arg, head, ...) fn(head, arg), _C2_MAP_57(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_57(fn, arg, head, ...) fn(head, arg), _C2_MAP_56(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_56(fn, arg, head, ...) fn(head, arg), _C2_MAP_55(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_55(fn, arg, head, ...) fn(head, arg), _C2_MAP_54(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_54(fn, arg, head, ...) fn(head, arg), _C2_MAP_53(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_53(fn, arg, head, ...) fn(head, arg), _C2_MAP_52(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_52(fn, arg, head, ...) fn(head, arg), _C2_MAP_51(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_51(fn, arg, head, ...) fn(head, arg), _C2_MAP_50(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_50(fn, arg, head, ...) fn(head, arg), _C2_MAP_49(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_49(fn, arg, head, ...) fn(head, arg), _C2_MAP_48(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_48(fn, arg, head, ...) fn(head, arg), _C2_MAP_47(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_47(fn, arg, head, ...) fn(head, arg), _C2_MAP_46(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_46(fn, arg, head, ...) fn(head, arg), _C2_MAP_45(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_45(fn, arg, head, ...) fn(head, arg), _C2_MAP_44(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_44(fn, arg, head, ...) fn(head, arg), _C2_MAP_43(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_43(fn, arg, head, ...) fn(head, arg), _C2_MAP_42(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_42(fn, arg, head, ...) fn(head, arg), _C2_MAP_41(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_41(fn, arg, head, ...) fn(head, arg), _C2_MAP_40(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_40(fn, arg, head, ...) fn(head, arg), _C2_MAP_39(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_39(fn, arg, head, ...) fn(head, arg), _C2_MAP_38(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_38(fn, arg, head, ...) fn(head, arg), _C2_MAP_37(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_37(fn, arg, head, ...) fn(head, arg), _C2_MAP_36(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_36(fn, arg, head, ...) fn(head, arg), _C2_MAP_35(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_35(fn, arg, head, ...) fn(head, arg), _C2_MAP_34(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_34(fn, arg, head, ...) fn(head, arg), _C2_MAP_33(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_33(fn, arg, head, ...) fn(head, arg), _C2_MAP_32(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_32(fn, arg, head, ...) fn(head, arg), _C2_MAP_31(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_31(fn, arg, head, ...) fn(head, arg), _C2_MAP_30(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_30(fn, arg, head, ...) fn(head, arg), _C2_MAP_29(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_29(fn, arg, head, ...) fn(head, arg), _C2_MAP_28(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_28(fn, arg, head, ...) fn(head, arg), _C2_MAP_27(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_27(fn, arg, head, ...) fn(head, arg), _C2_MAP_26(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_26(fn, arg, head, ...) fn(head, arg), _C2_MAP_25(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_25(fn, arg, head, ...) fn(head, arg), _C2_MAP_24(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_24(fn, arg, head, ...) fn(head, arg), _C2_MAP_23(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_23(fn, arg, head, ...) fn(head, arg), _C2_MAP_22(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_22(fn, arg, head, ...) fn(head, arg), _C2_MAP_21(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_21(fn, arg, head, ...) fn(head, arg), _C2_MAP_20(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_20(fn, arg, head, ...) fn(head, arg), _C2_MAP_19(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_19(fn, arg, head, ...) fn(head, arg), _C2_MAP_18(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_18(fn, arg, head, ...) fn(head, arg), _C2_MAP_17(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_17(fn, arg, head, ...) fn(head, arg), _C2_MAP_16(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_16(fn, arg, head, ...) fn(head, arg), _C2_MAP_15(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_15(fn, arg, head, ...) fn(head, arg), _C2_MAP_14(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_14(fn, arg, head, ...) fn(head, arg), _C2_MAP_13(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_13(fn, arg, head, ...) fn(head, arg), _C2_MAP_12(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_12(fn, arg, head, ...) fn(head, arg), _C2_MAP_11(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_11(fn, arg, head, ...) fn(head, arg), _C2_MAP_10(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_10(fn, arg, head, ...) fn(head, arg), _C2_MAP_9(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_9(fn, arg, head, ...) fn(head, arg), _C2_MAP_8(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_8(fn, arg, head, ...) fn(head, arg), _C2_MAP_7(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_7(fn, arg, head, ...) fn(head, arg), _C2_MAP_6(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_6(fn, arg, head, ...) fn(head, arg), _C2_MAP_5(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_5(fn, arg, head, ...) fn(head, arg), _C2_MAP_4(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_4(fn, arg, head, ...) fn(head, arg), _C2_MAP_3(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_3(fn, arg, head, ...) fn(head, arg), _C2_MAP_2(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_2(fn, arg, head, ...) fn(head, arg), _C2_MAP_1(fn, arg, ##__VA_ARGS__)
+#define _C2_MAP_1(fn, arg, head, ...) fn(head, arg)
+
+/// \endif
+
+/**
+ * Maps each argument using another macro x -> fn(x, arg)
+ */
+// use wrapper to call the proper mapper based on the number of arguments
+#define _C2_MAP(fn, arg, ...) _C2_MAP__(_C2_ARGC(__VA_ARGS__), fn, arg, ##__VA_ARGS__)
+
+/// \if 0
+
+// evaluate _n so it becomes a number
+#define _C2_MAP__(_n, fn, arg, ...) _C2_MAP_(_n, fn, arg, __VA_ARGS__)
+// call the proper mapper
+#define _C2_MAP_(_n, fn, arg, ...) _C2_MAP_##_n (fn, arg, __VA_ARGS__)
+
+/// \endif
+
+#endif // C2UTILS_MACRO_UTILS_H_
diff --git a/media/codec2/include/android-C2Buffer.h b/media/codec2/include/android-C2Buffer.h
new file mode 100644
index 0000000..26beab7
--- /dev/null
+++ b/media/codec2/include/android-C2Buffer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ANDROID_C2BUFFER_H_
+#define ANDROID_C2BUFFER_H_
+
+#include <cutils/native_handle.h>
+#include <hardware/gralloc.h>
+
+/* Use android native handle for C2Handle */
+typedef ::native_handle_t C2Handle;
+
+namespace android {
+
+/**
+ * Android platform buffer/memory usage bits.
+ */
+struct C2AndroidMemoryUsage : public C2MemoryUsage {
+ inline C2AndroidMemoryUsage(const C2MemoryUsage &usage) : C2MemoryUsage(usage) { }
+
+// public:
+ /**
+ * Reuse gralloc flags where possible, as Codec 2.0 API only uses bits 0 and 1.
+ */
+ enum consumer_t : uint64_t {
+ RENDERSCRIPT_READ = GRALLOC_USAGE_RENDERSCRIPT,
+ HW_TEXTURE_READ = GRALLOC_USAGE_HW_TEXTURE,
+ HW_COMPOSER_READ = GRALLOC_USAGE_HW_COMPOSER,
+ // gralloc does not define a video decoder read usage flag, so use encoder for
+ // now
+ HW_CODEC_READ = GRALLOC_USAGE_HW_VIDEO_ENCODER,
+ READ_PROTECTED = GRALLOC_USAGE_PROTECTED,
+ };
+
+ enum producer_t : uint64_t {
+ RENDERSCRIPT_WRITE = GRALLOC_USAGE_RENDERSCRIPT,
+ HW_TEXTURE_WRITE = GRALLOC_USAGE_HW_RENDER,
+ HW_COMPOSER_WRITE = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER,
+ HW_CODEC_WRITE = GRALLOC_USAGE_HW_VIDEO_ENCODER,
+ // gralloc does not define a write protected usage flag, so use read protected
+ // now
+ WRITE_PROTECTED = GRALLOC_USAGE_PROTECTED,
+ };
+
+ /**
+ * Convert from gralloc usage.
+ */
+ static C2MemoryUsage FromGrallocUsage(uint64_t usage);
+
+ /**
+ * Convert to gralloc usage.
+ */
+ uint64_t asGrallocUsage() const;
+};
+
+} // namespace android
+
+#endif // ANDROID_C2BUFFER_H_
diff --git a/media/codec2/include/media/stagefright/codec2/1.0/InputSurface.h b/media/codec2/include/media/stagefright/codec2/1.0/InputSurface.h
new file mode 100644
index 0000000..b011a06
--- /dev/null
+++ b/media/codec2/include/media/stagefright/codec2/1.0/InputSurface.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2018, 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.
+ */
+
+#ifndef ANDROID_HARDWARE_MEDIA_C2_V1_0_INPUT_SURFACE_H
+#define ANDROID_HARDWARE_MEDIA_C2_V1_0_INPUT_SURFACE_H
+
+#include <memory>
+
+#include <C2Component.h>
+#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
+#include <media/stagefright/codec2/1.0/InputSurfaceConnection.h>
+
+namespace android {
+
+class GraphicBufferSource;
+
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+
+typedef ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer
+ HGraphicBufferProducer;
+typedef ::android::IGraphicBufferProducer BGraphicBufferProducer;
+
+// TODO: ::android::TWGraphicBufferProducer<IInputSurface>
+typedef ::android::TWGraphicBufferProducer<HGraphicBufferProducer> InputSurfaceBase;
+
+class InputSurface : public InputSurfaceBase {
+public:
+ virtual ~InputSurface() = default;
+
+ // Methods from IInputSurface
+ sp<InputSurfaceConnection> connectToComponent(
+ const std::shared_ptr<::C2Component> &comp);
+ // TODO: intf()
+
+ static sp<InputSurface> Create();
+
+private:
+ InputSurface(
+ const sp<BGraphicBufferProducer> &base,
+ const sp<::android::GraphicBufferSource> &source);
+
+ sp<::android::GraphicBufferSource> mSource;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_MEDIA_C2_V1_0_INPUT_SURFACE_H
diff --git a/media/codec2/include/media/stagefright/codec2/1.0/InputSurfaceConnection.h b/media/codec2/include/media/stagefright/codec2/1.0/InputSurfaceConnection.h
new file mode 100644
index 0000000..b24a416
--- /dev/null
+++ b/media/codec2/include/media/stagefright/codec2/1.0/InputSurfaceConnection.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2018, 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.
+ */
+
+#ifndef ANDROID_HARDWARE_MEDIA_C2_V1_0_INPUT_SURFACE_CONNECTION_H
+#define ANDROID_HARDWARE_MEDIA_C2_V1_0_INPUT_SURFACE_CONNECTION_H
+
+#include <memory>
+
+#include <C2Component.h>
+#include <media/stagefright/bqhelper/GraphicBufferSource.h>
+#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
+#include <media/stagefright/codec2/1.0/InputSurfaceConnection.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace implementation {
+
+// TODO: inherit from IInputSurfaceConnection
+class InputSurfaceConnection : public RefBase {
+public:
+ virtual ~InputSurfaceConnection();
+
+ // From IInputSurfaceConnection
+ void disconnect();
+
+private:
+ friend class InputSurface;
+
+ // For InputSurface
+ InputSurfaceConnection(
+ const sp<GraphicBufferSource> &source, const std::shared_ptr<C2Component> &comp);
+ bool init();
+
+ InputSurfaceConnection() = delete;
+
+ class Impl;
+
+ sp<GraphicBufferSource> mSource;
+ sp<Impl> mImpl;
+
+ DISALLOW_EVIL_CONSTRUCTORS(InputSurfaceConnection);
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_MEDIA_C2_V1_0_INPUT_SURFACE_CONNECTION_H